2 * (c) 2005-2007 Richard Cowin (http://openrico.org)
4 * Rico is licensed under the Apache License, Version 2.0 (the "License"); you may not use this
5 * file except in compliance with the License. You may obtain a copy of the License at
6 * http://www.apache.org/licenses/LICENSE-2.0
9 Rico.animate = function(effect){
10 new Rico.Effect.Animator().play(effect, arguments[1]);
15 Rico.Effect.easeIn = function(step){
16 return Math.sqrt(step);
18 Rico.Effect.easeOut = function(step){
24 Rico.Stepping.easeIn = Rico.Effect.easeIn;
25 Rico.Stepping.easeOut = Rico.Effect.easeOut;
27 Rico.Effect.Animator = Class.create(
28 /** @lends Rico.Effect.Animator# */
31 * @class Class to animate effects.
34 initialize : function(effect) {
35 this.animateMethod = this.animate.bind(this);
36 this.options = arguments[1] || {};
39 this.reset(effect, arguments[1]);
41 reset: function(effect){
43 if (arguments[1]) this.setOptions(arguments[1]);
44 this.stepsLeft = this.options.steps;
45 this.duration = this.options.duration;
47 setOptions: function(options){
48 this.options = Object.extend({
51 rate: function(steps){ return steps;}
54 play: function(effect) {
55 this.setOptions(arguments[1]);
58 this.reset(effect, arguments[1]);
60 $H(effect).keys().each((function(e){
61 var effectClass = {fadeOut:Rico.Effect.FadeOut}[e];
62 this.reset(new effectClass(effect[e]));
69 if (this.timer) clearTimeout(this.timer);
71 if (this.effect && this.effect.finish) this.effect.finish();
72 if (this.options.onFinish) this.options.onFinish();
78 this.interupt = false;
79 if (this.stepsLeft >0)
85 if (this.stepsLeft <=0) {
89 if (this.timer) clearTimeout(this.timer);
90 this.effect.step(this.options.rate(this.stepsLeft));
93 startNextStep: function() {
94 var stepDuration = Math.round(this.duration/this.stepsLeft) ;
95 this.duration -= stepDuration;
97 this.timer = setTimeout(this.animateMethod, stepDuration);
99 isPlaying: function(){
100 return this.stepsLeft != 0 && !this.interupt;
104 Rico.Effect.Group = Class.create(
105 /** @lends Rico.Effect.Group# */
108 * @class Class to assist in applying an effect to a group of objects.
111 initialize: function(effects){
112 this.effects = effects;
114 step: function(stepsToGo){
115 this.effects.each(function(e){e.step(stepsToGo);});
118 this.effects.each(function(e){if (e.finish) e.finish();});
122 Rico.Effect.SizeAndPosition = Class.create(
123 /** @lends Rico.Effect.SizeAndPosition# */
126 * @class Animate size and position
129 initialize: function(element, x, y, w, h) {
130 Object.extend(this, new Rico.Effect.SizeAndPositionFade(element, x, y, w, h));
134 Rico.Effect.SizeAndPositionFade = Class.create(
135 /** @lends Rico.Effect.SizeAndPositionFade# */
141 initialize: function(element, x, y, w, h, value) {
142 this.element = $(element);
143 this.x = typeof(x)=='number' ? x : this.element.offsetLeft;
144 this.y = typeof(y)=='number' ? y : this.element.offsetTop;
145 if (!Prototype.Browser.IE || (document.compatMode && document.compatMode.indexOf("CSS")!=-1)) {
146 this.pw = RicoUtil.nan2zero(Element.getStyle(this.element,'padding-left'))+RicoUtil.nan2zero(Element.getStyle(this.element,'padding-right'));
147 this.pw += RicoUtil.nan2zero(Element.getStyle(this.element,'border-left-width'))+RicoUtil.nan2zero(Element.getStyle(this.element,'border-right-width'));
148 this.ph = RicoUtil.nan2zero(Element.getStyle(this.element,'padding-top'))+RicoUtil.nan2zero(Element.getStyle(this.element,'padding-bottom'));
149 this.ph += RicoUtil.nan2zero(Element.getStyle(this.element,'border-top-width'))+RicoUtil.nan2zero(Element.getStyle(this.element,'border-bottom-width'));
154 this.w = typeof(w)=='number' ? w : this.element.offsetWidth;
155 this.h = typeof(h)=='number' ? h : this.element.offsetHeight;
156 this.opacity = Element.getStyle(this.element, 'opacity') || 1.0;
157 this.target = arguments.length > 5 ? Math.min(value, 1.0) : this.opacity;
159 step: function(stepsToGo) {
160 var left = this.element.offsetLeft + ((this.x - this.element.offsetLeft)/stepsToGo);
161 var top = this.element.offsetTop + ((this.y - this.element.offsetTop)/stepsToGo);
162 var width = this.element.offsetWidth + ((this.w - this.element.offsetWidth)/stepsToGo) - this.pw;
163 var height = this.element.offsetHeight + ((this.h - this.element.offsetHeight)/stepsToGo) - this.ph;
164 var style = this.element.style;
165 var curOpacity = Element.getStyle(this.element, 'opacity');
166 var newOpacity = curOpacity + (this.target - curOpacity) / stepsToGo;
167 Rico.Effect.setOpacity(this.element, Math.min(Math.max(0,newOpacity),1.0));
168 style.left = left + "px";
169 style.top = top + "px";
170 style.width = width + "px";
171 style.height = height + "px";
175 Rico.AccordionEffect = Class.create(
176 /** @lends Rico.Effect.AccordionEffect# */
182 initialize: function(toClose, toOpen, height) {
183 this.toClose = toClose;
184 this.toOpen = toOpen;
185 toOpen.style.height = "0px";
186 Element.show(toOpen);
187 Element.makeClipping(toOpen);
188 Element.makeClipping(toClose);
189 Rico.Controls.disableNativeControls(toClose);
190 this.endHeight = height;
192 step: function(framesLeft) {
193 var cHeight = Math.max(1,this.toClose.offsetHeight - parseInt((parseInt(this.toClose.offsetHeight,10))/framesLeft,10));
194 var closeHeight = cHeight + "px";
195 var openHeight = (this.endHeight - cHeight) + "px";
196 this.toClose.style.height = closeHeight;
197 this.toOpen.style.height = openHeight;
200 Element.hide(this.toClose);
201 this.toOpen.style.height = this.endHeight + "px";
202 this.toClose.style.height = "0px";
203 Element.undoClipping(this.toOpen);
204 Element.undoClipping(this.toClose);
205 Rico.Controls.enableNativeControls(this.toOpen);
209 Rico.Effect.SizeFromBottom = Class.create(
210 /** @lends Rico.Effect.SizeFromBottom# */
216 initialize: function(element, y, h) {
217 this.element = $(element);
218 this.y = typeof(y)=='number' ? y : this.element.offsetTop;
219 this.h = typeof(h)=='number' ? h : this.element.offsetHeight;
220 this.options = arguments[3] || {};
222 step: function(framesToGo) {
223 var top = this.element.offsetTop + ((this.y - this.element.offsetTop)/framesToGo) + "px";
224 var height = this.element.offsetHeight + ((this.h - this.element.offsetHeight)/framesToGo) + "px";
225 var style = this.element.style;
226 style.height = height;
231 Rico.Effect.Position = Class.create(
232 /** @lends Rico.Effect.Position# */
238 initialize: function(element, x, y) {
239 this.element = $(element);
240 this.x = typeof(x)=='number' ? x : this.element.offsetLeft;
241 this.destTop = typeof(y)=='number' ? y : this.element.offsetTop;
243 step: function(stepsToGo) {
244 var left = this.element.offsetLeft + ((this.x - this.element.offsetLeft)/stepsToGo) + "px";
245 var top = this.element.offsetTop + ((this.destTop - this.element.offsetTop)/stepsToGo) + "px";
246 var style = this.element.style;
252 Rico.Effect.FadeTo = Class.create(
253 /** @lends Rico.Effect.FadeTo# */
259 initialize: function(element, value){
260 this.element = element;
261 this.opacity = Element.getStyle(this.element, 'opacity') || 1.0;
262 this.target = Math.min(value, 1.0);
264 step: function(framesLeft) {
265 var curOpacity = Element.getStyle(this.element, 'opacity');
266 var newOpacity = curOpacity + (this.target - curOpacity)/framesLeft;
267 Rico.Effect.setOpacity(this.element, Math.min(Math.max(0,newOpacity),1.0));
271 Rico.Effect.FadeOut = Class.create(
272 /** @lends Rico.Effect.FadeOut# */
278 initialize: function(element){
279 this.effect = new Rico.Effect.FadeTo(element, 0.0);
281 step: function(framesLeft) {
282 this.effect.step(framesLeft);
286 Rico.Effect.FadeIn = Class.create(
287 /** @lends Rico.Effect.FadeIn# */
293 initialize: function(element){
294 var options = arguments[1] || {};
295 var startValue = options.startValue || 0;
296 Rico.Effect.setOpacity(element, startValue);
297 this.effect = new Rico.Effect.FadeTo(element, 1.0);
299 step: function(framesLeft) {
300 this.effect.step(framesLeft);
304 Rico.Effect.setOpacity= function(element, value) {
305 if (element.setOpacity) {
306 element.setOpacity(value); // use prototype function
308 element.style.filter = "alpha(opacity="+Math.round(value*100)+")";
309 element.style.opacity = value;
313 Rico.Effect.SizeFromTop = Class.create(
314 /** @lends Rico.Effect.SizeFromTop# */
320 initialize: function(element, scrollElement, y, h) {
321 this.element = $(element);
322 this.h = typeof(h)=='number' ? h : this.element.offsetHeight;
323 // element.style.top = y;
324 this.scrollElement = scrollElement;
325 this.options = arguments[4] || {};
326 this.baseHeight = this.options.baseHeight || Math.max(this.h, this.element.offsetHeight);
328 step: function(framesToGo) {
329 var rawHeight = this.element.offsetHeight + ((this.h - this.element.offsetHeight)/framesToGo);
330 var height = rawHeight + "px";
331 var scroll = (rawHeight - this.baseHeight) + "px";
332 this.scrollElement.style.top = scroll;
333 this.element.style.height = height;
338 Rico.Effect.Height = Class.create(
339 /** @lends Rico.Effect.Height# */
345 initialize: function(element, endHeight) {
346 this.element = element;
347 this.endHeight = endHeight;
349 step: function(stepsLeft) {
351 if (this.element.constructor != Array){
352 height = this.element.offsetHeight + ((this.endHeight - this.element.offsetHeight)/stepsLeft) + "px";
353 this.element.style.height = height;
355 height = this.element[0].offsetHeight + ((this.endHeight - this.element[0].offsetHeight)/stepsLeft) + "px";
356 this.element.each(function(e){e.style.height = height;});
361 Rico.Effect.SizeWidth = Class.create(
362 /** @lends Rico.Effect.SizeWidth# */
368 initialize: function(element, endWidth) {
369 this.element = element;
370 this.endWidth = endWidth;
372 step: function(stepsLeft) {
373 var delta = Math.abs(this.endWidth - parseInt(this.element.offsetWidth,10))/(stepsLeft);
374 this.element.style.width = (this.element.offsetWidth - delta) + "px";
380 * these are to support non Safari browsers and keep controls from bleeding through on absolute positioned element.
386 disableNativeControls: function(element) {
387 Rico.Controls.defaultDisabler.disableNative(element);
389 enableNativeControls: function(element){
390 Rico.Controls.defaultDisabler.enableNative(element);
392 prepareForSizing: function(element){
393 Element.makeClipping(element);
394 Rico.Controls.disableNativeControls(element);
396 resetSizing: function(element){
397 Element.undoClipping(element);
398 Rico.Controls.enableNativeControls(element);
400 registerScrollSelectors: function(selectorSet) {
401 selectorSet.each(function(s){Rico.Controls.scrollSelectors.push(Rico.selector(s));});
405 Rico.Controls.Disabler = Class.create(
406 /** @lends Rico.Controls.Disabler# */
412 initialize: function(){
413 this.options = Object.extend({
415 hidables: Rico.Controls.editors
416 }, arguments[0] || {});
418 disableNative: function(element) {
419 if (!(/Konqueror|Safari|KHTML/.test(navigator.userAgent))){
420 if (!navigator.appVersion.match(/\bMSIE\b/))
421 this.blockControls(element).each(function(e){Element.makeClipping(e);});
423 this.hidableControls(element).each(function(e){e.disable();});
426 enableNative: function(element){
427 if (!(/Konqueror|Safari|KHTML/.test(navigator.userAgent))){
428 if (!navigator.appVersion.match(/\bMSIE\b/))
429 this.blockControls(element).each(function(e){Element.undoClipping(e);});
431 this.hidableControls(element).each(function(e){e.enable();});
434 blockControls: function(element){
437 if (this.options.includeSet)
438 includes = this.options.includeSet;
440 var selectors = this.options.includeSelectors || Rico.Controls.scrollSelectors;
441 includes = selectors.map(function(s){return s.findAll(element);}).flatten();
443 return includes.select(function(e){return (Element.getStyle(e, 'display') != 'none') && !this.options.excludeSet.include(e);}.bind(this));
444 } catch(e) { return []; }
446 hidableControls: function(element){
448 return this.options.hidables.select(function(e){return Element.childOf(e, element);});
450 return this.options.hidables;
454 Rico.Controls.defaultDisabler = new Rico.Controls.Disabler();
455 Rico.Controls.blankDisabler = new Rico.Controls.Disabler({includeSet:[],hidables:[]});
457 Rico.Controls.HidableInput = Class.create(
458 /** @lends Rico.Controls.HidableInput# */
464 initialize: function(field, view){
468 Rico.Controls.editors.push(this);
471 Element.hide(this.view);
472 Element.show(this.field);
475 this.view.value = $F(this.field);
476 if (this.field.offsetWidth > 1) {
477 this.view.style.width = parseInt(this.field.offsetWidth,10) + "px";
478 Element.hide(this.field);
479 Element.show(this.view);
487 Element.forceRefresh = function(item) {
489 var n = document.createTextNode(' ');
490 item.appendChild(n); item.removeChild(n);
494 Rico.includeLoaded('ricoEffects.js');