<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -4,26 +4,45 @@ ProtoFX
 ProtoFX is a animation light weight framework based on [Prototype](http://prototypejs.org).
 
 Question: One more?
-Answer: YES!
+Answer: YES! The only effect framework I know based on prototype is script.aculo.us. Current version is pretty old, slow and does
+seemed to be maintain. Scripty 2 is supposed to be the next version but nothing happened for months now.
+So I decided to create this framework for personal use. I needed to have something light, efficient with new features.
 
-ProtoFX is a simple animation framework, very light (base version is less than 5k) but with some great features:
-* speed, animation are pretty fluid.
-* with usefull behaviors: start, stop, reverse, rewind. I can stop animation when you wants and go back to start.
-* based on Penner equation.
-* 'cloneable'. You can create an animation, without giving a target, and apply it to any DOM element for instance
-* work with operator like width: +=200px
+So ProtoFX is a simple animation framework, very light (base version is less than 7k packed).
+
+The Semantic is inspired from music world. The object responsible of synchronized animations is called Metronome.
+Effect methods are inspired from a music player: play/stop/rewind/reverse ...
+Queue system is called 'Score' (it's reallu more powerful than standard queue system)
+
+Main features are:
+* Speed; animation are really fluid.
+* Useful commands: start, stop, reverse, rewind. You can stop animation when you want and go back to start again. 
+you can also reverse anamtio anin while playing.
+* based on Penner equations.
+* 'cloneable' effects. You can create an animation, without giving a target, and apply it to any DOM element for instance
+* work with operators: example width: +=200px
+* ...
 
 There are two versions:
-- base: has only simple effect on DOM element like: new FX.Element(&quot;block1&quot;).animate({width: '200px});
+- base: without 'Score': 
+  ex: new FX.Element(&quot;block1&quot;).animate({width: '200px});
+  in many cases, you do not have complex animations to run
+  
 - full: includes a 'Score' class to compose any kind of effects like:
     new FX.Score().add(fx1).add(fx2, {after: fx1});
 
+Check rake task to see how to build them but you can find them under dist directory
+
+Unit test are coming :)
+
 Documentation
 =============
+
 Documentation is done with [PDoc](http://pdoc.org).
 
 Rake Tasks
 ==========
+
 * rake build              # Build all dist files
 * rake build:base         # Builds base dist fill (not compressed)
 * rake build:full         # Builds full dist fill (not compressed)
@@ -31,4 +50,4 @@ Rake Tasks
 * rake build:packed_full  # Builds full dist fill (compressed by yui compressor)
 * rake doc                # Generates documentation
 
-ProtoFX is still under development and any contributions are welcome.
\ No newline at end of file
+ProtoFX is still under development and any contributions are welcome.</diff>
      <filename>README.markdown</filename>
    </modified>
    <modified>
      <diff>@@ -36,7 +36,8 @@ FX.Base = Class.create((function() {
     this.nextTime    = 0;
     this.playing     = false;
     this.backward    = false;
-    this.callbacks   = {onEnded: Prototype.emptyFunction, onStarted: Prototype.emptyFunction}
+    this.cycle       = false;
+    this.callbacks   = {onEnded: Prototype.emptyFunction, onStarted: Prototype.emptyFunction};
     this.setOptions(options);
   }
   
@@ -63,10 +64,23 @@ FX.Base = Class.create((function() {
   }
   
   /** 
+   *  FX.Base#setCycle(type, count) -&gt; FX.Base
+   *  - type (String): 
+   *    - 'loop' restarts from begin when effect is done
+   *    - 'backAndForth' starts in reverse mode when effect is done
+   *    - 'none' no cycles
+   *  - count (Number): number of cycles to run (default 1)
+   **/
+  function setCycle(type, count) {
+    this.cycle = type == 'none' ? false : {type: type, count: count || 1, current: 0}
+    return this;
+  }
+  
+  /** 
    *  FX.Base#play() -&gt; FX.Base
    *  
    *  Starts animation from current position
-   *  fires fx:started
+   *  fires fx:started, fx:beforeStarted
    **/
   function play() {
     if (this.playing) return;
@@ -124,6 +138,7 @@ FX.Base = Class.create((function() {
     this.fire('rewinded');
     this.updateAnimation(this.backward ? 1 : 0);
     this.currentTime = null;
+    if (this.cycle) this.cycle.current = 1;
     return this;
   }
 
@@ -136,13 +151,31 @@ FX.Base = Class.create((function() {
     if (this.currentTime &gt; this.getDuration() || this.currentTime &lt; 0) {
       // Force update to last position
       this.updateAnimation(this.currentTime &lt; 0 ? 0 : 1);
-      this.stopAnimation();
-      this.fire('ended');
+      // Check cycle
+      if (this.cycle &amp;&amp; this.cycle.current &lt; this.cycle.count) {
+        if (this.cycle.type == 'loop') {
+          this.cycle.current++;
+          this.updateAnimation(this.backward ? 1 : 0);
+          this.currentTime = this.backward ? this.getDuration() : 0;
+        }
+        else if (this.cycle.type == 'backAndForth') {
+          this.reverse();
+          if (this.backward) this.cycle.current++;
+        }
+      }
+      else {
+        this.stopAnimation();
+        this.fire('ended');
 
-      FX.Metronome.unregister(this);
+        FX.Metronome.unregister(this);
       
-      this.currentTime = null;
-      this.playing   = false;
+        this.currentTime = null;
+        this.playing   = false;
+        if (this.cycle) {
+          this.cycle.current = 0;
+          if (this.cycle.type == 'backAndForth') this.backward = !this.backward;
+        }
+      }
     }
     else {
       var pos = this.options.transition(this.currentTime / this.getDuration(), this.currentTime, 0, 1, this.getDuration());
@@ -180,6 +213,7 @@ FX.Base = Class.create((function() {
   return {           
     initialize:      initialize,
     setOptions:      setOptions,
+    setCycle:        setCycle,
     getDuration:     getDuration,
     play:            play,
     stop:            stop,</diff>
      <filename>dist/protofx.js</filename>
    </modified>
    <modified>
      <diff>@@ -36,7 +36,8 @@ FX.Base = Class.create((function() {
     this.nextTime    = 0;
     this.playing     = false;
     this.backward    = false;
-    this.callbacks   = {onEnded: Prototype.emptyFunction, onStarted: Prototype.emptyFunction}
+    this.cycle       = false;
+    this.callbacks   = {onEnded: Prototype.emptyFunction, onStarted: Prototype.emptyFunction};
     this.setOptions(options);
   }
   
@@ -63,10 +64,23 @@ FX.Base = Class.create((function() {
   }
   
   /** 
+   *  FX.Base#setCycle(type, count) -&gt; FX.Base
+   *  - type (String): 
+   *    - 'loop' restarts from begin when effect is done
+   *    - 'backAndForth' starts in reverse mode when effect is done
+   *    - 'none' no cycles
+   *  - count (Number): number of cycles to run (default 1)
+   **/
+  function setCycle(type, count) {
+    this.cycle = type == 'none' ? false : {type: type, count: count || 1, current: 0}
+    return this;
+  }
+  
+  /** 
    *  FX.Base#play() -&gt; FX.Base
    *  
    *  Starts animation from current position
-   *  fires fx:started
+   *  fires fx:started, fx:beforeStarted
    **/
   function play() {
     if (this.playing) return;
@@ -124,6 +138,7 @@ FX.Base = Class.create((function() {
     this.fire('rewinded');
     this.updateAnimation(this.backward ? 1 : 0);
     this.currentTime = null;
+    if (this.cycle) this.cycle.current = 1;
     return this;
   }
 
@@ -136,13 +151,31 @@ FX.Base = Class.create((function() {
     if (this.currentTime &gt; this.getDuration() || this.currentTime &lt; 0) {
       // Force update to last position
       this.updateAnimation(this.currentTime &lt; 0 ? 0 : 1);
-      this.stopAnimation();
-      this.fire('ended');
+      // Check cycle
+      if (this.cycle &amp;&amp; this.cycle.current &lt; this.cycle.count) {
+        if (this.cycle.type == 'loop') {
+          this.cycle.current++;
+          this.updateAnimation(this.backward ? 1 : 0);
+          this.currentTime = this.backward ? this.getDuration() : 0;
+        }
+        else if (this.cycle.type == 'backAndForth') {
+          this.reverse();
+          if (this.backward) this.cycle.current++;
+        }
+      }
+      else {
+        this.stopAnimation();
+        this.fire('ended');
 
-      FX.Metronome.unregister(this);
+        FX.Metronome.unregister(this);
       
-      this.currentTime = null;
-      this.playing   = false;
+        this.currentTime = null;
+        this.playing   = false;
+        if (this.cycle) {
+          this.cycle.current = 0;
+          if (this.cycle.type == 'backAndForth') this.backward = !this.backward;
+        }
+      }
     }
     else {
       var pos = this.options.transition(this.currentTime / this.getDuration(), this.currentTime, 0, 1, this.getDuration());
@@ -180,6 +213,7 @@ FX.Base = Class.create((function() {
   return {           
     initialize:      initialize,
     setOptions:      setOptions,
+    setCycle:        setCycle,
     getDuration:     getDuration,
     play:            play,
     stop:            stop,</diff>
      <filename>dist/protofx_base.js</filename>
    </modified>
    <modified>
      <diff>@@ -1 +1 @@
-FX={};FX.Transition={swing:function(B,C,A,E,D){return((-Math.cos(C/D*Math.PI)/2)+0.5)*E+A}};FX.DefaultOptions={duration:500,transition:FX.Transition.swing,eventNotifier:document,memoData:null};FX.Base=Class.create((function(){function G(O){this.options=Object.extend(Object.clone(FX.DefaultOptions),O);this.currentTime=null;this.nextTime=0;this.playing=false;this.backward=false;this.callbacks={onEnded:Prototype.emptyFunction,onStarted:Prototype.emptyFunction};this.setOptions(O)}function J(O){Object.extend(this.options,O||{});return this}function L(){return this.options.duration}function E(){return this.playing}function B(){if(this.playing){return }this.fire(&quot;beforeStarted&quot;);this.playing=true;if(this.currentTime==null){this.currentTime=this.backward?this.getDuration():0;this.startAnimation(this.backward)}FX.Metronome.register(this);this.fire(&quot;started&quot;);return this}function K(){this.fire(&quot;stopped&quot;);FX.Metronome.unregister(this);this.playing=false;return this}function I(){this.fire(&quot;reversed&quot;);this.backward=!this.backward;return this}function C(){this.stop();this.fire(&quot;rewinded&quot;);this.updateAnimation(this.backward?1:0);this.currentTime=null;return this}function N(P){this.currentTime+=this.backward?-P:P;if(this.currentTime&gt;this.getDuration()||this.currentTime&lt;0){this.updateAnimation(this.currentTime&lt;0?0:1);this.stopAnimation();this.fire(&quot;ended&quot;);FX.Metronome.unregister(this);this.currentTime=null;this.playing=false}else{var O=this.options.transition(this.currentTime/this.getDuration(),this.currentTime,0,1,this.getDuration());this.updateAnimation(O)}}function H(O){this.callbacks.onEnded=O;return this}function D(O){this.callbacks.onStarted=O;return this}function M(O){this.callbacks.onBeforestarted=O;return this}function A(O){var P;if(P=this.callbacks[&quot;on&quot;+O.capitalize()]){P()}this.options.eventNotifier.fire(&quot;fx:&quot;+O,{fx:this,data:this.memoData})}function F(O){throw&quot;FX.Base#updateAnimation(pos) must be implemented&quot;}return{initialize:G,setOptions:J,getDuration:L,play:B,stop:K,reverse:I,rewind:C,isPlaying:E,metronomeUpdate:N,startAnimation:Prototype.emptyFunction,stopAnimation:Prototype.emptyFunction,updateAnimation:F,fire:A,onStarted:D,onEnded:H,onBeforeStarted:M}})());FX.Attribute=Class.create((function(){function F(M,O,N){this.key=M;this.from=O;this.to=N;this.type=B(this.from);this.unit=D(this.from);this.fromFX=E(this.from,this.isColor());this.toFX=A(this)}function H(P){if(this.isNumber()){return I(this.fromFX,this.toFX,P)+this.unit}else{var O=parseInt(I(this.fromFX[0],this.toFX[0],P));var N=parseInt(I(this.fromFX[1],this.toFX[1],P));var M=parseInt(I(this.fromFX[2],this.toFX[2],P));return&quot;rgb(&quot;+O+&quot;, &quot;+N+&quot;, &quot;+M+&quot;)&quot;}}function G(O,N){if(O&amp;&amp;this.relative){this.from=O}this.fromFX=E(this.from,this.isColor());this.relative=false;this.toFX=A(this,N);if(N&amp;&amp;this.relative){var M=this.fromFX;this.fromFX=this.toFX,this.toFX=M}}function C(){return this.type==&quot;Color&quot;}function L(){return this.type==&quot;Number&quot;}function B(M){if(Object.isString(M)&amp;&amp;M.isColor()){return&quot;Color&quot;}else{return&quot;Number&quot;}}function D(N){var M;if(Object.isString(N)&amp;&amp;(M=N.match(/(\d+)([\w\%]*)/))){return M[2]}else{return&quot;&quot;}}function E(N,M){if(M){return N.getRGB()}else{if(Object.isString(N)){return parseFloat(N)}else{return N}}}function A(M,N){if(M.isColor()){return M.to.getRGB()}else{if(Object.isString(M.to)){if(K(M.to)){return J(M,N)}else{return parseFloat(M.to)}}else{return M.to}}}function I(O,N,M){return O+(N-O)*M}function K(M){return M.match(/^([\+\-\*\/]=)(\d*)$/)}function J(N,O){N.relative=true;var M=K(N.to);if((O&amp;&amp;M[1]==&quot;-=&quot;)||(!O&amp;&amp;M[1]==&quot;+=&quot;)){return N.fromFX+parseFloat(M[2])}else{if((O&amp;&amp;M[1]==&quot;+=&quot;)||(!O&amp;&amp;M[1]==&quot;-=&quot;)){return N.fromFX-parseFloat(M[2])}else{if((O&amp;&amp;M[1]==&quot;*=&quot;)||(!O&amp;&amp;M[1]==&quot;/=&quot;)){return N.fromFX/parseFloat(M[2])}else{if((O&amp;&amp;M[1]==&quot;/=&quot;)||(!O&amp;&amp;M[1]==&quot;*=&quot;)){return N.fromFX*parseFloat(M[2])}else{throw&quot;Operator &quot;+M[1]+&quot; not allowed&quot;}}}}}return{initialize:F,convert:H,reset:G,isNumber:L,isColor:C}})());FX.Metronome=(function(){var A=null,F=1000/60,C=null,I=new Array();function H(K){if(!J(K)){I.push(K);B()}}function E(K){I=I.reject(function(L){return L==K});if(I.length==0){G()}}function J(K){return I.find(function(L){return L==K})}function B(){if(A==null){C=new Date().getTime();A=setInterval(D,F);D()}}function G(){if(A){clearInterval(A);A=null;C=0}}function D(){var K=new Date().getTime();var L=K-C;C=K;I.invoke(&quot;metronomeUpdate&quot;,L)}return{register:H,unregister:E,isRegistered:J}})();Object.extend(String.prototype,{isColor:function(){return this.match(/^\#/)||this.match(/^rgb\(/)},getRGB:function(){function B(C){if(C.length==1){C+=C}return parseInt(C,16)}if(this.isColor()){var A;if(A=this.match(/(^rgb\()(\d+), (\d+), (\d+)(\))/i)){return[parseInt(A[2]),parseInt(A[3]),parseInt(A[4])]}if(A=this.match(/^\#([0-9a-f]{1})([0-9a-f]{1})([0-9a-f]{1})$/i)){return A.slice(1).collect(B)}if(A=this.match(/^\#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i)){return A.slice(1).collect(B)}}return null}});FX.Element=Class.create(FX.Base,(function(){function A($super,H,G){$super(G);this.element=$(H)}function D(G){this.originalAttributes=G;return this}function C(G){var H=new FX.Element(G,this.options).animate(this.originalAttributes);H.callbacks=this.callbacks;return H}function B(G){this.attributes=this.attributes||E(this.originalAttributes,this.element);this.attributes.each(function(H){H.reset(this.element.getStyle(H.key),G)},this)}function F(H){var G={};this.attributes.each(function(I){G[I.key]=I.convert(H)},this);this.element.setStyle(G)}function E(G,H){var I=[];$H(G).each(function(J){I.push(new FX.Attribute(J.key,H.getStyle(J.key),J.value))});return I}return{initialize:A,animate:D,cloneFor:C,startAnimation:B,updateAnimation:F}})());Element.addMethods({fade:function(B,A){new FX.Element(B).setOptions(A||{}).animate({opacity:0}).play();return B},appear:function(B,A){new FX.Element(B).setOptions(A||{}).animate({opacity:1}).play();return B},blindUp:function(B,A){if(!B.visible()){return }new FX.Element(B).setOptions(A||{}).onBeforeStarted(function(){B.originalHeight=B.style.height}).onEnded(function(){B.hide();B.style.height=B.originalHeight;(B.originalHeight)}).animate({height:0}).play();return B},blindDown:function(C,B){if(C.visible()){return }var A=C.getHeight();new FX.Element(C).setOptions(B||{}).onBeforeStarted(function(){C.show();C.style.height=&quot;0px&quot;}).animate({height:A+&quot;px&quot;}).play();return C}});
\ No newline at end of file
+FX={};FX.Transition={swing:function(B,C,A,E,D){return((-Math.cos(C/D*Math.PI)/2)+0.5)*E+A}};FX.DefaultOptions={duration:500,transition:FX.Transition.swing,eventNotifier:document,memoData:null};FX.Base=Class.create((function(){function G(P){this.options=Object.extend(Object.clone(FX.DefaultOptions),P);this.currentTime=null;this.nextTime=0;this.playing=false;this.backward=false;this.cycle=false;this.callbacks={onEnded:Prototype.emptyFunction,onStarted:Prototype.emptyFunction};this.setOptions(P)}function J(P){Object.extend(this.options,P||{});return this}function L(){return this.options.duration}function E(){return this.playing}function N(P,Q){this.cycle=P==&quot;none&quot;?false:{type:P,count:Q||1,current:0};return this}function B(){if(this.playing){return }this.fire(&quot;beforeStarted&quot;);this.playing=true;if(this.currentTime==null){this.currentTime=this.backward?this.getDuration():0;this.startAnimation(this.backward)}FX.Metronome.register(this);this.fire(&quot;started&quot;);return this}function K(){this.fire(&quot;stopped&quot;);FX.Metronome.unregister(this);this.playing=false;return this}function I(){this.fire(&quot;reversed&quot;);this.backward=!this.backward;return this}function C(){this.stop();this.fire(&quot;rewinded&quot;);this.updateAnimation(this.backward?1:0);this.currentTime=null;if(this.cycle){this.cycle.current=1}return this}function O(Q){this.currentTime+=this.backward?-Q:Q;if(this.currentTime&gt;this.getDuration()||this.currentTime&lt;0){this.updateAnimation(this.currentTime&lt;0?0:1);if(this.cycle&amp;&amp;this.cycle.current&lt;this.cycle.count){if(this.cycle.type==&quot;loop&quot;){this.cycle.current++;this.updateAnimation(this.backward?1:0);this.currentTime=this.backward?this.getDuration():0}else{if(this.cycle.type==&quot;backAndForth&quot;){this.reverse();if(this.backward){this.cycle.current++}}}}else{this.stopAnimation();this.fire(&quot;ended&quot;);FX.Metronome.unregister(this);this.currentTime=null;this.playing=false;if(this.cycle){this.cycle.current=0;if(this.cycle.type==&quot;backAndForth&quot;){this.backward=!this.backward}}}}else{var P=this.options.transition(this.currentTime/this.getDuration(),this.currentTime,0,1,this.getDuration());this.updateAnimation(P)}}function H(P){this.callbacks.onEnded=P;return this}function D(P){this.callbacks.onStarted=P;return this}function M(P){this.callbacks.onBeforestarted=P;return this}function A(P){var Q;if(Q=this.callbacks[&quot;on&quot;+P.capitalize()]){Q()}this.options.eventNotifier.fire(&quot;fx:&quot;+P,{fx:this,data:this.memoData})}function F(P){throw&quot;FX.Base#updateAnimation(pos) must be implemented&quot;}return{initialize:G,setOptions:J,setCycle:N,getDuration:L,play:B,stop:K,reverse:I,rewind:C,isPlaying:E,metronomeUpdate:O,startAnimation:Prototype.emptyFunction,stopAnimation:Prototype.emptyFunction,updateAnimation:F,fire:A,onStarted:D,onEnded:H,onBeforeStarted:M}})());FX.Attribute=Class.create((function(){function F(M,O,N){this.key=M;this.from=O;this.to=N;this.type=B(this.from);this.unit=D(this.from);this.fromFX=E(this.from,this.isColor());this.toFX=A(this)}function H(P){if(this.isNumber()){return I(this.fromFX,this.toFX,P)+this.unit}else{var O=parseInt(I(this.fromFX[0],this.toFX[0],P));var N=parseInt(I(this.fromFX[1],this.toFX[1],P));var M=parseInt(I(this.fromFX[2],this.toFX[2],P));return&quot;rgb(&quot;+O+&quot;, &quot;+N+&quot;, &quot;+M+&quot;)&quot;}}function G(O,N){if(O&amp;&amp;this.relative){this.from=O}this.fromFX=E(this.from,this.isColor());this.relative=false;this.toFX=A(this,N);if(N&amp;&amp;this.relative){var M=this.fromFX;this.fromFX=this.toFX,this.toFX=M}}function C(){return this.type==&quot;Color&quot;}function L(){return this.type==&quot;Number&quot;}function B(M){if(Object.isString(M)&amp;&amp;M.isColor()){return&quot;Color&quot;}else{return&quot;Number&quot;}}function D(N){var M;if(Object.isString(N)&amp;&amp;(M=N.match(/(\d+)([\w\%]*)/))){return M[2]}else{return&quot;&quot;}}function E(N,M){if(M){return N.getRGB()}else{if(Object.isString(N)){return parseFloat(N)}else{return N}}}function A(M,N){if(M.isColor()){return M.to.getRGB()}else{if(Object.isString(M.to)){if(K(M.to)){return J(M,N)}else{return parseFloat(M.to)}}else{return M.to}}}function I(O,N,M){return O+(N-O)*M}function K(M){return M.match(/^([\+\-\*\/]=)(\d*)$/)}function J(N,O){N.relative=true;var M=K(N.to);if((O&amp;&amp;M[1]==&quot;-=&quot;)||(!O&amp;&amp;M[1]==&quot;+=&quot;)){return N.fromFX+parseFloat(M[2])}else{if((O&amp;&amp;M[1]==&quot;+=&quot;)||(!O&amp;&amp;M[1]==&quot;-=&quot;)){return N.fromFX-parseFloat(M[2])}else{if((O&amp;&amp;M[1]==&quot;*=&quot;)||(!O&amp;&amp;M[1]==&quot;/=&quot;)){return N.fromFX/parseFloat(M[2])}else{if((O&amp;&amp;M[1]==&quot;/=&quot;)||(!O&amp;&amp;M[1]==&quot;*=&quot;)){return N.fromFX*parseFloat(M[2])}else{throw&quot;Operator &quot;+M[1]+&quot; not allowed&quot;}}}}}return{initialize:F,convert:H,reset:G,isNumber:L,isColor:C}})());FX.Metronome=(function(){var A=null,F=1000/60,C=null,I=new Array();function H(K){if(!J(K)){I.push(K);B()}}function E(K){I=I.reject(function(L){return L==K});if(I.length==0){G()}}function J(K){return I.find(function(L){return L==K})}function B(){if(A==null){C=new Date().getTime();A=setInterval(D,F);D()}}function G(){if(A){clearInterval(A);A=null;C=0}}function D(){var K=new Date().getTime();var L=K-C;C=K;I.invoke(&quot;metronomeUpdate&quot;,L)}return{register:H,unregister:E,isRegistered:J}})();Object.extend(String.prototype,{isColor:function(){return this.match(/^\#/)||this.match(/^rgb\(/)},getRGB:function(){function B(C){if(C.length==1){C+=C}return parseInt(C,16)}if(this.isColor()){var A;if(A=this.match(/(^rgb\()(\d+), (\d+), (\d+)(\))/i)){return[parseInt(A[2]),parseInt(A[3]),parseInt(A[4])]}if(A=this.match(/^\#([0-9a-f]{1})([0-9a-f]{1})([0-9a-f]{1})$/i)){return A.slice(1).collect(B)}if(A=this.match(/^\#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i)){return A.slice(1).collect(B)}}return null}});FX.Element=Class.create(FX.Base,(function(){function A($super,H,G){$super(G);this.element=$(H)}function D(G){this.originalAttributes=G;return this}function C(G){var H=new FX.Element(G,this.options).animate(this.originalAttributes);H.callbacks=this.callbacks;return H}function B(G){this.attributes=this.attributes||E(this.originalAttributes,this.element);this.attributes.each(function(H){H.reset(this.element.getStyle(H.key),G)},this)}function F(H){var G={};this.attributes.each(function(I){G[I.key]=I.convert(H)},this);this.element.setStyle(G)}function E(G,H){var I=[];$H(G).each(function(J){I.push(new FX.Attribute(J.key,H.getStyle(J.key),J.value))});return I}return{initialize:A,animate:D,cloneFor:C,startAnimation:B,updateAnimation:F}})());Element.addMethods({fade:function(B,A){new FX.Element(B).setOptions(A||{}).animate({opacity:0}).play();return B},appear:function(B,A){new FX.Element(B).setOptions(A||{}).animate({opacity:1}).play();return B},blindUp:function(B,A){if(!B.visible()){return }new FX.Element(B).setOptions(A||{}).onBeforeStarted(function(){B.originalHeight=B.style.height}).onEnded(function(){B.hide();B.style.height=B.originalHeight;(B.originalHeight)}).animate({height:0}).play();return B},blindDown:function(C,B){if(C.visible()){return }var A=C.getHeight();new FX.Element(C).setOptions(B||{}).onBeforeStarted(function(){C.show();C.style.height=&quot;0px&quot;}).animate({height:A+&quot;px&quot;}).play();return C}});
\ No newline at end of file</diff>
      <filename>dist/protofx_base_packed.js</filename>
    </modified>
    <modified>
      <diff>@@ -1 +1 @@
-FX={};FX.Transition={swing:function(B,C,A,E,D){return((-Math.cos(C/D*Math.PI)/2)+0.5)*E+A}};FX.DefaultOptions={duration:500,transition:FX.Transition.swing,eventNotifier:document,memoData:null};FX.Base=Class.create((function(){function G(O){this.options=Object.extend(Object.clone(FX.DefaultOptions),O);this.currentTime=null;this.nextTime=0;this.playing=false;this.backward=false;this.callbacks={onEnded:Prototype.emptyFunction,onStarted:Prototype.emptyFunction};this.setOptions(O)}function J(O){Object.extend(this.options,O||{});return this}function L(){return this.options.duration}function E(){return this.playing}function B(){if(this.playing){return }this.fire(&quot;beforeStarted&quot;);this.playing=true;if(this.currentTime==null){this.currentTime=this.backward?this.getDuration():0;this.startAnimation(this.backward)}FX.Metronome.register(this);this.fire(&quot;started&quot;);return this}function K(){this.fire(&quot;stopped&quot;);FX.Metronome.unregister(this);this.playing=false;return this}function I(){this.fire(&quot;reversed&quot;);this.backward=!this.backward;return this}function C(){this.stop();this.fire(&quot;rewinded&quot;);this.updateAnimation(this.backward?1:0);this.currentTime=null;return this}function N(P){this.currentTime+=this.backward?-P:P;if(this.currentTime&gt;this.getDuration()||this.currentTime&lt;0){this.updateAnimation(this.currentTime&lt;0?0:1);this.stopAnimation();this.fire(&quot;ended&quot;);FX.Metronome.unregister(this);this.currentTime=null;this.playing=false}else{var O=this.options.transition(this.currentTime/this.getDuration(),this.currentTime,0,1,this.getDuration());this.updateAnimation(O)}}function H(O){this.callbacks.onEnded=O;return this}function D(O){this.callbacks.onStarted=O;return this}function M(O){this.callbacks.onBeforestarted=O;return this}function A(O){var P;if(P=this.callbacks[&quot;on&quot;+O.capitalize()]){P()}this.options.eventNotifier.fire(&quot;fx:&quot;+O,{fx:this,data:this.memoData})}function F(O){throw&quot;FX.Base#updateAnimation(pos) must be implemented&quot;}return{initialize:G,setOptions:J,getDuration:L,play:B,stop:K,reverse:I,rewind:C,isPlaying:E,metronomeUpdate:N,startAnimation:Prototype.emptyFunction,stopAnimation:Prototype.emptyFunction,updateAnimation:F,fire:A,onStarted:D,onEnded:H,onBeforeStarted:M}})());FX.Attribute=Class.create((function(){function F(M,O,N){this.key=M;this.from=O;this.to=N;this.type=B(this.from);this.unit=D(this.from);this.fromFX=E(this.from,this.isColor());this.toFX=A(this)}function H(P){if(this.isNumber()){return I(this.fromFX,this.toFX,P)+this.unit}else{var O=parseInt(I(this.fromFX[0],this.toFX[0],P));var N=parseInt(I(this.fromFX[1],this.toFX[1],P));var M=parseInt(I(this.fromFX[2],this.toFX[2],P));return&quot;rgb(&quot;+O+&quot;, &quot;+N+&quot;, &quot;+M+&quot;)&quot;}}function G(O,N){if(O&amp;&amp;this.relative){this.from=O}this.fromFX=E(this.from,this.isColor());this.relative=false;this.toFX=A(this,N);if(N&amp;&amp;this.relative){var M=this.fromFX;this.fromFX=this.toFX,this.toFX=M}}function C(){return this.type==&quot;Color&quot;}function L(){return this.type==&quot;Number&quot;}function B(M){if(Object.isString(M)&amp;&amp;M.isColor()){return&quot;Color&quot;}else{return&quot;Number&quot;}}function D(N){var M;if(Object.isString(N)&amp;&amp;(M=N.match(/(\d+)([\w\%]*)/))){return M[2]}else{return&quot;&quot;}}function E(N,M){if(M){return N.getRGB()}else{if(Object.isString(N)){return parseFloat(N)}else{return N}}}function A(M,N){if(M.isColor()){return M.to.getRGB()}else{if(Object.isString(M.to)){if(K(M.to)){return J(M,N)}else{return parseFloat(M.to)}}else{return M.to}}}function I(O,N,M){return O+(N-O)*M}function K(M){return M.match(/^([\+\-\*\/]=)(\d*)$/)}function J(N,O){N.relative=true;var M=K(N.to);if((O&amp;&amp;M[1]==&quot;-=&quot;)||(!O&amp;&amp;M[1]==&quot;+=&quot;)){return N.fromFX+parseFloat(M[2])}else{if((O&amp;&amp;M[1]==&quot;+=&quot;)||(!O&amp;&amp;M[1]==&quot;-=&quot;)){return N.fromFX-parseFloat(M[2])}else{if((O&amp;&amp;M[1]==&quot;*=&quot;)||(!O&amp;&amp;M[1]==&quot;/=&quot;)){return N.fromFX/parseFloat(M[2])}else{if((O&amp;&amp;M[1]==&quot;/=&quot;)||(!O&amp;&amp;M[1]==&quot;*=&quot;)){return N.fromFX*parseFloat(M[2])}else{throw&quot;Operator &quot;+M[1]+&quot; not allowed&quot;}}}}}return{initialize:F,convert:H,reset:G,isNumber:L,isColor:C}})());FX.Metronome=(function(){var A=null,F=1000/60,C=null,I=new Array();function H(K){if(!J(K)){I.push(K);B()}}function E(K){I=I.reject(function(L){return L==K});if(I.length==0){G()}}function J(K){return I.find(function(L){return L==K})}function B(){if(A==null){C=new Date().getTime();A=setInterval(D,F);D()}}function G(){if(A){clearInterval(A);A=null;C=0}}function D(){var K=new Date().getTime();var L=K-C;C=K;I.invoke(&quot;metronomeUpdate&quot;,L)}return{register:H,unregister:E,isRegistered:J}})();Object.extend(String.prototype,{isColor:function(){return this.match(/^\#/)||this.match(/^rgb\(/)},getRGB:function(){function B(C){if(C.length==1){C+=C}return parseInt(C,16)}if(this.isColor()){var A;if(A=this.match(/(^rgb\()(\d+), (\d+), (\d+)(\))/i)){return[parseInt(A[2]),parseInt(A[3]),parseInt(A[4])]}if(A=this.match(/^\#([0-9a-f]{1})([0-9a-f]{1})([0-9a-f]{1})$/i)){return A.slice(1).collect(B)}if(A=this.match(/^\#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i)){return A.slice(1).collect(B)}}return null}});FX.Element=Class.create(FX.Base,(function(){function A($super,H,G){$super(G);this.element=$(H)}function D(G){this.originalAttributes=G;return this}function C(G){var H=new FX.Element(G,this.options).animate(this.originalAttributes);H.callbacks=this.callbacks;return H}function B(G){this.attributes=this.attributes||E(this.originalAttributes,this.element);this.attributes.each(function(H){H.reset(this.element.getStyle(H.key),G)},this)}function F(H){var G={};this.attributes.each(function(I){G[I.key]=I.convert(H)},this);this.element.setStyle(G)}function E(G,H){var I=[];$H(G).each(function(J){I.push(new FX.Attribute(J.key,H.getStyle(J.key),J.value))});return I}return{initialize:A,animate:D,cloneFor:C,startAnimation:B,updateAnimation:F}})());Element.addMethods({fade:function(B,A){new FX.Element(B).setOptions(A||{}).animate({opacity:0}).play();return B},appear:function(B,A){new FX.Element(B).setOptions(A||{}).animate({opacity:1}).play();return B},blindUp:function(B,A){if(!B.visible()){return }new FX.Element(B).setOptions(A||{}).onBeforeStarted(function(){B.originalHeight=B.style.height}).onEnded(function(){B.hide();B.style.height=B.originalHeight;(B.originalHeight)}).animate({height:0}).play();return B},blindDown:function(C,B){if(C.visible()){return }var A=C.getHeight();new FX.Element(C).setOptions(B||{}).onBeforeStarted(function(){C.show();C.style.height=&quot;0px&quot;}).animate({height:A+&quot;px&quot;}).play();return C}});Object.extend(FX.Transition,{linear:function(B,C,A,E,D){return E*C/D+A},sinus:function(B,C,A,E,D){return Math.sin(C/D*2*Math.PI)*E+A},cosinus:function(B,C,A,E,D){return Math.cos(C/D*2*Math.PI)*E+A},easeInQuad:function(B,C,A,E,D){return E*(C/=D)*C+A},easeOutQuad:function(B,C,A,E,D){return -E*(C/=D)*(C-2)+A},easeInOutQuad:function(B,C,A,E,D){if((C/=D/2)&lt;1){return E/2*C*C+A}return -E/2*((--C)*(C-2)-1)+A},easeInCubic:function(B,C,A,E,D){return E*(C/=D)*C*C+A},easeOutCubic:function(B,C,A,E,D){return E*((C=C/D-1)*C*C+1)+A},easeInOutCubic:function(B,C,A,E,D){if((C/=D/2)&lt;1){return E/2*C*C*C+A}return E/2*((C-=2)*C*C+2)+A},easeInQuart:function(B,C,A,E,D){return E*(C/=D)*C*C*C+A},easeOutQuart:function(B,C,A,E,D){return -E*((C=C/D-1)*C*C*C-1)+A},easeInOutQuart:function(B,C,A,E,D){if((C/=D/2)&lt;1){return E/2*C*C*C*C+A}return -E/2*((C-=2)*C*C*C-2)+A},easeInQuint:function(B,C,A,E,D){return E*(C/=D)*C*C*C*C+A},easeOutQuint:function(B,C,A,E,D){return E*((C=C/D-1)*C*C*C*C+1)+A},easeInOutQuint:function(B,C,A,E,D){if((C/=D/2)&lt;1){return E/2*C*C*C*C*C+A}return E/2*((C-=2)*C*C*C*C+2)+A},easeInSine:function(B,C,A,E,D){return -E*Math.cos(C/D*(Math.PI/2))+E+A},easeOutSine:function(B,C,A,E,D){return E*Math.sin(C/D*(Math.PI/2))+A},easeInOutSine:function(B,C,A,E,D){return -E/2*(Math.cos(Math.PI*C/D)-1)+A},easeInExpo:function(B,C,A,E,D){return(C==0)?A:E*Math.pow(2,10*(C/D-1))+A},easeOutExpo:function(B,C,A,E,D){return(C==D)?A+E:E*(-Math.pow(2,-10*C/D)+1)+A},easeInOutExpo:function(B,C,A,E,D){if(C==0){return A}if(C==D){return A+E}if((C/=D/2)&lt;1){return E/2*Math.pow(2,10*(C-1))+A}return E/2*(-Math.pow(2,-10*--C)+2)+A},easeInCirc:function(B,C,A,E,D){return -E*(Math.sqrt(1-(C/=D)*C)-1)+A},easeOutCirc:function(B,C,A,E,D){return E*Math.sqrt(1-(C=C/D-1)*C)+A},easeInOutCirc:function(B,C,A,E,D){if((C/=D/2)&lt;1){return -E/2*(Math.sqrt(1-C*C)-1)+A}return E/2*(Math.sqrt(1-(C-=2)*C)+1)+A},easeInElastic:function(B,D,A,H,G){var E=1.70158;var F=0;var C=H;if(D==0){return A}if((D/=G)==1){return A+H}if(!F){F=G*0.3}if(C&lt;Math.abs(H)){C=H;var E=F/4}else{var E=F/(2*Math.PI)*Math.asin(H/C)}return -(C*Math.pow(2,10*(D-=1))*Math.sin((D*G-E)*(2*Math.PI)/F))+A},easeOutElastic:function(B,D,A,H,G){var E=1.70158;var F=0;var C=H;if(D==0){return A}if((D/=G)==1){return A+H}if(!F){F=G*0.3}if(C&lt;Math.abs(H)){C=H;var E=F/4}else{var E=F/(2*Math.PI)*Math.asin(H/C)}return C*Math.pow(2,-10*D)*Math.sin((D*G-E)*(2*Math.PI)/F)+H+A},easeInOutElastic:function(B,D,A,H,G){var E=1.70158;var F=0;var C=H;if(D==0){return A}if((D/=G/2)==2){return A+H}if(!F){F=G*(0.3*1.5)}if(C&lt;Math.abs(H)){C=H;var E=F/4}else{var E=F/(2*Math.PI)*Math.asin(H/C)}if(D&lt;1){return -0.5*(C*Math.pow(2,10*(D-=1))*Math.sin((D*G-E)*(2*Math.PI)/F))+A}return C*Math.pow(2,-10*(D-=1))*Math.sin((D*G-E)*(2*Math.PI)/F)*0.5+H+A},easeInBack:function(B,C,A,F,E,D){if(D==undefined){D=1.70158}return F*(C/=E)*C*((D+1)*C-D)+A},easeOutBack:function(B,C,A,F,E,D){if(D==undefined){D=1.70158}return F*((C=C/E-1)*C*((D+1)*C+D)+1)+A},easeInOutBack:function(B,C,A,F,E,D){if(D==undefined){D=1.70158}if((C/=E/2)&lt;1){return F/2*(C*C*(((D*=(1.525))+1)*C-D))+A}return F/2*((C-=2)*C*(((D*=(1.525))+1)*C+D)+2)+A},easeInBounce:function(B,C,A,E,D){return E-FX.Transition.easeOutBounce(B,D-C,0,E,D)+A},easeOutBounce:function(B,C,A,E,D){if((C/=D)&lt;(1/2.75)){return E*(7.5625*C*C)+A}else{if(C&lt;(2/2.75)){return E*(7.5625*(C-=(1.5/2.75))*C+0.75)+A}else{if(C&lt;(2.5/2.75)){return E*(7.5625*(C-=(2.25/2.75))*C+0.9375)+A}else{return E*(7.5625*(C-=(2.625/2.75))*C+0.984375)+A}}}},easeInOutBounce:function(B,C,A,E,D){if(C&lt;D/2){return FX.Transition.easeInBounce(B,C*2,0,E,D)*0.5+A}return FX.Transition.easeOutBounce(B,C*2-D,0,E,D)*0.5+E*0.5+A}});FX.Score=Class.create(FX.Base,(function(){function D($super){$super();this.duration=0;this.runningFx=new Array;this.effects=new Array}function H(){return this.duration}function A($super){if(this.playing){return }if(this.currentTime==null){G(this,this.backward?this.duration:0)}return $super()}function F($super){if(this.currentTime!=null){G(this,this.currentTime)}return $super()}function B(L){this.stop();this.backward=!this.backward;G(this,this.currentTime);while(this.runningFx.length&gt;0){this.runningFx.each(function(M){M.fx.rewind()});G(this,this.nextTime+(this.backward?-0.000001:0.000001))}this.backward=!this.backward;this.currentTime=this.backward?this.duration:0;if(!L){this.fire(&quot;rewinded&quot;)}return this}function J(O,N){if(N){var R=N.after;var L=N.position;var M=N.delay||0;if(R&amp;&amp;L){throw&quot;Error: Score#add options after and position cannot be set at the same time&quot;}if(R){var Q=R.fx||R;var P=this.effects.find(function(S){return S.fx==Q});this.effects.push({fx:O,start:P.end+M,end:P.end+O.options.duration+M});this.duration=Math.max(this.duration,P.end+O.options.duration+M)}if(L==&quot;last&quot;){this.effects.push({fx:O,start:this.duration+M,end:this.duration+O.options.duration+M});this.duration+=O.options.duration+M}}else{this.effects.push({fx:O,start:0,end:O.options.duration});this.duration=Math.max(this.duration,O.options.duration)}return this}function I(L){if((this.backward&amp;&amp;this.currentTime&lt;=this.nextTime)||(!this.backward&amp;&amp;this.currentTime&gt;=this.nextTime)){G(this,this.currentTime)}this.currentTime+=this.backward?-L:L;this.runningFx.each(function(N){var M=N.fx;var O=M.options.transition((this.currentTime-N.start)/M.getDuration(),this.currentTime-N.start,0,1,M.getDuration());N.fx.updateAnimation(O)},this);if(this.currentTime&gt;this.duration||this.currentTime&lt;0){FX.Metronome.unregister(this);this.currentTime=null;this.playing=false}}function G(N,M){var L=new Array();N.runningFx.each(function(O){if(M&lt;O.start||M&gt;O.end){O.fx.updateAnimation(N.backward?0:1);O.fx.stopAnimation()}else{L.push(O)}},this);N.runningFx.clear();N.nextTime=N.backward?0:N.duration;N.effects.each(function(O){if(K(O,M,N.backward)){var P=C(O,M);if(P){N.runningFx.push(O);if(!L.include(O)){O.fx.startAnimation(N.backward)}}if(N.backward){N.nextTime=Math.max(N.nextTime,P?O.start:O.end)}else{N.nextTime=Math.min(N.nextTime,P?O.end:O.start)}}},N)}function E(N,L,M){return(M&amp;&amp;L&lt;N.start)||(!M&amp;&amp;L&gt;N.end)}function K(N,L,M){return !E(N,L,M)}function C(M,L){return(M.start&lt;=L&amp;&amp;L&lt;=M.end)}return{initialize:D,getDuration:H,play:A,reverse:F,rewind:B,add:J,metronomeUpdate:I}})());
\ No newline at end of file
+FX={};FX.Transition={swing:function(B,C,A,E,D){return((-Math.cos(C/D*Math.PI)/2)+0.5)*E+A}};FX.DefaultOptions={duration:500,transition:FX.Transition.swing,eventNotifier:document,memoData:null};FX.Base=Class.create((function(){function G(P){this.options=Object.extend(Object.clone(FX.DefaultOptions),P);this.currentTime=null;this.nextTime=0;this.playing=false;this.backward=false;this.cycle=false;this.callbacks={onEnded:Prototype.emptyFunction,onStarted:Prototype.emptyFunction};this.setOptions(P)}function J(P){Object.extend(this.options,P||{});return this}function L(){return this.options.duration}function E(){return this.playing}function N(P,Q){this.cycle=P==&quot;none&quot;?false:{type:P,count:Q||1,current:0};return this}function B(){if(this.playing){return }this.fire(&quot;beforeStarted&quot;);this.playing=true;if(this.currentTime==null){this.currentTime=this.backward?this.getDuration():0;this.startAnimation(this.backward)}FX.Metronome.register(this);this.fire(&quot;started&quot;);return this}function K(){this.fire(&quot;stopped&quot;);FX.Metronome.unregister(this);this.playing=false;return this}function I(){this.fire(&quot;reversed&quot;);this.backward=!this.backward;return this}function C(){this.stop();this.fire(&quot;rewinded&quot;);this.updateAnimation(this.backward?1:0);this.currentTime=null;if(this.cycle){this.cycle.current=1}return this}function O(Q){this.currentTime+=this.backward?-Q:Q;if(this.currentTime&gt;this.getDuration()||this.currentTime&lt;0){this.updateAnimation(this.currentTime&lt;0?0:1);if(this.cycle&amp;&amp;this.cycle.current&lt;this.cycle.count){if(this.cycle.type==&quot;loop&quot;){this.cycle.current++;this.updateAnimation(this.backward?1:0);this.currentTime=this.backward?this.getDuration():0}else{if(this.cycle.type==&quot;backAndForth&quot;){this.reverse();if(this.backward){this.cycle.current++}}}}else{this.stopAnimation();this.fire(&quot;ended&quot;);FX.Metronome.unregister(this);this.currentTime=null;this.playing=false;if(this.cycle){this.cycle.current=0;if(this.cycle.type==&quot;backAndForth&quot;){this.backward=!this.backward}}}}else{var P=this.options.transition(this.currentTime/this.getDuration(),this.currentTime,0,1,this.getDuration());this.updateAnimation(P)}}function H(P){this.callbacks.onEnded=P;return this}function D(P){this.callbacks.onStarted=P;return this}function M(P){this.callbacks.onBeforestarted=P;return this}function A(P){var Q;if(Q=this.callbacks[&quot;on&quot;+P.capitalize()]){Q()}this.options.eventNotifier.fire(&quot;fx:&quot;+P,{fx:this,data:this.memoData})}function F(P){throw&quot;FX.Base#updateAnimation(pos) must be implemented&quot;}return{initialize:G,setOptions:J,setCycle:N,getDuration:L,play:B,stop:K,reverse:I,rewind:C,isPlaying:E,metronomeUpdate:O,startAnimation:Prototype.emptyFunction,stopAnimation:Prototype.emptyFunction,updateAnimation:F,fire:A,onStarted:D,onEnded:H,onBeforeStarted:M}})());FX.Attribute=Class.create((function(){function F(M,O,N){this.key=M;this.from=O;this.to=N;this.type=B(this.from);this.unit=D(this.from);this.fromFX=E(this.from,this.isColor());this.toFX=A(this)}function H(P){if(this.isNumber()){return I(this.fromFX,this.toFX,P)+this.unit}else{var O=parseInt(I(this.fromFX[0],this.toFX[0],P));var N=parseInt(I(this.fromFX[1],this.toFX[1],P));var M=parseInt(I(this.fromFX[2],this.toFX[2],P));return&quot;rgb(&quot;+O+&quot;, &quot;+N+&quot;, &quot;+M+&quot;)&quot;}}function G(O,N){if(O&amp;&amp;this.relative){this.from=O}this.fromFX=E(this.from,this.isColor());this.relative=false;this.toFX=A(this,N);if(N&amp;&amp;this.relative){var M=this.fromFX;this.fromFX=this.toFX,this.toFX=M}}function C(){return this.type==&quot;Color&quot;}function L(){return this.type==&quot;Number&quot;}function B(M){if(Object.isString(M)&amp;&amp;M.isColor()){return&quot;Color&quot;}else{return&quot;Number&quot;}}function D(N){var M;if(Object.isString(N)&amp;&amp;(M=N.match(/(\d+)([\w\%]*)/))){return M[2]}else{return&quot;&quot;}}function E(N,M){if(M){return N.getRGB()}else{if(Object.isString(N)){return parseFloat(N)}else{return N}}}function A(M,N){if(M.isColor()){return M.to.getRGB()}else{if(Object.isString(M.to)){if(K(M.to)){return J(M,N)}else{return parseFloat(M.to)}}else{return M.to}}}function I(O,N,M){return O+(N-O)*M}function K(M){return M.match(/^([\+\-\*\/]=)(\d*)$/)}function J(N,O){N.relative=true;var M=K(N.to);if((O&amp;&amp;M[1]==&quot;-=&quot;)||(!O&amp;&amp;M[1]==&quot;+=&quot;)){return N.fromFX+parseFloat(M[2])}else{if((O&amp;&amp;M[1]==&quot;+=&quot;)||(!O&amp;&amp;M[1]==&quot;-=&quot;)){return N.fromFX-parseFloat(M[2])}else{if((O&amp;&amp;M[1]==&quot;*=&quot;)||(!O&amp;&amp;M[1]==&quot;/=&quot;)){return N.fromFX/parseFloat(M[2])}else{if((O&amp;&amp;M[1]==&quot;/=&quot;)||(!O&amp;&amp;M[1]==&quot;*=&quot;)){return N.fromFX*parseFloat(M[2])}else{throw&quot;Operator &quot;+M[1]+&quot; not allowed&quot;}}}}}return{initialize:F,convert:H,reset:G,isNumber:L,isColor:C}})());FX.Metronome=(function(){var A=null,F=1000/60,C=null,I=new Array();function H(K){if(!J(K)){I.push(K);B()}}function E(K){I=I.reject(function(L){return L==K});if(I.length==0){G()}}function J(K){return I.find(function(L){return L==K})}function B(){if(A==null){C=new Date().getTime();A=setInterval(D,F);D()}}function G(){if(A){clearInterval(A);A=null;C=0}}function D(){var K=new Date().getTime();var L=K-C;C=K;I.invoke(&quot;metronomeUpdate&quot;,L)}return{register:H,unregister:E,isRegistered:J}})();Object.extend(String.prototype,{isColor:function(){return this.match(/^\#/)||this.match(/^rgb\(/)},getRGB:function(){function B(C){if(C.length==1){C+=C}return parseInt(C,16)}if(this.isColor()){var A;if(A=this.match(/(^rgb\()(\d+), (\d+), (\d+)(\))/i)){return[parseInt(A[2]),parseInt(A[3]),parseInt(A[4])]}if(A=this.match(/^\#([0-9a-f]{1})([0-9a-f]{1})([0-9a-f]{1})$/i)){return A.slice(1).collect(B)}if(A=this.match(/^\#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i)){return A.slice(1).collect(B)}}return null}});FX.Element=Class.create(FX.Base,(function(){function A($super,H,G){$super(G);this.element=$(H)}function D(G){this.originalAttributes=G;return this}function C(G){var H=new FX.Element(G,this.options).animate(this.originalAttributes);H.callbacks=this.callbacks;return H}function B(G){this.attributes=this.attributes||E(this.originalAttributes,this.element);this.attributes.each(function(H){H.reset(this.element.getStyle(H.key),G)},this)}function F(H){var G={};this.attributes.each(function(I){G[I.key]=I.convert(H)},this);this.element.setStyle(G)}function E(G,H){var I=[];$H(G).each(function(J){I.push(new FX.Attribute(J.key,H.getStyle(J.key),J.value))});return I}return{initialize:A,animate:D,cloneFor:C,startAnimation:B,updateAnimation:F}})());Element.addMethods({fade:function(B,A){new FX.Element(B).setOptions(A||{}).animate({opacity:0}).play();return B},appear:function(B,A){new FX.Element(B).setOptions(A||{}).animate({opacity:1}).play();return B},blindUp:function(B,A){if(!B.visible()){return }new FX.Element(B).setOptions(A||{}).onBeforeStarted(function(){B.originalHeight=B.style.height}).onEnded(function(){B.hide();B.style.height=B.originalHeight;(B.originalHeight)}).animate({height:0}).play();return B},blindDown:function(C,B){if(C.visible()){return }var A=C.getHeight();new FX.Element(C).setOptions(B||{}).onBeforeStarted(function(){C.show();C.style.height=&quot;0px&quot;}).animate({height:A+&quot;px&quot;}).play();return C}});Object.extend(FX.Transition,{linear:function(B,C,A,E,D){return E*C/D+A},sinus:function(B,C,A,E,D){return Math.sin(C/D*2*Math.PI)*E+A},cosinus:function(B,C,A,E,D){return Math.cos(C/D*2*Math.PI)*E+A},easeInQuad:function(B,C,A,E,D){return E*(C/=D)*C+A},easeOutQuad:function(B,C,A,E,D){return -E*(C/=D)*(C-2)+A},easeInOutQuad:function(B,C,A,E,D){if((C/=D/2)&lt;1){return E/2*C*C+A}return -E/2*((--C)*(C-2)-1)+A},easeInCubic:function(B,C,A,E,D){return E*(C/=D)*C*C+A},easeOutCubic:function(B,C,A,E,D){return E*((C=C/D-1)*C*C+1)+A},easeInOutCubic:function(B,C,A,E,D){if((C/=D/2)&lt;1){return E/2*C*C*C+A}return E/2*((C-=2)*C*C+2)+A},easeInQuart:function(B,C,A,E,D){return E*(C/=D)*C*C*C+A},easeOutQuart:function(B,C,A,E,D){return -E*((C=C/D-1)*C*C*C-1)+A},easeInOutQuart:function(B,C,A,E,D){if((C/=D/2)&lt;1){return E/2*C*C*C*C+A}return -E/2*((C-=2)*C*C*C-2)+A},easeInQuint:function(B,C,A,E,D){return E*(C/=D)*C*C*C*C+A},easeOutQuint:function(B,C,A,E,D){return E*((C=C/D-1)*C*C*C*C+1)+A},easeInOutQuint:function(B,C,A,E,D){if((C/=D/2)&lt;1){return E/2*C*C*C*C*C+A}return E/2*((C-=2)*C*C*C*C+2)+A},easeInSine:function(B,C,A,E,D){return -E*Math.cos(C/D*(Math.PI/2))+E+A},easeOutSine:function(B,C,A,E,D){return E*Math.sin(C/D*(Math.PI/2))+A},easeInOutSine:function(B,C,A,E,D){return -E/2*(Math.cos(Math.PI*C/D)-1)+A},easeInExpo:function(B,C,A,E,D){return(C==0)?A:E*Math.pow(2,10*(C/D-1))+A},easeOutExpo:function(B,C,A,E,D){return(C==D)?A+E:E*(-Math.pow(2,-10*C/D)+1)+A},easeInOutExpo:function(B,C,A,E,D){if(C==0){return A}if(C==D){return A+E}if((C/=D/2)&lt;1){return E/2*Math.pow(2,10*(C-1))+A}return E/2*(-Math.pow(2,-10*--C)+2)+A},easeInCirc:function(B,C,A,E,D){return -E*(Math.sqrt(1-(C/=D)*C)-1)+A},easeOutCirc:function(B,C,A,E,D){return E*Math.sqrt(1-(C=C/D-1)*C)+A},easeInOutCirc:function(B,C,A,E,D){if((C/=D/2)&lt;1){return -E/2*(Math.sqrt(1-C*C)-1)+A}return E/2*(Math.sqrt(1-(C-=2)*C)+1)+A},easeInElastic:function(B,D,A,H,G){var E=1.70158;var F=0;var C=H;if(D==0){return A}if((D/=G)==1){return A+H}if(!F){F=G*0.3}if(C&lt;Math.abs(H)){C=H;var E=F/4}else{var E=F/(2*Math.PI)*Math.asin(H/C)}return -(C*Math.pow(2,10*(D-=1))*Math.sin((D*G-E)*(2*Math.PI)/F))+A},easeOutElastic:function(B,D,A,H,G){var E=1.70158;var F=0;var C=H;if(D==0){return A}if((D/=G)==1){return A+H}if(!F){F=G*0.3}if(C&lt;Math.abs(H)){C=H;var E=F/4}else{var E=F/(2*Math.PI)*Math.asin(H/C)}return C*Math.pow(2,-10*D)*Math.sin((D*G-E)*(2*Math.PI)/F)+H+A},easeInOutElastic:function(B,D,A,H,G){var E=1.70158;var F=0;var C=H;if(D==0){return A}if((D/=G/2)==2){return A+H}if(!F){F=G*(0.3*1.5)}if(C&lt;Math.abs(H)){C=H;var E=F/4}else{var E=F/(2*Math.PI)*Math.asin(H/C)}if(D&lt;1){return -0.5*(C*Math.pow(2,10*(D-=1))*Math.sin((D*G-E)*(2*Math.PI)/F))+A}return C*Math.pow(2,-10*(D-=1))*Math.sin((D*G-E)*(2*Math.PI)/F)*0.5+H+A},easeInBack:function(B,C,A,F,E,D){if(D==undefined){D=1.70158}return F*(C/=E)*C*((D+1)*C-D)+A},easeOutBack:function(B,C,A,F,E,D){if(D==undefined){D=1.70158}return F*((C=C/E-1)*C*((D+1)*C+D)+1)+A},easeInOutBack:function(B,C,A,F,E,D){if(D==undefined){D=1.70158}if((C/=E/2)&lt;1){return F/2*(C*C*(((D*=(1.525))+1)*C-D))+A}return F/2*((C-=2)*C*(((D*=(1.525))+1)*C+D)+2)+A},easeInBounce:function(B,C,A,E,D){return E-FX.Transition.easeOutBounce(B,D-C,0,E,D)+A},easeOutBounce:function(B,C,A,E,D){if((C/=D)&lt;(1/2.75)){return E*(7.5625*C*C)+A}else{if(C&lt;(2/2.75)){return E*(7.5625*(C-=(1.5/2.75))*C+0.75)+A}else{if(C&lt;(2.5/2.75)){return E*(7.5625*(C-=(2.25/2.75))*C+0.9375)+A}else{return E*(7.5625*(C-=(2.625/2.75))*C+0.984375)+A}}}},easeInOutBounce:function(B,C,A,E,D){if(C&lt;D/2){return FX.Transition.easeInBounce(B,C*2,0,E,D)*0.5+A}return FX.Transition.easeOutBounce(B,C*2-D,0,E,D)*0.5+E*0.5+A}});FX.Score=Class.create(FX.Base,(function(){function D($super){$super();this.duration=0;this.runningFx=new Array;this.effects=new Array}function H(){return this.duration}function A($super){if(this.playing){return }if(this.currentTime==null){G(this,this.backward?this.duration:0)}return $super()}function F($super){if(this.currentTime!=null){G(this,this.currentTime)}return $super()}function B(L){this.stop();this.backward=!this.backward;G(this,this.currentTime);while(this.runningFx.length&gt;0){this.runningFx.each(function(M){M.fx.rewind()});G(this,this.nextTime+(this.backward?-0.000001:0.000001))}this.backward=!this.backward;this.currentTime=this.backward?this.duration:0;if(!L){this.fire(&quot;rewinded&quot;)}return this}function J(O,N){if(N){var R=N.after;var L=N.position;var M=N.delay||0;if(R&amp;&amp;L){throw&quot;Error: Score#add options after and position cannot be set at the same time&quot;}if(R){var Q=R.fx||R;var P=this.effects.find(function(S){return S.fx==Q});this.effects.push({fx:O,start:P.end+M,end:P.end+O.options.duration+M});this.duration=Math.max(this.duration,P.end+O.options.duration+M)}if(L==&quot;last&quot;){this.effects.push({fx:O,start:this.duration+M,end:this.duration+O.options.duration+M});this.duration+=O.options.duration+M}}else{this.effects.push({fx:O,start:0,end:O.options.duration});this.duration=Math.max(this.duration,O.options.duration)}return this}function I(L){if((this.backward&amp;&amp;this.currentTime&lt;=this.nextTime)||(!this.backward&amp;&amp;this.currentTime&gt;=this.nextTime)){G(this,this.currentTime)}this.currentTime+=this.backward?-L:L;this.runningFx.each(function(N){var M=N.fx;var O=M.options.transition((this.currentTime-N.start)/M.getDuration(),this.currentTime-N.start,0,1,M.getDuration());N.fx.updateAnimation(O)},this);if(this.currentTime&gt;this.duration||this.currentTime&lt;0){FX.Metronome.unregister(this);this.currentTime=null;this.playing=false}}function G(N,M){var L=new Array();N.runningFx.each(function(O){if(M&lt;O.start||M&gt;O.end){O.fx.updateAnimation(N.backward?0:1);O.fx.stopAnimation()}else{L.push(O)}},this);N.runningFx.clear();N.nextTime=N.backward?0:N.duration;N.effects.each(function(O){if(K(O,M,N.backward)){var P=C(O,M);if(P){N.runningFx.push(O);if(!L.include(O)){O.fx.startAnimation(N.backward)}}if(N.backward){N.nextTime=Math.max(N.nextTime,P?O.start:O.end)}else{N.nextTime=Math.min(N.nextTime,P?O.end:O.start)}}},N)}function E(N,L,M){return(M&amp;&amp;L&lt;N.start)||(!M&amp;&amp;L&gt;N.end)}function K(N,L,M){return !E(N,L,M)}function C(M,L){return(M.start&lt;=L&amp;&amp;L&lt;=M.end)}return{initialize:D,getDuration:H,play:A,reverse:F,rewind:B,add:J,metronomeUpdate:I}})());
\ No newline at end of file</diff>
      <filename>dist/protofx_packed.js</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>f75b1543c6af465fb3cd4ff0a1fe16e40890c3ff</id>
    </parent>
  </parents>
  <author>
    <name>sgruhier</name>
    <email>sgruhier@mac.com</email>
  </author>
  <url>http://github.com/xilinus/protofx/commit/33eedb9657b0c0acf6c01378774ef1072908c2e3</url>
  <id>33eedb9657b0c0acf6c01378774ef1072908c2e3</id>
  <committed-date>2008-12-13T04:16:21-08:00</committed-date>
  <authored-date>2008-12-13T04:16:21-08:00</authored-date>
  <message>update README</message>
  <tree>073a346c8aaa99e9ed3dcae3b21d656cee374be5</tree>
  <committer>
    <name>sgruhier</name>
    <email>sgruhier@mac.com</email>
  </committer>
</commit>
