7a116201f7
The script that automatically adds the copyright notice was wrongly configured.
1977 lines
62 KiB
JavaScript
1977 lines
62 KiB
JavaScript
/***
|
|
|
|
MochiKit.Visual 1.5
|
|
|
|
See <http://mochikit.com/> for documentation, downloads, license, etc.
|
|
|
|
(c) 2005 Bob Ippolito and others. All rights Reserved.
|
|
|
|
***/
|
|
|
|
MochiKit.Base.module(MochiKit, 'Visual', '1.5', ['Base', 'DOM', 'Style', 'Color', 'Position']);
|
|
|
|
MochiKit.Visual._RoundCorners = function (e, options) {
|
|
e = MochiKit.DOM.getElement(e);
|
|
this._setOptions(options);
|
|
if (this.options.__unstable__wrapElement) {
|
|
e = this._doWrap(e);
|
|
}
|
|
|
|
var color = this.options.color;
|
|
var C = MochiKit.Color.Color;
|
|
if (this.options.color === "fromElement") {
|
|
color = C.fromBackground(e);
|
|
} else if (!(color instanceof C)) {
|
|
color = C.fromString(color);
|
|
}
|
|
this.isTransparent = (color.asRGB().a <= 0);
|
|
|
|
var bgColor = this.options.bgColor;
|
|
if (this.options.bgColor === "fromParent") {
|
|
bgColor = C.fromBackground(e.offsetParent);
|
|
} else if (!(bgColor instanceof C)) {
|
|
bgColor = C.fromString(bgColor);
|
|
}
|
|
|
|
this._roundCornersImpl(e, color, bgColor);
|
|
};
|
|
|
|
MochiKit.Visual._RoundCorners.prototype = {
|
|
_doWrap: function (e) {
|
|
var parent = e.parentNode;
|
|
var doc = MochiKit.DOM.currentDocument();
|
|
if (typeof(doc.defaultView) === "undefined"
|
|
|| doc.defaultView === null) {
|
|
return e;
|
|
}
|
|
var style = doc.defaultView.getComputedStyle(e, null);
|
|
if (typeof(style) === "undefined" || style === null) {
|
|
return e;
|
|
}
|
|
var wrapper = MochiKit.DOM.DIV({"style": {
|
|
display: "block",
|
|
// convert padding to margin
|
|
marginTop: style.getPropertyValue("padding-top"),
|
|
marginRight: style.getPropertyValue("padding-right"),
|
|
marginBottom: style.getPropertyValue("padding-bottom"),
|
|
marginLeft: style.getPropertyValue("padding-left"),
|
|
// remove padding so the rounding looks right
|
|
padding: "0px"
|
|
/*
|
|
paddingRight: "0px",
|
|
paddingLeft: "0px"
|
|
*/
|
|
}});
|
|
wrapper.innerHTML = e.innerHTML;
|
|
e.innerHTML = "";
|
|
e.appendChild(wrapper);
|
|
return e;
|
|
},
|
|
|
|
_roundCornersImpl: function (e, color, bgColor) {
|
|
if (this.options.border) {
|
|
this._renderBorder(e, bgColor);
|
|
}
|
|
if (this._isTopRounded()) {
|
|
this._roundTopCorners(e, color, bgColor);
|
|
}
|
|
if (this._isBottomRounded()) {
|
|
this._roundBottomCorners(e, color, bgColor);
|
|
}
|
|
},
|
|
|
|
_renderBorder: function (el, bgColor) {
|
|
var borderValue = "1px solid " + this._borderColor(bgColor);
|
|
var borderL = "border-left: " + borderValue;
|
|
var borderR = "border-right: " + borderValue;
|
|
var style = "style='" + borderL + ";" + borderR + "'";
|
|
el.innerHTML = "<div " + style + ">" + el.innerHTML + "</div>";
|
|
},
|
|
|
|
_roundTopCorners: function (el, color, bgColor) {
|
|
var corner = this._createCorner(bgColor);
|
|
for (var i = 0; i < this.options.numSlices; i++) {
|
|
corner.appendChild(
|
|
this._createCornerSlice(color, bgColor, i, "top")
|
|
);
|
|
}
|
|
el.style.paddingTop = 0;
|
|
el.insertBefore(corner, el.firstChild);
|
|
},
|
|
|
|
_roundBottomCorners: function (el, color, bgColor) {
|
|
var corner = this._createCorner(bgColor);
|
|
for (var i = (this.options.numSlices - 1); i >= 0; i--) {
|
|
corner.appendChild(
|
|
this._createCornerSlice(color, bgColor, i, "bottom")
|
|
);
|
|
}
|
|
el.style.paddingBottom = 0;
|
|
el.appendChild(corner);
|
|
},
|
|
|
|
_createCorner: function (bgColor) {
|
|
var dom = MochiKit.DOM;
|
|
return dom.DIV({style: {backgroundColor: bgColor.toString()}});
|
|
},
|
|
|
|
_createCornerSlice: function (color, bgColor, n, position) {
|
|
var slice = MochiKit.DOM.SPAN();
|
|
|
|
var inStyle = slice.style;
|
|
inStyle.backgroundColor = color.toString();
|
|
inStyle.display = "block";
|
|
inStyle.height = "1px";
|
|
inStyle.overflow = "hidden";
|
|
inStyle.fontSize = "1px";
|
|
|
|
var borderColor = this._borderColor(color, bgColor);
|
|
if (this.options.border && n === 0) {
|
|
inStyle.borderTopStyle = "solid";
|
|
inStyle.borderTopWidth = "1px";
|
|
inStyle.borderLeftWidth = "0px";
|
|
inStyle.borderRightWidth = "0px";
|
|
inStyle.borderBottomWidth = "0px";
|
|
// assumes css compliant box model
|
|
inStyle.height = "0px";
|
|
inStyle.borderColor = borderColor.toString();
|
|
} else if (borderColor) {
|
|
inStyle.borderColor = borderColor.toString();
|
|
inStyle.borderStyle = "solid";
|
|
inStyle.borderWidth = "0px 1px";
|
|
}
|
|
|
|
if (!this.options.compact && (n == (this.options.numSlices - 1))) {
|
|
inStyle.height = "2px";
|
|
}
|
|
|
|
this._setMargin(slice, n, position);
|
|
this._setBorder(slice, n, position);
|
|
|
|
return slice;
|
|
},
|
|
|
|
_setOptions: function (options) {
|
|
this.options = {
|
|
corners: "all",
|
|
color: "fromElement",
|
|
bgColor: "fromParent",
|
|
blend: true,
|
|
border: false,
|
|
compact: false,
|
|
__unstable__wrapElement: false
|
|
};
|
|
MochiKit.Base.update(this.options, options);
|
|
|
|
this.options.numSlices = (this.options.compact ? 2 : 4);
|
|
},
|
|
|
|
_whichSideTop: function () {
|
|
var corners = this.options.corners;
|
|
if (this._hasString(corners, "all", "top")) {
|
|
return "";
|
|
}
|
|
|
|
var has_tl = (corners.indexOf("tl") != -1);
|
|
var has_tr = (corners.indexOf("tr") != -1);
|
|
if (has_tl && has_tr) {
|
|
return "";
|
|
}
|
|
if (has_tl) {
|
|
return "left";
|
|
}
|
|
if (has_tr) {
|
|
return "right";
|
|
}
|
|
return "";
|
|
},
|
|
|
|
_whichSideBottom: function () {
|
|
var corners = this.options.corners;
|
|
if (this._hasString(corners, "all", "bottom")) {
|
|
return "";
|
|
}
|
|
|
|
var has_bl = (corners.indexOf('bl') != -1);
|
|
var has_br = (corners.indexOf('br') != -1);
|
|
if (has_bl && has_br) {
|
|
return "";
|
|
}
|
|
if (has_bl) {
|
|
return "left";
|
|
}
|
|
if (has_br) {
|
|
return "right";
|
|
}
|
|
return "";
|
|
},
|
|
|
|
_borderColor: function (color, bgColor) {
|
|
if (color == "transparent") {
|
|
return bgColor;
|
|
} else if (this.options.border) {
|
|
return this.options.border;
|
|
} else if (this.options.blend) {
|
|
return bgColor.blendedColor(color);
|
|
}
|
|
return "";
|
|
},
|
|
|
|
|
|
_setMargin: function (el, n, corners) {
|
|
var marginSize = this._marginSize(n) + "px";
|
|
var whichSide = (
|
|
corners == "top" ? this._whichSideTop() : this._whichSideBottom()
|
|
);
|
|
var style = el.style;
|
|
|
|
if (whichSide == "left") {
|
|
style.marginLeft = marginSize;
|
|
style.marginRight = "0px";
|
|
} else if (whichSide == "right") {
|
|
style.marginRight = marginSize;
|
|
style.marginLeft = "0px";
|
|
} else {
|
|
style.marginLeft = marginSize;
|
|
style.marginRight = marginSize;
|
|
}
|
|
},
|
|
|
|
_setBorder: function (el, n, corners) {
|
|
var borderSize = this._borderSize(n) + "px";
|
|
var whichSide = (
|
|
corners == "top" ? this._whichSideTop() : this._whichSideBottom()
|
|
);
|
|
|
|
var style = el.style;
|
|
if (whichSide == "left") {
|
|
style.borderLeftWidth = borderSize;
|
|
style.borderRightWidth = "0px";
|
|
} else if (whichSide == "right") {
|
|
style.borderRightWidth = borderSize;
|
|
style.borderLeftWidth = "0px";
|
|
} else {
|
|
style.borderLeftWidth = borderSize;
|
|
style.borderRightWidth = borderSize;
|
|
}
|
|
},
|
|
|
|
_marginSize: function (n) {
|
|
if (this.isTransparent) {
|
|
return 0;
|
|
}
|
|
|
|
var o = this.options;
|
|
if (o.compact && o.blend) {
|
|
var smBlendedMarginSizes = [1, 0];
|
|
return smBlendedMarginSizes[n];
|
|
} else if (o.compact) {
|
|
var compactMarginSizes = [2, 1];
|
|
return compactMarginSizes[n];
|
|
} else if (o.blend) {
|
|
var blendedMarginSizes = [3, 2, 1, 0];
|
|
return blendedMarginSizes[n];
|
|
} else {
|
|
var marginSizes = [5, 3, 2, 1];
|
|
return marginSizes[n];
|
|
}
|
|
},
|
|
|
|
_borderSize: function (n) {
|
|
var o = this.options;
|
|
var borderSizes;
|
|
if (o.compact && (o.blend || this.isTransparent)) {
|
|
return 1;
|
|
} else if (o.compact) {
|
|
borderSizes = [1, 0];
|
|
} else if (o.blend) {
|
|
borderSizes = [2, 1, 1, 1];
|
|
} else if (o.border) {
|
|
borderSizes = [0, 2, 0, 0];
|
|
} else if (this.isTransparent) {
|
|
borderSizes = [5, 3, 2, 1];
|
|
} else {
|
|
return 0;
|
|
}
|
|
return borderSizes[n];
|
|
},
|
|
|
|
_hasString: function (str) {
|
|
for (var i = 1; i< arguments.length; i++) {
|
|
if (str.indexOf(arguments[i]) != -1) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
},
|
|
|
|
_isTopRounded: function () {
|
|
return this._hasString(this.options.corners,
|
|
"all", "top", "tl", "tr"
|
|
);
|
|
},
|
|
|
|
_isBottomRounded: function () {
|
|
return this._hasString(this.options.corners,
|
|
"all", "bottom", "bl", "br"
|
|
);
|
|
},
|
|
|
|
_hasSingleTextChild: function (el) {
|
|
return (el.childNodes.length == 1 && el.childNodes[0].nodeType == 3);
|
|
}
|
|
};
|
|
|
|
/** @id MochiKit.Visual.roundElement */
|
|
MochiKit.Visual.roundElement = function (e, options) {
|
|
new MochiKit.Visual._RoundCorners(e, options);
|
|
};
|
|
|
|
/** @id MochiKit.Visual.roundClass */
|
|
MochiKit.Visual.roundClass = function (tagName, className, options) {
|
|
var elements = MochiKit.DOM.getElementsByTagAndClassName(
|
|
tagName, className
|
|
);
|
|
for (var i = 0; i < elements.length; i++) {
|
|
MochiKit.Visual.roundElement(elements[i], options);
|
|
}
|
|
};
|
|
|
|
/** @id MochiKit.Visual.tagifyText */
|
|
MochiKit.Visual.tagifyText = function (element, /* optional */tagifyStyle) {
|
|
/***
|
|
|
|
Change a node text to character in tags.
|
|
|
|
@param tagifyStyle: the style to apply to character nodes, default to
|
|
'position: relative'.
|
|
|
|
***/
|
|
tagifyStyle = tagifyStyle || 'position:relative';
|
|
if (/MSIE/.test(navigator.userAgent)) {
|
|
tagifyStyle += ';zoom:1';
|
|
}
|
|
element = MochiKit.DOM.getElement(element);
|
|
var ma = MochiKit.Base.map;
|
|
ma(function (child) {
|
|
if (child.nodeType == 3) {
|
|
ma(function (character) {
|
|
element.insertBefore(
|
|
MochiKit.DOM.SPAN({style: tagifyStyle},
|
|
character == ' ' ? String.fromCharCode(160) : character), child);
|
|
}, child.nodeValue.split(''));
|
|
MochiKit.DOM.removeElement(child);
|
|
}
|
|
}, element.childNodes);
|
|
};
|
|
|
|
MochiKit.Visual._forceRerendering = function (element) {
|
|
try {
|
|
element = MochiKit.DOM.getElement(element);
|
|
var n = document.createTextNode(' ');
|
|
element.appendChild(n);
|
|
element.removeChild(n);
|
|
} catch(e) {
|
|
}
|
|
};
|
|
|
|
/** @id MochiKit.Visual.multiple */
|
|
MochiKit.Visual.multiple = function (elements, effect, /* optional */options) {
|
|
/***
|
|
|
|
Launch the same effect subsequently on given elements.
|
|
|
|
***/
|
|
options = MochiKit.Base.update({
|
|
speed: 0.1, delay: 0.0
|
|
}, options);
|
|
var masterDelay = options.delay;
|
|
var index = 0;
|
|
MochiKit.Base.map(function (innerelement) {
|
|
options.delay = index * options.speed + masterDelay;
|
|
new effect(innerelement, options);
|
|
index += 1;
|
|
}, elements);
|
|
};
|
|
|
|
MochiKit.Visual.PAIRS = {
|
|
'slide': ['slideDown', 'slideUp'],
|
|
'blind': ['blindDown', 'blindUp'],
|
|
'appear': ['appear', 'fade'],
|
|
'size': ['grow', 'shrink']
|
|
};
|
|
|
|
/** @id MochiKit.Visual.toggle */
|
|
MochiKit.Visual.toggle = function (element, /* optional */effect, /* optional */options) {
|
|
/***
|
|
|
|
Toggle an item between two state depending of its visibility, making
|
|
a effect between these states. Default effect is 'appear', can be
|
|
'slide' or 'blind'.
|
|
|
|
***/
|
|
element = MochiKit.DOM.getElement(element);
|
|
effect = (effect || 'appear').toLowerCase();
|
|
options = MochiKit.Base.update({
|
|
queue: {position: 'end', scope: (element.id || 'global'), limit: 1}
|
|
}, options);
|
|
var v = MochiKit.Visual;
|
|
v[MochiKit.Style.getStyle(element, 'display') != 'none' ?
|
|
v.PAIRS[effect][1] : v.PAIRS[effect][0]](element, options);
|
|
};
|
|
|
|
/***
|
|
|
|
Transitions: define functions calculating variations depending of a position.
|
|
|
|
***/
|
|
|
|
MochiKit.Visual.Transitions = { __export__: false };
|
|
|
|
/** @id MochiKit.Visual.Transitions.linear */
|
|
MochiKit.Visual.Transitions.linear = function (pos) {
|
|
return pos;
|
|
};
|
|
|
|
/** @id MochiKit.Visual.Transitions.sinoidal */
|
|
MochiKit.Visual.Transitions.sinoidal = function (pos) {
|
|
return 0.5 - Math.cos(pos*Math.PI)/2;
|
|
};
|
|
|
|
/** @id MochiKit.Visual.Transitions.reverse */
|
|
MochiKit.Visual.Transitions.reverse = function (pos) {
|
|
return 1 - pos;
|
|
};
|
|
|
|
/** @id MochiKit.Visual.Transitions.flicker */
|
|
MochiKit.Visual.Transitions.flicker = function (pos) {
|
|
return 0.25 - Math.cos(pos*Math.PI)/4 + Math.random()/2;
|
|
};
|
|
|
|
/** @id MochiKit.Visual.Transitions.wobble */
|
|
MochiKit.Visual.Transitions.wobble = function (pos) {
|
|
return 0.5 - Math.cos(9*pos*Math.PI)/2;
|
|
};
|
|
|
|
/** @id MochiKit.Visual.Transitions.pulse */
|
|
MochiKit.Visual.Transitions.pulse = function (pos, pulses) {
|
|
if (pulses) {
|
|
pos *= 2 * pulses;
|
|
} else {
|
|
pos *= 10;
|
|
}
|
|
var decimals = pos - Math.floor(pos);
|
|
return (Math.floor(pos) % 2 == 0) ? decimals : 1 - decimals;
|
|
};
|
|
|
|
/** @id MochiKit.Visual.Transitions.parabolic */
|
|
MochiKit.Visual.Transitions.parabolic = function (pos) {
|
|
return pos * pos;
|
|
};
|
|
|
|
/** @id MochiKit.Visual.Transitions.spring */
|
|
MochiKit.Visual.Transitions.spring = function (pos) {
|
|
return 1 - (Math.cos(pos * 2.5 * Math.PI) * Math.exp(-pos * 6));
|
|
};
|
|
|
|
/** @id MochiKit.Visual.Transitions.none */
|
|
MochiKit.Visual.Transitions.none = function (pos) {
|
|
return 0;
|
|
};
|
|
|
|
/** @id MochiKit.Visual.Transitions.full */
|
|
MochiKit.Visual.Transitions.full = function (pos) {
|
|
return 1;
|
|
};
|
|
|
|
/***
|
|
|
|
Core effects
|
|
|
|
***/
|
|
|
|
MochiKit.Visual.ScopedQueue = function () {
|
|
var cls = arguments.callee;
|
|
if (!(this instanceof cls)) {
|
|
return new cls();
|
|
}
|
|
this.__init__();
|
|
};
|
|
MochiKit.Visual.ScopedQueue.__export__ = false;
|
|
|
|
MochiKit.Base.update(MochiKit.Visual.ScopedQueue.prototype, {
|
|
__init__: function () {
|
|
this.effects = [];
|
|
this.interval = null;
|
|
},
|
|
|
|
/** @id MochiKit.Visual.ScopedQueue.prototype.add */
|
|
add: function (effect) {
|
|
var timestamp = new Date().getTime();
|
|
|
|
var position = (typeof(effect.options.queue) == 'string') ?
|
|
effect.options.queue : effect.options.queue.position;
|
|
|
|
var ma = MochiKit.Base.map;
|
|
switch (position) {
|
|
case 'front':
|
|
// move unstarted effects after this effect
|
|
ma(function (e) {
|
|
if (e.state == 'idle') {
|
|
e.startOn += effect.finishOn;
|
|
e.finishOn += effect.finishOn;
|
|
}
|
|
}, this.effects);
|
|
break;
|
|
case 'end':
|
|
var finish;
|
|
// start effect after last queued effect has finished
|
|
ma(function (e) {
|
|
var i = e.finishOn;
|
|
if (i >= (finish || i)) {
|
|
finish = i;
|
|
}
|
|
}, this.effects);
|
|
timestamp = finish || timestamp;
|
|
break;
|
|
case 'break':
|
|
ma(function (e) {
|
|
e.finalize();
|
|
}, this.effects);
|
|
break;
|
|
case 'replace':
|
|
ma(function (e) {
|
|
e.cancel();
|
|
}, this.effects);
|
|
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 = this.startLoop(MochiKit.Base.bind(this.loop, this),
|
|
40);
|
|
}
|
|
},
|
|
|
|
/** @id MochiKit.Visual.ScopedQueue.prototype.startLoop */
|
|
startLoop: function (func, interval) {
|
|
return setInterval(func, interval);
|
|
},
|
|
|
|
/** @id MochiKit.Visual.ScopedQueue.prototype.remove */
|
|
remove: function (effect) {
|
|
this.effects = MochiKit.Base.filter(function (e) {
|
|
return e != effect;
|
|
}, this.effects);
|
|
if (!this.effects.length) {
|
|
this.stopLoop(this.interval);
|
|
this.interval = null;
|
|
}
|
|
},
|
|
|
|
/** @id MochiKit.Visual.ScopedQueue.prototype.stopLoop */
|
|
stopLoop: function (interval) {
|
|
clearInterval(interval);
|
|
},
|
|
|
|
/** @id MochiKit.Visual.ScopedQueue.prototype.loop */
|
|
loop: function () {
|
|
var timePos = new Date().getTime();
|
|
MochiKit.Base.map(function (effect) {
|
|
effect.loop(timePos);
|
|
}, this.effects);
|
|
}
|
|
});
|
|
|
|
MochiKit.Visual.Queues = {
|
|
__export__: false,
|
|
instances: {},
|
|
get: function (queueName) {
|
|
if (typeof(queueName) != 'string') {
|
|
return queueName;
|
|
}
|
|
|
|
if (!this.instances[queueName]) {
|
|
this.instances[queueName] = new MochiKit.Visual.ScopedQueue();
|
|
}
|
|
return this.instances[queueName];
|
|
}
|
|
};
|
|
|
|
MochiKit.Visual.Queue = MochiKit.Visual.Queues.get('global');
|
|
MochiKit.Visual.Queue.__export__ = false;
|
|
|
|
MochiKit.Visual.DefaultOptions = {
|
|
__export__: false,
|
|
transition: MochiKit.Visual.Transitions.sinoidal,
|
|
duration: 1.0, // seconds
|
|
fps: 25.0, // max. 25fps due to MochiKit.Visual.Queue implementation
|
|
sync: false, // true for combining
|
|
from: 0.0,
|
|
to: 1.0,
|
|
delay: 0.0,
|
|
queue: 'parallel'
|
|
};
|
|
|
|
MochiKit.Visual.Base = function () {};
|
|
|
|
MochiKit.Visual.Base.prototype = {
|
|
/***
|
|
|
|
Basic class for all Effects. Define a looping mechanism called for each step
|
|
of an effect. Don't instantiate it, only subclass it.
|
|
|
|
***/
|
|
|
|
__class__ : MochiKit.Visual.Base,
|
|
|
|
/** @id MochiKit.Visual.Base.prototype.start */
|
|
start: function (options) {
|
|
var v = MochiKit.Visual;
|
|
this.options = MochiKit.Base.setdefault(options,
|
|
v.DefaultOptions);
|
|
this.currentFrame = 0;
|
|
this.state = 'idle';
|
|
this.startOn = this.options.delay*1000;
|
|
this.finishOn = this.startOn + (this.options.duration*1000);
|
|
this.event('beforeStart');
|
|
if (!this.options.sync) {
|
|
v.Queues.get(typeof(this.options.queue) == 'string' ?
|
|
'global' : this.options.queue.scope).add(this);
|
|
}
|
|
},
|
|
|
|
/** @id MochiKit.Visual.Base.prototype.loop */
|
|
loop: function (timePos) {
|
|
if (timePos >= this.startOn) {
|
|
if (timePos >= this.finishOn) {
|
|
return this.finalize();
|
|
}
|
|
var pos = (timePos - this.startOn) / (this.finishOn - this.startOn);
|
|
var frame =
|
|
Math.round(pos * this.options.fps * this.options.duration);
|
|
if (frame > this.currentFrame) {
|
|
this.render(pos);
|
|
this.currentFrame = frame;
|
|
}
|
|
}
|
|
},
|
|
|
|
/** @id MochiKit.Visual.Base.prototype.render */
|
|
render: function (pos) {
|
|
if (this.state == 'idle') {
|
|
this.state = 'running';
|
|
this.event('beforeSetup');
|
|
this.setup();
|
|
this.event('afterSetup');
|
|
}
|
|
if (this.state == 'running') {
|
|
var trans = this.options.transition;
|
|
if (typeof(trans) == "string") {
|
|
trans = MochiKit.Visual.Transitions[trans];
|
|
}
|
|
if (typeof(trans) == "function") {
|
|
pos = trans(pos);
|
|
}
|
|
pos *= (this.options.to - this.options.from);
|
|
pos += this.options.from;
|
|
this.event('beforeUpdate');
|
|
this.update(pos);
|
|
this.event('afterUpdate');
|
|
}
|
|
},
|
|
|
|
/** @id MochiKit.Visual.Base.prototype.cancel */
|
|
cancel: function () {
|
|
if (!this.options.sync) {
|
|
MochiKit.Visual.Queues.get(typeof(this.options.queue) == 'string' ?
|
|
'global' : this.options.queue.scope).remove(this);
|
|
}
|
|
this.state = 'finished';
|
|
},
|
|
|
|
/** @id MochiKit.Visual.Base.prototype.finalize */
|
|
finalize: function () {
|
|
this.render(1.0);
|
|
this.cancel();
|
|
this.event('beforeFinish');
|
|
this.finish();
|
|
this.event('afterFinish');
|
|
},
|
|
|
|
setup: function () {
|
|
},
|
|
|
|
finish: function () {
|
|
},
|
|
|
|
update: function (position) {
|
|
},
|
|
|
|
/** @id MochiKit.Visual.Base.prototype.event */
|
|
event: function (eventName) {
|
|
if (this.options[eventName + 'Internal']) {
|
|
this.options[eventName + 'Internal'](this);
|
|
}
|
|
if (this.options[eventName]) {
|
|
this.options[eventName](this);
|
|
}
|
|
},
|
|
|
|
/** @id MochiKit.Visual.Base.prototype.repr */
|
|
repr: function () {
|
|
return '[' + this.__class__.NAME + ', options:' +
|
|
MochiKit.Base.repr(this.options) + ']';
|
|
}
|
|
};
|
|
|
|
/** @id MochiKit.Visual.Parallel */
|
|
MochiKit.Visual.Parallel = function (effects, options) {
|
|
var cls = arguments.callee;
|
|
if (!(this instanceof cls)) {
|
|
return new cls(effects, options);
|
|
}
|
|
|
|
this.__init__(effects, options);
|
|
};
|
|
|
|
MochiKit.Visual.Parallel.prototype = new MochiKit.Visual.Base();
|
|
|
|
MochiKit.Base.update(MochiKit.Visual.Parallel.prototype, {
|
|
/***
|
|
|
|
Run multiple effects at the same time.
|
|
|
|
***/
|
|
|
|
__class__ : MochiKit.Visual.Parallel,
|
|
|
|
__init__: function (effects, options) {
|
|
this.effects = effects || [];
|
|
this.start(options);
|
|
},
|
|
|
|
/** @id MochiKit.Visual.Parallel.prototype.update */
|
|
update: function (position) {
|
|
MochiKit.Base.map(function (effect) {
|
|
effect.render(position);
|
|
}, this.effects);
|
|
},
|
|
|
|
/** @id MochiKit.Visual.Parallel.prototype.finish */
|
|
finish: function () {
|
|
MochiKit.Base.map(function (effect) {
|
|
effect.finalize();
|
|
}, this.effects);
|
|
}
|
|
});
|
|
|
|
/** @id MochiKit.Visual.Sequence */
|
|
MochiKit.Visual.Sequence = function (effects, options) {
|
|
var cls = arguments.callee;
|
|
if (!(this instanceof cls)) {
|
|
return new cls(effects, options);
|
|
}
|
|
this.__init__(effects, options);
|
|
};
|
|
|
|
MochiKit.Visual.Sequence.prototype = new MochiKit.Visual.Base();
|
|
|
|
MochiKit.Base.update(MochiKit.Visual.Sequence.prototype, {
|
|
|
|
__class__ : MochiKit.Visual.Sequence,
|
|
|
|
__init__: function (effects, options) {
|
|
var defs = { transition: MochiKit.Visual.Transitions.linear,
|
|
duration: 0 };
|
|
this.effects = effects || [];
|
|
MochiKit.Base.map(function (effect) {
|
|
defs.duration += effect.options.duration;
|
|
}, this.effects);
|
|
MochiKit.Base.setdefault(options, defs);
|
|
this.start(options);
|
|
},
|
|
|
|
/** @id MochiKit.Visual.Sequence.prototype.update */
|
|
update: function (position) {
|
|
var time = position * this.options.duration;
|
|
for (var i = 0; i < this.effects.length; i++) {
|
|
var effect = this.effects[i];
|
|
if (time <= effect.options.duration) {
|
|
effect.render(time / effect.options.duration);
|
|
break;
|
|
} else {
|
|
time -= effect.options.duration;
|
|
}
|
|
}
|
|
},
|
|
|
|
/** @id MochiKit.Visual.Sequence.prototype.finish */
|
|
finish: function () {
|
|
MochiKit.Base.map(function (effect) {
|
|
effect.finalize();
|
|
}, this.effects);
|
|
}
|
|
});
|
|
|
|
/** @id MochiKit.Visual.Opacity */
|
|
MochiKit.Visual.Opacity = function (element, options) {
|
|
var cls = arguments.callee;
|
|
if (!(this instanceof cls)) {
|
|
return new cls(element, options);
|
|
}
|
|
this.__init__(element, options);
|
|
};
|
|
|
|
MochiKit.Visual.Opacity.prototype = new MochiKit.Visual.Base();
|
|
|
|
MochiKit.Base.update(MochiKit.Visual.Opacity.prototype, {
|
|
/***
|
|
|
|
Change the opacity of an element.
|
|
|
|
@param options: 'from' and 'to' change the starting and ending opacities.
|
|
Must be between 0.0 and 1.0. Default to current opacity and 1.0.
|
|
|
|
***/
|
|
|
|
__class__ : MochiKit.Visual.Opacity,
|
|
|
|
__init__: function (element, /* optional */options) {
|
|
var b = MochiKit.Base;
|
|
var s = MochiKit.Style;
|
|
this.element = MochiKit.DOM.getElement(element);
|
|
// make this work on IE on elements without 'layout'
|
|
if (this.element.currentStyle &&
|
|
(!this.element.currentStyle.hasLayout)) {
|
|
s.setStyle(this.element, {zoom: 1});
|
|
}
|
|
options = b.update({
|
|
from: s.getStyle(this.element, 'opacity') || 0.0,
|
|
to: 1.0
|
|
}, options);
|
|
this.start(options);
|
|
},
|
|
|
|
/** @id MochiKit.Visual.Opacity.prototype.update */
|
|
update: function (position) {
|
|
MochiKit.Style.setStyle(this.element, {'opacity': position});
|
|
}
|
|
});
|
|
|
|
/** @id MochiKit.Visual.Move.prototype */
|
|
MochiKit.Visual.Move = function (element, options) {
|
|
var cls = arguments.callee;
|
|
if (!(this instanceof cls)) {
|
|
return new cls(element, options);
|
|
}
|
|
this.__init__(element, options);
|
|
};
|
|
|
|
MochiKit.Visual.Move.prototype = new MochiKit.Visual.Base();
|
|
|
|
MochiKit.Base.update(MochiKit.Visual.Move.prototype, {
|
|
/***
|
|
|
|
Move an element between its current position to a defined position
|
|
|
|
@param options: 'x' and 'y' for final positions, default to 0, 0.
|
|
|
|
***/
|
|
|
|
__class__ : MochiKit.Visual.Move,
|
|
|
|
__init__: function (element, /* optional */options) {
|
|
this.element = MochiKit.DOM.getElement(element);
|
|
options = MochiKit.Base.update({
|
|
x: 0,
|
|
y: 0,
|
|
mode: 'relative'
|
|
}, options);
|
|
this.start(options);
|
|
},
|
|
|
|
/** @id MochiKit.Visual.Move.prototype.setup */
|
|
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)
|
|
MochiKit.Style.makePositioned(this.element);
|
|
|
|
var s = this.element.style;
|
|
var originalVisibility = s.visibility;
|
|
var originalDisplay = s.display;
|
|
if (originalDisplay == 'none') {
|
|
s.visibility = 'hidden';
|
|
s.display = '';
|
|
}
|
|
|
|
this.originalLeft = parseFloat(MochiKit.Style.getStyle(this.element, 'left') || '0');
|
|
this.originalTop = parseFloat(MochiKit.Style.getStyle(this.element, 'top') || '0');
|
|
|
|
if (this.options.mode == 'absolute') {
|
|
// absolute movement, so we need to calc deltaX and deltaY
|
|
this.options.x -= this.originalLeft;
|
|
this.options.y -= this.originalTop;
|
|
}
|
|
if (originalDisplay == 'none') {
|
|
s.visibility = originalVisibility;
|
|
s.display = originalDisplay;
|
|
}
|
|
},
|
|
|
|
/** @id MochiKit.Visual.Move.prototype.update */
|
|
update: function (position) {
|
|
MochiKit.Style.setStyle(this.element, {
|
|
left: Math.round(this.options.x * position + this.originalLeft) + 'px',
|
|
top: Math.round(this.options.y * position + this.originalTop) + 'px'
|
|
});
|
|
}
|
|
});
|
|
|
|
/** @id MochiKit.Visual.Scale */
|
|
MochiKit.Visual.Scale = function (element, percent, options) {
|
|
var cls = arguments.callee;
|
|
if (!(this instanceof cls)) {
|
|
return new cls(element, percent, options);
|
|
}
|
|
this.__init__(element, percent, options);
|
|
};
|
|
|
|
MochiKit.Visual.Scale.prototype = new MochiKit.Visual.Base();
|
|
|
|
MochiKit.Base.update(MochiKit.Visual.Scale.prototype, {
|
|
/***
|
|
|
|
Change the size of an element.
|
|
|
|
@param percent: final_size = percent*original_size
|
|
|
|
@param options: several options changing scale behaviour
|
|
|
|
***/
|
|
|
|
__class__ : MochiKit.Visual.Scale,
|
|
|
|
__init__: function (element, percent, /* optional */options) {
|
|
this.element = MochiKit.DOM.getElement(element);
|
|
options = MochiKit.Base.update({
|
|
scaleX: true,
|
|
scaleY: true,
|
|
scaleContent: true,
|
|
scaleFromCenter: false,
|
|
scaleMode: 'box', // 'box' or 'contents' or {} with provided values
|
|
scaleFrom: 100.0,
|
|
scaleTo: percent
|
|
}, options);
|
|
this.start(options);
|
|
},
|
|
|
|
/** @id MochiKit.Visual.Scale.prototype.setup */
|
|
setup: function () {
|
|
this.restoreAfterFinish = this.options.restoreAfterFinish || false;
|
|
this.elementPositioning = MochiKit.Style.getStyle(this.element,
|
|
'position');
|
|
|
|
var ma = MochiKit.Base.map;
|
|
var b = MochiKit.Base.bind;
|
|
this.originalStyle = {};
|
|
ma(b(function (k) {
|
|
this.originalStyle[k] = this.element.style[k];
|
|
}, this), ['top', 'left', 'width', 'height', 'fontSize']);
|
|
|
|
this.originalTop = this.element.offsetTop;
|
|
this.originalLeft = this.element.offsetLeft;
|
|
|
|
var fontSize = MochiKit.Style.getStyle(this.element,
|
|
'font-size') || '100%';
|
|
ma(b(function (fontSizeType) {
|
|
if (fontSize.indexOf(fontSizeType) > 0) {
|
|
this.fontSize = parseFloat(fontSize);
|
|
this.fontSizeType = fontSizeType;
|
|
}
|
|
}, this), ['em', 'px', '%']);
|
|
|
|
this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
|
|
|
|
if (/^content/.test(this.options.scaleMode)) {
|
|
this.dims = [this.element.scrollHeight, this.element.scrollWidth];
|
|
} else if (this.options.scaleMode == 'box') {
|
|
this.dims = [this.element.offsetHeight, this.element.offsetWidth];
|
|
} else {
|
|
this.dims = [this.options.scaleMode.originalHeight,
|
|
this.options.scaleMode.originalWidth];
|
|
}
|
|
},
|
|
|
|
/** @id MochiKit.Visual.Scale.prototype.update */
|
|
update: function (position) {
|
|
var currentScale = (this.options.scaleFrom/100.0) +
|
|
(this.factor * position);
|
|
if (this.options.scaleContent && this.fontSize) {
|
|
MochiKit.Style.setStyle(this.element, {
|
|
fontSize: this.fontSize * currentScale + this.fontSizeType
|
|
});
|
|
}
|
|
this.setDimensions(this.dims[0] * currentScale,
|
|
this.dims[1] * currentScale);
|
|
},
|
|
|
|
/** @id MochiKit.Visual.Scale.prototype.finish */
|
|
finish: function () {
|
|
if (this.restoreAfterFinish) {
|
|
MochiKit.Style.setStyle(this.element, this.originalStyle);
|
|
}
|
|
},
|
|
|
|
/** @id MochiKit.Visual.Scale.prototype.setDimensions */
|
|
setDimensions: function (height, width) {
|
|
var d = {};
|
|
var r = Math.round;
|
|
if (/MSIE/.test(navigator.userAgent)) {
|
|
r = Math.ceil;
|
|
}
|
|
if (this.options.scaleX) {
|
|
d.width = r(width) + 'px';
|
|
}
|
|
if (this.options.scaleY) {
|
|
d.height = r(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';
|
|
}
|
|
}
|
|
}
|
|
MochiKit.Style.setStyle(this.element, d);
|
|
}
|
|
});
|
|
|
|
/** @id MochiKit.Visual.Highlight */
|
|
MochiKit.Visual.Highlight = function (element, options) {
|
|
var cls = arguments.callee;
|
|
if (!(this instanceof cls)) {
|
|
return new cls(element, options);
|
|
}
|
|
this.__init__(element, options);
|
|
};
|
|
|
|
MochiKit.Visual.Highlight.prototype = new MochiKit.Visual.Base();
|
|
|
|
MochiKit.Base.update(MochiKit.Visual.Highlight.prototype, {
|
|
/***
|
|
|
|
Highlight an item of the page.
|
|
|
|
@param options: 'startcolor' for choosing highlighting color, default
|
|
to '#ffff99'.
|
|
|
|
***/
|
|
|
|
__class__ : MochiKit.Visual.Highlight,
|
|
|
|
__init__: function (element, /* optional */options) {
|
|
this.element = MochiKit.DOM.getElement(element);
|
|
options = MochiKit.Base.update({
|
|
startcolor: '#ffff99'
|
|
}, options);
|
|
this.start(options);
|
|
},
|
|
|
|
/** @id MochiKit.Visual.Highlight.prototype.setup */
|
|
setup: function () {
|
|
var b = MochiKit.Base;
|
|
var s = MochiKit.Style;
|
|
// Prevent executing on elements not in the layout flow
|
|
if (s.getStyle(this.element, 'display') == 'none') {
|
|
this.cancel();
|
|
return;
|
|
}
|
|
// Disable background image during the effect
|
|
this.oldStyle = {
|
|
backgroundImage: s.getStyle(this.element, 'background-image')
|
|
};
|
|
s.setStyle(this.element, {
|
|
backgroundImage: 'none'
|
|
});
|
|
|
|
if (!this.options.endcolor) {
|
|
this.options.endcolor =
|
|
MochiKit.Color.Color.fromBackground(this.element).toHexString();
|
|
}
|
|
if (b.isUndefinedOrNull(this.options.restorecolor)) {
|
|
this.options.restorecolor = s.getStyle(this.element,
|
|
'background-color');
|
|
}
|
|
// init color calculations
|
|
this._base = b.map(b.bind(function (i) {
|
|
return parseInt(
|
|
this.options.startcolor.slice(i*2 + 1, i*2 + 3), 16);
|
|
}, this), [0, 1, 2]);
|
|
this._delta = b.map(b.bind(function (i) {
|
|
return parseInt(this.options.endcolor.slice(i*2 + 1, i*2 + 3), 16)
|
|
- this._base[i];
|
|
}, this), [0, 1, 2]);
|
|
},
|
|
|
|
/** @id MochiKit.Visual.Highlight.prototype.update */
|
|
update: function (position) {
|
|
var m = '#';
|
|
MochiKit.Base.map(MochiKit.Base.bind(function (i) {
|
|
m += MochiKit.Color.toColorPart(Math.round(this._base[i] +
|
|
this._delta[i]*position));
|
|
}, this), [0, 1, 2]);
|
|
MochiKit.Style.setStyle(this.element, {
|
|
backgroundColor: m
|
|
});
|
|
},
|
|
|
|
/** @id MochiKit.Visual.Highlight.prototype.finish */
|
|
finish: function () {
|
|
MochiKit.Style.setStyle(this.element,
|
|
MochiKit.Base.update(this.oldStyle, {
|
|
backgroundColor: this.options.restorecolor
|
|
}));
|
|
}
|
|
});
|
|
|
|
/** @id MochiKit.Visual.ScrollTo */
|
|
MochiKit.Visual.ScrollTo = function (element, options) {
|
|
var cls = arguments.callee;
|
|
if (!(this instanceof cls)) {
|
|
return new cls(element, options);
|
|
}
|
|
this.__init__(element, options);
|
|
};
|
|
|
|
MochiKit.Visual.ScrollTo.prototype = new MochiKit.Visual.Base();
|
|
|
|
MochiKit.Base.update(MochiKit.Visual.ScrollTo.prototype, {
|
|
/***
|
|
|
|
Scroll to an element in the page.
|
|
|
|
***/
|
|
|
|
__class__ : MochiKit.Visual.ScrollTo,
|
|
|
|
__init__: function (element, /* optional */options) {
|
|
this.element = MochiKit.DOM.getElement(element);
|
|
this.start(options);
|
|
},
|
|
|
|
/** @id MochiKit.Visual.ScrollTo.prototype.setup */
|
|
setup: function () {
|
|
var p = MochiKit.Position;
|
|
p.prepare();
|
|
var offsets = p.cumulativeOffset(this.element);
|
|
if (this.options.offset) {
|
|
offsets.y += this.options.offset;
|
|
}
|
|
var max;
|
|
if (window.innerHeight) {
|
|
max = window.innerHeight - window.height;
|
|
} else if (document.documentElement &&
|
|
document.documentElement.clientHeight) {
|
|
max = document.documentElement.clientHeight -
|
|
document.body.scrollHeight;
|
|
} else if (document.body) {
|
|
max = document.body.clientHeight - document.body.scrollHeight;
|
|
}
|
|
this.scrollStart = p.windowOffset.y;
|
|
this.delta = (offsets.y > max ? max : offsets.y) - this.scrollStart;
|
|
},
|
|
|
|
/** @id MochiKit.Visual.ScrollTo.prototype.update */
|
|
update: function (position) {
|
|
var p = MochiKit.Position;
|
|
p.prepare();
|
|
window.scrollTo(p.windowOffset.x, this.scrollStart + (position * this.delta));
|
|
}
|
|
});
|
|
|
|
MochiKit.Visual._CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
|
|
|
|
MochiKit.Visual.Morph = function (element, options) {
|
|
var cls = arguments.callee;
|
|
if (!(this instanceof cls)) {
|
|
return new cls(element, options);
|
|
}
|
|
this.__init__(element, options);
|
|
};
|
|
|
|
MochiKit.Visual.Morph.prototype = new MochiKit.Visual.Base();
|
|
|
|
MochiKit.Base.update(MochiKit.Visual.Morph.prototype, {
|
|
/***
|
|
|
|
Morph effect: make a transformation from current style to the given style,
|
|
automatically making a transition between the two.
|
|
|
|
***/
|
|
|
|
__class__ : MochiKit.Visual.Morph,
|
|
|
|
__init__: function (element, /* optional */options) {
|
|
this.element = MochiKit.DOM.getElement(element);
|
|
this.start(options);
|
|
},
|
|
|
|
/** @id MochiKit.Visual.Morph.prototype.setup */
|
|
setup: function () {
|
|
var b = MochiKit.Base;
|
|
var style = this.options.style;
|
|
this.styleStart = {};
|
|
this.styleEnd = {};
|
|
this.units = {};
|
|
var value, unit;
|
|
for (var s in style) {
|
|
value = style[s];
|
|
s = b.camelize(s);
|
|
if (MochiKit.Visual._CSS_LENGTH.test(value)) {
|
|
var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
|
|
value = parseFloat(components[1]);
|
|
unit = (components.length == 3) ? components[2] : null;
|
|
this.styleEnd[s] = value;
|
|
this.units[s] = unit;
|
|
value = MochiKit.Style.getStyle(this.element, s);
|
|
components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
|
|
value = parseFloat(components[1]);
|
|
this.styleStart[s] = value;
|
|
} else if (/[Cc]olor$/.test(s)) {
|
|
var c = MochiKit.Color.Color;
|
|
value = c.fromString(value);
|
|
if (value) {
|
|
this.units[s] = "color";
|
|
this.styleEnd[s] = value.toHexString();
|
|
value = MochiKit.Style.getStyle(this.element, s);
|
|
this.styleStart[s] = c.fromString(value).toHexString();
|
|
|
|
this.styleStart[s] = b.map(b.bind(function (i) {
|
|
return parseInt(
|
|
this.styleStart[s].slice(i*2 + 1, i*2 + 3), 16);
|
|
}, this), [0, 1, 2]);
|
|
this.styleEnd[s] = b.map(b.bind(function (i) {
|
|
return parseInt(
|
|
this.styleEnd[s].slice(i*2 + 1, i*2 + 3), 16);
|
|
}, this), [0, 1, 2]);
|
|
}
|
|
} else {
|
|
// For non-length & non-color properties, we just set the value
|
|
this.element.style[s] = value;
|
|
}
|
|
}
|
|
},
|
|
|
|
/** @id MochiKit.Visual.Morph.prototype.update */
|
|
update: function (position) {
|
|
var value;
|
|
for (var s in this.styleStart) {
|
|
if (this.units[s] == "color") {
|
|
var m = '#';
|
|
var start = this.styleStart[s];
|
|
var end = this.styleEnd[s];
|
|
MochiKit.Base.map(MochiKit.Base.bind(function (i) {
|
|
m += MochiKit.Color.toColorPart(Math.round(start[i] +
|
|
(end[i] - start[i])*position));
|
|
}, this), [0, 1, 2]);
|
|
this.element.style[s] = m;
|
|
} else {
|
|
value = this.styleStart[s] + Math.round((this.styleEnd[s] - this.styleStart[s]) * position * 1000) / 1000 + this.units[s];
|
|
this.element.style[s] = value;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
/***
|
|
|
|
Combination effects.
|
|
|
|
***/
|
|
|
|
/** @id MochiKit.Visual.fade */
|
|
MochiKit.Visual.fade = function (element, /* optional */ options) {
|
|
/***
|
|
|
|
Fade a given element: change its opacity and hide it in the end.
|
|
|
|
@param options: 'to' and 'from' to change opacity.
|
|
|
|
***/
|
|
var s = MochiKit.Style;
|
|
var oldOpacity = s.getStyle(element, 'opacity');
|
|
options = MochiKit.Base.update({
|
|
from: s.getStyle(element, 'opacity') || 1.0,
|
|
to: 0.0,
|
|
afterFinishInternal: function (effect) {
|
|
if (effect.options.to !== 0) {
|
|
return;
|
|
}
|
|
s.hideElement(effect.element);
|
|
s.setStyle(effect.element, {'opacity': oldOpacity});
|
|
}
|
|
}, options);
|
|
return new MochiKit.Visual.Opacity(element, options);
|
|
};
|
|
|
|
/** @id MochiKit.Visual.appear */
|
|
MochiKit.Visual.appear = function (element, /* optional */ options) {
|
|
/***
|
|
|
|
Make an element appear.
|
|
|
|
@param options: 'to' and 'from' to change opacity.
|
|
|
|
***/
|
|
var s = MochiKit.Style;
|
|
var v = MochiKit.Visual;
|
|
options = MochiKit.Base.update({
|
|
from: (s.getStyle(element, 'display') == 'none' ? 0.0 :
|
|
s.getStyle(element, 'opacity') || 0.0),
|
|
to: 1.0,
|
|
// force Safari to render floated elements properly
|
|
afterFinishInternal: function (effect) {
|
|
v._forceRerendering(effect.element);
|
|
},
|
|
beforeSetupInternal: function (effect) {
|
|
s.setStyle(effect.element, {'opacity': effect.options.from});
|
|
s.showElement(effect.element);
|
|
}
|
|
}, options);
|
|
return new v.Opacity(element, options);
|
|
};
|
|
|
|
/** @id MochiKit.Visual.puff */
|
|
MochiKit.Visual.puff = function (element, /* optional */ options) {
|
|
/***
|
|
|
|
'Puff' an element: grow it to double size, fading it and make it hidden.
|
|
|
|
***/
|
|
var s = MochiKit.Style;
|
|
var v = MochiKit.Visual;
|
|
element = MochiKit.DOM.getElement(element);
|
|
var elementDimensions = MochiKit.Style.getElementDimensions(element, true);
|
|
var oldStyle = {
|
|
position: s.getStyle(element, 'position'),
|
|
top: element.style.top,
|
|
left: element.style.left,
|
|
width: element.style.width,
|
|
height: element.style.height,
|
|
opacity: s.getStyle(element, 'opacity')
|
|
};
|
|
options = MochiKit.Base.update({
|
|
beforeSetupInternal: function (effect) {
|
|
MochiKit.Position.absolutize(effect.effects[0].element);
|
|
},
|
|
afterFinishInternal: function (effect) {
|
|
s.hideElement(effect.effects[0].element);
|
|
s.setStyle(effect.effects[0].element, oldStyle);
|
|
},
|
|
scaleContent: true,
|
|
scaleFromCenter: true
|
|
}, options);
|
|
return new v.Parallel(
|
|
[new v.Scale(element, 200,
|
|
{sync: true, scaleFromCenter: options.scaleFromCenter,
|
|
scaleMode: {originalHeight: elementDimensions.h,
|
|
originalWidth: elementDimensions.w},
|
|
scaleContent: options.scaleContent, restoreAfterFinish: true}),
|
|
new v.Opacity(element, {sync: true, to: 0.0 })],
|
|
options);
|
|
};
|
|
|
|
/** @id MochiKit.Visual.blindUp */
|
|
MochiKit.Visual.blindUp = function (element, /* optional */ options) {
|
|
/***
|
|
|
|
Blind an element up: change its vertical size to 0.
|
|
|
|
***/
|
|
var d = MochiKit.DOM;
|
|
var s = MochiKit.Style;
|
|
element = d.getElement(element);
|
|
var elementDimensions = s.getElementDimensions(element, true);
|
|
var elemClip = s.makeClipping(element);
|
|
options = MochiKit.Base.update({
|
|
scaleContent: false,
|
|
scaleX: false,
|
|
scaleMode: {originalHeight: elementDimensions.h,
|
|
originalWidth: elementDimensions.w},
|
|
restoreAfterFinish: true,
|
|
afterFinishInternal: function (effect) {
|
|
s.hideElement(effect.element);
|
|
s.undoClipping(effect.element, elemClip);
|
|
}
|
|
}, options);
|
|
return new MochiKit.Visual.Scale(element, 0, options);
|
|
};
|
|
|
|
/** @id MochiKit.Visual.blindDown */
|
|
MochiKit.Visual.blindDown = function (element, /* optional */ options) {
|
|
/***
|
|
|
|
Blind an element down: restore its vertical size.
|
|
|
|
***/
|
|
var d = MochiKit.DOM;
|
|
var s = MochiKit.Style;
|
|
element = d.getElement(element);
|
|
var elementDimensions = s.getElementDimensions(element, true);
|
|
var elemClip;
|
|
options = MochiKit.Base.update({
|
|
scaleContent: false,
|
|
scaleX: false,
|
|
scaleFrom: 0,
|
|
scaleMode: {originalHeight: elementDimensions.h,
|
|
originalWidth: elementDimensions.w},
|
|
restoreAfterFinish: true,
|
|
afterSetupInternal: function (effect) {
|
|
elemClip = s.makeClipping(effect.element);
|
|
s.setStyle(effect.element, {height: '0px'});
|
|
s.showElement(effect.element);
|
|
},
|
|
afterFinishInternal: function (effect) {
|
|
s.undoClipping(effect.element, elemClip);
|
|
}
|
|
}, options);
|
|
return new MochiKit.Visual.Scale(element, 100, options);
|
|
};
|
|
|
|
/** @id MochiKit.Visual.switchOff */
|
|
MochiKit.Visual.switchOff = function (element, /* optional */ options) {
|
|
/***
|
|
|
|
Apply a switch-off-like effect.
|
|
|
|
***/
|
|
var d = MochiKit.DOM;
|
|
var s = MochiKit.Style;
|
|
element = d.getElement(element);
|
|
var elementDimensions = s.getElementDimensions(element, true);
|
|
var oldOpacity = s.getStyle(element, 'opacity');
|
|
var elemClip;
|
|
options = MochiKit.Base.update({
|
|
duration: 0.7,
|
|
restoreAfterFinish: true,
|
|
beforeSetupInternal: function (effect) {
|
|
s.makePositioned(element);
|
|
elemClip = s.makeClipping(element);
|
|
},
|
|
afterFinishInternal: function (effect) {
|
|
s.hideElement(element);
|
|
s.undoClipping(element, elemClip);
|
|
s.undoPositioned(element);
|
|
s.setStyle(element, {'opacity': oldOpacity});
|
|
}
|
|
}, options);
|
|
var v = MochiKit.Visual;
|
|
return new v.Sequence(
|
|
[new v.appear(element,
|
|
{ sync: true, duration: 0.57 * options.duration,
|
|
from: 0, transition: v.Transitions.flicker }),
|
|
new v.Scale(element, 1,
|
|
{ sync: true, duration: 0.43 * options.duration,
|
|
scaleFromCenter: true, scaleX: false,
|
|
scaleMode: {originalHeight: elementDimensions.h,
|
|
originalWidth: elementDimensions.w},
|
|
scaleContent: false, restoreAfterFinish: true })],
|
|
options);
|
|
};
|
|
|
|
/** @id MochiKit.Visual.dropOut */
|
|
MochiKit.Visual.dropOut = function (element, /* optional */ options) {
|
|
/***
|
|
|
|
Make an element fall and disappear.
|
|
|
|
***/
|
|
var d = MochiKit.DOM;
|
|
var s = MochiKit.Style;
|
|
element = d.getElement(element);
|
|
var oldStyle = {
|
|
top: s.getStyle(element, 'top'),
|
|
left: s.getStyle(element, 'left'),
|
|
opacity: s.getStyle(element, 'opacity')
|
|
};
|
|
|
|
options = MochiKit.Base.update({
|
|
duration: 0.5,
|
|
distance: 100,
|
|
beforeSetupInternal: function (effect) {
|
|
s.makePositioned(effect.effects[0].element);
|
|
},
|
|
afterFinishInternal: function (effect) {
|
|
s.hideElement(effect.effects[0].element);
|
|
s.undoPositioned(effect.effects[0].element);
|
|
s.setStyle(effect.effects[0].element, oldStyle);
|
|
}
|
|
}, options);
|
|
var v = MochiKit.Visual;
|
|
return new v.Parallel(
|
|
[new v.Move(element, {x: 0, y: options.distance, sync: true}),
|
|
new v.Opacity(element, {sync: true, to: 0.0})],
|
|
options);
|
|
};
|
|
|
|
/** @id MochiKit.Visual.shake */
|
|
MochiKit.Visual.shake = function (element, /* optional */ options) {
|
|
/***
|
|
|
|
Move an element from left to right several times.
|
|
|
|
***/
|
|
var d = MochiKit.DOM;
|
|
var v = MochiKit.Visual;
|
|
var s = MochiKit.Style;
|
|
element = d.getElement(element);
|
|
var oldStyle = {
|
|
top: s.getStyle(element, 'top'),
|
|
left: s.getStyle(element, 'left')
|
|
};
|
|
options = MochiKit.Base.update({
|
|
duration: 0.5,
|
|
afterFinishInternal: function (effect) {
|
|
s.undoPositioned(element);
|
|
s.setStyle(element, oldStyle);
|
|
}
|
|
}, options);
|
|
return new v.Sequence(
|
|
[new v.Move(element, { sync: true, duration: 0.1 * options.duration,
|
|
x: 20, y: 0 }),
|
|
new v.Move(element, { sync: true, duration: 0.2 * options.duration,
|
|
x: -40, y: 0 }),
|
|
new v.Move(element, { sync: true, duration: 0.2 * options.duration,
|
|
x: 40, y: 0 }),
|
|
new v.Move(element, { sync: true, duration: 0.2 * options.duration,
|
|
x: -40, y: 0 }),
|
|
new v.Move(element, { sync: true, duration: 0.2 * options.duration,
|
|
x: 40, y: 0 }),
|
|
new v.Move(element, { sync: true, duration: 0.1 * options.duration,
|
|
x: -20, y: 0 })],
|
|
options);
|
|
};
|
|
|
|
/** @id MochiKit.Visual.slideDown */
|
|
MochiKit.Visual.slideDown = function (element, /* optional */ options) {
|
|
/***
|
|
|
|
Slide an element down.
|
|
It needs to have the content of the element wrapped in a container
|
|
element with fixed height.
|
|
|
|
***/
|
|
var d = MochiKit.DOM;
|
|
var b = MochiKit.Base;
|
|
var s = MochiKit.Style;
|
|
element = d.getElement(element);
|
|
if (!element.firstChild) {
|
|
throw new Error("MochiKit.Visual.slideDown must be used on a element with a child");
|
|
}
|
|
d.removeEmptyTextNodes(element);
|
|
var oldInnerBottom = s.getStyle(element.firstChild, 'bottom') || 0;
|
|
var elementDimensions = s.getElementDimensions(element, true);
|
|
var elemClip;
|
|
options = b.update({
|
|
scaleContent: false,
|
|
scaleX: false,
|
|
scaleFrom: 0,
|
|
scaleMode: {originalHeight: elementDimensions.h,
|
|
originalWidth: elementDimensions.w},
|
|
restoreAfterFinish: true,
|
|
afterSetupInternal: function (effect) {
|
|
s.makePositioned(effect.element);
|
|
s.makePositioned(effect.element.firstChild);
|
|
if (/Opera/.test(navigator.userAgent)) {
|
|
s.setStyle(effect.element, {top: ''});
|
|
}
|
|
elemClip = s.makeClipping(effect.element);
|
|
s.setStyle(effect.element, {height: '0px'});
|
|
s.showElement(effect.element);
|
|
},
|
|
afterUpdateInternal: function (effect) {
|
|
var elementDimensions = s.getElementDimensions(effect.element, true);
|
|
s.setStyle(effect.element.firstChild,
|
|
{bottom: (effect.dims[0] - elementDimensions.h) + 'px'});
|
|
},
|
|
afterFinishInternal: function (effect) {
|
|
s.undoClipping(effect.element, elemClip);
|
|
// IE will crash if child is undoPositioned first
|
|
if (/MSIE/.test(navigator.userAgent)) {
|
|
s.undoPositioned(effect.element);
|
|
s.undoPositioned(effect.element.firstChild);
|
|
} else {
|
|
s.undoPositioned(effect.element.firstChild);
|
|
s.undoPositioned(effect.element);
|
|
}
|
|
s.setStyle(effect.element.firstChild, {bottom: oldInnerBottom});
|
|
}
|
|
}, options);
|
|
|
|
return new MochiKit.Visual.Scale(element, 100, options);
|
|
};
|
|
|
|
/** @id MochiKit.Visual.slideUp */
|
|
MochiKit.Visual.slideUp = function (element, /* optional */ options) {
|
|
/***
|
|
|
|
Slide an element up.
|
|
It needs to have the content of the element wrapped in a container
|
|
element with fixed height.
|
|
|
|
***/
|
|
var d = MochiKit.DOM;
|
|
var b = MochiKit.Base;
|
|
var s = MochiKit.Style;
|
|
element = d.getElement(element);
|
|
if (!element.firstChild) {
|
|
throw new Error("MochiKit.Visual.slideUp must be used on a element with a child");
|
|
}
|
|
d.removeEmptyTextNodes(element);
|
|
var oldInnerBottom = s.getStyle(element.firstChild, 'bottom');
|
|
var elementDimensions = s.getElementDimensions(element, true);
|
|
var elemClip;
|
|
options = b.update({
|
|
scaleContent: false,
|
|
scaleX: false,
|
|
scaleMode: {originalHeight: elementDimensions.h,
|
|
originalWidth: elementDimensions.w},
|
|
scaleFrom: 100,
|
|
restoreAfterFinish: true,
|
|
beforeStartInternal: function (effect) {
|
|
s.makePositioned(effect.element);
|
|
s.makePositioned(effect.element.firstChild);
|
|
if (/Opera/.test(navigator.userAgent)) {
|
|
s.setStyle(effect.element, {top: ''});
|
|
}
|
|
elemClip = s.makeClipping(effect.element);
|
|
s.showElement(effect.element);
|
|
},
|
|
afterUpdateInternal: function (effect) {
|
|
var elementDimensions = s.getElementDimensions(effect.element, true);
|
|
s.setStyle(effect.element.firstChild,
|
|
{bottom: (effect.dims[0] - elementDimensions.h) + 'px'});
|
|
},
|
|
afterFinishInternal: function (effect) {
|
|
s.hideElement(effect.element);
|
|
s.undoClipping(effect.element, elemClip);
|
|
s.undoPositioned(effect.element.firstChild);
|
|
s.undoPositioned(effect.element);
|
|
s.setStyle(effect.element.firstChild, {bottom: oldInnerBottom});
|
|
}
|
|
}, options);
|
|
return new MochiKit.Visual.Scale(element, 0, options);
|
|
};
|
|
|
|
// Bug in opera makes the TD containing this element expand for a instance
|
|
// after finish
|
|
/** @id MochiKit.Visual.squish */
|
|
MochiKit.Visual.squish = function (element, /* optional */ options) {
|
|
/***
|
|
|
|
Reduce an element and make it disappear.
|
|
|
|
***/
|
|
var d = MochiKit.DOM;
|
|
var b = MochiKit.Base;
|
|
var s = MochiKit.Style;
|
|
var elementDimensions = s.getElementDimensions(element, true);
|
|
var elemClip;
|
|
options = b.update({
|
|
restoreAfterFinish: true,
|
|
scaleMode: {originalHeight: elementDimensions.h,
|
|
originalWidth: elementDimensions.w},
|
|
beforeSetupInternal: function (effect) {
|
|
elemClip = s.makeClipping(effect.element);
|
|
},
|
|
afterFinishInternal: function (effect) {
|
|
s.hideElement(effect.element);
|
|
s.undoClipping(effect.element, elemClip);
|
|
}
|
|
}, options);
|
|
|
|
return new MochiKit.Visual.Scale(element, /Opera/.test(navigator.userAgent) ? 1 : 0, options);
|
|
};
|
|
|
|
/** @id MochiKit.Visual.grow */
|
|
MochiKit.Visual.grow = function (element, /* optional */ options) {
|
|
/***
|
|
|
|
Grow an element to its original size. Make it zero-sized before
|
|
if necessary.
|
|
|
|
***/
|
|
var d = MochiKit.DOM;
|
|
var v = MochiKit.Visual;
|
|
var s = MochiKit.Style;
|
|
element = d.getElement(element);
|
|
options = MochiKit.Base.update({
|
|
direction: 'center',
|
|
moveTransition: v.Transitions.sinoidal,
|
|
scaleTransition: v.Transitions.sinoidal,
|
|
opacityTransition: v.Transitions.full,
|
|
scaleContent: true,
|
|
scaleFromCenter: false
|
|
}, options);
|
|
var oldStyle = {
|
|
top: element.style.top,
|
|
left: element.style.left,
|
|
height: element.style.height,
|
|
width: element.style.width,
|
|
opacity: s.getStyle(element, 'opacity')
|
|
};
|
|
var dims = s.getElementDimensions(element, true);
|
|
var initialMoveX, initialMoveY;
|
|
var moveX, moveY;
|
|
|
|
switch (options.direction) {
|
|
case 'top-left':
|
|
initialMoveX = initialMoveY = moveX = moveY = 0;
|
|
break;
|
|
case 'top-right':
|
|
initialMoveX = dims.w;
|
|
initialMoveY = moveY = 0;
|
|
moveX = -dims.w;
|
|
break;
|
|
case 'bottom-left':
|
|
initialMoveX = moveX = 0;
|
|
initialMoveY = dims.h;
|
|
moveY = -dims.h;
|
|
break;
|
|
case 'bottom-right':
|
|
initialMoveX = dims.w;
|
|
initialMoveY = dims.h;
|
|
moveX = -dims.w;
|
|
moveY = -dims.h;
|
|
break;
|
|
case 'center':
|
|
initialMoveX = dims.w / 2;
|
|
initialMoveY = dims.h / 2;
|
|
moveX = -dims.w / 2;
|
|
moveY = -dims.h / 2;
|
|
break;
|
|
}
|
|
|
|
var optionsParallel = MochiKit.Base.update({
|
|
beforeSetupInternal: function (effect) {
|
|
s.setStyle(effect.effects[0].element, {height: '0px'});
|
|
s.showElement(effect.effects[0].element);
|
|
},
|
|
afterFinishInternal: function (effect) {
|
|
s.undoClipping(effect.effects[0].element);
|
|
s.undoPositioned(effect.effects[0].element);
|
|
s.setStyle(effect.effects[0].element, oldStyle);
|
|
}
|
|
}, options);
|
|
|
|
return new v.Move(element, {
|
|
x: initialMoveX,
|
|
y: initialMoveY,
|
|
duration: 0.01,
|
|
beforeSetupInternal: function (effect) {
|
|
s.hideElement(effect.element);
|
|
s.makeClipping(effect.element);
|
|
s.makePositioned(effect.element);
|
|
},
|
|
afterFinishInternal: function (effect) {
|
|
new v.Parallel(
|
|
[new v.Opacity(effect.element, {
|
|
sync: true, to: 1.0, from: 0.0,
|
|
transition: options.opacityTransition
|
|
}),
|
|
new v.Move(effect.element, {
|
|
x: moveX, y: moveY, sync: true,
|
|
transition: options.moveTransition
|
|
}),
|
|
new v.Scale(effect.element, 100, {
|
|
scaleMode: {originalHeight: dims.h,
|
|
originalWidth: dims.w},
|
|
sync: true,
|
|
scaleFrom: /Opera/.test(navigator.userAgent) ? 1 : 0,
|
|
transition: options.scaleTransition,
|
|
scaleContent: options.scaleContent,
|
|
scaleFromCenter: options.scaleFromCenter,
|
|
restoreAfterFinish: true
|
|
})
|
|
], optionsParallel
|
|
);
|
|
}
|
|
});
|
|
};
|
|
|
|
/** @id MochiKit.Visual.shrink */
|
|
MochiKit.Visual.shrink = function (element, /* optional */ options) {
|
|
/***
|
|
|
|
Shrink an element and make it disappear.
|
|
|
|
***/
|
|
var d = MochiKit.DOM;
|
|
var v = MochiKit.Visual;
|
|
var s = MochiKit.Style;
|
|
element = d.getElement(element);
|
|
options = MochiKit.Base.update({
|
|
direction: 'center',
|
|
moveTransition: v.Transitions.sinoidal,
|
|
scaleTransition: v.Transitions.sinoidal,
|
|
opacityTransition: v.Transitions.none,
|
|
scaleContent: true,
|
|
scaleFromCenter: false
|
|
}, options);
|
|
var oldStyle = {
|
|
top: element.style.top,
|
|
left: element.style.left,
|
|
height: element.style.height,
|
|
width: element.style.width,
|
|
opacity: s.getStyle(element, 'opacity')
|
|
};
|
|
|
|
var dims = s.getElementDimensions(element, true);
|
|
var moveX, moveY;
|
|
|
|
switch (options.direction) {
|
|
case 'top-left':
|
|
moveX = moveY = 0;
|
|
break;
|
|
case 'top-right':
|
|
moveX = dims.w;
|
|
moveY = 0;
|
|
break;
|
|
case 'bottom-left':
|
|
moveX = 0;
|
|
moveY = dims.h;
|
|
break;
|
|
case 'bottom-right':
|
|
moveX = dims.w;
|
|
moveY = dims.h;
|
|
break;
|
|
case 'center':
|
|
moveX = dims.w / 2;
|
|
moveY = dims.h / 2;
|
|
break;
|
|
}
|
|
var elemClip;
|
|
|
|
var optionsParallel = MochiKit.Base.update({
|
|
beforeStartInternal: function (effect) {
|
|
s.makePositioned(effect.effects[0].element);
|
|
elemClip = s.makeClipping(effect.effects[0].element);
|
|
},
|
|
afterFinishInternal: function (effect) {
|
|
s.hideElement(effect.effects[0].element);
|
|
s.undoClipping(effect.effects[0].element, elemClip);
|
|
s.undoPositioned(effect.effects[0].element);
|
|
s.setStyle(effect.effects[0].element, oldStyle);
|
|
}
|
|
}, options);
|
|
|
|
return new v.Parallel(
|
|
[new v.Opacity(element, {
|
|
sync: true, to: 0.0, from: 1.0,
|
|
transition: options.opacityTransition
|
|
}),
|
|
new v.Scale(element, /Opera/.test(navigator.userAgent) ? 1 : 0, {
|
|
scaleMode: {originalHeight: dims.h, originalWidth: dims.w},
|
|
sync: true, transition: options.scaleTransition,
|
|
scaleContent: options.scaleContent,
|
|
scaleFromCenter: options.scaleFromCenter,
|
|
restoreAfterFinish: true
|
|
}),
|
|
new v.Move(element, {
|
|
x: moveX, y: moveY, sync: true, transition: options.moveTransition
|
|
})
|
|
], optionsParallel
|
|
);
|
|
};
|
|
|
|
/** @id MochiKit.Visual.pulsate */
|
|
MochiKit.Visual.pulsate = function (element, /* optional */ options) {
|
|
/***
|
|
|
|
Pulse an element between appear/fade.
|
|
|
|
***/
|
|
var d = MochiKit.DOM;
|
|
var v = MochiKit.Visual;
|
|
var b = MochiKit.Base;
|
|
var oldOpacity = MochiKit.Style.getStyle(element, 'opacity');
|
|
options = b.update({
|
|
duration: 3.0,
|
|
from: 0,
|
|
afterFinishInternal: function (effect) {
|
|
MochiKit.Style.setStyle(effect.element, {'opacity': oldOpacity});
|
|
}
|
|
}, options);
|
|
var transition = options.transition || v.Transitions.sinoidal;
|
|
options.transition = function (pos) {
|
|
return transition(1 - v.Transitions.pulse(pos, options.pulses));
|
|
};
|
|
return new v.Opacity(element, options);
|
|
};
|
|
|
|
/** @id MochiKit.Visual.fold */
|
|
MochiKit.Visual.fold = function (element, /* optional */ options) {
|
|
/***
|
|
|
|
Fold an element, first vertically, then horizontally.
|
|
|
|
***/
|
|
var d = MochiKit.DOM;
|
|
var v = MochiKit.Visual;
|
|
var s = MochiKit.Style;
|
|
element = d.getElement(element);
|
|
var elementDimensions = s.getElementDimensions(element, true);
|
|
var oldStyle = {
|
|
top: element.style.top,
|
|
left: element.style.left,
|
|
width: element.style.width,
|
|
height: element.style.height
|
|
};
|
|
var elemClip = s.makeClipping(element);
|
|
options = MochiKit.Base.update({
|
|
scaleContent: false,
|
|
scaleX: false,
|
|
scaleMode: {originalHeight: elementDimensions.h,
|
|
originalWidth: elementDimensions.w},
|
|
afterFinishInternal: function (effect) {
|
|
new v.Scale(element, 1, {
|
|
scaleContent: false,
|
|
scaleY: false,
|
|
scaleMode: {originalHeight: elementDimensions.h,
|
|
originalWidth: elementDimensions.w},
|
|
afterFinishInternal: function (effect) {
|
|
s.hideElement(effect.element);
|
|
s.undoClipping(effect.element, elemClip);
|
|
s.setStyle(effect.element, oldStyle);
|
|
}
|
|
});
|
|
}
|
|
}, options);
|
|
return new v.Scale(element, 5, options);
|
|
};
|
|
|
|
|
|
MochiKit.Base.nameFunctions(MochiKit.Visual);
|
|
MochiKit.Base._exportSymbols(this, MochiKit.Visual);
|