mirror of
https://github.com/Dolibarr/dolibarr.git
synced 2025-12-17 15:01:26 +01:00
Début ajout de tooltips "Prototip", essai en cours sur les lignes produits d'une propale, ce tooltip est actif et montre la description produit lorsque cette dernière est désactivée en visualisation dans les formulaires.
1094 lines
37 KiB
JavaScript
1094 lines
37 KiB
JavaScript
// script.aculo.us effects.js v1.7.1_beta3, Fri May 25 17:19:41 +0200 2007
|
|
|
|
// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
|
|
// Contributors:
|
|
// Justin Palmer (http://encytemedia.com/)
|
|
// Mark Pilgrim (http://diveintomark.org/)
|
|
// Martin Bialasinki
|
|
//
|
|
// script.aculo.us is freely distributable under the terms of an MIT-style license.
|
|
// For details, see the script.aculo.us web site: http://script.aculo.us/
|
|
|
|
// converts rgb() and #xxx to #xxxxxx format,
|
|
// returns self (or first argument) if not convertable
|
|
String.prototype.parseColor = function() {
|
|
var color = '#';
|
|
if(this.slice(0,4) == 'rgb(') {
|
|
var cols = this.slice(4,this.length-1).split(',');
|
|
var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
|
|
} else {
|
|
if(this.slice(0,1) == '#') {
|
|
if(this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
|
|
if(this.length==7) color = this.toLowerCase();
|
|
}
|
|
}
|
|
return(color.length==7 ? color : (arguments[0] || this));
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
Element.collectTextNodes = function(element) {
|
|
return $A($(element).childNodes).collect( function(node) {
|
|
return (node.nodeType==3 ? node.nodeValue :
|
|
(node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
|
|
}).flatten().join('');
|
|
}
|
|
|
|
Element.collectTextNodesIgnoreClass = function(element, className) {
|
|
return $A($(element).childNodes).collect( function(node) {
|
|
return (node.nodeType==3 ? node.nodeValue :
|
|
((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
|
|
Element.collectTextNodesIgnoreClass(node, className) : ''));
|
|
}).flatten().join('');
|
|
}
|
|
|
|
Element.setContentZoom = function(element, percent) {
|
|
element = $(element);
|
|
element.setStyle({fontSize: (percent/100) + 'em'});
|
|
if(Prototype.Browser.WebKit) window.scrollBy(0,0);
|
|
return element;
|
|
}
|
|
|
|
Element.getInlineOpacity = function(element){
|
|
return $(element).style.opacity || '';
|
|
}
|
|
|
|
Element.forceRerendering = function(element) {
|
|
try {
|
|
element = $(element);
|
|
var n = document.createTextNode(' ');
|
|
element.appendChild(n);
|
|
element.removeChild(n);
|
|
} catch(e) { }
|
|
};
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
Array.prototype.call = function() {
|
|
var args = arguments;
|
|
this.each(function(f){ f.apply(this, args) });
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
var Effect = {
|
|
_elementDoesNotExistError: {
|
|
name: 'ElementDoesNotExistError',
|
|
message: 'The specified DOM element does not exist, but is required for this effect to operate'
|
|
},
|
|
tagifyText: function(element) {
|
|
if(typeof Builder == 'undefined')
|
|
throw("Effect.tagifyText requires including script.aculo.us' builder.js library");
|
|
|
|
var tagifyStyle = 'position:relative';
|
|
if(Prototype.Browser.IE) tagifyStyle += ';zoom:1';
|
|
|
|
element = $(element);
|
|
$A(element.childNodes).each( function(child) {
|
|
if(child.nodeType==3) {
|
|
child.nodeValue.toArray().each( function(character) {
|
|
element.insertBefore(
|
|
Builder.node('span',{style: tagifyStyle},
|
|
character == ' ' ? String.fromCharCode(160) : character),
|
|
child);
|
|
});
|
|
Element.remove(child);
|
|
}
|
|
});
|
|
},
|
|
multiple: function(element, effect) {
|
|
var elements;
|
|
if(((typeof element == 'object') ||
|
|
(typeof element == 'function')) &&
|
|
(element.length))
|
|
elements = element;
|
|
else
|
|
elements = $(element).childNodes;
|
|
|
|
var options = Object.extend({
|
|
speed: 0.1,
|
|
delay: 0.0
|
|
}, arguments[2] || {});
|
|
var masterDelay = options.delay;
|
|
|
|
$A(elements).each( function(element, index) {
|
|
new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
|
|
});
|
|
},
|
|
PAIRS: {
|
|
'slide': ['SlideDown','SlideUp'],
|
|
'blind': ['BlindDown','BlindUp'],
|
|
'appear': ['Appear','Fade']
|
|
},
|
|
toggle: function(element, effect) {
|
|
element = $(element);
|
|
effect = (effect || 'appear').toLowerCase();
|
|
var options = Object.extend({
|
|
queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
|
|
}, arguments[2] || {});
|
|
Effect[element.visible() ?
|
|
Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
|
|
}
|
|
};
|
|
|
|
var Effect2 = Effect; // deprecated
|
|
|
|
/* ------------- transitions ------------- */
|
|
|
|
Effect.Transitions = {
|
|
linear: Prototype.K,
|
|
sinoidal: function(pos) {
|
|
return (-Math.cos(pos*Math.PI)/2) + 0.5;
|
|
},
|
|
reverse: function(pos) {
|
|
return 1-pos;
|
|
},
|
|
flicker: function(pos) {
|
|
var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
|
|
return (pos > 1 ? 1 : pos);
|
|
},
|
|
wobble: function(pos) {
|
|
return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
|
|
},
|
|
pulse: function(pos, pulses) {
|
|
pulses = pulses || 5;
|
|
return (
|
|
Math.round((pos % (1/pulses)) * pulses) == 0 ?
|
|
((pos * pulses * 2) - Math.floor(pos * pulses * 2)) :
|
|
1 - ((pos * pulses * 2) - Math.floor(pos * pulses * 2))
|
|
);
|
|
},
|
|
none: function(pos) {
|
|
return 0;
|
|
},
|
|
full: function(pos) {
|
|
return 1;
|
|
}
|
|
};
|
|
|
|
/* ------------- core effects ------------- */
|
|
|
|
Effect.ScopedQueue = Class.create();
|
|
Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), {
|
|
initialize: function() {
|
|
this.effects = [];
|
|
this.interval = null;
|
|
},
|
|
_each: function(iterator) {
|
|
this.effects._each(iterator);
|
|
},
|
|
add: function(effect) {
|
|
var timestamp = new Date().getTime();
|
|
|
|
var position = (typeof effect.options.queue == 'string') ?
|
|
effect.options.queue : effect.options.queue.position;
|
|
|
|
switch(position) {
|
|
case 'front':
|
|
// move unstarted effects after this effect
|
|
this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
|
|
e.startOn += effect.finishOn;
|
|
e.finishOn += effect.finishOn;
|
|
});
|
|
break;
|
|
case 'with-last':
|
|
timestamp = this.effects.pluck('startOn').max() || timestamp;
|
|
break;
|
|
case 'end':
|
|
// start effect after last queued effect has finished
|
|
timestamp = this.effects.pluck('finishOn').max() || timestamp;
|
|
break;
|
|
}
|
|
|
|
effect.startOn += timestamp;
|
|
effect.finishOn += timestamp;
|
|
|
|
if(!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
|
|
this.effects.push(effect);
|
|
|
|
if(!this.interval)
|
|
this.interval = setInterval(this.loop.bind(this), 15);
|
|
},
|
|
remove: function(effect) {
|
|
this.effects = this.effects.reject(function(e) { return e==effect });
|
|
if(this.effects.length == 0) {
|
|
clearInterval(this.interval);
|
|
this.interval = null;
|
|
}
|
|
},
|
|
loop: function() {
|
|
var timePos = new Date().getTime();
|
|
for(var i=0, len=this.effects.length;i<len;i++)
|
|
this.effects[i] && this.effects[i].loop(timePos);
|
|
}
|
|
});
|
|
|
|
Effect.Queues = {
|
|
instances: $H(),
|
|
get: function(queueName) {
|
|
if(typeof queueName != 'string') return queueName;
|
|
|
|
if(!this.instances[queueName])
|
|
this.instances[queueName] = new Effect.ScopedQueue();
|
|
|
|
return this.instances[queueName];
|
|
}
|
|
}
|
|
Effect.Queue = Effect.Queues.get('global');
|
|
|
|
Effect.DefaultOptions = {
|
|
transition: Effect.Transitions.sinoidal,
|
|
duration: 1.0, // seconds
|
|
fps: 100, // 100= assume 66fps max.
|
|
sync: false, // true for combining
|
|
from: 0.0,
|
|
to: 1.0,
|
|
delay: 0.0,
|
|
queue: 'parallel'
|
|
}
|
|
|
|
Effect.Base = function() {};
|
|
Effect.Base.prototype = {
|
|
position: null,
|
|
start: function(options) {
|
|
function codeForEvent(options,eventName){
|
|
return (
|
|
(options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
|
|
(options[eventName] ? 'this.options.'+eventName+'(this);' : '')
|
|
);
|
|
}
|
|
if(options.transition === false) options.transition = Effect.Transitions.linear;
|
|
this.options = Object.extend(Object.extend({},Effect.DefaultOptions), options || {});
|
|
this.currentFrame = 0;
|
|
this.state = 'idle';
|
|
this.startOn = this.options.delay*1000;
|
|
this.finishOn = this.startOn+(this.options.duration*1000);
|
|
this.fromToDelta = this.options.to-this.options.from;
|
|
this.totalTime = this.finishOn-this.startOn;
|
|
this.totalFrames = this.options.fps*this.options.duration;
|
|
|
|
eval('this.render = function(pos){ '+
|
|
'if(this.state=="idle"){this.state="running";'+
|
|
codeForEvent(options,'beforeSetup')+
|
|
(this.setup ? 'this.setup();':'')+
|
|
codeForEvent(options,'afterSetup')+
|
|
'};if(this.state=="running"){'+
|
|
'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+
|
|
'this.position=pos;'+
|
|
codeForEvent(options,'beforeUpdate')+
|
|
(this.update ? 'this.update(pos);':'')+
|
|
codeForEvent(options,'afterUpdate')+
|
|
'}}');
|
|
|
|
this.event('beforeStart');
|
|
if(!this.options.sync)
|
|
Effect.Queues.get(typeof this.options.queue == 'string' ?
|
|
'global' : this.options.queue.scope).add(this);
|
|
},
|
|
loop: function(timePos) {
|
|
if(timePos >= this.startOn) {
|
|
if(timePos >= this.finishOn) {
|
|
this.render(1.0);
|
|
this.cancel();
|
|
this.event('beforeFinish');
|
|
if(this.finish) this.finish();
|
|
this.event('afterFinish');
|
|
return;
|
|
}
|
|
var pos = (timePos - this.startOn) / this.totalTime,
|
|
frame = Math.round(pos * this.totalFrames);
|
|
if(frame > this.currentFrame) {
|
|
this.render(pos);
|
|
this.currentFrame = frame;
|
|
}
|
|
}
|
|
},
|
|
cancel: function() {
|
|
if(!this.options.sync)
|
|
Effect.Queues.get(typeof this.options.queue == 'string' ?
|
|
'global' : this.options.queue.scope).remove(this);
|
|
this.state = 'finished';
|
|
},
|
|
event: function(eventName) {
|
|
if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
|
|
if(this.options[eventName]) this.options[eventName](this);
|
|
},
|
|
inspect: function() {
|
|
var data = $H();
|
|
for(property in this)
|
|
if(typeof this[property] != 'function') data[property] = this[property];
|
|
return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
|
|
}
|
|
}
|
|
|
|
Effect.Parallel = Class.create();
|
|
Object.extend(Object.extend(Effect.Parallel.prototype, Effect.Base.prototype), {
|
|
initialize: function(effects) {
|
|
this.effects = effects || [];
|
|
this.start(arguments[1]);
|
|
},
|
|
update: function(position) {
|
|
this.effects.invoke('render', position);
|
|
},
|
|
finish: function(position) {
|
|
this.effects.each( function(effect) {
|
|
effect.render(1.0);
|
|
effect.cancel();
|
|
effect.event('beforeFinish');
|
|
if(effect.finish) effect.finish(position);
|
|
effect.event('afterFinish');
|
|
});
|
|
}
|
|
});
|
|
|
|
Effect.Event = Class.create();
|
|
Object.extend(Object.extend(Effect.Event.prototype, Effect.Base.prototype), {
|
|
initialize: function() {
|
|
var options = Object.extend({
|
|
duration: 0
|
|
}, arguments[0] || {});
|
|
this.start(options);
|
|
},
|
|
update: Prototype.emptyFunction
|
|
});
|
|
|
|
Effect.Opacity = Class.create();
|
|
Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), {
|
|
initialize: function(element) {
|
|
this.element = $(element);
|
|
if(!this.element) throw(Effect._elementDoesNotExistError);
|
|
// make this work on IE on elements without 'layout'
|
|
if(Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
|
|
this.element.setStyle({zoom: 1});
|
|
var options = Object.extend({
|
|
from: this.element.getOpacity() || 0.0,
|
|
to: 1.0
|
|
}, arguments[1] || {});
|
|
this.start(options);
|
|
},
|
|
update: function(position) {
|
|
this.element.setOpacity(position);
|
|
}
|
|
});
|
|
|
|
Effect.Move = Class.create();
|
|
Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), {
|
|
initialize: function(element) {
|
|
this.element = $(element);
|
|
if(!this.element) throw(Effect._elementDoesNotExistError);
|
|
var options = Object.extend({
|
|
x: 0,
|
|
y: 0,
|
|
mode: 'relative'
|
|
}, arguments[1] || {});
|
|
this.start(options);
|
|
},
|
|
setup: function() {
|
|
// Bug in Opera: Opera returns the "real" position of a static element or
|
|
// relative element that does not have top/left explicitly set.
|
|
// ==> Always set top and left for position relative elements in your stylesheets
|
|
// (to 0 if you do not need them)
|
|
this.element.makePositioned();
|
|
this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
|
|
this.originalTop = parseFloat(this.element.getStyle('top') || '0');
|
|
if(this.options.mode == 'absolute') {
|
|
// absolute movement, so we need to calc deltaX and deltaY
|
|
this.options.x = this.options.x - this.originalLeft;
|
|
this.options.y = this.options.y - this.originalTop;
|
|
}
|
|
},
|
|
update: function(position) {
|
|
this.element.setStyle({
|
|
left: Math.round(this.options.x * position + this.originalLeft) + 'px',
|
|
top: Math.round(this.options.y * position + this.originalTop) + 'px'
|
|
});
|
|
}
|
|
});
|
|
|
|
// for backwards compatibility
|
|
Effect.MoveBy = function(element, toTop, toLeft) {
|
|
return new Effect.Move(element,
|
|
Object.extend({ x: toLeft, y: toTop }, arguments[3] || {}));
|
|
};
|
|
|
|
Effect.Scale = Class.create();
|
|
Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), {
|
|
initialize: function(element, percent) {
|
|
this.element = $(element);
|
|
if(!this.element) throw(Effect._elementDoesNotExistError);
|
|
var options = Object.extend({
|
|
scaleX: true,
|
|
scaleY: true,
|
|
scaleContent: true,
|
|
scaleFromCenter: false,
|
|
scaleMode: 'box', // 'box' or 'contents' or {} with provided values
|
|
scaleFrom: 100.0,
|
|
scaleTo: percent
|
|
}, arguments[2] || {});
|
|
this.start(options);
|
|
},
|
|
setup: function() {
|
|
this.restoreAfterFinish = this.options.restoreAfterFinish || false;
|
|
this.elementPositioning = this.element.getStyle('position');
|
|
|
|
this.originalStyle = {};
|
|
['top','left','width','height','fontSize'].each( function(k) {
|
|
this.originalStyle[k] = this.element.style[k];
|
|
}.bind(this));
|
|
|
|
this.originalTop = this.element.offsetTop;
|
|
this.originalLeft = this.element.offsetLeft;
|
|
|
|
var fontSize = this.element.getStyle('font-size') || '100%';
|
|
['em','px','%','pt'].each( function(fontSizeType) {
|
|
if(fontSize.indexOf(fontSizeType)>0) {
|
|
this.fontSize = parseFloat(fontSize);
|
|
this.fontSizeType = fontSizeType;
|
|
}
|
|
}.bind(this));
|
|
|
|
this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
|
|
|
|
this.dims = null;
|
|
if(this.options.scaleMode=='box')
|
|
this.dims = [this.element.offsetHeight, this.element.offsetWidth];
|
|
if(/^content/.test(this.options.scaleMode))
|
|
this.dims = [this.element.scrollHeight, this.element.scrollWidth];
|
|
if(!this.dims)
|
|
this.dims = [this.options.scaleMode.originalHeight,
|
|
this.options.scaleMode.originalWidth];
|
|
},
|
|
update: function(position) {
|
|
var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
|
|
if(this.options.scaleContent && this.fontSize)
|
|
this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
|
|
this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
|
|
},
|
|
finish: function(position) {
|
|
if(this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
|
|
},
|
|
setDimensions: function(height, width) {
|
|
var d = {};
|
|
if(this.options.scaleX) d.width = Math.round(width) + 'px';
|
|
if(this.options.scaleY) d.height = Math.round(height) + 'px';
|
|
if(this.options.scaleFromCenter) {
|
|
var topd = (height - this.dims[0])/2;
|
|
var leftd = (width - this.dims[1])/2;
|
|
if(this.elementPositioning == 'absolute') {
|
|
if(this.options.scaleY) d.top = this.originalTop-topd + 'px';
|
|
if(this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
|
|
} else {
|
|
if(this.options.scaleY) d.top = -topd + 'px';
|
|
if(this.options.scaleX) d.left = -leftd + 'px';
|
|
}
|
|
}
|
|
this.element.setStyle(d);
|
|
}
|
|
});
|
|
|
|
Effect.Highlight = Class.create();
|
|
Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype), {
|
|
initialize: function(element) {
|
|
this.element = $(element);
|
|
if(!this.element) throw(Effect._elementDoesNotExistError);
|
|
var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || {});
|
|
this.start(options);
|
|
},
|
|
setup: function() {
|
|
// Prevent executing on elements not in the layout flow
|
|
if(this.element.getStyle('display')=='none') { this.cancel(); return; }
|
|
// Disable background image during the effect
|
|
this.oldStyle = {};
|
|
if (!this.options.keepBackgroundImage) {
|
|
this.oldStyle.backgroundImage = this.element.getStyle('background-image');
|
|
this.element.setStyle({backgroundImage: 'none'});
|
|
}
|
|
if(!this.options.endcolor)
|
|
this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
|
|
if(!this.options.restorecolor)
|
|
this.options.restorecolor = this.element.getStyle('background-color');
|
|
// init color calculations
|
|
this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
|
|
this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
|
|
},
|
|
update: function(position) {
|
|
this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
|
|
return m+(Math.round(this._base[i]+(this._delta[i]*position)).toColorPart()); }.bind(this)) });
|
|
},
|
|
finish: function() {
|
|
this.element.setStyle(Object.extend(this.oldStyle, {
|
|
backgroundColor: this.options.restorecolor
|
|
}));
|
|
}
|
|
});
|
|
|
|
Effect.ScrollTo = Class.create();
|
|
Object.extend(Object.extend(Effect.ScrollTo.prototype, Effect.Base.prototype), {
|
|
initialize: function(element) {
|
|
this.element = $(element);
|
|
this.start(arguments[1] || {});
|
|
},
|
|
setup: function() {
|
|
Position.prepare();
|
|
var offsets = Position.cumulativeOffset(this.element);
|
|
if(this.options.offset) offsets[1] += this.options.offset;
|
|
var max = window.innerHeight ?
|
|
window.height - window.innerHeight :
|
|
document.body.scrollHeight -
|
|
(document.documentElement.clientHeight ?
|
|
document.documentElement.clientHeight : document.body.clientHeight);
|
|
this.scrollStart = Position.deltaY;
|
|
this.delta = (offsets[1] > max ? max : offsets[1]) - this.scrollStart;
|
|
},
|
|
update: function(position) {
|
|
Position.prepare();
|
|
window.scrollTo(Position.deltaX,
|
|
this.scrollStart + (position*this.delta));
|
|
}
|
|
});
|
|
|
|
/* ------------- combination effects ------------- */
|
|
|
|
Effect.Fade = function(element) {
|
|
element = $(element);
|
|
var oldOpacity = element.getInlineOpacity();
|
|
var options = Object.extend({
|
|
from: element.getOpacity() || 1.0,
|
|
to: 0.0,
|
|
afterFinishInternal: function(effect) {
|
|
if(effect.options.to!=0) return;
|
|
effect.element.hide().setStyle({opacity: oldOpacity});
|
|
}}, arguments[1] || {});
|
|
return new Effect.Opacity(element,options);
|
|
}
|
|
|
|
Effect.Appear = function(element) {
|
|
element = $(element);
|
|
var options = Object.extend({
|
|
from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
|
|
to: 1.0,
|
|
// force Safari to render floated elements properly
|
|
afterFinishInternal: function(effect) {
|
|
effect.element.forceRerendering();
|
|
},
|
|
beforeSetup: function(effect) {
|
|
effect.element.setOpacity(effect.options.from).show();
|
|
}}, arguments[1] || {});
|
|
return new Effect.Opacity(element,options);
|
|
}
|
|
|
|
Effect.Puff = function(element) {
|
|
element = $(element);
|
|
var oldStyle = {
|
|
opacity: element.getInlineOpacity(),
|
|
position: element.getStyle('position'),
|
|
top: element.style.top,
|
|
left: element.style.left,
|
|
width: element.style.width,
|
|
height: element.style.height
|
|
};
|
|
return new Effect.Parallel(
|
|
[ new Effect.Scale(element, 200,
|
|
{ sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }),
|
|
new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
|
|
Object.extend({ duration: 1.0,
|
|
beforeSetupInternal: function(effect) {
|
|
Position.absolutize(effect.effects[0].element)
|
|
},
|
|
afterFinishInternal: function(effect) {
|
|
effect.effects[0].element.hide().setStyle(oldStyle); }
|
|
}, arguments[1] || {})
|
|
);
|
|
}
|
|
|
|
Effect.BlindUp = function(element) {
|
|
element = $(element);
|
|
element.makeClipping();
|
|
return new Effect.Scale(element, 0,
|
|
Object.extend({ scaleContent: false,
|
|
scaleX: false,
|
|
restoreAfterFinish: true,
|
|
afterFinishInternal: function(effect) {
|
|
effect.element.hide().undoClipping();
|
|
}
|
|
}, arguments[1] || {})
|
|
);
|
|
}
|
|
|
|
Effect.BlindDown = function(element) {
|
|
element = $(element);
|
|
var elementDimensions = element.getDimensions();
|
|
return new Effect.Scale(element, 100, Object.extend({
|
|
scaleContent: false,
|
|
scaleX: false,
|
|
scaleFrom: 0,
|
|
scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
|
|
restoreAfterFinish: true,
|
|
afterSetup: function(effect) {
|
|
effect.element.makeClipping().setStyle({height: '0px'}).show();
|
|
},
|
|
afterFinishInternal: function(effect) {
|
|
effect.element.undoClipping();
|
|
}
|
|
}, arguments[1] || {}));
|
|
}
|
|
|
|
Effect.SwitchOff = function(element) {
|
|
element = $(element);
|
|
var oldOpacity = element.getInlineOpacity();
|
|
return new Effect.Appear(element, Object.extend({
|
|
duration: 0.4,
|
|
from: 0,
|
|
transition: Effect.Transitions.flicker,
|
|
afterFinishInternal: function(effect) {
|
|
new Effect.Scale(effect.element, 1, {
|
|
duration: 0.3, scaleFromCenter: true,
|
|
scaleX: false, scaleContent: false, restoreAfterFinish: true,
|
|
beforeSetup: function(effect) {
|
|
effect.element.makePositioned().makeClipping();
|
|
},
|
|
afterFinishInternal: function(effect) {
|
|
effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
|
|
}
|
|
})
|
|
}
|
|
}, arguments[1] || {}));
|
|
}
|
|
|
|
Effect.DropOut = function(element) {
|
|
element = $(element);
|
|
var oldStyle = {
|
|
top: element.getStyle('top'),
|
|
left: element.getStyle('left'),
|
|
opacity: element.getInlineOpacity() };
|
|
return new Effect.Parallel(
|
|
[ new Effect.Move(element, {x: 0, y: 100, sync: true }),
|
|
new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
|
|
Object.extend(
|
|
{ duration: 0.5,
|
|
beforeSetup: function(effect) {
|
|
effect.effects[0].element.makePositioned();
|
|
},
|
|
afterFinishInternal: function(effect) {
|
|
effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
|
|
}
|
|
}, arguments[1] || {}));
|
|
}
|
|
|
|
Effect.Shake = function(element) {
|
|
element = $(element);
|
|
var oldStyle = {
|
|
top: element.getStyle('top'),
|
|
left: element.getStyle('left') };
|
|
return new Effect.Move(element,
|
|
{ x: 20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
|
|
new Effect.Move(effect.element,
|
|
{ x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
|
|
new Effect.Move(effect.element,
|
|
{ x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
|
|
new Effect.Move(effect.element,
|
|
{ x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
|
|
new Effect.Move(effect.element,
|
|
{ x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
|
|
new Effect.Move(effect.element,
|
|
{ x: -20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
|
|
effect.element.undoPositioned().setStyle(oldStyle);
|
|
}}) }}) }}) }}) }}) }});
|
|
}
|
|
|
|
Effect.SlideDown = function(element) {
|
|
element = $(element).cleanWhitespace();
|
|
// SlideDown need to have the content of the element wrapped in a container element with fixed height!
|
|
var oldInnerBottom = element.down().getStyle('bottom');
|
|
var elementDimensions = element.getDimensions();
|
|
return new Effect.Scale(element, 100, Object.extend({
|
|
scaleContent: false,
|
|
scaleX: false,
|
|
scaleFrom: window.opera ? 0 : 1,
|
|
scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
|
|
restoreAfterFinish: true,
|
|
afterSetup: function(effect) {
|
|
effect.element.makePositioned();
|
|
effect.element.down().makePositioned();
|
|
if(window.opera) effect.element.setStyle({top: ''});
|
|
effect.element.makeClipping().setStyle({height: '0px'}).show();
|
|
},
|
|
afterUpdateInternal: function(effect) {
|
|
effect.element.down().setStyle({bottom:
|
|
(effect.dims[0] - effect.element.clientHeight) + 'px' });
|
|
},
|
|
afterFinishInternal: function(effect) {
|
|
effect.element.undoClipping().undoPositioned();
|
|
effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
|
|
}, arguments[1] || {})
|
|
);
|
|
}
|
|
|
|
Effect.SlideUp = function(element) {
|
|
element = $(element).cleanWhitespace();
|
|
var oldInnerBottom = element.down().getStyle('bottom');
|
|
return new Effect.Scale(element, window.opera ? 0 : 1,
|
|
Object.extend({ scaleContent: false,
|
|
scaleX: false,
|
|
scaleMode: 'box',
|
|
scaleFrom: 100,
|
|
restoreAfterFinish: true,
|
|
beforeStartInternal: function(effect) {
|
|
effect.element.makePositioned();
|
|
effect.element.down().makePositioned();
|
|
if(window.opera) effect.element.setStyle({top: ''});
|
|
effect.element.makeClipping().show();
|
|
},
|
|
afterUpdateInternal: function(effect) {
|
|
effect.element.down().setStyle({bottom:
|
|
(effect.dims[0] - effect.element.clientHeight) + 'px' });
|
|
},
|
|
afterFinishInternal: function(effect) {
|
|
effect.element.hide().undoClipping().undoPositioned().setStyle({bottom: oldInnerBottom});
|
|
effect.element.down().undoPositioned();
|
|
}
|
|
}, arguments[1] || {})
|
|
);
|
|
}
|
|
|
|
// Bug in opera makes the TD containing this element expand for a instance after finish
|
|
Effect.Squish = function(element) {
|
|
return new Effect.Scale(element, window.opera ? 1 : 0, {
|
|
restoreAfterFinish: true,
|
|
beforeSetup: function(effect) {
|
|
effect.element.makeClipping();
|
|
},
|
|
afterFinishInternal: function(effect) {
|
|
effect.element.hide().undoClipping();
|
|
}
|
|
});
|
|
}
|
|
|
|
Effect.Grow = function(element) {
|
|
element = $(element);
|
|
var options = Object.extend({
|
|
direction: 'center',
|
|
moveTransition: Effect.Transitions.sinoidal,
|
|
scaleTransition: Effect.Transitions.sinoidal,
|
|
opacityTransition: Effect.Transitions.full
|
|
}, arguments[1] || {});
|
|
var oldStyle = {
|
|
top: element.style.top,
|
|
left: element.style.left,
|
|
height: element.style.height,
|
|
width: element.style.width,
|
|
opacity: element.getInlineOpacity() };
|
|
|
|
var dims = element.getDimensions();
|
|
var initialMoveX, initialMoveY;
|
|
var moveX, moveY;
|
|
|
|
switch (options.direction) {
|
|
case 'top-left':
|
|
initialMoveX = initialMoveY = moveX = moveY = 0;
|
|
break;
|
|
case 'top-right':
|
|
initialMoveX = dims.width;
|
|
initialMoveY = moveY = 0;
|
|
moveX = -dims.width;
|
|
break;
|
|
case 'bottom-left':
|
|
initialMoveX = moveX = 0;
|
|
initialMoveY = dims.height;
|
|
moveY = -dims.height;
|
|
break;
|
|
case 'bottom-right':
|
|
initialMoveX = dims.width;
|
|
initialMoveY = dims.height;
|
|
moveX = -dims.width;
|
|
moveY = -dims.height;
|
|
break;
|
|
case 'center':
|
|
initialMoveX = dims.width / 2;
|
|
initialMoveY = dims.height / 2;
|
|
moveX = -dims.width / 2;
|
|
moveY = -dims.height / 2;
|
|
break;
|
|
}
|
|
|
|
return new Effect.Move(element, {
|
|
x: initialMoveX,
|
|
y: initialMoveY,
|
|
duration: 0.01,
|
|
beforeSetup: function(effect) {
|
|
effect.element.hide().makeClipping().makePositioned();
|
|
},
|
|
afterFinishInternal: function(effect) {
|
|
new Effect.Parallel(
|
|
[ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
|
|
new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
|
|
new Effect.Scale(effect.element, 100, {
|
|
scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
|
|
sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
|
|
], Object.extend({
|
|
beforeSetup: function(effect) {
|
|
effect.effects[0].element.setStyle({height: '0px'}).show();
|
|
},
|
|
afterFinishInternal: function(effect) {
|
|
effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
|
|
}
|
|
}, options)
|
|
)
|
|
}
|
|
});
|
|
}
|
|
|
|
Effect.Shrink = function(element) {
|
|
element = $(element);
|
|
var options = Object.extend({
|
|
direction: 'center',
|
|
moveTransition: Effect.Transitions.sinoidal,
|
|
scaleTransition: Effect.Transitions.sinoidal,
|
|
opacityTransition: Effect.Transitions.none
|
|
}, arguments[1] || {});
|
|
var oldStyle = {
|
|
top: element.style.top,
|
|
left: element.style.left,
|
|
height: element.style.height,
|
|
width: element.style.width,
|
|
opacity: element.getInlineOpacity() };
|
|
|
|
var dims = element.getDimensions();
|
|
var moveX, moveY;
|
|
|
|
switch (options.direction) {
|
|
case 'top-left':
|
|
moveX = moveY = 0;
|
|
break;
|
|
case 'top-right':
|
|
moveX = dims.width;
|
|
moveY = 0;
|
|
break;
|
|
case 'bottom-left':
|
|
moveX = 0;
|
|
moveY = dims.height;
|
|
break;
|
|
case 'bottom-right':
|
|
moveX = dims.width;
|
|
moveY = dims.height;
|
|
break;
|
|
case 'center':
|
|
moveX = dims.width / 2;
|
|
moveY = dims.height / 2;
|
|
break;
|
|
}
|
|
|
|
return new Effect.Parallel(
|
|
[ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
|
|
new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
|
|
new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
|
|
], Object.extend({
|
|
beforeStartInternal: function(effect) {
|
|
effect.effects[0].element.makePositioned().makeClipping();
|
|
},
|
|
afterFinishInternal: function(effect) {
|
|
effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
|
|
}, options)
|
|
);
|
|
}
|
|
|
|
Effect.Pulsate = function(element) {
|
|
element = $(element);
|
|
var options = arguments[1] || {};
|
|
var oldOpacity = element.getInlineOpacity();
|
|
var transition = options.transition || Effect.Transitions.sinoidal;
|
|
var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) };
|
|
reverser.bind(transition);
|
|
return new Effect.Opacity(element,
|
|
Object.extend(Object.extend({ duration: 2.0, from: 0,
|
|
afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
|
|
}, options), {transition: reverser}));
|
|
}
|
|
|
|
Effect.Fold = function(element) {
|
|
element = $(element);
|
|
var oldStyle = {
|
|
top: element.style.top,
|
|
left: element.style.left,
|
|
width: element.style.width,
|
|
height: element.style.height };
|
|
element.makeClipping();
|
|
return new Effect.Scale(element, 5, Object.extend({
|
|
scaleContent: false,
|
|
scaleX: false,
|
|
afterFinishInternal: function(effect) {
|
|
new Effect.Scale(element, 1, {
|
|
scaleContent: false,
|
|
scaleY: false,
|
|
afterFinishInternal: function(effect) {
|
|
effect.element.hide().undoClipping().setStyle(oldStyle);
|
|
} });
|
|
}}, arguments[1] || {}));
|
|
};
|
|
|
|
Effect.Morph = Class.create();
|
|
Object.extend(Object.extend(Effect.Morph.prototype, Effect.Base.prototype), {
|
|
initialize: function(element) {
|
|
this.element = $(element);
|
|
if(!this.element) throw(Effect._elementDoesNotExistError);
|
|
var options = Object.extend({
|
|
style: {}
|
|
}, arguments[1] || {});
|
|
if (typeof options.style == 'string') {
|
|
if(options.style.indexOf(':') == -1) {
|
|
var cssText = '', selector = '.' + options.style;
|
|
$A(document.styleSheets).reverse().each(function(styleSheet) {
|
|
if (styleSheet.cssRules) cssRules = styleSheet.cssRules;
|
|
else if (styleSheet.rules) cssRules = styleSheet.rules;
|
|
$A(cssRules).reverse().each(function(rule) {
|
|
if (selector == rule.selectorText) {
|
|
cssText = rule.style.cssText;
|
|
throw $break;
|
|
}
|
|
});
|
|
if (cssText) throw $break;
|
|
});
|
|
this.style = cssText.parseStyle();
|
|
options.afterFinishInternal = function(effect){
|
|
effect.element.addClassName(effect.options.style);
|
|
effect.transforms.each(function(transform) {
|
|
if(transform.style != 'opacity')
|
|
effect.element.style[transform.style] = '';
|
|
});
|
|
}
|
|
} else this.style = options.style.parseStyle();
|
|
} else this.style = $H(options.style)
|
|
this.start(options);
|
|
},
|
|
setup: function(){
|
|
function parseColor(color){
|
|
if(!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
|
|
color = color.parseColor();
|
|
return $R(0,2).map(function(i){
|
|
return parseInt( color.slice(i*2+1,i*2+3), 16 )
|
|
});
|
|
}
|
|
this.transforms = this.style.map(function(pair){
|
|
var property = pair[0], value = pair[1], unit = null;
|
|
|
|
if(value.parseColor('#zzzzzz') != '#zzzzzz') {
|
|
value = value.parseColor();
|
|
unit = 'color';
|
|
} else if(property == 'opacity') {
|
|
value = parseFloat(value);
|
|
if(Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
|
|
this.element.setStyle({zoom: 1});
|
|
} else if(Element.CSS_LENGTH.test(value)) {
|
|
var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
|
|
value = parseFloat(components[1]);
|
|
unit = (components.length == 3) ? components[2] : null;
|
|
}
|
|
|
|
var originalValue = this.element.getStyle(property);
|
|
return {
|
|
style: property.camelize(),
|
|
originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
|
|
targetValue: unit=='color' ? parseColor(value) : value,
|
|
unit: unit
|
|
};
|
|
}.bind(this)).reject(function(transform){
|
|
return (
|
|
(transform.originalValue == transform.targetValue) ||
|
|
(
|
|
transform.unit != 'color' &&
|
|
(isNaN(transform.originalValue) || isNaN(transform.targetValue))
|
|
)
|
|
)
|
|
});
|
|
},
|
|
update: function(position) {
|
|
var style = {}, transform, i = this.transforms.length;
|
|
while(i--)
|
|
style[(transform = this.transforms[i]).style] =
|
|
transform.unit=='color' ? '#'+
|
|
(Math.round(transform.originalValue[0]+
|
|
(transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
|
|
(Math.round(transform.originalValue[1]+
|
|
(transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
|
|
(Math.round(transform.originalValue[2]+
|
|
(transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
|
|
transform.originalValue + Math.round(
|
|
((transform.targetValue - transform.originalValue) * position) * 1000)/1000 + transform.unit;
|
|
this.element.setStyle(style, true);
|
|
}
|
|
});
|
|
|
|
Effect.Transform = Class.create();
|
|
Object.extend(Effect.Transform.prototype, {
|
|
initialize: function(tracks){
|
|
this.tracks = [];
|
|
this.options = arguments[1] || {};
|
|
this.addTracks(tracks);
|
|
},
|
|
addTracks: function(tracks){
|
|
tracks.each(function(track){
|
|
var data = $H(track).values().first();
|
|
this.tracks.push($H({
|
|
ids: $H(track).keys().first(),
|
|
effect: Effect.Morph,
|
|
options: { style: data }
|
|
}));
|
|
}.bind(this));
|
|
return this;
|
|
},
|
|
play: function(){
|
|
return new Effect.Parallel(
|
|
this.tracks.map(function(track){
|
|
var elements = [$(track.ids) || $$(track.ids)].flatten();
|
|
return elements.map(function(e){ return new track.effect(e, Object.extend({ sync:true }, track.options)) });
|
|
}).flatten(),
|
|
this.options
|
|
);
|
|
}
|
|
});
|
|
|
|
Element.CSS_PROPERTIES = $w(
|
|
'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
|
|
'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
|
|
'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
|
|
'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
|
|
'fontSize fontWeight height left letterSpacing lineHeight ' +
|
|
'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
|
|
'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
|
|
'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
|
|
'right textIndent top width wordSpacing zIndex');
|
|
|
|
Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
|
|
|
|
String.prototype.parseStyle = function(){
|
|
var element = document.createElement('div');
|
|
element.innerHTML = '<div style="' + this + '"></div>';
|
|
var style = element.childNodes[0].style, styleRules = $H();
|
|
|
|
Element.CSS_PROPERTIES.each(function(property){
|
|
if(style[property]) styleRules[property] = style[property];
|
|
});
|
|
if(Prototype.Browser.IE && this.indexOf('opacity') > -1) {
|
|
styleRules.opacity = this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1];
|
|
}
|
|
return styleRules;
|
|
};
|
|
|
|
Element.morph = function(element, style) {
|
|
new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || {}));
|
|
return element;
|
|
};
|
|
|
|
['getInlineOpacity','forceRerendering','setContentZoom',
|
|
'collectTextNodes','collectTextNodesIgnoreClass','morph'].each(
|
|
function(f) { Element.Methods[f] = Element[f]; }
|
|
);
|
|
|
|
Element.Methods.visualEffect = function(element, effect, options) {
|
|
s = effect.dasherize().camelize();
|
|
effect_class = s.charAt(0).toUpperCase() + s.substring(1);
|
|
new Effect[effect_class](element, options);
|
|
return $(element);
|
|
};
|
|
|
|
Element.addMethods(); |