Subversion Repositories Applications.papyrus

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
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
}