author | Giulio Cesare Solaroli <giulio.cesare@clipperz.com> | 2013-08-30 15:56:53 (UTC) |
---|---|---|
committer | Giulio Cesare Solaroli <giulio.cesare@clipperz.com> | 2013-08-30 21:23:42 (UTC) |
commit | 20bea94ab6b91c85b171dcf86baba0a64169d508 (patch) (unidiff) | |
tree | 6e38e91498dcdb861620eba1e237d1026fe79cc5 /frontend/delta/js/MochiKit/Visual.js | |
parent | bde3c7b98523112ade9c5bbf7390c4ecb494cd2e (diff) | |
download | clipperz-20bea94ab6b91c85b171dcf86baba0a64169d508.zip clipperz-20bea94ab6b91c85b171dcf86baba0a64169d508.tar.gz clipperz-20bea94ab6b91c85b171dcf86baba0a64169d508.tar.bz2 |
First release of /delta version
Diffstat (limited to 'frontend/delta/js/MochiKit/Visual.js') (more/less context) (show whitespace changes)
-rw-r--r-- | frontend/delta/js/MochiKit/Visual.js | 1999 |
1 files changed, 1999 insertions, 0 deletions
diff --git a/frontend/delta/js/MochiKit/Visual.js b/frontend/delta/js/MochiKit/Visual.js new file mode 100644 index 0000000..9bcd805 --- a/dev/null +++ b/frontend/delta/js/MochiKit/Visual.js | |||
@@ -0,0 +1,1999 @@ | |||
1 | /* | ||
2 | |||
3 | Copyright 2008-2013 Clipperz Srl | ||
4 | |||
5 | This file is part of Clipperz, the online password manager. | ||
6 | For further information about its features and functionalities please | ||
7 | refer to http://www.clipperz.com. | ||
8 | |||
9 | * Clipperz is free software: you can redistribute it and/or modify it | ||
10 | under the terms of the GNU Affero General Public License as published | ||
11 | by the Free Software Foundation, either version 3 of the License, or | ||
12 | (at your option) any later version. | ||
13 | |||
14 | * Clipperz is distributed in the hope that it will be useful, but | ||
15 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
17 | See the GNU Affero General Public License for more details. | ||
18 | |||
19 | * You should have received a copy of the GNU Affero General Public | ||
20 | License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||
21 | |||
22 | */ | ||
23 | |||
24 | /*** | ||
25 | |||
26 | MochiKit.Visual 1.5 | ||
27 | |||
28 | See <http://mochikit.com/> for documentation, downloads, license, etc. | ||
29 | |||
30 | (c) 2005 Bob Ippolito and others. All rights Reserved. | ||
31 | |||
32 | ***/ | ||
33 | |||
34 | MochiKit.Base.module(MochiKit, 'Visual', '1.5', ['Base', 'DOM', 'Style', 'Color', 'Position']); | ||
35 | |||
36 | MochiKit.Visual._RoundCorners = function (e, options) { | ||
37 | e = MochiKit.DOM.getElement(e); | ||
38 | this._setOptions(options); | ||
39 | if (this.options.__unstable__wrapElement) { | ||
40 | e = this._doWrap(e); | ||
41 | } | ||
42 | |||
43 | var color = this.options.color; | ||
44 | var C = MochiKit.Color.Color; | ||
45 | if (this.options.color === "fromElement") { | ||
46 | color = C.fromBackground(e); | ||
47 | } else if (!(color instanceof C)) { | ||
48 | color = C.fromString(color); | ||
49 | } | ||
50 | this.isTransparent = (color.asRGB().a <= 0); | ||
51 | |||
52 | var bgColor = this.options.bgColor; | ||
53 | if (this.options.bgColor === "fromParent") { | ||
54 | bgColor = C.fromBackground(e.offsetParent); | ||
55 | } else if (!(bgColor instanceof C)) { | ||
56 | bgColor = C.fromString(bgColor); | ||
57 | } | ||
58 | |||
59 | this._roundCornersImpl(e, color, bgColor); | ||
60 | }; | ||
61 | |||
62 | MochiKit.Visual._RoundCorners.prototype = { | ||
63 | _doWrap: function (e) { | ||
64 | var parent = e.parentNode; | ||
65 | var doc = MochiKit.DOM.currentDocument(); | ||
66 | if (typeof(doc.defaultView) === "undefined" | ||
67 | || doc.defaultView === null) { | ||
68 | return e; | ||
69 | } | ||
70 | var style = doc.defaultView.getComputedStyle(e, null); | ||
71 | if (typeof(style) === "undefined" || style === null) { | ||
72 | return e; | ||
73 | } | ||
74 | var wrapper = MochiKit.DOM.DIV({"style": { | ||
75 | display: "block", | ||
76 | // convert padding to margin | ||
77 | marginTop: style.getPropertyValue("padding-top"), | ||
78 | marginRight: style.getPropertyValue("padding-right"), | ||
79 | marginBottom: style.getPropertyValue("padding-bottom"), | ||
80 | marginLeft: style.getPropertyValue("padding-left"), | ||
81 | // remove padding so the rounding looks right | ||
82 | padding: "0px" | ||
83 | /* | ||
84 | paddingRight: "0px", | ||
85 | paddingLeft: "0px" | ||
86 | */ | ||
87 | }}); | ||
88 | wrapper.innerHTML = e.innerHTML; | ||
89 | e.innerHTML = ""; | ||
90 | e.appendChild(wrapper); | ||
91 | return e; | ||
92 | }, | ||
93 | |||
94 | _roundCornersImpl: function (e, color, bgColor) { | ||
95 | if (this.options.border) { | ||
96 | this._renderBorder(e, bgColor); | ||
97 | } | ||
98 | if (this._isTopRounded()) { | ||
99 | this._roundTopCorners(e, color, bgColor); | ||
100 | } | ||
101 | if (this._isBottomRounded()) { | ||
102 | this._roundBottomCorners(e, color, bgColor); | ||
103 | } | ||
104 | }, | ||
105 | |||
106 | _renderBorder: function (el, bgColor) { | ||
107 | var borderValue = "1px solid " + this._borderColor(bgColor); | ||
108 | var borderL = "border-left: " + borderValue; | ||
109 | var borderR = "border-right: " + borderValue; | ||
110 | var style = "style='" + borderL + ";" + borderR + "'"; | ||
111 | el.innerHTML = "<div " + style + ">" + el.innerHTML + "</div>"; | ||
112 | }, | ||
113 | |||
114 | _roundTopCorners: function (el, color, bgColor) { | ||
115 | var corner = this._createCorner(bgColor); | ||
116 | for (var i = 0; i < this.options.numSlices; i++) { | ||
117 | corner.appendChild( | ||
118 | this._createCornerSlice(color, bgColor, i, "top") | ||
119 | ); | ||
120 | } | ||
121 | el.style.paddingTop = 0; | ||
122 | el.insertBefore(corner, el.firstChild); | ||
123 | }, | ||
124 | |||
125 | _roundBottomCorners: function (el, color, bgColor) { | ||
126 | var corner = this._createCorner(bgColor); | ||
127 | for (var i = (this.options.numSlices - 1); i >= 0; i--) { | ||
128 | corner.appendChild( | ||
129 | this._createCornerSlice(color, bgColor, i, "bottom") | ||
130 | ); | ||
131 | } | ||
132 | el.style.paddingBottom = 0; | ||
133 | el.appendChild(corner); | ||
134 | }, | ||
135 | |||
136 | _createCorner: function (bgColor) { | ||
137 | var dom = MochiKit.DOM; | ||
138 | return dom.DIV({style: {backgroundColor: bgColor.toString()}}); | ||
139 | }, | ||
140 | |||
141 | _createCornerSlice: function (color, bgColor, n, position) { | ||
142 | var slice = MochiKit.DOM.SPAN(); | ||
143 | |||
144 | var inStyle = slice.style; | ||
145 | inStyle.backgroundColor = color.toString(); | ||
146 | inStyle.display = "block"; | ||
147 | inStyle.height = "1px"; | ||
148 | inStyle.overflow = "hidden"; | ||
149 | inStyle.fontSize = "1px"; | ||
150 | |||
151 | var borderColor = this._borderColor(color, bgColor); | ||
152 | if (this.options.border && n === 0) { | ||
153 | inStyle.borderTopStyle = "solid"; | ||
154 | inStyle.borderTopWidth = "1px"; | ||
155 | inStyle.borderLeftWidth = "0px"; | ||
156 | inStyle.borderRightWidth = "0px"; | ||
157 | inStyle.borderBottomWidth = "0px"; | ||
158 | // assumes css compliant box model | ||
159 | inStyle.height = "0px"; | ||
160 | inStyle.borderColor = borderColor.toString(); | ||
161 | } else if (borderColor) { | ||
162 | inStyle.borderColor = borderColor.toString(); | ||
163 | inStyle.borderStyle = "solid"; | ||
164 | inStyle.borderWidth = "0px 1px"; | ||
165 | } | ||
166 | |||
167 | if (!this.options.compact && (n == (this.options.numSlices - 1))) { | ||
168 | inStyle.height = "2px"; | ||
169 | } | ||
170 | |||
171 | this._setMargin(slice, n, position); | ||
172 | this._setBorder(slice, n, position); | ||
173 | |||
174 | return slice; | ||
175 | }, | ||
176 | |||
177 | _setOptions: function (options) { | ||
178 | this.options = { | ||
179 | corners: "all", | ||
180 | color: "fromElement", | ||
181 | bgColor: "fromParent", | ||
182 | blend: true, | ||
183 | border: false, | ||
184 | compact: false, | ||
185 | __unstable__wrapElement: false | ||
186 | }; | ||
187 | MochiKit.Base.update(this.options, options); | ||
188 | |||
189 | this.options.numSlices = (this.options.compact ? 2 : 4); | ||
190 | }, | ||
191 | |||
192 | _whichSideTop: function () { | ||
193 | var corners = this.options.corners; | ||
194 | if (this._hasString(corners, "all", "top")) { | ||
195 | return ""; | ||
196 | } | ||
197 | |||
198 | var has_tl = (corners.indexOf("tl") != -1); | ||
199 | var has_tr = (corners.indexOf("tr") != -1); | ||
200 | if (has_tl && has_tr) { | ||
201 | return ""; | ||
202 | } | ||
203 | if (has_tl) { | ||
204 | return "left"; | ||
205 | } | ||
206 | if (has_tr) { | ||
207 | return "right"; | ||
208 | } | ||
209 | return ""; | ||
210 | }, | ||
211 | |||
212 | _whichSideBottom: function () { | ||
213 | var corners = this.options.corners; | ||
214 | if (this._hasString(corners, "all", "bottom")) { | ||
215 | return ""; | ||
216 | } | ||
217 | |||
218 | var has_bl = (corners.indexOf('bl') != -1); | ||
219 | var has_br = (corners.indexOf('br') != -1); | ||
220 | if (has_bl && has_br) { | ||
221 | return ""; | ||
222 | } | ||
223 | if (has_bl) { | ||
224 | return "left"; | ||
225 | } | ||
226 | if (has_br) { | ||
227 | return "right"; | ||
228 | } | ||
229 | return ""; | ||
230 | }, | ||
231 | |||
232 | _borderColor: function (color, bgColor) { | ||
233 | if (color == "transparent") { | ||
234 | return bgColor; | ||
235 | } else if (this.options.border) { | ||
236 | return this.options.border; | ||
237 | } else if (this.options.blend) { | ||
238 | return bgColor.blendedColor(color); | ||
239 | } | ||
240 | return ""; | ||
241 | }, | ||
242 | |||
243 | |||
244 | _setMargin: function (el, n, corners) { | ||
245 | var marginSize = this._marginSize(n) + "px"; | ||
246 | var whichSide = ( | ||
247 | corners == "top" ? this._whichSideTop() : this._whichSideBottom() | ||
248 | ); | ||
249 | var style = el.style; | ||
250 | |||
251 | if (whichSide == "left") { | ||
252 | style.marginLeft = marginSize; | ||
253 | style.marginRight = "0px"; | ||
254 | } else if (whichSide == "right") { | ||
255 | style.marginRight = marginSize; | ||
256 | style.marginLeft = "0px"; | ||
257 | } else { | ||
258 | style.marginLeft = marginSize; | ||
259 | style.marginRight = marginSize; | ||
260 | } | ||
261 | }, | ||
262 | |||
263 | _setBorder: function (el, n, corners) { | ||
264 | var borderSize = this._borderSize(n) + "px"; | ||
265 | var whichSide = ( | ||
266 | corners == "top" ? this._whichSideTop() : this._whichSideBottom() | ||
267 | ); | ||
268 | |||
269 | var style = el.style; | ||
270 | if (whichSide == "left") { | ||
271 | style.borderLeftWidth = borderSize; | ||
272 | style.borderRightWidth = "0px"; | ||
273 | } else if (whichSide == "right") { | ||
274 | style.borderRightWidth = borderSize; | ||
275 | style.borderLeftWidth = "0px"; | ||
276 | } else { | ||
277 | style.borderLeftWidth = borderSize; | ||
278 | style.borderRightWidth = borderSize; | ||
279 | } | ||
280 | }, | ||
281 | |||
282 | _marginSize: function (n) { | ||
283 | if (this.isTransparent) { | ||
284 | return 0; | ||
285 | } | ||
286 | |||
287 | var o = this.options; | ||
288 | if (o.compact && o.blend) { | ||
289 | var smBlendedMarginSizes = [1, 0]; | ||
290 | return smBlendedMarginSizes[n]; | ||
291 | } else if (o.compact) { | ||
292 | var compactMarginSizes = [2, 1]; | ||
293 | return compactMarginSizes[n]; | ||
294 | } else if (o.blend) { | ||
295 | var blendedMarginSizes = [3, 2, 1, 0]; | ||
296 | return blendedMarginSizes[n]; | ||
297 | } else { | ||
298 | var marginSizes = [5, 3, 2, 1]; | ||
299 | return marginSizes[n]; | ||
300 | } | ||
301 | }, | ||
302 | |||
303 | _borderSize: function (n) { | ||
304 | var o = this.options; | ||
305 | var borderSizes; | ||
306 | if (o.compact && (o.blend || this.isTransparent)) { | ||
307 | return 1; | ||
308 | } else if (o.compact) { | ||
309 | borderSizes = [1, 0]; | ||
310 | } else if (o.blend) { | ||
311 | borderSizes = [2, 1, 1, 1]; | ||
312 | } else if (o.border) { | ||
313 | borderSizes = [0, 2, 0, 0]; | ||
314 | } else if (this.isTransparent) { | ||
315 | borderSizes = [5, 3, 2, 1]; | ||
316 | } else { | ||
317 | return 0; | ||
318 | } | ||
319 | return borderSizes[n]; | ||
320 | }, | ||
321 | |||
322 | _hasString: function (str) { | ||
323 | for (var i = 1; i< arguments.length; i++) { | ||
324 | if (str.indexOf(arguments[i]) != -1) { | ||
325 | return true; | ||
326 | } | ||
327 | } | ||
328 | return false; | ||
329 | }, | ||
330 | |||
331 | _isTopRounded: function () { | ||
332 | return this._hasString(this.options.corners, | ||
333 | "all", "top", "tl", "tr" | ||
334 | ); | ||
335 | }, | ||
336 | |||
337 | _isBottomRounded: function () { | ||
338 | return this._hasString(this.options.corners, | ||
339 | "all", "bottom", "bl", "br" | ||
340 | ); | ||
341 | }, | ||
342 | |||
343 | _hasSingleTextChild: function (el) { | ||
344 | return (el.childNodes.length == 1 && el.childNodes[0].nodeType == 3); | ||
345 | } | ||
346 | }; | ||
347 | |||
348 | /** @id MochiKit.Visual.roundElement */ | ||
349 | MochiKit.Visual.roundElement = function (e, options) { | ||
350 | new MochiKit.Visual._RoundCorners(e, options); | ||
351 | }; | ||
352 | |||
353 | /** @id MochiKit.Visual.roundClass */ | ||
354 | MochiKit.Visual.roundClass = function (tagName, className, options) { | ||
355 | var elements = MochiKit.DOM.getElementsByTagAndClassName( | ||
356 | tagName, className | ||
357 | ); | ||
358 | for (var i = 0; i < elements.length; i++) { | ||
359 | MochiKit.Visual.roundElement(elements[i], options); | ||
360 | } | ||
361 | }; | ||
362 | |||
363 | /** @id MochiKit.Visual.tagifyText */ | ||
364 | MochiKit.Visual.tagifyText = function (element, /* optional */tagifyStyle) { | ||
365 | /*** | ||
366 | |||
367 | Change a node text to character in tags. | ||
368 | |||
369 | @param tagifyStyle: the style to apply to character nodes, default to | ||
370 | 'position: relative'. | ||
371 | |||
372 | ***/ | ||
373 | tagifyStyle = tagifyStyle || 'position:relative'; | ||
374 | if (/MSIE/.test(navigator.userAgent)) { | ||
375 | tagifyStyle += ';zoom:1'; | ||
376 | } | ||
377 | element = MochiKit.DOM.getElement(element); | ||
378 | var ma = MochiKit.Base.map; | ||
379 | ma(function (child) { | ||
380 | if (child.nodeType == 3) { | ||
381 | ma(function (character) { | ||
382 | element.insertBefore( | ||
383 | MochiKit.DOM.SPAN({style: tagifyStyle}, | ||
384 | character == ' ' ? String.fromCharCode(160) : character), child); | ||
385 | }, child.nodeValue.split('')); | ||
386 | MochiKit.DOM.removeElement(child); | ||
387 | } | ||
388 | }, element.childNodes); | ||
389 | }; | ||
390 | |||
391 | MochiKit.Visual._forceRerendering = function (element) { | ||
392 | try { | ||
393 | element = MochiKit.DOM.getElement(element); | ||
394 | var n = document.createTextNode(' '); | ||
395 | element.appendChild(n); | ||
396 | element.removeChild(n); | ||
397 | } catch(e) { | ||
398 | } | ||
399 | }; | ||
400 | |||
401 | /** @id MochiKit.Visual.multiple */ | ||
402 | MochiKit.Visual.multiple = function (elements, effect, /* optional */options) { | ||
403 | /*** | ||
404 | |||
405 | Launch the same effect subsequently on given elements. | ||
406 | |||
407 | ***/ | ||
408 | options = MochiKit.Base.update({ | ||
409 | speed: 0.1, delay: 0.0 | ||
410 | }, options); | ||
411 | var masterDelay = options.delay; | ||
412 | var index = 0; | ||
413 | MochiKit.Base.map(function (innerelement) { | ||
414 | options.delay = index * options.speed + masterDelay; | ||
415 | new effect(innerelement, options); | ||
416 | index += 1; | ||
417 | }, elements); | ||
418 | }; | ||
419 | |||
420 | MochiKit.Visual.PAIRS = { | ||
421 | 'slide': ['slideDown', 'slideUp'], | ||
422 | 'blind': ['blindDown', 'blindUp'], | ||
423 | 'appear': ['appear', 'fade'], | ||
424 | 'size': ['grow', 'shrink'] | ||
425 | }; | ||
426 | |||
427 | /** @id MochiKit.Visual.toggle */ | ||
428 | MochiKit.Visual.toggle = function (element, /* optional */effect, /* optional */options) { | ||
429 | /*** | ||
430 | |||
431 | Toggle an item between two state depending of its visibility, making | ||
432 | a effect between these states. Default effect is 'appear', can be | ||
433 | 'slide' or 'blind'. | ||
434 | |||
435 | ***/ | ||
436 | element = MochiKit.DOM.getElement(element); | ||
437 | effect = (effect || 'appear').toLowerCase(); | ||
438 | options = MochiKit.Base.update({ | ||
439 | queue: {position: 'end', scope: (element.id || 'global'), limit: 1} | ||
440 | }, options); | ||
441 | var v = MochiKit.Visual; | ||
442 | v[MochiKit.Style.getStyle(element, 'display') != 'none' ? | ||
443 | v.PAIRS[effect][1] : v.PAIRS[effect][0]](element, options); | ||
444 | }; | ||
445 | |||
446 | /*** | ||
447 | |||
448 | Transitions: define functions calculating variations depending of a position. | ||
449 | |||
450 | ***/ | ||
451 | |||
452 | MochiKit.Visual.Transitions = { __export__: false }; | ||
453 | |||
454 | /** @id MochiKit.Visual.Transitions.linear */ | ||
455 | MochiKit.Visual.Transitions.linear = function (pos) { | ||
456 | return pos; | ||
457 | }; | ||
458 | |||
459 | /** @id MochiKit.Visual.Transitions.sinoidal */ | ||
460 | MochiKit.Visual.Transitions.sinoidal = function (pos) { | ||
461 | return 0.5 - Math.cos(pos*Math.PI)/2; | ||
462 | }; | ||
463 | |||
464 | /** @id MochiKit.Visual.Transitions.reverse */ | ||
465 | MochiKit.Visual.Transitions.reverse = function (pos) { | ||
466 | return 1 - pos; | ||
467 | }; | ||
468 | |||
469 | /** @id MochiKit.Visual.Transitions.flicker */ | ||
470 | MochiKit.Visual.Transitions.flicker = function (pos) { | ||
471 | return 0.25 - Math.cos(pos*Math.PI)/4 + Math.random()/2; | ||
472 | }; | ||
473 | |||
474 | /** @id MochiKit.Visual.Transitions.wobble */ | ||
475 | MochiKit.Visual.Transitions.wobble = function (pos) { | ||
476 | return 0.5 - Math.cos(9*pos*Math.PI)/2; | ||
477 | }; | ||
478 | |||
479 | /** @id MochiKit.Visual.Transitions.pulse */ | ||
480 | MochiKit.Visual.Transitions.pulse = function (pos, pulses) { | ||
481 | if (pulses) { | ||
482 | pos *= 2 * pulses; | ||
483 | } else { | ||
484 | pos *= 10; | ||
485 | } | ||
486 | var decimals = pos - Math.floor(pos); | ||
487 | return (Math.floor(pos) % 2 == 0) ? decimals : 1 - decimals; | ||
488 | }; | ||
489 | |||
490 | /** @id MochiKit.Visual.Transitions.parabolic */ | ||
491 | MochiKit.Visual.Transitions.parabolic = function (pos) { | ||
492 | return pos * pos; | ||
493 | }; | ||
494 | |||
495 | /** @id MochiKit.Visual.Transitions.spring */ | ||
496 | MochiKit.Visual.Transitions.spring = function (pos) { | ||
497 | return 1 - (Math.cos(pos * 2.5 * Math.PI) * Math.exp(-pos * 6)); | ||
498 | }; | ||
499 | |||
500 | /** @id MochiKit.Visual.Transitions.none */ | ||
501 | MochiKit.Visual.Transitions.none = function (pos) { | ||
502 | return 0; | ||
503 | }; | ||
504 | |||
505 | /** @id MochiKit.Visual.Transitions.full */ | ||
506 | MochiKit.Visual.Transitions.full = function (pos) { | ||
507 | return 1; | ||
508 | }; | ||
509 | |||
510 | /*** | ||
511 | |||
512 | Core effects | ||
513 | |||
514 | ***/ | ||
515 | |||
516 | MochiKit.Visual.ScopedQueue = function () { | ||
517 | var cls = arguments.callee; | ||
518 | if (!(this instanceof cls)) { | ||
519 | return new cls(); | ||
520 | } | ||
521 | this.__init__(); | ||
522 | }; | ||
523 | MochiKit.Visual.ScopedQueue.__export__ = false; | ||
524 | |||
525 | MochiKit.Base.update(MochiKit.Visual.ScopedQueue.prototype, { | ||
526 | __init__: function () { | ||
527 | this.effects = []; | ||
528 | this.interval = null; | ||
529 | }, | ||
530 | |||
531 | /** @id MochiKit.Visual.ScopedQueue.prototype.add */ | ||
532 | add: function (effect) { | ||
533 | var timestamp = new Date().getTime(); | ||
534 | |||
535 | var position = (typeof(effect.options.queue) == 'string') ? | ||
536 | effect.options.queue : effect.options.queue.position; | ||
537 | |||
538 | var ma = MochiKit.Base.map; | ||
539 | switch (position) { | ||
540 | case 'front': | ||
541 | // move unstarted effects after this effect | ||
542 | ma(function (e) { | ||
543 | if (e.state == 'idle') { | ||
544 | e.startOn += effect.finishOn; | ||
545 | e.finishOn += effect.finishOn; | ||
546 | } | ||
547 | }, this.effects); | ||
548 | break; | ||
549 | case 'end': | ||
550 | var finish; | ||
551 | // start effect after last queued effect has finished | ||
552 | ma(function (e) { | ||
553 | var i = e.finishOn; | ||
554 | if (i >= (finish || i)) { | ||
555 | finish = i; | ||
556 | } | ||
557 | }, this.effects); | ||
558 | timestamp = finish || timestamp; | ||
559 | break; | ||
560 | case 'break': | ||
561 | ma(function (e) { | ||
562 | e.finalize(); | ||
563 | }, this.effects); | ||
564 | break; | ||
565 | case 'replace': | ||
566 | ma(function (e) { | ||
567 | e.cancel(); | ||
568 | }, this.effects); | ||
569 | break; | ||
570 | } | ||
571 | |||
572 | effect.startOn += timestamp; | ||
573 | effect.finishOn += timestamp; | ||
574 | if (!effect.options.queue.limit || | ||
575 | this.effects.length < effect.options.queue.limit) { | ||
576 | this.effects.push(effect); | ||
577 | } | ||
578 | |||
579 | if (!this.interval) { | ||
580 | this.interval = this.startLoop(MochiKit.Base.bind(this.loop, this), | ||
581 | 40); | ||
582 | } | ||
583 | }, | ||
584 | |||
585 | /** @id MochiKit.Visual.ScopedQueue.prototype.startLoop */ | ||
586 | startLoop: function (func, interval) { | ||
587 | return setInterval(func, interval); | ||
588 | }, | ||
589 | |||
590 | /** @id MochiKit.Visual.ScopedQueue.prototype.remove */ | ||
591 | remove: function (effect) { | ||
592 | this.effects = MochiKit.Base.filter(function (e) { | ||
593 | return e != effect; | ||
594 | }, this.effects); | ||
595 | if (!this.effects.length) { | ||
596 | this.stopLoop(this.interval); | ||
597 | this.interval = null; | ||
598 | } | ||
599 | }, | ||
600 | |||
601 | /** @id MochiKit.Visual.ScopedQueue.prototype.stopLoop */ | ||
602 | stopLoop: function (interval) { | ||
603 | clearInterval(interval); | ||
604 | }, | ||
605 | |||
606 | /** @id MochiKit.Visual.ScopedQueue.prototype.loop */ | ||
607 | loop: function () { | ||
608 | var timePos = new Date().getTime(); | ||
609 | MochiKit.Base.map(function (effect) { | ||
610 | effect.loop(timePos); | ||
611 | }, this.effects); | ||
612 | } | ||
613 | }); | ||
614 | |||
615 | MochiKit.Visual.Queues = { | ||
616 | __export__: false, | ||
617 | instances: {}, | ||
618 | get: function (queueName) { | ||
619 | if (typeof(queueName) != 'string') { | ||
620 | return queueName; | ||
621 | } | ||
622 | |||
623 | if (!this.instances[queueName]) { | ||
624 | this.instances[queueName] = new MochiKit.Visual.ScopedQueue(); | ||
625 | } | ||
626 | return this.instances[queueName]; | ||
627 | } | ||
628 | }; | ||
629 | |||
630 | MochiKit.Visual.Queue = MochiKit.Visual.Queues.get('global'); | ||
631 | MochiKit.Visual.Queue.__export__ = false; | ||
632 | |||
633 | MochiKit.Visual.DefaultOptions = { | ||
634 | __export__: false, | ||
635 | transition: MochiKit.Visual.Transitions.sinoidal, | ||
636 | duration: 1.0, // seconds | ||
637 | fps: 25.0, // max. 25fps due to MochiKit.Visual.Queue implementation | ||
638 | sync: false, // true for combining | ||
639 | from: 0.0, | ||
640 | to: 1.0, | ||
641 | delay: 0.0, | ||
642 | queue: 'parallel' | ||
643 | }; | ||
644 | |||
645 | MochiKit.Visual.Base = function () {}; | ||
646 | |||
647 | MochiKit.Visual.Base.prototype = { | ||
648 | /*** | ||
649 | |||
650 | Basic class for all Effects. Define a looping mechanism called for each step | ||
651 | of an effect. Don't instantiate it, only subclass it. | ||
652 | |||
653 | ***/ | ||
654 | |||
655 | __class__ : MochiKit.Visual.Base, | ||
656 | |||
657 | /** @id MochiKit.Visual.Base.prototype.start */ | ||
658 | start: function (options) { | ||
659 | var v = MochiKit.Visual; | ||
660 | this.options = MochiKit.Base.setdefault(options, | ||
661 | v.DefaultOptions); | ||
662 | this.currentFrame = 0; | ||
663 | this.state = 'idle'; | ||
664 | this.startOn = this.options.delay*1000; | ||
665 | this.finishOn = this.startOn + (this.options.duration*1000); | ||
666 | this.event('beforeStart'); | ||
667 | if (!this.options.sync) { | ||
668 | v.Queues.get(typeof(this.options.queue) == 'string' ? | ||
669 | 'global' : this.options.queue.scope).add(this); | ||
670 | } | ||
671 | }, | ||
672 | |||
673 | /** @id MochiKit.Visual.Base.prototype.loop */ | ||
674 | loop: function (timePos) { | ||
675 | if (timePos >= this.startOn) { | ||
676 | if (timePos >= this.finishOn) { | ||
677 | return this.finalize(); | ||
678 | } | ||
679 | var pos = (timePos - this.startOn) / (this.finishOn - this.startOn); | ||
680 | var frame = | ||
681 | Math.round(pos * this.options.fps * this.options.duration); | ||
682 | if (frame > this.currentFrame) { | ||
683 | this.render(pos); | ||
684 | this.currentFrame = frame; | ||
685 | } | ||
686 | } | ||
687 | }, | ||
688 | |||
689 | /** @id MochiKit.Visual.Base.prototype.render */ | ||
690 | render: function (pos) { | ||
691 | if (this.state == 'idle') { | ||
692 | this.state = 'running'; | ||
693 | this.event('beforeSetup'); | ||
694 | this.setup(); | ||
695 | this.event('afterSetup'); | ||
696 | } | ||
697 | if (this.state == 'running') { | ||
698 | var trans = this.options.transition; | ||
699 | if (typeof(trans) == "string") { | ||
700 | trans = MochiKit.Visual.Transitions[trans]; | ||
701 | } | ||
702 | if (typeof(trans) == "function") { | ||
703 | pos = trans(pos); | ||
704 | } | ||
705 | pos *= (this.options.to - this.options.from); | ||
706 | pos += this.options.from; | ||
707 | this.event('beforeUpdate'); | ||
708 | this.update(pos); | ||
709 | this.event('afterUpdate'); | ||
710 | } | ||
711 | }, | ||
712 | |||
713 | /** @id MochiKit.Visual.Base.prototype.cancel */ | ||
714 | cancel: function () { | ||
715 | if (!this.options.sync) { | ||
716 | MochiKit.Visual.Queues.get(typeof(this.options.queue) == 'string' ? | ||
717 | 'global' : this.options.queue.scope).remove(this); | ||
718 | } | ||
719 | this.state = 'finished'; | ||
720 | }, | ||
721 | |||
722 | /** @id MochiKit.Visual.Base.prototype.finalize */ | ||
723 | finalize: function () { | ||
724 | this.render(1.0); | ||
725 | this.cancel(); | ||
726 | this.event('beforeFinish'); | ||
727 | this.finish(); | ||
728 | this.event('afterFinish'); | ||
729 | }, | ||
730 | |||
731 | setup: function () { | ||
732 | }, | ||
733 | |||
734 | finish: function () { | ||
735 | }, | ||
736 | |||
737 | update: function (position) { | ||
738 | }, | ||
739 | |||
740 | /** @id MochiKit.Visual.Base.prototype.event */ | ||
741 | event: function (eventName) { | ||
742 | if (this.options[eventName + 'Internal']) { | ||
743 | this.options[eventName + 'Internal'](this); | ||
744 | } | ||
745 | if (this.options[eventName]) { | ||
746 | this.options[eventName](this); | ||
747 | } | ||
748 | }, | ||
749 | |||
750 | /** @id MochiKit.Visual.Base.prototype.repr */ | ||
751 | repr: function () { | ||
752 | return '[' + this.__class__.NAME + ', options:' + | ||
753 | MochiKit.Base.repr(this.options) + ']'; | ||
754 | } | ||
755 | }; | ||
756 | |||
757 | /** @id MochiKit.Visual.Parallel */ | ||
758 | MochiKit.Visual.Parallel = function (effects, options) { | ||
759 | var cls = arguments.callee; | ||
760 | if (!(this instanceof cls)) { | ||
761 | return new cls(effects, options); | ||
762 | } | ||
763 | |||
764 | this.__init__(effects, options); | ||
765 | }; | ||
766 | |||
767 | MochiKit.Visual.Parallel.prototype = new MochiKit.Visual.Base(); | ||
768 | |||
769 | MochiKit.Base.update(MochiKit.Visual.Parallel.prototype, { | ||
770 | /*** | ||
771 | |||
772 | Run multiple effects at the same time. | ||
773 | |||
774 | ***/ | ||
775 | |||
776 | __class__ : MochiKit.Visual.Parallel, | ||
777 | |||
778 | __init__: function (effects, options) { | ||
779 | this.effects = effects || []; | ||
780 | this.start(options); | ||
781 | }, | ||
782 | |||
783 | /** @id MochiKit.Visual.Parallel.prototype.update */ | ||
784 | update: function (position) { | ||
785 | MochiKit.Base.map(function (effect) { | ||
786 | effect.render(position); | ||
787 | }, this.effects); | ||
788 | }, | ||
789 | |||
790 | /** @id MochiKit.Visual.Parallel.prototype.finish */ | ||
791 | finish: function () { | ||
792 | MochiKit.Base.map(function (effect) { | ||
793 | effect.finalize(); | ||
794 | }, this.effects); | ||
795 | } | ||
796 | }); | ||
797 | |||
798 | /** @id MochiKit.Visual.Sequence */ | ||
799 | MochiKit.Visual.Sequence = function (effects, options) { | ||
800 | var cls = arguments.callee; | ||
801 | if (!(this instanceof cls)) { | ||
802 | return new cls(effects, options); | ||
803 | } | ||
804 | this.__init__(effects, options); | ||
805 | }; | ||
806 | |||
807 | MochiKit.Visual.Sequence.prototype = new MochiKit.Visual.Base(); | ||
808 | |||
809 | MochiKit.Base.update(MochiKit.Visual.Sequence.prototype, { | ||
810 | |||
811 | __class__ : MochiKit.Visual.Sequence, | ||
812 | |||
813 | __init__: function (effects, options) { | ||
814 | var defs = { transition: MochiKit.Visual.Transitions.linear, | ||
815 | duration: 0 }; | ||
816 | this.effects = effects || []; | ||
817 | MochiKit.Base.map(function (effect) { | ||
818 | defs.duration += effect.options.duration; | ||
819 | }, this.effects); | ||
820 | MochiKit.Base.setdefault(options, defs); | ||
821 | this.start(options); | ||
822 | }, | ||
823 | |||
824 | /** @id MochiKit.Visual.Sequence.prototype.update */ | ||
825 | update: function (position) { | ||
826 | var time = position * this.options.duration; | ||
827 | for (var i = 0; i < this.effects.length; i++) { | ||
828 | var effect = this.effects[i]; | ||
829 | if (time <= effect.options.duration) { | ||
830 | effect.render(time / effect.options.duration); | ||
831 | break; | ||
832 | } else { | ||
833 | time -= effect.options.duration; | ||
834 | } | ||
835 | } | ||
836 | }, | ||
837 | |||
838 | /** @id MochiKit.Visual.Sequence.prototype.finish */ | ||
839 | finish: function () { | ||
840 | MochiKit.Base.map(function (effect) { | ||
841 | effect.finalize(); | ||
842 | }, this.effects); | ||
843 | } | ||
844 | }); | ||
845 | |||
846 | /** @id MochiKit.Visual.Opacity */ | ||
847 | MochiKit.Visual.Opacity = function (element, options) { | ||
848 | var cls = arguments.callee; | ||
849 | if (!(this instanceof cls)) { | ||
850 | return new cls(element, options); | ||
851 | } | ||
852 | this.__init__(element, options); | ||
853 | }; | ||
854 | |||
855 | MochiKit.Visual.Opacity.prototype = new MochiKit.Visual.Base(); | ||
856 | |||
857 | MochiKit.Base.update(MochiKit.Visual.Opacity.prototype, { | ||
858 | /*** | ||
859 | |||
860 | Change the opacity of an element. | ||
861 | |||
862 | @param options: 'from' and 'to' change the starting and ending opacities. | ||
863 | Must be between 0.0 and 1.0. Default to current opacity and 1.0. | ||
864 | |||
865 | ***/ | ||
866 | |||
867 | __class__ : MochiKit.Visual.Opacity, | ||
868 | |||
869 | __init__: function (element, /* optional */options) { | ||
870 | var b = MochiKit.Base; | ||
871 | var s = MochiKit.Style; | ||
872 | this.element = MochiKit.DOM.getElement(element); | ||
873 | // make this work on IE on elements without 'layout' | ||
874 | if (this.element.currentStyle && | ||
875 | (!this.element.currentStyle.hasLayout)) { | ||
876 | s.setStyle(this.element, {zoom: 1}); | ||
877 | } | ||
878 | options = b.update({ | ||
879 | from: s.getStyle(this.element, 'opacity') || 0.0, | ||
880 | to: 1.0 | ||
881 | }, options); | ||
882 | this.start(options); | ||
883 | }, | ||
884 | |||
885 | /** @id MochiKit.Visual.Opacity.prototype.update */ | ||
886 | update: function (position) { | ||
887 | MochiKit.Style.setStyle(this.element, {'opacity': position}); | ||
888 | } | ||
889 | }); | ||
890 | |||
891 | /** @id MochiKit.Visual.Move.prototype */ | ||
892 | MochiKit.Visual.Move = function (element, options) { | ||
893 | var cls = arguments.callee; | ||
894 | if (!(this instanceof cls)) { | ||
895 | return new cls(element, options); | ||
896 | } | ||
897 | this.__init__(element, options); | ||
898 | }; | ||
899 | |||
900 | MochiKit.Visual.Move.prototype = new MochiKit.Visual.Base(); | ||
901 | |||
902 | MochiKit.Base.update(MochiKit.Visual.Move.prototype, { | ||
903 | /*** | ||
904 | |||
905 | Move an element between its current position to a defined position | ||
906 | |||
907 | @param options: 'x' and 'y' for final positions, default to 0, 0. | ||
908 | |||
909 | ***/ | ||
910 | |||
911 | __class__ : MochiKit.Visual.Move, | ||
912 | |||
913 | __init__: function (element, /* optional */options) { | ||
914 | this.element = MochiKit.DOM.getElement(element); | ||
915 | options = MochiKit.Base.update({ | ||
916 | x: 0, | ||
917 | y: 0, | ||
918 | mode: 'relative' | ||
919 | }, options); | ||
920 | this.start(options); | ||
921 | }, | ||
922 | |||
923 | /** @id MochiKit.Visual.Move.prototype.setup */ | ||
924 | setup: function () { | ||
925 | // Bug in Opera: Opera returns the 'real' position of a static element | ||
926 | // or relative element that does not have top/left explicitly set. | ||
927 | // ==> Always set top and left for position relative elements in your | ||
928 | // stylesheets (to 0 if you do not need them) | ||
929 | MochiKit.Style.makePositioned(this.element); | ||
930 | |||
931 | var s = this.element.style; | ||
932 | var originalVisibility = s.visibility; | ||
933 | var originalDisplay = s.display; | ||
934 | if (originalDisplay == 'none') { | ||
935 | s.visibility = 'hidden'; | ||
936 | s.display = ''; | ||
937 | } | ||
938 | |||
939 | this.originalLeft = parseFloat(MochiKit.Style.getStyle(this.element, 'left') || '0'); | ||
940 | this.originalTop = parseFloat(MochiKit.Style.getStyle(this.element, 'top') || '0'); | ||
941 | |||
942 | if (this.options.mode == 'absolute') { | ||
943 | // absolute movement, so we need to calc deltaX and deltaY | ||
944 | this.options.x -= this.originalLeft; | ||
945 | this.options.y -= this.originalTop; | ||
946 | } | ||
947 | if (originalDisplay == 'none') { | ||
948 | s.visibility = originalVisibility; | ||
949 | s.display = originalDisplay; | ||
950 | } | ||
951 | }, | ||
952 | |||
953 | /** @id MochiKit.Visual.Move.prototype.update */ | ||
954 | update: function (position) { | ||
955 | MochiKit.Style.setStyle(this.element, { | ||
956 | left: Math.round(this.options.x * position + this.originalLeft) + 'px', | ||
957 | top: Math.round(this.options.y * position + this.originalTop) + 'px' | ||
958 | }); | ||
959 | } | ||
960 | }); | ||
961 | |||
962 | /** @id MochiKit.Visual.Scale */ | ||
963 | MochiKit.Visual.Scale = function (element, percent, options) { | ||
964 | var cls = arguments.callee; | ||
965 | if (!(this instanceof cls)) { | ||
966 | return new cls(element, percent, options); | ||
967 | } | ||
968 | this.__init__(element, percent, options); | ||
969 | }; | ||
970 | |||
971 | MochiKit.Visual.Scale.prototype = new MochiKit.Visual.Base(); | ||
972 | |||
973 | MochiKit.Base.update(MochiKit.Visual.Scale.prototype, { | ||
974 | /*** | ||
975 | |||
976 | Change the size of an element. | ||
977 | |||
978 | @param percent: final_size = percent*original_size | ||
979 | |||
980 | @param options: several options changing scale behaviour | ||
981 | |||
982 | ***/ | ||
983 | |||
984 | __class__ : MochiKit.Visual.Scale, | ||
985 | |||
986 | __init__: function (element, percent, /* optional */options) { | ||
987 | this.element = MochiKit.DOM.getElement(element); | ||
988 | options = MochiKit.Base.update({ | ||
989 | scaleX: true, | ||
990 | scaleY: true, | ||
991 | scaleContent: true, | ||
992 | scaleFromCenter: false, | ||
993 | scaleMode: 'box', // 'box' or 'contents' or {} with provided values | ||
994 | scaleFrom: 100.0, | ||
995 | scaleTo: percent | ||
996 | }, options); | ||
997 | this.start(options); | ||
998 | }, | ||
999 | |||
1000 | /** @id MochiKit.Visual.Scale.prototype.setup */ | ||
1001 | setup: function () { | ||
1002 | this.restoreAfterFinish = this.options.restoreAfterFinish || false; | ||
1003 | this.elementPositioning = MochiKit.Style.getStyle(this.element, | ||
1004 | 'position'); | ||
1005 | |||
1006 | var ma = MochiKit.Base.map; | ||
1007 | var b = MochiKit.Base.bind; | ||
1008 | this.originalStyle = {}; | ||
1009 | ma(b(function (k) { | ||
1010 | this.originalStyle[k] = this.element.style[k]; | ||
1011 | }, this), ['top', 'left', 'width', 'height', 'fontSize']); | ||
1012 | |||
1013 | this.originalTop = this.element.offsetTop; | ||
1014 | this.originalLeft = this.element.offsetLeft; | ||
1015 | |||
1016 | var fontSize = MochiKit.Style.getStyle(this.element, | ||
1017 | 'font-size') || '100%'; | ||
1018 | ma(b(function (fontSizeType) { | ||
1019 | if (fontSize.indexOf(fontSizeType) > 0) { | ||
1020 | this.fontSize = parseFloat(fontSize); | ||
1021 | this.fontSizeType = fontSizeType; | ||
1022 | } | ||
1023 | }, this), ['em', 'px', '%']); | ||
1024 | |||
1025 | this.factor = (this.options.scaleTo - this.options.scaleFrom)/100; | ||
1026 | |||
1027 | if (/^content/.test(this.options.scaleMode)) { | ||
1028 | this.dims = [this.element.scrollHeight, this.element.scrollWidth]; | ||
1029 | } else if (this.options.scaleMode == 'box') { | ||
1030 | this.dims = [this.element.offsetHeight, this.element.offsetWidth]; | ||
1031 | } else { | ||
1032 | this.dims = [this.options.scaleMode.originalHeight, | ||
1033 | this.options.scaleMode.originalWidth]; | ||
1034 | } | ||
1035 | }, | ||
1036 | |||
1037 | /** @id MochiKit.Visual.Scale.prototype.update */ | ||
1038 | update: function (position) { | ||
1039 | var currentScale = (this.options.scaleFrom/100.0) + | ||
1040 | (this.factor * position); | ||
1041 | if (this.options.scaleContent && this.fontSize) { | ||
1042 | MochiKit.Style.setStyle(this.element, { | ||
1043 | fontSize: this.fontSize * currentScale + this.fontSizeType | ||
1044 | }); | ||
1045 | } | ||
1046 | this.setDimensions(this.dims[0] * currentScale, | ||
1047 | this.dims[1] * currentScale); | ||
1048 | }, | ||
1049 | |||
1050 | /** @id MochiKit.Visual.Scale.prototype.finish */ | ||
1051 | finish: function () { | ||
1052 | if (this.restoreAfterFinish) { | ||
1053 | MochiKit.Style.setStyle(this.element, this.originalStyle); | ||
1054 | } | ||
1055 | }, | ||
1056 | |||
1057 | /** @id MochiKit.Visual.Scale.prototype.setDimensions */ | ||
1058 | setDimensions: function (height, width) { | ||
1059 | var d = {}; | ||
1060 | var r = Math.round; | ||
1061 | if (/MSIE/.test(navigator.userAgent)) { | ||
1062 | r = Math.ceil; | ||
1063 | } | ||
1064 | if (this.options.scaleX) { | ||
1065 | d.width = r(width) + 'px'; | ||
1066 | } | ||
1067 | if (this.options.scaleY) { | ||
1068 | d.height = r(height) + 'px'; | ||
1069 | } | ||
1070 | if (this.options.scaleFromCenter) { | ||
1071 | var topd = (height - this.dims[0])/2; | ||
1072 | var leftd = (width - this.dims[1])/2; | ||
1073 | if (this.elementPositioning == 'absolute') { | ||
1074 | if (this.options.scaleY) { | ||
1075 | d.top = this.originalTop - topd + 'px'; | ||
1076 | } | ||
1077 | if (this.options.scaleX) { | ||
1078 | d.left = this.originalLeft - leftd + 'px'; | ||
1079 | } | ||
1080 | } else { | ||
1081 | if (this.options.scaleY) { | ||
1082 | d.top = -topd + 'px'; | ||
1083 | } | ||
1084 | if (this.options.scaleX) { | ||
1085 | d.left = -leftd + 'px'; | ||
1086 | } | ||
1087 | } | ||
1088 | } | ||
1089 | MochiKit.Style.setStyle(this.element, d); | ||
1090 | } | ||
1091 | }); | ||
1092 | |||
1093 | /** @id MochiKit.Visual.Highlight */ | ||
1094 | MochiKit.Visual.Highlight = function (element, options) { | ||
1095 | var cls = arguments.callee; | ||
1096 | if (!(this instanceof cls)) { | ||
1097 | return new cls(element, options); | ||
1098 | } | ||
1099 | this.__init__(element, options); | ||
1100 | }; | ||
1101 | |||
1102 | MochiKit.Visual.Highlight.prototype = new MochiKit.Visual.Base(); | ||
1103 | |||
1104 | MochiKit.Base.update(MochiKit.Visual.Highlight.prototype, { | ||
1105 | /*** | ||
1106 | |||
1107 | Highlight an item of the page. | ||
1108 | |||
1109 | @param options: 'startcolor' for choosing highlighting color, default | ||
1110 | to '#ffff99'. | ||
1111 | |||
1112 | ***/ | ||
1113 | |||
1114 | __class__ : MochiKit.Visual.Highlight, | ||
1115 | |||
1116 | __init__: function (element, /* optional */options) { | ||
1117 | this.element = MochiKit.DOM.getElement(element); | ||
1118 | options = MochiKit.Base.update({ | ||
1119 | startcolor: '#ffff99' | ||
1120 | }, options); | ||
1121 | this.start(options); | ||
1122 | }, | ||
1123 | |||
1124 | /** @id MochiKit.Visual.Highlight.prototype.setup */ | ||
1125 | setup: function () { | ||
1126 | var b = MochiKit.Base; | ||
1127 | var s = MochiKit.Style; | ||
1128 | // Prevent executing on elements not in the layout flow | ||
1129 | if (s.getStyle(this.element, 'display') == 'none') { | ||
1130 | this.cancel(); | ||
1131 | return; | ||
1132 | } | ||
1133 | // Disable background image during the effect | ||
1134 | this.oldStyle = { | ||
1135 | backgroundImage: s.getStyle(this.element, 'background-image') | ||
1136 | }; | ||
1137 | s.setStyle(this.element, { | ||
1138 | backgroundImage: 'none' | ||
1139 | }); | ||
1140 | |||
1141 | if (!this.options.endcolor) { | ||
1142 | this.options.endcolor = | ||
1143 | MochiKit.Color.Color.fromBackground(this.element).toHexString(); | ||
1144 | } | ||
1145 | if (b.isUndefinedOrNull(this.options.restorecolor)) { | ||
1146 | this.options.restorecolor = s.getStyle(this.element, | ||
1147 | 'background-color'); | ||
1148 | } | ||
1149 | // init color calculations | ||
1150 | this._base = b.map(b.bind(function (i) { | ||
1151 | return parseInt( | ||
1152 | this.options.startcolor.slice(i*2 + 1, i*2 + 3), 16); | ||
1153 | }, this), [0, 1, 2]); | ||
1154 | this._delta = b.map(b.bind(function (i) { | ||
1155 | return parseInt(this.options.endcolor.slice(i*2 + 1, i*2 + 3), 16) | ||
1156 | - this._base[i]; | ||
1157 | }, this), [0, 1, 2]); | ||
1158 | }, | ||
1159 | |||
1160 | /** @id MochiKit.Visual.Highlight.prototype.update */ | ||
1161 | update: function (position) { | ||
1162 | var m = '#'; | ||
1163 | MochiKit.Base.map(MochiKit.Base.bind(function (i) { | ||
1164 | m += MochiKit.Color.toColorPart(Math.round(this._base[i] + | ||
1165 | this._delta[i]*position)); | ||
1166 | }, this), [0, 1, 2]); | ||
1167 | MochiKit.Style.setStyle(this.element, { | ||
1168 | backgroundColor: m | ||
1169 | }); | ||
1170 | }, | ||
1171 | |||
1172 | /** @id MochiKit.Visual.Highlight.prototype.finish */ | ||
1173 | finish: function () { | ||
1174 | MochiKit.Style.setStyle(this.element, | ||
1175 | MochiKit.Base.update(this.oldStyle, { | ||
1176 | backgroundColor: this.options.restorecolor | ||
1177 | })); | ||
1178 | } | ||
1179 | }); | ||
1180 | |||
1181 | /** @id MochiKit.Visual.ScrollTo */ | ||
1182 | MochiKit.Visual.ScrollTo = function (element, options) { | ||
1183 | var cls = arguments.callee; | ||
1184 | if (!(this instanceof cls)) { | ||
1185 | return new cls(element, options); | ||
1186 | } | ||
1187 | this.__init__(element, options); | ||
1188 | }; | ||
1189 | |||
1190 | MochiKit.Visual.ScrollTo.prototype = new MochiKit.Visual.Base(); | ||
1191 | |||
1192 | MochiKit.Base.update(MochiKit.Visual.ScrollTo.prototype, { | ||
1193 | /*** | ||
1194 | |||
1195 | Scroll to an element in the page. | ||
1196 | |||
1197 | ***/ | ||
1198 | |||
1199 | __class__ : MochiKit.Visual.ScrollTo, | ||
1200 | |||
1201 | __init__: function (element, /* optional */options) { | ||
1202 | this.element = MochiKit.DOM.getElement(element); | ||
1203 | this.start(options); | ||
1204 | }, | ||
1205 | |||
1206 | /** @id MochiKit.Visual.ScrollTo.prototype.setup */ | ||
1207 | setup: function () { | ||
1208 | var p = MochiKit.Position; | ||
1209 | p.prepare(); | ||
1210 | var offsets = p.cumulativeOffset(this.element); | ||
1211 | if (this.options.offset) { | ||
1212 | offsets.y += this.options.offset; | ||
1213 | } | ||
1214 | var max; | ||
1215 | if (window.innerHeight) { | ||
1216 | max = window.innerHeight - window.height; | ||
1217 | } else if (document.documentElement && | ||
1218 | document.documentElement.clientHeight) { | ||
1219 | max = document.documentElement.clientHeight - | ||
1220 | document.body.scrollHeight; | ||
1221 | } else if (document.body) { | ||
1222 | max = document.body.clientHeight - document.body.scrollHeight; | ||
1223 | } | ||
1224 | this.scrollStart = p.windowOffset.y; | ||
1225 | this.delta = (offsets.y > max ? max : offsets.y) - this.scrollStart; | ||
1226 | }, | ||
1227 | |||
1228 | /** @id MochiKit.Visual.ScrollTo.prototype.update */ | ||
1229 | update: function (position) { | ||
1230 | var p = MochiKit.Position; | ||
1231 | p.prepare(); | ||
1232 | window.scrollTo(p.windowOffset.x, this.scrollStart + (position * this.delta)); | ||
1233 | } | ||
1234 | }); | ||
1235 | |||
1236 | MochiKit.Visual._CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/; | ||
1237 | |||
1238 | MochiKit.Visual.Morph = function (element, options) { | ||
1239 | var cls = arguments.callee; | ||
1240 | if (!(this instanceof cls)) { | ||
1241 | return new cls(element, options); | ||
1242 | } | ||
1243 | this.__init__(element, options); | ||
1244 | }; | ||
1245 | |||
1246 | MochiKit.Visual.Morph.prototype = new MochiKit.Visual.Base(); | ||
1247 | |||
1248 | MochiKit.Base.update(MochiKit.Visual.Morph.prototype, { | ||
1249 | /*** | ||
1250 | |||
1251 | Morph effect: make a transformation from current style to the given style, | ||
1252 | automatically making a transition between the two. | ||
1253 | |||
1254 | ***/ | ||
1255 | |||
1256 | __class__ : MochiKit.Visual.Morph, | ||
1257 | |||
1258 | __init__: function (element, /* optional */options) { | ||
1259 | this.element = MochiKit.DOM.getElement(element); | ||
1260 | this.start(options); | ||
1261 | }, | ||
1262 | |||
1263 | /** @id MochiKit.Visual.Morph.prototype.setup */ | ||
1264 | setup: function () { | ||
1265 | var b = MochiKit.Base; | ||
1266 | var style = this.options.style; | ||
1267 | this.styleStart = {}; | ||
1268 | this.styleEnd = {}; | ||
1269 | this.units = {}; | ||
1270 | var value, unit; | ||
1271 | for (var s in style) { | ||
1272 | value = style[s]; | ||
1273 | s = b.camelize(s); | ||
1274 | if (MochiKit.Visual._CSS_LENGTH.test(value)) { | ||
1275 | var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/); | ||
1276 | value = parseFloat(components[1]); | ||
1277 | unit = (components.length == 3) ? components[2] : null; | ||
1278 | this.styleEnd[s] = value; | ||
1279 | this.units[s] = unit; | ||
1280 | value = MochiKit.Style.getStyle(this.element, s); | ||
1281 | components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/); | ||
1282 | value = parseFloat(components[1]); | ||
1283 | this.styleStart[s] = value; | ||
1284 | } else if (/[Cc]olor$/.test(s)) { | ||
1285 | var c = MochiKit.Color.Color; | ||
1286 | value = c.fromString(value); | ||
1287 | if (value) { | ||
1288 | this.units[s] = "color"; | ||
1289 | this.styleEnd[s] = value.toHexString(); | ||
1290 | value = MochiKit.Style.getStyle(this.element, s); | ||
1291 | this.styleStart[s] = c.fromString(value).toHexString(); | ||
1292 | |||
1293 | this.styleStart[s] = b.map(b.bind(function (i) { | ||
1294 | return parseInt( | ||
1295 | this.styleStart[s].slice(i*2 + 1, i*2 + 3), 16); | ||
1296 | }, this), [0, 1, 2]); | ||
1297 | this.styleEnd[s] = b.map(b.bind(function (i) { | ||
1298 | return parseInt( | ||
1299 | this.styleEnd[s].slice(i*2 + 1, i*2 + 3), 16); | ||
1300 | }, this), [0, 1, 2]); | ||
1301 | } | ||
1302 | } else { | ||
1303 | // For non-length & non-color properties, we just set the value | ||
1304 | this.element.style[s] = value; | ||
1305 | } | ||
1306 | } | ||
1307 | }, | ||
1308 | |||
1309 | /** @id MochiKit.Visual.Morph.prototype.update */ | ||
1310 | update: function (position) { | ||
1311 | var value; | ||
1312 | for (var s in this.styleStart) { | ||
1313 | if (this.units[s] == "color") { | ||
1314 | var m = '#'; | ||
1315 | var start = this.styleStart[s]; | ||
1316 | var end = this.styleEnd[s]; | ||
1317 | MochiKit.Base.map(MochiKit.Base.bind(function (i) { | ||
1318 | m += MochiKit.Color.toColorPart(Math.round(start[i] + | ||
1319 | (end[i] - start[i])*position)); | ||
1320 | }, this), [0, 1, 2]); | ||
1321 | this.element.style[s] = m; | ||
1322 | } else { | ||
1323 | value = this.styleStart[s] + Math.round((this.styleEnd[s] - this.styleStart[s]) * position * 1000) / 1000 + this.units[s]; | ||
1324 | this.element.style[s] = value; | ||
1325 | } | ||
1326 | } | ||
1327 | } | ||
1328 | }); | ||
1329 | |||
1330 | /*** | ||
1331 | |||
1332 | Combination effects. | ||
1333 | |||
1334 | ***/ | ||
1335 | |||
1336 | /** @id MochiKit.Visual.fade */ | ||
1337 | MochiKit.Visual.fade = function (element, /* optional */ options) { | ||
1338 | /*** | ||
1339 | |||
1340 | Fade a given element: change its opacity and hide it in the end. | ||
1341 | |||
1342 | @param options: 'to' and 'from' to change opacity. | ||
1343 | |||
1344 | ***/ | ||
1345 | var s = MochiKit.Style; | ||
1346 | var oldOpacity = s.getStyle(element, 'opacity'); | ||
1347 | options = MochiKit.Base.update({ | ||
1348 | from: s.getStyle(element, 'opacity') || 1.0, | ||
1349 | to: 0.0, | ||
1350 | afterFinishInternal: function (effect) { | ||
1351 | if (effect.options.to !== 0) { | ||
1352 | return; | ||
1353 | } | ||
1354 | s.hideElement(effect.element); | ||
1355 | s.setStyle(effect.element, {'opacity': oldOpacity}); | ||
1356 | } | ||
1357 | }, options); | ||
1358 | return new MochiKit.Visual.Opacity(element, options); | ||
1359 | }; | ||
1360 | |||
1361 | /** @id MochiKit.Visual.appear */ | ||
1362 | MochiKit.Visual.appear = function (element, /* optional */ options) { | ||
1363 | /*** | ||
1364 | |||
1365 | Make an element appear. | ||
1366 | |||
1367 | @param options: 'to' and 'from' to change opacity. | ||
1368 | |||
1369 | ***/ | ||
1370 | var s = MochiKit.Style; | ||
1371 | var v = MochiKit.Visual; | ||
1372 | options = MochiKit.Base.update({ | ||
1373 | from: (s.getStyle(element, 'display') == 'none' ? 0.0 : | ||
1374 | s.getStyle(element, 'opacity') || 0.0), | ||
1375 | to: 1.0, | ||
1376 | // force Safari to render floated elements properly | ||
1377 | afterFinishInternal: function (effect) { | ||
1378 | v._forceRerendering(effect.element); | ||
1379 | }, | ||
1380 | beforeSetupInternal: function (effect) { | ||
1381 | s.setStyle(effect.element, {'opacity': effect.options.from}); | ||
1382 | s.showElement(effect.element); | ||
1383 | } | ||
1384 | }, options); | ||
1385 | return new v.Opacity(element, options); | ||
1386 | }; | ||
1387 | |||
1388 | /** @id MochiKit.Visual.puff */ | ||
1389 | MochiKit.Visual.puff = function (element, /* optional */ options) { | ||
1390 | /*** | ||
1391 | |||
1392 | 'Puff' an element: grow it to double size, fading it and make it hidden. | ||
1393 | |||
1394 | ***/ | ||
1395 | var s = MochiKit.Style; | ||
1396 | var v = MochiKit.Visual; | ||
1397 | element = MochiKit.DOM.getElement(element); | ||
1398 | var elementDimensions = MochiKit.Style.getElementDimensions(element, true); | ||
1399 | var oldStyle = { | ||
1400 | position: s.getStyle(element, 'position'), | ||
1401 | top: element.style.top, | ||
1402 | left: element.style.left, | ||
1403 | width: element.style.width, | ||
1404 | height: element.style.height, | ||
1405 | opacity: s.getStyle(element, 'opacity') | ||
1406 | }; | ||
1407 | options = MochiKit.Base.update({ | ||
1408 | beforeSetupInternal: function (effect) { | ||
1409 | MochiKit.Position.absolutize(effect.effects[0].element); | ||
1410 | }, | ||
1411 | afterFinishInternal: function (effect) { | ||
1412 | s.hideElement(effect.effects[0].element); | ||
1413 | s.setStyle(effect.effects[0].element, oldStyle); | ||
1414 | }, | ||
1415 | scaleContent: true, | ||
1416 | scaleFromCenter: true | ||
1417 | }, options); | ||
1418 | return new v.Parallel( | ||
1419 | [new v.Scale(element, 200, | ||
1420 | {sync: true, scaleFromCenter: options.scaleFromCenter, | ||
1421 | scaleMode: {originalHeight: elementDimensions.h, | ||
1422 | originalWidth: elementDimensions.w}, | ||
1423 | scaleContent: options.scaleContent, restoreAfterFinish: true}), | ||
1424 | new v.Opacity(element, {sync: true, to: 0.0 })], | ||
1425 | options); | ||
1426 | }; | ||
1427 | |||
1428 | /** @id MochiKit.Visual.blindUp */ | ||
1429 | MochiKit.Visual.blindUp = function (element, /* optional */ options) { | ||
1430 | /*** | ||
1431 | |||
1432 | Blind an element up: change its vertical size to 0. | ||
1433 | |||
1434 | ***/ | ||
1435 | var d = MochiKit.DOM; | ||
1436 | var s = MochiKit.Style; | ||
1437 | element = d.getElement(element); | ||
1438 | var elementDimensions = s.getElementDimensions(element, true); | ||
1439 | var elemClip = s.makeClipping(element); | ||
1440 | options = MochiKit.Base.update({ | ||
1441 | scaleContent: false, | ||
1442 | scaleX: false, | ||
1443 | scaleMode: {originalHeight: elementDimensions.h, | ||
1444 | originalWidth: elementDimensions.w}, | ||
1445 | restoreAfterFinish: true, | ||
1446 | afterFinishInternal: function (effect) { | ||
1447 | s.hideElement(effect.element); | ||
1448 | s.undoClipping(effect.element, elemClip); | ||
1449 | } | ||
1450 | }, options); | ||
1451 | return new MochiKit.Visual.Scale(element, 0, options); | ||
1452 | }; | ||
1453 | |||
1454 | /** @id MochiKit.Visual.blindDown */ | ||
1455 | MochiKit.Visual.blindDown = function (element, /* optional */ options) { | ||
1456 | /*** | ||
1457 | |||
1458 | Blind an element down: restore its vertical size. | ||
1459 | |||
1460 | ***/ | ||
1461 | var d = MochiKit.DOM; | ||
1462 | var s = MochiKit.Style; | ||
1463 | element = d.getElement(element); | ||
1464 | var elementDimensions = s.getElementDimensions(element, true); | ||
1465 | var elemClip; | ||
1466 | options = MochiKit.Base.update({ | ||
1467 | scaleContent: false, | ||
1468 | scaleX: false, | ||
1469 | scaleFrom: 0, | ||
1470 | scaleMode: {originalHeight: elementDimensions.h, | ||
1471 | originalWidth: elementDimensions.w}, | ||
1472 | restoreAfterFinish: true, | ||
1473 | afterSetupInternal: function (effect) { | ||
1474 | elemClip = s.makeClipping(effect.element); | ||
1475 | s.setStyle(effect.element, {height: '0px'}); | ||
1476 | s.showElement(effect.element); | ||
1477 | }, | ||
1478 | afterFinishInternal: function (effect) { | ||
1479 | s.undoClipping(effect.element, elemClip); | ||
1480 | } | ||
1481 | }, options); | ||
1482 | return new MochiKit.Visual.Scale(element, 100, options); | ||
1483 | }; | ||
1484 | |||
1485 | /** @id MochiKit.Visual.switchOff */ | ||
1486 | MochiKit.Visual.switchOff = function (element, /* optional */ options) { | ||
1487 | /*** | ||
1488 | |||
1489 | Apply a switch-off-like effect. | ||
1490 | |||
1491 | ***/ | ||
1492 | var d = MochiKit.DOM; | ||
1493 | var s = MochiKit.Style; | ||
1494 | element = d.getElement(element); | ||
1495 | var elementDimensions = s.getElementDimensions(element, true); | ||
1496 | var oldOpacity = s.getStyle(element, 'opacity'); | ||
1497 | var elemClip; | ||
1498 | options = MochiKit.Base.update({ | ||
1499 | duration: 0.7, | ||
1500 | restoreAfterFinish: true, | ||
1501 | beforeSetupInternal: function (effect) { | ||
1502 | s.makePositioned(element); | ||
1503 | elemClip = s.makeClipping(element); | ||
1504 | }, | ||
1505 | afterFinishInternal: function (effect) { | ||
1506 | s.hideElement(element); | ||
1507 | s.undoClipping(element, elemClip); | ||
1508 | s.undoPositioned(element); | ||
1509 | s.setStyle(element, {'opacity': oldOpacity}); | ||
1510 | } | ||
1511 | }, options); | ||
1512 | var v = MochiKit.Visual; | ||
1513 | return new v.Sequence( | ||
1514 | [new v.appear(element, | ||
1515 | { sync: true, duration: 0.57 * options.duration, | ||
1516 | from: 0, transition: v.Transitions.flicker }), | ||
1517 | new v.Scale(element, 1, | ||
1518 | { sync: true, duration: 0.43 * options.duration, | ||
1519 | scaleFromCenter: true, scaleX: false, | ||
1520 | scaleMode: {originalHeight: elementDimensions.h, | ||
1521 | originalWidth: elementDimensions.w}, | ||
1522 | scaleContent: false, restoreAfterFinish: true })], | ||
1523 | options); | ||
1524 | }; | ||
1525 | |||
1526 | /** @id MochiKit.Visual.dropOut */ | ||
1527 | MochiKit.Visual.dropOut = function (element, /* optional */ options) { | ||
1528 | /*** | ||
1529 | |||
1530 | Make an element fall and disappear. | ||
1531 | |||
1532 | ***/ | ||
1533 | var d = MochiKit.DOM; | ||
1534 | var s = MochiKit.Style; | ||
1535 | element = d.getElement(element); | ||
1536 | var oldStyle = { | ||
1537 | top: s.getStyle(element, 'top'), | ||
1538 | left: s.getStyle(element, 'left'), | ||
1539 | opacity: s.getStyle(element, 'opacity') | ||
1540 | }; | ||
1541 | |||
1542 | options = MochiKit.Base.update({ | ||
1543 | duration: 0.5, | ||
1544 | distance: 100, | ||
1545 | beforeSetupInternal: function (effect) { | ||
1546 | s.makePositioned(effect.effects[0].element); | ||
1547 | }, | ||
1548 | afterFinishInternal: function (effect) { | ||
1549 | s.hideElement(effect.effects[0].element); | ||
1550 | s.undoPositioned(effect.effects[0].element); | ||
1551 | s.setStyle(effect.effects[0].element, oldStyle); | ||
1552 | } | ||
1553 | }, options); | ||
1554 | var v = MochiKit.Visual; | ||
1555 | return new v.Parallel( | ||
1556 | [new v.Move(element, {x: 0, y: options.distance, sync: true}), | ||
1557 | new v.Opacity(element, {sync: true, to: 0.0})], | ||
1558 | options); | ||
1559 | }; | ||
1560 | |||
1561 | /** @id MochiKit.Visual.shake */ | ||
1562 | MochiKit.Visual.shake = function (element, /* optional */ options) { | ||
1563 | /*** | ||
1564 | |||
1565 | Move an element from left to right several times. | ||
1566 | |||
1567 | ***/ | ||
1568 | var d = MochiKit.DOM; | ||
1569 | var v = MochiKit.Visual; | ||
1570 | var s = MochiKit.Style; | ||
1571 | element = d.getElement(element); | ||
1572 | var oldStyle = { | ||
1573 | top: s.getStyle(element, 'top'), | ||
1574 | left: s.getStyle(element, 'left') | ||
1575 | }; | ||
1576 | options = MochiKit.Base.update({ | ||
1577 | duration: 0.5, | ||
1578 | afterFinishInternal: function (effect) { | ||
1579 | s.undoPositioned(element); | ||
1580 | s.setStyle(element, oldStyle); | ||
1581 | } | ||
1582 | }, options); | ||
1583 | return new v.Sequence( | ||
1584 | [new v.Move(element, { sync: true, duration: 0.1 * options.duration, | ||
1585 | x: 20, y: 0 }), | ||
1586 | new v.Move(element, { sync: true, duration: 0.2 * options.duration, | ||
1587 | x: -40, y: 0 }), | ||
1588 | new v.Move(element, { sync: true, duration: 0.2 * options.duration, | ||
1589 | x: 40, y: 0 }), | ||
1590 | new v.Move(element, { sync: true, duration: 0.2 * options.duration, | ||
1591 | x: -40, y: 0 }), | ||
1592 | new v.Move(element, { sync: true, duration: 0.2 * options.duration, | ||
1593 | x: 40, y: 0 }), | ||
1594 | new v.Move(element, { sync: true, duration: 0.1 * options.duration, | ||
1595 | x: -20, y: 0 })], | ||
1596 | options); | ||
1597 | }; | ||
1598 | |||
1599 | /** @id MochiKit.Visual.slideDown */ | ||
1600 | MochiKit.Visual.slideDown = function (element, /* optional */ options) { | ||
1601 | /*** | ||
1602 | |||
1603 | Slide an element down. | ||
1604 | It needs to have the content of the element wrapped in a container | ||
1605 | element with fixed height. | ||
1606 | |||
1607 | ***/ | ||
1608 | var d = MochiKit.DOM; | ||
1609 | var b = MochiKit.Base; | ||
1610 | var s = MochiKit.Style; | ||
1611 | element = d.getElement(element); | ||
1612 | if (!element.firstChild) { | ||
1613 | throw new Error("MochiKit.Visual.slideDown must be used on a element with a child"); | ||
1614 | } | ||
1615 | d.removeEmptyTextNodes(element); | ||
1616 | var oldInnerBottom = s.getStyle(element.firstChild, 'bottom') || 0; | ||
1617 | var elementDimensions = s.getElementDimensions(element, true); | ||
1618 | var elemClip; | ||
1619 | options = b.update({ | ||
1620 | scaleContent: false, | ||
1621 | scaleX: false, | ||
1622 | scaleFrom: 0, | ||
1623 | scaleMode: {originalHeight: elementDimensions.h, | ||
1624 | originalWidth: elementDimensions.w}, | ||
1625 | restoreAfterFinish: true, | ||
1626 | afterSetupInternal: function (effect) { | ||
1627 | s.makePositioned(effect.element); | ||
1628 | s.makePositioned(effect.element.firstChild); | ||
1629 | if (/Opera/.test(navigator.userAgent)) { | ||
1630 | s.setStyle(effect.element, {top: ''}); | ||
1631 | } | ||
1632 | elemClip = s.makeClipping(effect.element); | ||
1633 | s.setStyle(effect.element, {height: '0px'}); | ||
1634 | s.showElement(effect.element); | ||
1635 | }, | ||
1636 | afterUpdateInternal: function (effect) { | ||
1637 | var elementDimensions = s.getElementDimensions(effect.element, true); | ||
1638 | s.setStyle(effect.element.firstChild, | ||
1639 | {bottom: (effect.dims[0] - elementDimensions.h) + 'px'}); | ||
1640 | }, | ||
1641 | afterFinishInternal: function (effect) { | ||
1642 | s.undoClipping(effect.element, elemClip); | ||
1643 | // IE will crash if child is undoPositioned first | ||
1644 | if (/MSIE/.test(navigator.userAgent)) { | ||
1645 | s.undoPositioned(effect.element); | ||
1646 | s.undoPositioned(effect.element.firstChild); | ||
1647 | } else { | ||
1648 | s.undoPositioned(effect.element.firstChild); | ||
1649 | s.undoPositioned(effect.element); | ||
1650 | } | ||
1651 | s.setStyle(effect.element.firstChild, {bottom: oldInnerBottom}); | ||
1652 | } | ||
1653 | }, options); | ||
1654 | |||
1655 | return new MochiKit.Visual.Scale(element, 100, options); | ||
1656 | }; | ||
1657 | |||
1658 | /** @id MochiKit.Visual.slideUp */ | ||
1659 | MochiKit.Visual.slideUp = function (element, /* optional */ options) { | ||
1660 | /*** | ||
1661 | |||
1662 | Slide an element up. | ||
1663 | It needs to have the content of the element wrapped in a container | ||
1664 | element with fixed height. | ||
1665 | |||
1666 | ***/ | ||
1667 | var d = MochiKit.DOM; | ||
1668 | var b = MochiKit.Base; | ||
1669 | var s = MochiKit.Style; | ||
1670 | element = d.getElement(element); | ||
1671 | if (!element.firstChild) { | ||
1672 | throw new Error("MochiKit.Visual.slideUp must be used on a element with a child"); | ||
1673 | } | ||
1674 | d.removeEmptyTextNodes(element); | ||
1675 | var oldInnerBottom = s.getStyle(element.firstChild, 'bottom'); | ||
1676 | var elementDimensions = s.getElementDimensions(element, true); | ||
1677 | var elemClip; | ||
1678 | options = b.update({ | ||
1679 | scaleContent: false, | ||
1680 | scaleX: false, | ||
1681 | scaleMode: {originalHeight: elementDimensions.h, | ||
1682 | originalWidth: elementDimensions.w}, | ||
1683 | scaleFrom: 100, | ||
1684 | restoreAfterFinish: true, | ||
1685 | beforeStartInternal: function (effect) { | ||
1686 | s.makePositioned(effect.element); | ||
1687 | s.makePositioned(effect.element.firstChild); | ||
1688 | if (/Opera/.test(navigator.userAgent)) { | ||
1689 | s.setStyle(effect.element, {top: ''}); | ||
1690 | } | ||
1691 | elemClip = s.makeClipping(effect.element); | ||
1692 | s.showElement(effect.element); | ||
1693 | }, | ||
1694 | afterUpdateInternal: function (effect) { | ||
1695 | var elementDimensions = s.getElementDimensions(effect.element, true); | ||
1696 | s.setStyle(effect.element.firstChild, | ||
1697 | {bottom: (effect.dims[0] - elementDimensions.h) + 'px'}); | ||
1698 | }, | ||
1699 | afterFinishInternal: function (effect) { | ||
1700 | s.hideElement(effect.element); | ||
1701 | s.undoClipping(effect.element, elemClip); | ||
1702 | s.undoPositioned(effect.element.firstChild); | ||
1703 | s.undoPositioned(effect.element); | ||
1704 | s.setStyle(effect.element.firstChild, {bottom: oldInnerBottom}); | ||
1705 | } | ||
1706 | }, options); | ||
1707 | return new MochiKit.Visual.Scale(element, 0, options); | ||
1708 | }; | ||
1709 | |||
1710 | // Bug in opera makes the TD containing this element expand for a instance | ||
1711 | // after finish | ||
1712 | /** @id MochiKit.Visual.squish */ | ||
1713 | MochiKit.Visual.squish = function (element, /* optional */ options) { | ||
1714 | /*** | ||
1715 | |||
1716 | Reduce an element and make it disappear. | ||
1717 | |||
1718 | ***/ | ||
1719 | var d = MochiKit.DOM; | ||
1720 | var b = MochiKit.Base; | ||
1721 | var s = MochiKit.Style; | ||
1722 | var elementDimensions = s.getElementDimensions(element, true); | ||
1723 | var elemClip; | ||
1724 | options = b.update({ | ||
1725 | restoreAfterFinish: true, | ||
1726 | scaleMode: {originalHeight: elementDimensions.h, | ||
1727 | originalWidth: elementDimensions.w}, | ||
1728 | beforeSetupInternal: function (effect) { | ||
1729 | elemClip = s.makeClipping(effect.element); | ||
1730 | }, | ||
1731 | afterFinishInternal: function (effect) { | ||
1732 | s.hideElement(effect.element); | ||
1733 | s.undoClipping(effect.element, elemClip); | ||
1734 | } | ||
1735 | }, options); | ||
1736 | |||
1737 | return new MochiKit.Visual.Scale(element, /Opera/.test(navigator.userAgent) ? 1 : 0, options); | ||
1738 | }; | ||
1739 | |||
1740 | /** @id MochiKit.Visual.grow */ | ||
1741 | MochiKit.Visual.grow = function (element, /* optional */ options) { | ||
1742 | /*** | ||
1743 | |||
1744 | Grow an element to its original size. Make it zero-sized before | ||
1745 | if necessary. | ||
1746 | |||
1747 | ***/ | ||
1748 | var d = MochiKit.DOM; | ||
1749 | var v = MochiKit.Visual; | ||
1750 | var s = MochiKit.Style; | ||
1751 | element = d.getElement(element); | ||
1752 | options = MochiKit.Base.update({ | ||
1753 | direction: 'center', | ||
1754 | moveTransition: v.Transitions.sinoidal, | ||
1755 | scaleTransition: v.Transitions.sinoidal, | ||
1756 | opacityTransition: v.Transitions.full, | ||
1757 | scaleContent: true, | ||
1758 | scaleFromCenter: false | ||
1759 | }, options); | ||
1760 | var oldStyle = { | ||
1761 | top: element.style.top, | ||
1762 | left: element.style.left, | ||
1763 | height: element.style.height, | ||
1764 | width: element.style.width, | ||
1765 | opacity: s.getStyle(element, 'opacity') | ||
1766 | }; | ||
1767 | var dims = s.getElementDimensions(element, true); | ||
1768 | var initialMoveX, initialMoveY; | ||
1769 | var moveX, moveY; | ||
1770 | |||
1771 | switch (options.direction) { | ||
1772 | case 'top-left': | ||
1773 | initialMoveX = initialMoveY = moveX = moveY = 0; | ||
1774 | break; | ||
1775 | case 'top-right': | ||
1776 | initialMoveX = dims.w; | ||
1777 | initialMoveY = moveY = 0; | ||
1778 | moveX = -dims.w; | ||
1779 | break; | ||
1780 | case 'bottom-left': | ||
1781 | initialMoveX = moveX = 0; | ||
1782 | initialMoveY = dims.h; | ||
1783 | moveY = -dims.h; | ||
1784 | break; | ||
1785 | case 'bottom-right': | ||
1786 | initialMoveX = dims.w; | ||
1787 | initialMoveY = dims.h; | ||
1788 | moveX = -dims.w; | ||
1789 | moveY = -dims.h; | ||
1790 | break; | ||
1791 | case 'center': | ||
1792 | initialMoveX = dims.w / 2; | ||
1793 | initialMoveY = dims.h / 2; | ||
1794 | moveX = -dims.w / 2; | ||
1795 | moveY = -dims.h / 2; | ||
1796 | break; | ||
1797 | } | ||
1798 | |||
1799 | var optionsParallel = MochiKit.Base.update({ | ||
1800 | beforeSetupInternal: function (effect) { | ||
1801 | s.setStyle(effect.effects[0].element, {height: '0px'}); | ||
1802 | s.showElement(effect.effects[0].element); | ||
1803 | }, | ||
1804 | afterFinishInternal: function (effect) { | ||
1805 | s.undoClipping(effect.effects[0].element); | ||
1806 | s.undoPositioned(effect.effects[0].element); | ||
1807 | s.setStyle(effect.effects[0].element, oldStyle); | ||
1808 | } | ||
1809 | }, options); | ||
1810 | |||
1811 | return new v.Move(element, { | ||
1812 | x: initialMoveX, | ||
1813 | y: initialMoveY, | ||
1814 | duration: 0.01, | ||
1815 | beforeSetupInternal: function (effect) { | ||
1816 | s.hideElement(effect.element); | ||
1817 | s.makeClipping(effect.element); | ||
1818 | s.makePositioned(effect.element); | ||
1819 | }, | ||
1820 | afterFinishInternal: function (effect) { | ||
1821 | new v.Parallel( | ||
1822 | [new v.Opacity(effect.element, { | ||
1823 | sync: true, to: 1.0, from: 0.0, | ||
1824 | transition: options.opacityTransition | ||
1825 | }), | ||
1826 | new v.Move(effect.element, { | ||
1827 | x: moveX, y: moveY, sync: true, | ||
1828 | transition: options.moveTransition | ||
1829 | }), | ||
1830 | new v.Scale(effect.element, 100, { | ||
1831 | scaleMode: {originalHeight: dims.h, | ||
1832 | originalWidth: dims.w}, | ||
1833 | sync: true, | ||
1834 | scaleFrom: /Opera/.test(navigator.userAgent) ? 1 : 0, | ||
1835 | transition: options.scaleTransition, | ||
1836 | scaleContent: options.scaleContent, | ||
1837 | scaleFromCenter: options.scaleFromCenter, | ||
1838 | restoreAfterFinish: true | ||
1839 | }) | ||
1840 | ], optionsParallel | ||
1841 | ); | ||
1842 | } | ||
1843 | }); | ||
1844 | }; | ||
1845 | |||
1846 | /** @id MochiKit.Visual.shrink */ | ||
1847 | MochiKit.Visual.shrink = function (element, /* optional */ options) { | ||
1848 | /*** | ||
1849 | |||
1850 | Shrink an element and make it disappear. | ||
1851 | |||
1852 | ***/ | ||
1853 | var d = MochiKit.DOM; | ||
1854 | var v = MochiKit.Visual; | ||
1855 | var s = MochiKit.Style; | ||
1856 | element = d.getElement(element); | ||
1857 | options = MochiKit.Base.update({ | ||
1858 | direction: 'center', | ||
1859 | moveTransition: v.Transitions.sinoidal, | ||
1860 | scaleTransition: v.Transitions.sinoidal, | ||
1861 | opacityTransition: v.Transitions.none, | ||
1862 | scaleContent: true, | ||
1863 | scaleFromCenter: false | ||
1864 | }, options); | ||
1865 | var oldStyle = { | ||
1866 | top: element.style.top, | ||
1867 | left: element.style.left, | ||
1868 | height: element.style.height, | ||
1869 | width: element.style.width, | ||
1870 | opacity: s.getStyle(element, 'opacity') | ||
1871 | }; | ||
1872 | |||
1873 | var dims = s.getElementDimensions(element, true); | ||
1874 | var moveX, moveY; | ||
1875 | |||
1876 | switch (options.direction) { | ||
1877 | case 'top-left': | ||
1878 | moveX = moveY = 0; | ||
1879 | break; | ||
1880 | case 'top-right': | ||
1881 | moveX = dims.w; | ||
1882 | moveY = 0; | ||
1883 | break; | ||
1884 | case 'bottom-left': | ||
1885 | moveX = 0; | ||
1886 | moveY = dims.h; | ||
1887 | break; | ||
1888 | case 'bottom-right': | ||
1889 | moveX = dims.w; | ||
1890 | moveY = dims.h; | ||
1891 | break; | ||
1892 | case 'center': | ||
1893 | moveX = dims.w / 2; | ||
1894 | moveY = dims.h / 2; | ||
1895 | break; | ||
1896 | } | ||
1897 | var elemClip; | ||
1898 | |||
1899 | var optionsParallel = MochiKit.Base.update({ | ||
1900 | beforeStartInternal: function (effect) { | ||
1901 | s.makePositioned(effect.effects[0].element); | ||
1902 | elemClip = s.makeClipping(effect.effects[0].element); | ||
1903 | }, | ||
1904 | afterFinishInternal: function (effect) { | ||
1905 | s.hideElement(effect.effects[0].element); | ||
1906 | s.undoClipping(effect.effects[0].element, elemClip); | ||
1907 | s.undoPositioned(effect.effects[0].element); | ||
1908 | s.setStyle(effect.effects[0].element, oldStyle); | ||
1909 | } | ||
1910 | }, options); | ||
1911 | |||
1912 | return new v.Parallel( | ||
1913 | [new v.Opacity(element, { | ||
1914 | sync: true, to: 0.0, from: 1.0, | ||
1915 | transition: options.opacityTransition | ||
1916 | }), | ||
1917 | new v.Scale(element, /Opera/.test(navigator.userAgent) ? 1 : 0, { | ||
1918 | scaleMode: {originalHeight: dims.h, originalWidth: dims.w}, | ||
1919 | sync: true, transition: options.scaleTransition, | ||
1920 | scaleContent: options.scaleContent, | ||
1921 | scaleFromCenter: options.scaleFromCenter, | ||
1922 | restoreAfterFinish: true | ||
1923 | }), | ||
1924 | new v.Move(element, { | ||
1925 | x: moveX, y: moveY, sync: true, transition: options.moveTransition | ||
1926 | }) | ||
1927 | ], optionsParallel | ||
1928 | ); | ||
1929 | }; | ||
1930 | |||
1931 | /** @id MochiKit.Visual.pulsate */ | ||
1932 | MochiKit.Visual.pulsate = function (element, /* optional */ options) { | ||
1933 | /*** | ||
1934 | |||
1935 | Pulse an element between appear/fade. | ||
1936 | |||
1937 | ***/ | ||
1938 | var d = MochiKit.DOM; | ||
1939 | var v = MochiKit.Visual; | ||
1940 | var b = MochiKit.Base; | ||
1941 | var oldOpacity = MochiKit.Style.getStyle(element, 'opacity'); | ||
1942 | options = b.update({ | ||
1943 | duration: 3.0, | ||
1944 | from: 0, | ||
1945 | afterFinishInternal: function (effect) { | ||
1946 | MochiKit.Style.setStyle(effect.element, {'opacity': oldOpacity}); | ||
1947 | } | ||
1948 | }, options); | ||
1949 | var transition = options.transition || v.Transitions.sinoidal; | ||
1950 | options.transition = function (pos) { | ||
1951 | return transition(1 - v.Transitions.pulse(pos, options.pulses)); | ||
1952 | }; | ||
1953 | return new v.Opacity(element, options); | ||
1954 | }; | ||
1955 | |||
1956 | /** @id MochiKit.Visual.fold */ | ||
1957 | MochiKit.Visual.fold = function (element, /* optional */ options) { | ||
1958 | /*** | ||
1959 | |||
1960 | Fold an element, first vertically, then horizontally. | ||
1961 | |||
1962 | ***/ | ||
1963 | var d = MochiKit.DOM; | ||
1964 | var v = MochiKit.Visual; | ||
1965 | var s = MochiKit.Style; | ||
1966 | element = d.getElement(element); | ||
1967 | var elementDimensions = s.getElementDimensions(element, true); | ||
1968 | var oldStyle = { | ||
1969 | top: element.style.top, | ||
1970 | left: element.style.left, | ||
1971 | width: element.style.width, | ||
1972 | height: element.style.height | ||
1973 | }; | ||
1974 | var elemClip = s.makeClipping(element); | ||
1975 | options = MochiKit.Base.update({ | ||
1976 | scaleContent: false, | ||
1977 | scaleX: false, | ||
1978 | scaleMode: {originalHeight: elementDimensions.h, | ||
1979 | originalWidth: elementDimensions.w}, | ||
1980 | afterFinishInternal: function (effect) { | ||
1981 | new v.Scale(element, 1, { | ||
1982 | scaleContent: false, | ||
1983 | scaleY: false, | ||
1984 | scaleMode: {originalHeight: elementDimensions.h, | ||
1985 | originalWidth: elementDimensions.w}, | ||
1986 | afterFinishInternal: function (effect) { | ||
1987 | s.hideElement(effect.element); | ||
1988 | s.undoClipping(effect.element, elemClip); | ||
1989 | s.setStyle(effect.element, oldStyle); | ||
1990 | } | ||
1991 | }); | ||
1992 | } | ||
1993 | }, options); | ||
1994 | return new v.Scale(element, 5, options); | ||
1995 | }; | ||
1996 | |||
1997 | |||
1998 | MochiKit.Base.nameFunctions(MochiKit.Visual); | ||
1999 | MochiKit.Base._exportSymbols(this, MochiKit.Visual); | ||