* Normalizing Request status
[mootools/dkf.git] / Source / Fx / Fx.js
blob07e6787c7bf15015082374d1d172d9cd1a0c4f03
1 /*
2 ---
4 name: Fx
6 description: Contains the basic animation logic to be extended by all other Fx Classes.
8 license: MIT-style license.
10 requires: [Chain, Events, Options]
12 provides: Fx
14 ...
17 (function(){
19 var Fx = this.Fx = new Class({
21         Implements: [Chain, Events, Options],
23         options: {
24                 /*
25                 onStart: nil,
26                 onCancel: nil,
27                 onComplete: nil,
28                 */
29                 fps: 50,
30                 unit: false,
31                 duration: 500,
32                 link: 'ignore'
33         },
35         initialize: function(options){
36                 this.subject = this.subject || this;
37                 this.setOptions(options);
38         },
40         getTransition: function(){
41                 return function(p){
42                         return -(Math.cos(Math.PI * p) - 1) / 2;
43                 };
44         },
46         step: function(){
47                 var time = Date.now();
48                 if (time < this.time + this.options.duration){
49                         var delta = this.transition((time - this.time) / this.options.duration);
50                         this.set(this.compute(this.from, this.to, delta));
51                 } else {
52                         this.set(this.compute(this.from, this.to, 1));
53                         this.complete();
54                 }
55         },
57         set: function(now){
58                 return now;
59         },
61         compute: function(from, to, delta){
62                 return Fx.compute(from, to, delta);
63         },
65         check: function(){
66                 if (!this.timer) return true;
67                 switch (this.options.link){
68                         case 'cancel': this.cancel(); return true;
69                         case 'chain': this.chain(this.caller.pass(arguments, this)); return false;
70                 }
71                 return false;
72         },
74         start: function(from, to){
75                 if (!this.check(from, to)) return this;
76                 var duration = this.options.duration;
77                 this.options.duration = Fx.Durations[duration] || duration.toInt();
78                 this.from = from;
79                 this.to = to;
80                 this.time = 0;
81                 this.transition = this.getTransition();
82                 this.startTimer();
83                 this.onStart();
84                 return this;
85         },
87         complete: function(){
88                 if (this.stopTimer()) this.onComplete();
89                 return this;
90         },
92         cancel: function(){
93                 if (this.stopTimer()) this.onCancel();
94                 return this;
95         },
97         onStart: function(){
98                 this.triggerEvent('start', this.subject);
99         },
101         onComplete: function(){
102                 this.triggerEvent('complete', this.subject);
103                 if (!this.callChain()) this.triggerEvent('chainComplete', this.subject);
104         },
106         onCancel: function(){
107                 this.triggerEvent('cancel', this.subject).clearChain();
108         },
110         pause: function(){
111                 this.stopTimer();
112                 return this;
113         },
115         resume: function(){
116                 this.startTimer();
117                 return this;
118         },
120         stopTimer: function(){
121                 if (!this.timer) return false;
122                 this.time = Date.now() - this.time;
123                 this.timer = removeInstance(this);
124                 return true;
125         },
127         startTimer: function(){
128                 if (this.timer) return false;
129                 this.time = Date.now() - this.time;
130                 this.timer = addInstance(this);
131                 return true;
132         }
136 Fx.compute = function(from, to, delta){
137         return (to - from) * delta + from;
140 Fx.Durations = {'short': 250, 'normal': 500, 'long': 1000};
142 // global timers
144 var instances = {}, timers = {};
146 var loop = function(){
147         for (var i = this.length; i--;){
148                 if (this[i]) this[i].step();
149         }
152 var addInstance = function(instance){
153         var fps = instance.options.fps,
154                 list = instances[fps] || (instances[fps] = []);
155         list.push(instance);
156         if (!timers[fps]) timers[fps] = loop.periodical(Math.round(1000 / fps), list);
157         return true;
160 var removeInstance = function(instance){
161         var fps = instance.options.fps,
162                 list = instances[fps] || [];
163         list.erase(instance);
164         if (!list.length && timers[fps]) timers[fps] = clearInterval(timers[fps]);
165         return false;
168 })();