2150 |
mathias |
1 |
if(!dojo._hasResource["dojo._base.fx"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
|
|
2 |
dojo._hasResource["dojo._base.fx"] = true;
|
|
|
3 |
dojo.provide("dojo._base.fx");
|
|
|
4 |
dojo.require("dojo._base.Color");
|
|
|
5 |
dojo.require("dojo._base.connect");
|
|
|
6 |
dojo.require("dojo._base.declare");
|
|
|
7 |
dojo.require("dojo._base.lang");
|
|
|
8 |
dojo.require("dojo._base.html");
|
|
|
9 |
|
|
|
10 |
/*
|
|
|
11 |
Animation losely package based on Dan Pupius' work, contributed under CLA:
|
|
|
12 |
http://pupius.co.uk/js/Toolkit.Drawing.js
|
|
|
13 |
*/
|
|
|
14 |
|
|
|
15 |
dojo._Line = function(/*int*/ start, /*int*/ end){
|
|
|
16 |
// summary:
|
|
|
17 |
// dojo._Line is the object used to generate values from a start value
|
|
|
18 |
// to an end value
|
|
|
19 |
// start: int
|
|
|
20 |
// Beginning value for range
|
|
|
21 |
// end: int
|
|
|
22 |
// Ending value for range
|
|
|
23 |
this.start = start;
|
|
|
24 |
this.end = end;
|
|
|
25 |
this.getValue = function(/*float*/ n){
|
|
|
26 |
// summary: returns the point on the line
|
|
|
27 |
// n: a floating point number greater than 0 and less than 1
|
|
|
28 |
return ((this.end - this.start) * n) + this.start; // Decimal
|
|
|
29 |
}
|
|
|
30 |
}
|
|
|
31 |
|
|
|
32 |
dojo.declare("dojo._Animation", null, {
|
|
|
33 |
// summary
|
|
|
34 |
// A generic animation object that fires callbacks into it's handlers
|
|
|
35 |
// object at various states
|
|
|
36 |
//
|
|
|
37 |
constructor: function(/*Object*/ args){
|
|
|
38 |
dojo.mixin(this, args);
|
|
|
39 |
if(dojo.isArray(this.curve)){
|
|
|
40 |
/* curve: Array
|
|
|
41 |
pId: a */
|
|
|
42 |
this.curve = new dojo._Line(this.curve[0], this.curve[1]);
|
|
|
43 |
}
|
|
|
44 |
},
|
|
|
45 |
|
|
|
46 |
// duration: Integer
|
|
|
47 |
// The time in milliseonds the animation will take to run
|
|
|
48 |
duration: 1000,
|
|
|
49 |
|
|
|
50 |
/*=====
|
|
|
51 |
// curve: dojo._Line||Array
|
|
|
52 |
// A two element array of start and end values, or a dojo._Line instance to be
|
|
|
53 |
// used in the Animation.
|
|
|
54 |
curve: null,
|
|
|
55 |
|
|
|
56 |
// easing: Function
|
|
|
57 |
// A Function to adjust the acceleration (or deceleration) of the progress
|
|
|
58 |
// across a dojo._Line
|
|
|
59 |
easing: null,
|
|
|
60 |
=====*/
|
|
|
61 |
|
|
|
62 |
// repeat: Integer
|
|
|
63 |
// The number of times to loop the animation
|
|
|
64 |
repeat: 0,
|
|
|
65 |
|
|
|
66 |
// rate: Integer
|
|
|
67 |
// the time in milliseconds to wait before advancing to next frame
|
|
|
68 |
// (used as a fps timer: rate/1000 = fps)
|
|
|
69 |
rate: 10 /* 100 fps */,
|
|
|
70 |
|
|
|
71 |
/*=====
|
|
|
72 |
// delay: Integer
|
|
|
73 |
// The time in milliseconds to wait before starting animation after it has been .play()'ed
|
|
|
74 |
delay: null,
|
|
|
75 |
|
|
|
76 |
// events
|
|
|
77 |
//
|
|
|
78 |
// beforeBegin: Event
|
|
|
79 |
// Synthetic event fired before a dojo._Animation begins playing (synhcronous)
|
|
|
80 |
beforeBegin: null,
|
|
|
81 |
|
|
|
82 |
// onBegin: Event
|
|
|
83 |
// Synthetic event fired as a dojo._Animation begins playing (useful?)
|
|
|
84 |
onBegin: null,
|
|
|
85 |
|
|
|
86 |
// onAnimate: Event
|
|
|
87 |
// Synthetic event fired at each interval of a dojo._Animation
|
|
|
88 |
onAnimate: null,
|
|
|
89 |
|
|
|
90 |
// onEnd: Event
|
|
|
91 |
// Synthetic event fired after the final frame of a dojo._Animation
|
|
|
92 |
onEnd: null,
|
|
|
93 |
|
|
|
94 |
// ???
|
|
|
95 |
onPlay: null,
|
|
|
96 |
|
|
|
97 |
// onPause: Event
|
|
|
98 |
// Synthetic event fired when a dojo._Animation is paused
|
|
|
99 |
onPause: null,
|
|
|
100 |
|
|
|
101 |
// onStop: Event
|
|
|
102 |
// Synthetic event fires when a dojo._Animation is stopped
|
|
|
103 |
onStop: null,
|
|
|
104 |
|
|
|
105 |
=====*/
|
|
|
106 |
|
|
|
107 |
_percent: 0,
|
|
|
108 |
_startRepeatCount: 0,
|
|
|
109 |
|
|
|
110 |
fire: function(/*Event*/ evt, /*Array?*/ args){
|
|
|
111 |
// summary:
|
|
|
112 |
// Convenience function. Fire event "evt" and pass it the
|
|
|
113 |
// arguments specified in "args".
|
|
|
114 |
// evt:
|
|
|
115 |
// The event to fire.
|
|
|
116 |
// args:
|
|
|
117 |
// The arguments to pass to the event.
|
|
|
118 |
if(this[evt]){
|
|
|
119 |
this[evt].apply(this, args||[]);
|
|
|
120 |
}
|
|
|
121 |
return this; // dojo._Animation
|
|
|
122 |
},
|
|
|
123 |
|
|
|
124 |
play: function(/*int?*/ delay, /*Boolean?*/ gotoStart){
|
|
|
125 |
// summary:
|
|
|
126 |
// Start the animation.
|
|
|
127 |
// delay:
|
|
|
128 |
// How many milliseconds to delay before starting.
|
|
|
129 |
// gotoStart:
|
|
|
130 |
// If true, starts the animation from the beginning; otherwise,
|
|
|
131 |
// starts it from its current position.
|
|
|
132 |
var _t = this;
|
|
|
133 |
if(gotoStart){
|
|
|
134 |
_t._stopTimer();
|
|
|
135 |
_t._active = _t._paused = false;
|
|
|
136 |
_t._percent = 0;
|
|
|
137 |
}else if(_t._active && !_t._paused){
|
|
|
138 |
return _t; // dojo._Animation
|
|
|
139 |
}
|
|
|
140 |
|
|
|
141 |
_t.fire("beforeBegin");
|
|
|
142 |
|
|
|
143 |
var d = delay||_t.delay;
|
|
|
144 |
var _p = dojo.hitch(_t, "_play", gotoStart);
|
|
|
145 |
if(d > 0){
|
|
|
146 |
setTimeout(_p, d);
|
|
|
147 |
return _t; // dojo._Animation
|
|
|
148 |
}
|
|
|
149 |
_p();
|
|
|
150 |
return _t;
|
|
|
151 |
},
|
|
|
152 |
|
|
|
153 |
_play: function(gotoStart){
|
|
|
154 |
var _t = this;
|
|
|
155 |
_t._startTime = new Date().valueOf();
|
|
|
156 |
if(_t._paused){
|
|
|
157 |
_t._startTime -= _t.duration * _t._percent;
|
|
|
158 |
}
|
|
|
159 |
_t._endTime = _t._startTime + _t.duration;
|
|
|
160 |
|
|
|
161 |
_t._active = true;
|
|
|
162 |
_t._paused = false;
|
|
|
163 |
|
|
|
164 |
var value = _t.curve.getValue(_t._percent);
|
|
|
165 |
if(!_t._percent){
|
|
|
166 |
if(!_t._startRepeatCount){
|
|
|
167 |
_t._startRepeatCount = _t.repeat;
|
|
|
168 |
}
|
|
|
169 |
_t.fire("onBegin", [value]);
|
|
|
170 |
}
|
|
|
171 |
|
|
|
172 |
_t.fire("onPlay", [value]);
|
|
|
173 |
|
|
|
174 |
_t._cycle();
|
|
|
175 |
return _t; // dojo._Animation
|
|
|
176 |
},
|
|
|
177 |
|
|
|
178 |
pause: function(){
|
|
|
179 |
// summary: Pauses a running animation.
|
|
|
180 |
this._stopTimer();
|
|
|
181 |
if(!this._active){ return this; /*dojo._Animation*/}
|
|
|
182 |
this._paused = true;
|
|
|
183 |
this.fire("onPause", [this.curve.getValue(this._percent)]);
|
|
|
184 |
return this; // dojo._Animation
|
|
|
185 |
},
|
|
|
186 |
|
|
|
187 |
gotoPercent: function(/*Decimal*/ percent, /*Boolean?*/ andPlay){
|
|
|
188 |
// summary:
|
|
|
189 |
// Sets the progress of the animation.
|
|
|
190 |
// percent:
|
|
|
191 |
// A percentage in decimal notation (between and including 0.0 and 1.0).
|
|
|
192 |
// andPlay:
|
|
|
193 |
// If true, play the animation after setting the progress.
|
|
|
194 |
this._stopTimer();
|
|
|
195 |
this._active = this._paused = true;
|
|
|
196 |
this._percent = percent;
|
|
|
197 |
if(andPlay){ this.play(); }
|
|
|
198 |
return this; // dojo._Animation
|
|
|
199 |
},
|
|
|
200 |
|
|
|
201 |
stop: function(/*boolean?*/ gotoEnd){
|
|
|
202 |
// summary: Stops a running animation.
|
|
|
203 |
// gotoEnd: If true, the animation will end.
|
|
|
204 |
if(!this._timer){ return; }
|
|
|
205 |
this._stopTimer();
|
|
|
206 |
if(gotoEnd){
|
|
|
207 |
this._percent = 1;
|
|
|
208 |
}
|
|
|
209 |
this.fire("onStop", [this.curve.getValue(this._percent)]);
|
|
|
210 |
this._active = this._paused = false;
|
|
|
211 |
return this; // dojo._Animation
|
|
|
212 |
},
|
|
|
213 |
|
|
|
214 |
status: function(){
|
|
|
215 |
// summary: Returns a string token representation of the status of
|
|
|
216 |
// the animation, one of: "paused", "playing", "stopped"
|
|
|
217 |
if(this._active){
|
|
|
218 |
return this._paused ? "paused" : "playing"; // String
|
|
|
219 |
}
|
|
|
220 |
return "stopped"; // String
|
|
|
221 |
},
|
|
|
222 |
|
|
|
223 |
_cycle: function(){
|
|
|
224 |
var _t = this;
|
|
|
225 |
if(_t._active){
|
|
|
226 |
var curr = new Date().valueOf();
|
|
|
227 |
var step = (curr - _t._startTime) / (_t._endTime - _t._startTime);
|
|
|
228 |
|
|
|
229 |
if(step >= 1){
|
|
|
230 |
step = 1;
|
|
|
231 |
}
|
|
|
232 |
_t._percent = step;
|
|
|
233 |
|
|
|
234 |
// Perform easing
|
|
|
235 |
if(_t.easing){
|
|
|
236 |
step = _t.easing(step);
|
|
|
237 |
}
|
|
|
238 |
|
|
|
239 |
_t.fire("onAnimate", [_t.curve.getValue(step)]);
|
|
|
240 |
|
|
|
241 |
if(step < 1){
|
|
|
242 |
_t._startTimer();
|
|
|
243 |
}else{
|
|
|
244 |
_t._active = false;
|
|
|
245 |
|
|
|
246 |
if(_t.repeat > 0){
|
|
|
247 |
_t.repeat--;
|
|
|
248 |
_t.play(null, true);
|
|
|
249 |
}else if(_t.repeat == -1){
|
|
|
250 |
_t.play(null, true);
|
|
|
251 |
}else{
|
|
|
252 |
if(_t._startRepeatCount){
|
|
|
253 |
_t.repeat = _t._startRepeatCount;
|
|
|
254 |
_t._startRepeatCount = 0;
|
|
|
255 |
}
|
|
|
256 |
}
|
|
|
257 |
_t._percent = 0;
|
|
|
258 |
_t.fire("onEnd");
|
|
|
259 |
}
|
|
|
260 |
}
|
|
|
261 |
return _t; // dojo._Animation
|
|
|
262 |
}
|
|
|
263 |
});
|
|
|
264 |
|
|
|
265 |
(function(){
|
|
|
266 |
var d = dojo;
|
|
|
267 |
var ctr = 0;
|
|
|
268 |
var _globalTimerList = [];
|
|
|
269 |
var runner = {
|
|
|
270 |
run: function(){}
|
|
|
271 |
};
|
|
|
272 |
var timer = null;
|
|
|
273 |
dojo._Animation.prototype._startTimer = function(){
|
|
|
274 |
// this._timer = setTimeout(dojo.hitch(this, "_cycle"), this.rate);
|
|
|
275 |
if(!this._timer){
|
|
|
276 |
this._timer = dojo.connect(runner, "run", this, "_cycle");
|
|
|
277 |
ctr++;
|
|
|
278 |
}
|
|
|
279 |
if(!timer){
|
|
|
280 |
timer = setInterval(dojo.hitch(runner, "run"), this.rate);
|
|
|
281 |
}
|
|
|
282 |
};
|
|
|
283 |
|
|
|
284 |
dojo._Animation.prototype._stopTimer = function(){
|
|
|
285 |
dojo.disconnect(this._timer);
|
|
|
286 |
this._timer = null;
|
|
|
287 |
ctr--;
|
|
|
288 |
if(!ctr){
|
|
|
289 |
clearInterval(timer);
|
|
|
290 |
timer = null;
|
|
|
291 |
}
|
|
|
292 |
};
|
|
|
293 |
|
|
|
294 |
var _makeFadeable = (d.isIE) ? function(node){
|
|
|
295 |
// only set the zoom if the "tickle" value would be the same as the
|
|
|
296 |
// default
|
|
|
297 |
var ns = node.style;
|
|
|
298 |
if(!ns.zoom.length && d.style(node, "zoom") == "normal"){
|
|
|
299 |
// make sure the node "hasLayout"
|
|
|
300 |
// NOTE: this has been tested with larger and smaller user-set text
|
|
|
301 |
// sizes and works fine
|
|
|
302 |
ns.zoom = "1";
|
|
|
303 |
// node.style.zoom = "normal";
|
|
|
304 |
}
|
|
|
305 |
// don't set the width to auto if it didn't already cascade that way.
|
|
|
306 |
// We don't want to f anyones designs
|
|
|
307 |
if(!ns.width.length && d.style(node, "width") == "auto"){
|
|
|
308 |
ns.width = "auto";
|
|
|
309 |
}
|
|
|
310 |
} : function(){};
|
|
|
311 |
|
|
|
312 |
dojo._fade = function(/*Object*/ args){
|
|
|
313 |
// summary:
|
|
|
314 |
// Returns an animation that will fade the node defined by
|
|
|
315 |
// args.node from the start to end values passed (args.start
|
|
|
316 |
// args.end) (end is mandatory, start is optional)
|
|
|
317 |
|
|
|
318 |
args.node = d.byId(args.node);
|
|
|
319 |
var fArgs = d.mixin({ properties: {} }, args);
|
|
|
320 |
var props = (fArgs.properties.opacity = {});
|
|
|
321 |
props.start = !("start" in fArgs) ?
|
|
|
322 |
function(){ return Number(d.style(fArgs.node, "opacity")); } : fArgs.start;
|
|
|
323 |
props.end = fArgs.end;
|
|
|
324 |
|
|
|
325 |
var anim = d.animateProperty(fArgs);
|
|
|
326 |
d.connect(anim, "beforeBegin", d.partial(_makeFadeable, fArgs.node));
|
|
|
327 |
|
|
|
328 |
return anim; // dojo._Animation
|
|
|
329 |
}
|
|
|
330 |
|
|
|
331 |
/*=====
|
|
|
332 |
dojo.__fadeArgs = function(kwArgs){
|
|
|
333 |
// duration: Integer?
|
|
|
334 |
// Duration of the animation in milliseconds.
|
|
|
335 |
// easing: Function?
|
|
|
336 |
// An easing function.
|
|
|
337 |
}
|
|
|
338 |
=====*/
|
|
|
339 |
|
|
|
340 |
dojo.fadeIn = function(/*dojo.__fadeArgs*/ args){
|
|
|
341 |
// summary:
|
|
|
342 |
// Returns an animation that will fade node defined in 'args' from
|
|
|
343 |
// its current opacity to fully opaque.
|
|
|
344 |
return d._fade(d.mixin({ end: 1 }, args)); // dojo._Animation
|
|
|
345 |
}
|
|
|
346 |
|
|
|
347 |
dojo.fadeOut = function(/*dojo.__fadeArgs*/ args){
|
|
|
348 |
// summary:
|
|
|
349 |
// Returns an animation that will fade node defined in 'args'
|
|
|
350 |
// from its current opacity to fully transparent.
|
|
|
351 |
return d._fade(d.mixin({ end: 0 }, args)); // dojo._Animation
|
|
|
352 |
}
|
|
|
353 |
|
|
|
354 |
dojo._defaultEasing = function(/*Decimal?*/ n){
|
|
|
355 |
// summary: The default easing function for dojo._Animation(s)
|
|
|
356 |
return 0.5 + ((Math.sin((n + 1.5) * Math.PI))/2);
|
|
|
357 |
}
|
|
|
358 |
|
|
|
359 |
var PropLine = function(properties){
|
|
|
360 |
this._properties = properties;
|
|
|
361 |
for(var p in properties){
|
|
|
362 |
var prop = properties[p];
|
|
|
363 |
if(prop.start instanceof d.Color){
|
|
|
364 |
// create a reusable temp color object to keep intermediate results
|
|
|
365 |
prop.tempColor = new d.Color();
|
|
|
366 |
}
|
|
|
367 |
}
|
|
|
368 |
this.getValue = function(r){
|
|
|
369 |
var ret = {};
|
|
|
370 |
for(var p in this._properties){
|
|
|
371 |
var prop = this._properties[p];
|
|
|
372 |
var start = prop.start;
|
|
|
373 |
if(start instanceof d.Color){
|
|
|
374 |
ret[p] = d.blendColors(start, prop.end, r, prop.tempColor).toCss();
|
|
|
375 |
}else if(!d.isArray(start)){
|
|
|
376 |
ret[p] = ((prop.end - start) * r) + start + (p != "opacity" ? prop.units||"px" : "");
|
|
|
377 |
}
|
|
|
378 |
}
|
|
|
379 |
return ret;
|
|
|
380 |
}
|
|
|
381 |
}
|
|
|
382 |
|
|
|
383 |
dojo.animateProperty = function(/*Object*/ args){
|
|
|
384 |
// summary:
|
|
|
385 |
// Returns an animation that will transition the properties of
|
|
|
386 |
// node defined in 'args' depending how they are defined in
|
|
|
387 |
// 'args.properties'
|
|
|
388 |
//
|
|
|
389 |
// description:
|
|
|
390 |
// The foundation of most dojo.fx animations, dojo.AnimateProperty
|
|
|
391 |
// will take an object of "properties" corresponding to style
|
|
|
392 |
// properties, and animate them in parallel over a set duration.
|
|
|
393 |
//
|
|
|
394 |
// args.node can be a String or a DomNode reference
|
|
|
395 |
//
|
|
|
396 |
// example:
|
|
|
397 |
// | dojo.animateProperty({ node: node, duration:2000,
|
|
|
398 |
// | properties: {
|
|
|
399 |
// | width: { start: '200', end: '400', unit:"px" },
|
|
|
400 |
// | height: { start:'200', end: '400', unit:"px" },
|
|
|
401 |
// | paddingTop: { start:'5', end:'50', unit:"px" }
|
|
|
402 |
// | }
|
|
|
403 |
// | }).play();
|
|
|
404 |
//
|
|
|
405 |
|
|
|
406 |
args.node = d.byId(args.node);
|
|
|
407 |
if(!args.easing){ args.easing = d._defaultEasing; }
|
|
|
408 |
|
|
|
409 |
var anim = new d._Animation(args);
|
|
|
410 |
d.connect(anim, "beforeBegin", anim, function(){
|
|
|
411 |
var pm = {};
|
|
|
412 |
for(var p in this.properties){
|
|
|
413 |
// Make shallow copy of properties into pm because we overwrite some values below.
|
|
|
414 |
// In particular if start/end are functions we don't want to overwrite them or
|
|
|
415 |
// the functions won't be called if the animation is reused.
|
|
|
416 |
var prop = (pm[p] = d.mixin({}, this.properties[p]));
|
|
|
417 |
|
|
|
418 |
if(d.isFunction(prop.start)){
|
|
|
419 |
prop.start = prop.start();
|
|
|
420 |
}
|
|
|
421 |
if(d.isFunction(prop.end)){
|
|
|
422 |
prop.end = prop.end();
|
|
|
423 |
}
|
|
|
424 |
|
|
|
425 |
var isColor = (p.toLowerCase().indexOf("color") >= 0);
|
|
|
426 |
function getStyle(node, p){
|
|
|
427 |
// dojo.style(node, "height") can return "auto" or "" on IE; this is more reliable:
|
|
|
428 |
var v = ({height: node.offsetHeight, width: node.offsetWidth})[p];
|
|
|
429 |
if(v !== undefined){ return v; }
|
|
|
430 |
v = d.style(node, p);
|
|
|
431 |
return (p=="opacity") ? Number(v) : parseFloat(v);
|
|
|
432 |
}
|
|
|
433 |
if(!("end" in prop)){
|
|
|
434 |
prop.end = getStyle(this.node, p);
|
|
|
435 |
}else if(!("start" in prop)){
|
|
|
436 |
prop.start = getStyle(this.node, p);
|
|
|
437 |
}
|
|
|
438 |
|
|
|
439 |
if(isColor){
|
|
|
440 |
// console.debug("it's a color!");
|
|
|
441 |
prop.start = new d.Color(prop.start);
|
|
|
442 |
prop.end = new d.Color(prop.end);
|
|
|
443 |
}else{
|
|
|
444 |
prop.start = (p == "opacity") ? Number(prop.start) : parseFloat(prop.start);
|
|
|
445 |
}
|
|
|
446 |
// console.debug("start:", prop.start);
|
|
|
447 |
// console.debug("end:", prop.end);
|
|
|
448 |
}
|
|
|
449 |
this.curve = new PropLine(pm);
|
|
|
450 |
});
|
|
|
451 |
d.connect(anim, "onAnimate", anim, function(propValues){
|
|
|
452 |
// try{
|
|
|
453 |
for(var s in propValues){
|
|
|
454 |
// console.debug(s, propValues[s], this.node.style[s]);
|
|
|
455 |
d.style(this.node, s, propValues[s]);
|
|
|
456 |
// this.node.style[s] = propValues[s];
|
|
|
457 |
}
|
|
|
458 |
// }catch(e){ console.debug(dojo.toJson(e)); }
|
|
|
459 |
});
|
|
|
460 |
return anim; // dojo._Animation
|
|
|
461 |
}
|
|
|
462 |
})();
|
|
|
463 |
|
|
|
464 |
}
|