]> git.pond.sub.org Git - eow/blob - static/dojo-release-1.1.1/dojo/fx.js
add Dojo 1.1.1
[eow] / static / dojo-release-1.1.1 / dojo / fx.js
1 if(!dojo._hasResource["dojo.fx"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2 dojo._hasResource["dojo.fx"] = true;
3 dojo.provide("dojo.fx");
4 dojo.provide("dojo.fx.Toggler");
5
6 /*=====
7 dojo.fx = {
8         // summary: Effects library on top of Base animations
9 };
10 =====*/
11
12 (function(){
13         var _baseObj = {
14                         _fire: function(evt, args){
15                                 if(this[evt]){
16                                         this[evt].apply(this, args||[]);
17                                 }
18                                 return this;
19                         }
20                 };
21
22         var _chain = function(animations){
23                 this._index = -1;
24                 this._animations = animations||[];
25                 this._current = this._onAnimateCtx = this._onEndCtx = null;
26
27                 this.duration = 0;
28                 dojo.forEach(this._animations, function(a){
29                         this.duration += a.duration;
30                         if(a.delay){ this.duration += a.delay; }
31                 }, this);
32         };
33         dojo.extend(_chain, {
34                 _onAnimate: function(){
35                         this._fire("onAnimate", arguments);
36                 },
37                 _onEnd: function(){
38                         dojo.disconnect(this._onAnimateCtx);
39                         dojo.disconnect(this._onEndCtx);
40                         this._onAnimateCtx = this._onEndCtx = null;
41                         if(this._index + 1 == this._animations.length){
42                                 this._fire("onEnd");
43                         }else{
44                                 // switch animations
45                                 this._current = this._animations[++this._index];
46                                 this._onAnimateCtx = dojo.connect(this._current, "onAnimate", this, "_onAnimate");
47                                 this._onEndCtx = dojo.connect(this._current, "onEnd", this, "_onEnd");
48                                 this._current.play(0, true);
49                         }
50                 },
51                 play: function(/*int?*/ delay, /*Boolean?*/ gotoStart){
52                         if(!this._current){ this._current = this._animations[this._index = 0]; }
53                         if(!gotoStart && this._current.status() == "playing"){ return this; }
54                         var beforeBegin = dojo.connect(this._current, "beforeBegin", this, function(){
55                                         this._fire("beforeBegin");
56                                 }),
57                                 onBegin = dojo.connect(this._current, "onBegin", this, function(arg){
58                                         this._fire("onBegin", arguments);
59                                 }),
60                                 onPlay = dojo.connect(this._current, "onPlay", this, function(arg){
61                                         this._fire("onPlay", arguments);
62                                         dojo.disconnect(beforeBegin);
63                                         dojo.disconnect(onBegin);
64                                         dojo.disconnect(onPlay);
65                                 });
66                         if(this._onAnimateCtx){
67                                 dojo.disconnect(this._onAnimateCtx);
68                         }
69                         this._onAnimateCtx = dojo.connect(this._current, "onAnimate", this, "_onAnimate");
70                         if(this._onEndCtx){
71                                 dojo.disconnect(this._onEndCtx);
72                         }
73                         this._onEndCtx = dojo.connect(this._current, "onEnd", this, "_onEnd");
74                         this._current.play.apply(this._current, arguments);
75                         return this;
76                 },
77                 pause: function(){
78                         if(this._current){
79                                 var e = dojo.connect(this._current, "onPause", this, function(arg){
80                                                 this._fire("onPause", arguments);
81                                                 dojo.disconnect(e);
82                                         });
83                                 this._current.pause();
84                         }
85                         return this;
86                 },
87                 gotoPercent: function(/*Decimal*/percent, /*Boolean?*/ andPlay){
88                         this.pause();
89                         var offset = this.duration * percent;
90                         this._current = null;
91                         dojo.some(this._animations, function(a){
92                                 if(a.duration <= offset){
93                                         this._current = a;
94                                         return true;
95                                 }
96                                 offset -= a.duration;
97                                 return false;
98                         });
99                         if(this._current){
100                                 this._current.gotoPercent(offset / _current.duration, andPlay);
101                         }
102                         return this;
103                 },
104                 stop: function(/*boolean?*/ gotoEnd){
105                         if(this._current){
106                                 if(gotoEnd){
107                                         for(; this._index + 1 < this._animations.length; ++this._index){
108                                                 this._animations[this._index].stop(true);
109                                         }
110                                         this._current = this._animations[this._index];
111                                 }
112                                 var e = dojo.connect(this._current, "onStop", this, function(arg){
113                                                 this._fire("onStop", arguments);
114                                                 dojo.disconnect(e);
115                                         });
116                                 this._current.stop();
117                         }
118                         return this;
119                 },
120                 status: function(){
121                         return this._current ? this._current.status() : "stopped";
122                 },
123                 destroy: function(){
124                         if(this._onAnimateCtx){ dojo.disconnect(this._onAnimateCtx); }
125                         if(this._onEndCtx){ dojo.disconnect(this._onEndCtx); }
126                 }
127         });
128         dojo.extend(_chain, _baseObj);
129
130         dojo.fx.chain = function(/*dojo._Animation[]*/ animations){
131                 // summary: Chain a list of dojo._Animation s to run in sequence
132                 // example:
133                 //      |       dojo.fx.chain([
134                 //      |               dojo.fadeIn({ node:node }),
135                 //      |               dojo.fadeOut({ node:otherNode })
136                 //      |       ]).play();
137                 //
138                 return new _chain(animations) // dojo._Animation
139         };
140
141         var _combine = function(animations){
142                 this._animations = animations||[];
143                 this._connects = [];
144                 this._finished = 0;
145
146                 this.duration = 0;
147                 dojo.forEach(animations, function(a){
148                         var duration = a.duration;
149                         if(a.delay){ duration += a.delay; }
150                         if(this.duration < duration){ this.duration = duration; }
151                         this._connects.push(dojo.connect(a, "onEnd", this, "_onEnd"));
152                 }, this);
153                 
154                 this._pseudoAnimation = new dojo._Animation({curve: [0, 1], duration: this.duration});
155                 dojo.forEach(["beforeBegin", "onBegin", "onPlay", "onAnimate", "onPause", "onStop"], 
156                         function(evt){
157                                 this._connects.push(dojo.connect(this._pseudoAnimation, evt, dojo.hitch(this, "_fire", evt)));
158                         },
159                         this
160                 );
161         };
162         dojo.extend(_combine, {
163                 _doAction: function(action, args){
164                         dojo.forEach(this._animations, function(a){
165                                 a[action].apply(a, args);
166                         });
167                         return this;
168                 },
169                 _onEnd: function(){
170                         if(++this._finished == this._animations.length){
171                                 this._fire("onEnd");
172                         }
173                 },
174                 _call: function(action, args){
175                         var t = this._pseudoAnimation;
176                         t[action].apply(t, args);
177                 },
178                 play: function(/*int?*/ delay, /*Boolean?*/ gotoStart){
179                         this._finished = 0;
180                         this._doAction("play", arguments);
181                         this._call("play", arguments);
182                         return this;
183                 },
184                 pause: function(){
185                         this._doAction("pause", arguments);
186                         this._call("pause", arguments);
187                         return this;
188                 },
189                 gotoPercent: function(/*Decimal*/percent, /*Boolean?*/ andPlay){
190                         var ms = this.duration * percent;
191                         dojo.forEach(this._animations, function(a){
192                                 a.gotoPercent(a.duration < ms ? 1 : (ms / a.duration), andPlay);
193                         });
194                         this._call("gotoProcent", arguments);
195                         return this;
196                 },
197                 stop: function(/*boolean?*/ gotoEnd){
198                         this._doAction("stop", arguments);
199                         this._call("stop", arguments);
200                         return this;
201                 },
202                 status: function(){
203                         return this._pseudoAnimation.status();
204                 },
205                 destroy: function(){
206                         dojo.forEach(this._connects, dojo.disconnect);
207                 }
208         });
209         dojo.extend(_combine, _baseObj);
210
211         dojo.fx.combine = function(/*dojo._Animation[]*/ animations){
212                 // summary: Combine a list of dojo._Animation s to run in parallel
213                 // example:
214                 //      |       dojo.fx.combine([
215                 //      |               dojo.fadeIn({ node:node }),
216                 //      |               dojo.fadeOut({ node:otherNode })
217                 //      |       ]).play();
218                 return new _combine(animations); // dojo._Animation
219         };
220 })();
221
222 dojo.declare("dojo.fx.Toggler", null, {
223         // summary:
224         //              class constructor for an animation toggler. It accepts a packed
225         //              set of arguments about what type of animation to use in each
226         //              direction, duration, etc.
227         //
228         // example:
229         //      |       var t = new dojo.fx.Toggler({
230         //      |               node: "nodeId",
231         //      |               showDuration: 500,
232         //      |               // hideDuration will default to "200"
233         //      |               showFunc: dojo.wipeIn, 
234         //      |               // hideFunc will default to "fadeOut"
235         //      |       });
236         //      |       t.show(100); // delay showing for 100ms
237         //      |       // ...time passes...
238         //      |       t.hide();
239
240         // FIXME: need a policy for where the toggler should "be" the next
241         // time show/hide are called if we're stopped somewhere in the
242         // middle.
243
244         constructor: function(args){
245                 var _t = this;
246
247                 dojo.mixin(_t, args);
248                 _t.node = args.node;
249                 _t._showArgs = dojo.mixin({}, args);
250                 _t._showArgs.node = _t.node;
251                 _t._showArgs.duration = _t.showDuration;
252                 _t.showAnim = _t.showFunc(_t._showArgs);
253
254                 _t._hideArgs = dojo.mixin({}, args);
255                 _t._hideArgs.node = _t.node;
256                 _t._hideArgs.duration = _t.hideDuration;
257                 _t.hideAnim = _t.hideFunc(_t._hideArgs);
258
259                 dojo.connect(_t.showAnim, "beforeBegin", dojo.hitch(_t.hideAnim, "stop", true));
260                 dojo.connect(_t.hideAnim, "beforeBegin", dojo.hitch(_t.showAnim, "stop", true));
261         },
262
263         // node: DomNode
264         //      the node to toggle
265         node: null,
266
267         // showFunc: Function
268         //      The function that returns the dojo._Animation to show the node
269         showFunc: dojo.fadeIn,
270
271         // hideFunc: Function   
272         //      The function that returns the dojo._Animation to hide the node
273         hideFunc: dojo.fadeOut,
274
275         // showDuration:
276         //      Time in milliseconds to run the show Animation
277         showDuration: 200,
278
279         // hideDuration:
280         //      Time in milliseconds to run the hide Animation
281         hideDuration: 200,
282
283         /*=====
284         _showArgs: null,
285         _showAnim: null,
286
287         _hideArgs: null,
288         _hideAnim: null,
289
290         _isShowing: false,
291         _isHiding: false,
292         =====*/
293
294         show: function(delay){
295                 // summary: Toggle the node to showing
296                 return this.showAnim.play(delay || 0);
297         },
298
299         hide: function(delay){
300                 // summary: Toggle the node to hidden
301                 return this.hideAnim.play(delay || 0);
302         }
303 });
304
305 dojo.fx.wipeIn = function(/*Object*/ args){
306         // summary
307         //              Returns an animation that will expand the
308         //              node defined in 'args' object from it's current height to
309         //              it's natural height (with no scrollbar).
310         //              Node must have no margin/border/padding.
311         args.node = dojo.byId(args.node);
312         var node = args.node, s = node.style;
313
314         var anim = dojo.animateProperty(dojo.mixin({
315                 properties: {
316                         height: {
317                                 // wrapped in functions so we wait till the last second to query (in case value has changed)
318                                 start: function(){
319                                         // start at current [computed] height, but use 1px rather than 0
320                                         // because 0 causes IE to display the whole panel
321                                         s.overflow="hidden";
322                                         if(s.visibility=="hidden"||s.display=="none"){
323                                                 s.height="1px";
324                                                 s.display="";
325                                                 s.visibility="";
326                                                 return 1;
327                                         }else{
328                                                 var height = dojo.style(node, "height");
329                                                 return Math.max(height, 1);
330                                         }
331                                 },
332                                 end: function(){
333                                         return node.scrollHeight;
334                                 }
335                         }
336                 }
337         }, args));
338
339         dojo.connect(anim, "onEnd", function(){ 
340                 s.height = "auto";
341         });
342
343         return anim; // dojo._Animation
344 }
345
346 dojo.fx.wipeOut = function(/*Object*/ args){
347         // summary
348         //              Returns an animation that will shrink node defined in "args"
349         //              from it's current height to 1px, and then hide it.
350         var node = args.node = dojo.byId(args.node);
351         var s = node.style;
352
353         var anim = dojo.animateProperty(dojo.mixin({
354                 properties: {
355                         height: {
356                                 end: 1 // 0 causes IE to display the whole panel
357                         }
358                 }
359         }, args));
360
361         dojo.connect(anim, "beforeBegin", function(){
362                 s.overflow = "hidden";
363                 s.display = "";
364         });
365         dojo.connect(anim, "onEnd", function(){
366                 s.height = "auto";
367                 s.display = "none";
368         });
369
370         return anim; // dojo._Animation
371 }
372
373 dojo.fx.slideTo = function(/*Object?*/ args){
374         // summary
375         //              Returns an animation that will slide "node" 
376         //              defined in args Object from its current position to
377         //              the position defined by (args.left, args.top).
378         // example:
379         //      |       dojo.fx.slideTo({ node: node, left:"40", top:"50", unit:"px" }).play()
380
381         var node = (args.node = dojo.byId(args.node));
382         
383         var top = null;
384         var left = null;
385         
386         var init = (function(n){
387                 return function(){
388                         var cs = dojo.getComputedStyle(n);
389                         var pos = cs.position;
390                         top = (pos == 'absolute' ? n.offsetTop : parseInt(cs.top) || 0);
391                         left = (pos == 'absolute' ? n.offsetLeft : parseInt(cs.left) || 0);
392                         if(pos != 'absolute' && pos != 'relative'){
393                                 var ret = dojo.coords(n, true);
394                                 top = ret.y;
395                                 left = ret.x;
396                                 n.style.position="absolute";
397                                 n.style.top=top+"px";
398                                 n.style.left=left+"px";
399                         }
400                 };
401         })(node);
402         init();
403
404         var anim = dojo.animateProperty(dojo.mixin({
405                 properties: {
406                         top: { end: args.top||0 },
407                         left: { end: args.left||0 }
408                 }
409         }, args));
410         dojo.connect(anim, "beforeBegin", anim, init);
411
412         return anim; // dojo._Animation
413 }
414
415 }