testing/mochitest/MochiKit/Visual.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial