summaryrefslogtreecommitdiff
path: root/frontend/beta/js/YUI-extensions/anim/Animator.js
Unidiff
Diffstat (limited to 'frontend/beta/js/YUI-extensions/anim/Animator.js') (more/less context) (ignore whitespace changes)
-rw-r--r--frontend/beta/js/YUI-extensions/anim/Animator.js482
1 files changed, 482 insertions, 0 deletions
diff --git a/frontend/beta/js/YUI-extensions/anim/Animator.js b/frontend/beta/js/YUI-extensions/anim/Animator.js
new file mode 100644
index 0000000..ed250fb
--- a/dev/null
+++ b/frontend/beta/js/YUI-extensions/anim/Animator.js
@@ -0,0 +1,482 @@
1/**
2 * @class YAHOO.ext.Animator
3 * Provides support for syncing animations for multiple {@link YAHOO.ext.Actor}s.<br><br>
4* <br><br>This example can be seen in action <a href="http://www.jackslocum.com/yui/2006/08/19/a-splitbar-component-for-yahoo-ui/" target="_new">here</a>
5* by clicking on "Click here and I will point it out" at the end of the first paragraph.<br>
6 * <pre><code>
7var animator = new YAHOO.ext.Animator();
8var cursor = new YAHOO.ext.Actor('cursor-img', animator);
9var click = new YAHOO.ext.Actor('click-img', animator);
10var resize = new YAHOO.ext.Actor('resize-img', animator);
11
12// start capturing
13animator.startCapture();
14
15// these animations will be run in sequence
16cursor.show();
17cursor.moveTo(500,400);
18cursor.moveTo(20, getEl('navbar').getY()+10, true, .75);
19click.show();
20click.alignTo(cursor, 'tl', [-4, -4]);
21
22// Add an async function call, pass callback to argument 1
23animator.addAsyncCall(Blog.navbar.undockDelegate, 1);
24
25// pause .5 seconds
26animator.pause(.5);
27
28// again, these animations will be run in sequence
29click.hide(true, .7);
30cursor.alignTo('splitter', 'tr', [0, +100], true, 1);
31resize.alignTo('splitter', 'tr', [-12, +100]);
32
33// start sync block: these animations will run at the same time
34animator.beginSync();
35cursor.hide();
36resize.show();
37animator.endSync();
38
39// play the captured animation sequences, call myCallback when done
40animator.play(myCallback);
41 * </code></pre>
42 * @requires YAHOO.ext.Element
43 * @requires YAHOO.util.Dom
44 * @requires YAHOO.util.Event
45 * @requires YAHOO.util.CustomEvent
46 * @requires YAHOO.util.Anim
47 * @requires YAHOO.util.ColorAnim
48 * @requires YAHOO.util.Motion
49 * @constructor
50 * @param {String/HTMLElement} el The dom element or element id
51 * @param {<i>YAHOO.ext.Animator</i>} animator (optional) The Animator that will capture this Actor's actions
52 * @param {<i>Boolean</i>} selfCapture (optional) Whether this actor should capture it's own actions to support self playback without an animator (defaults to false)
53 */
54 YAHOO.ext.Animator = function(/*Actors...*/){
55 this.actors = [];
56 this.playlist = new YAHOO.ext.Animator.AnimSequence();
57 this.captureDelegate = this.capture.createDelegate(this);
58 this.playDelegate = this.play.createDelegate(this);
59 this.syncing = false;
60 this.stopping = false;
61 this.playing = false;
62 for(var i = 0; i < arguments.length; i++){
63 this.addActor(arguments[i]);
64 }
65 };
66
67 YAHOO.ext.Animator.prototype = {
68
69 capture : function(actor, action){
70 if(this.syncing){
71 if(!this.syncMap[actor.id]){
72 this.syncMap[actor.id] = new YAHOO.ext.Animator.AnimSequence();
73 }
74 this.syncMap[actor.id].add(action);
75 }else{
76 this.playlist.add(action);
77 }
78 },
79
80 /**
81 * Add an actor. The actor is also set to capturing = true.
82 * @param {YAHOO.ext.Actor} actor
83 */
84 addActor : function(actor){
85 actor.onCapture.subscribe(this.captureDelegate);
86 this.actors.push(actor);
87 },
88
89
90 /**
91 * Start capturing actions on the added actors.
92 * @param {<i>Boolean</i>} clearPlaylist Whether to also create a new playlist
93 */
94 startCapture : function(clearPlaylist){
95 for(var i = 0; i < this.actors.length; i++){
96 var a = this.actors[i];
97 if(!this.isCapturing(a)){
98 a.onCapture.subscribe(this.captureDelegate);
99 }
100 a.capturing = true;
101 }
102 if(clearPlaylist){
103 this.playlist = new YAHOO.ext.Animator.AnimSequence();
104 }
105 },
106
107 /**
108 * Checks whether this animator is listening to a specific actor.
109 * @param {YAHOO.ext.Actor} actor
110 */
111 isCapturing : function(actor){
112 var subscribers = actor.onCapture.subscribers;
113 if(subscribers){
114 for(var i = 0; i < subscribers.length; i++){
115 if(subscribers[i] && subscribers[i].contains(this.captureDelegate)){
116 return true;
117 }
118 }
119 }
120 return false;
121 },
122
123 /**
124 * Stop capturing on all added actors.
125 */
126 stopCapture : function(){
127 for(var i = 0; i < this.actors.length; i++){
128 var a = this.actors[i];
129 a.onCapture.unsubscribe(this.captureDelegate);
130 a.capturing = false;
131 }
132 },
133
134 /**
135 * Start a multi-actor sync block. By default all animations are run in sequence. While in the sync block
136 * each actor's own animations will still be sequenced, but all actors will animate at the same time.
137 */
138 beginSync : function(){
139 this.syncing = true;
140 this.syncMap = {};
141 },
142
143 /**
144 * End the multi-actor sync block
145 */
146 endSync : function(){
147 this.syncing = false;
148 var composite = new YAHOO.ext.Animator.CompositeSequence();
149 for(key in this.syncMap){
150 if(typeof this.syncMap[key] != 'function'){
151 composite.add(this.syncMap[key]);
152 }
153 }
154 this.playlist.add(composite);
155 this.syncMap = null;
156 },
157
158 /**
159 * Starts playback of the playlist, also stops any capturing. To start capturing again call {@link #startCapture}.
160 * @param {<i>Function</i>} oncomplete (optional) Callback to execute when playback has completed
161 */
162 play : function(oncomplete){
163 if(this.playing) return; // can't play the same animation twice at once
164 this.stopCapture();
165 this.playlist.play(oncomplete);
166 },
167
168 /**
169 * Stop at the next available stopping point
170 */
171 stop : function(){
172 this.playlist.stop();
173 },
174
175 /**
176 * Check if this animator is currently playing
177 */
178 isPlaying : function(){
179 return this.playlist.isPlaying();
180 },
181 /**
182 * Clear the playlist
183 */
184 clear : function(){
185 this.playlist = new YAHOO.ext.Animator.AnimSequence();
186 },
187
188 /**
189 * Add a function call to the playlist.
190 * @param {Function} fcn The function to call
191 * @param {<i>Array</i>} args The arguments to call the function with
192 * @param {<i>Object</i>} scope (optional) The scope of the function
193 */
194 addCall : function(fcn, args, scope){
195 this.playlist.add(new YAHOO.ext.Actor.Action(scope, fcn, args || []));
196 },
197
198 /**
199 * Add an async function call to the playlist.
200 * @param {Function} fcn The function to call
201 * @param {Number} callbackIndex The index of the callback parameter on the passed function. A CALLBACK IS REQUIRED.
202 * @param {<i>Array</i>} args The arguments to call the function with
203 * @param {<i>Object</i>} scope (optional) The scope of the function
204 */
205 addAsyncCall : function(fcn, callbackIndex, args, scope){
206 this.playlist.add(new YAHOO.ext.Actor.AsyncAction(scope, fcn, args || [], callbackIndex));
207 },
208
209 /**
210 * Add a pause to the playlist (in seconds)
211 * @param {Number} seconds The number of seconds to pause.
212 */
213 pause : function(seconds){
214 this.playlist.add(new YAHOO.ext.Actor.PauseAction(seconds));
215 }
216
217 };
218/**
219 * Static function to build a AnimatorComposite from a css selector (requires YAHOO.ext.Element.selectorFunction be defined)
220 * @param {String/Array} selector The css selector or an array of nodes to animate
221 * @method @static
222 */
223YAHOO.ext.Animator.select = function(selector){
224 var els;
225 if(typeof selector == 'string'){
226 els = YAHOO.ext.Element.selectorFunction(selector);
227 }else if(selector instanceof Array){
228 els = selector;
229 }else{
230 throw 'Invalid selector';
231 }
232 return new YAHOO.ext.AnimatorComposite(els);
233};
234var getActors = YAHOO.ext.Animator.select;
235
236/**
237 * @class YAHOO.ext.AnimatorComposite
238 * Composite class with synchronized animations. This is the class returned by getActors(selector) or YAHOO.ext.Animator.select().
239 */
240YAHOO.ext.AnimatorComposite = function(els){
241 this.animator = new YAHOO.ext.Animator();
242 this.addElements(els);
243 this.syncAnims = true;
244};
245YAHOO.ext.AnimatorComposite.prototype = {
246 isComposite: true,
247 /**
248 * Adds elements to this composite.
249 * @param {Array} els An array of elements to add
250 * @return {AnimatorComposite} this
251 */
252 addElements : function(els){
253 if(!els) return this;
254 var anim = this.animator;
255 for(var i = 0, len = els.length; i < len; i++) {
256 anim.addActor(new YAHOO.ext.Actor(els[i]));
257 }
258 anim.startCapture();
259 return this;
260 },
261 /**
262 * Operations called after sequence() will be performed one by one on each element in this composite.
263 * @return {AnimatorComposite} this
264 */
265 sequence : function(){
266 this.syncAnims = false;
267 return this;
268 },
269 /**
270 * Operations called after sync() will be performed at the same time on each element in this composite.
271 * @return {AnimatorComposite} this
272 */
273 sync : function(){
274 this.syncAnims = true;
275 return this;
276 },
277 invoke : function(fn, args){
278 var els = this.animator.actors;
279 if(this.syncAnims) this.animator.beginSync();
280 for(var i = 0, len = els.length; i < len; i++) {
281 YAHOO.ext.Actor.prototype[fn].apply(els[i], args);
282 }
283 if(this.syncAnims) this.animator.endSync();
284 return this;
285 },
286 /**
287 * Play the actions queued in this composite.
288 * @param {Function} callback (optional) callback is called when all animations have compelted
289 * @return {AnimatorComposite} this
290 */
291 play : function(callback){
292 this.animator.play(callback);
293 return this;
294 },
295 /**
296 * Clear all actions in the queue.
297 * @param {Function} callback (optional) callback is called when all animations have compelted
298 * @return {AnimatorComposite} this
299 */
300 reset : function(callback){
301 this.animator.startCapture(true);
302 return this;
303 },
304 /**
305 * Add a pause
306 * @param {Number} seconds
307 * @return {AnimatorComposite} this
308 */
309 pause : function(seconds){
310 this.animator.pause(seconds);
311 return this;
312 },
313 /**
314 * Get the YAHOO.ext.Animator that controls the animations for this composite.
315 * @return {YAHOO.ext.Animator}
316 */
317 getAnimator : function(){
318 return this.animator;
319 },
320 /**
321 * Calls the passed function passing (el, this, index) for each element in this composite.
322 * @param {Function} fn The function to call
323 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
324 * @return {AnimatorComposite} this
325 */
326 each : function(fn, scope){
327 var els = this.animator.actors;
328 if(this.syncAnims) this.animator.beginSync();
329 for(var i = 0, len = els.length; i < len; i++){
330 fn.call(scope || els[i], els[i], this, i);
331 }
332 if(this.syncAnims) this.animator.endSync();
333 return this;
334 },
335 /**
336 * Add a function call to the playlist.
337 * @param {Function} fcn The function to call
338 * @param {<i>Array</i>} args (optional) The arguments to call the function with
339 * @param {<i>Object</i>} scope (optional) The scope of the function
340 * @return {AnimatorComposite} this
341 */
342 addCall : function(fcn, args, scope){
343 this.animator.addCall(fcn, args, scope);
344 return this;
345 },
346 /**
347 * Add an async function call to the playlist.
348 * @param {Function} fcn The function to call
349 * @param {Number} callbackIndex The index of the callback parameter on the passed function. <b>A CALLBACK IS REQUIRED</b>.
350 * @param {<i>Array</i>} args (optional) The arguments to call the function with
351 * @param {<i>Object</i>} scope (optional) The scope of the function
352 * @return {AnimatorComposite} this
353 */
354 addAsyncCall : function(fcn, callbackIndex, args, scope){
355 this.animator.addAsyncCall(fcn, callbackIndex, args, scope);
356 return this;
357 }
358};
359for(var fnName in YAHOO.ext.Actor.prototype){
360 if(typeof YAHOO.ext.Actor.prototype[fnName] == 'function'){
361 YAHOO.ext.CompositeElement.createCall(YAHOO.ext.AnimatorComposite.prototype, fnName);
362 }
363}
364
365
366YAHOO.ext.Animator.AnimSequence = function(){
367 this.actions = [];
368 this.nextDelegate = this.next.createDelegate(this);
369 this.playDelegate = this.play.createDelegate(this);
370 this.oncomplete = null;
371 this.playing = false;
372 this.stopping = false;
373 this.actionIndex = -1;
374 };
375
376 YAHOO.ext.Animator.AnimSequence.prototype = {
377
378 add : function(action){
379 this.actions.push(action);
380 },
381
382 next : function(){
383 if(this.stopping){
384 this.playing = false;
385 if(this.oncomplete){
386 this.oncomplete(this, false);
387 }
388 return;
389 }
390 var nextAction = this.actions[++this.actionIndex];
391 if(nextAction){
392 nextAction.play(this.nextDelegate);
393 }else{
394 this.playing = false;
395 if(this.oncomplete){
396 this.oncomplete(this, true);
397 }
398 }
399 },
400
401 play : function(oncomplete){
402 if(this.playing) return; // can't play the same sequence twice at once
403 this.oncomplete = oncomplete;
404 this.stopping = false;
405 this.playing = true;
406 this.actionIndex = -1;
407 this.next();
408 },
409
410 stop : function(){
411 this.stopping = true;
412 },
413
414 isPlaying : function(){
415 return this.playing;
416 },
417
418 clear : function(){
419 this.actions = [];
420 },
421
422 addCall : function(fcn, args, scope){
423 this.actions.push(new YAHOO.ext.Actor.Action(scope, fcn, args || []));
424 },
425
426 addAsyncCall : function(fcn, callbackIndex, args, scope){
427 this.actions.push(new YAHOO.ext.Actor.AsyncAction(scope, fcn, args || [], callbackIndex));
428 },
429
430 pause : function(seconds){
431 this.actions.push(new YAHOO.ext.Actor.PauseAction(seconds));
432 }
433
434 };
435
436YAHOO.ext.Animator.CompositeSequence = function(){
437 this.sequences = [];
438 this.completed = 0;
439 this.trackDelegate = this.trackCompletion.createDelegate(this);
440}
441
442YAHOO.ext.Animator.CompositeSequence.prototype = {
443 add : function(sequence){
444 this.sequences.push(sequence);
445 },
446
447 play : function(onComplete){
448 this.completed = 0;
449 if(this.sequences.length < 1){
450 if(onComplete)onComplete();
451 return;
452 }
453 this.onComplete = onComplete;
454 for(var i = 0; i < this.sequences.length; i++){
455 this.sequences[i].play(this.trackDelegate);
456 }
457 },
458
459 trackCompletion : function(){
460 ++this.completed;
461 if(this.completed >= this.sequences.length && this.onComplete){
462 this.onComplete();
463 }
464 },
465
466 stop : function(){
467 for(var i = 0; i < this.sequences.length; i++){
468 this.sequences[i].stop();
469 }
470 },
471
472 isPlaying : function(){
473 for(var i = 0; i < this.sequences.length; i++){
474 if(this.sequences[i].isPlaying()){
475 return true;
476 }
477 }
478 return false;
479 }
480};
481
482