[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 /* 2 YUI 3.17.2 (build 9c3c78e) 3 Copyright 2014 Yahoo! Inc. All rights reserved. 4 Licensed under the BSD License. 5 http://yuilibrary.com/license/ 6 */ 7 8 YUI.add('anim-base', function (Y, NAME) { 9 10 /** 11 * The Animation Utility provides an API for creating advanced transitions. 12 * @module anim 13 */ 14 15 /** 16 * Provides the base Anim class, for animating numeric properties. 17 * 18 * @module anim 19 * @submodule anim-base 20 */ 21 22 /** 23 * A class for constructing animation instances. 24 * @class Anim 25 * @for Anim 26 * @constructor 27 * @extends Base 28 */ 29 30 var RUNNING = 'running', 31 START_TIME = 'startTime', 32 ELAPSED_TIME = 'elapsedTime', 33 /** 34 * @for Anim 35 * @event start 36 * @description fires when an animation begins. 37 * @param {Event} ev The start event. 38 * @type Event.Custom 39 */ 40 START = 'start', 41 42 /** 43 * @event tween 44 * @description fires every frame of the animation. 45 * @param {Event} ev The tween event. 46 * @type Event.Custom 47 */ 48 TWEEN = 'tween', 49 50 /** 51 * @event end 52 * @description fires after the animation completes. 53 * @param {Event} ev The end event. 54 * @type Event.Custom 55 */ 56 END = 'end', 57 NODE = 'node', 58 PAUSED = 'paused', 59 REVERSE = 'reverse', // TODO: cleanup 60 ITERATION_COUNT = 'iterationCount', 61 62 NUM = Number; 63 64 var _running = {}, 65 _timer; 66 67 Y.Anim = function() { 68 Y.Anim.superclass.constructor.apply(this, arguments); 69 Y.Anim._instances[Y.stamp(this)] = this; 70 }; 71 72 Y.Anim.NAME = 'anim'; 73 74 Y.Anim._instances = {}; 75 76 /** 77 * Regex of properties that should use the default unit. 78 * 79 * @property RE_DEFAULT_UNIT 80 * @static 81 */ 82 Y.Anim.RE_DEFAULT_UNIT = /^width|height|top|right|bottom|left|margin.*|padding.*|border.*$/i; 83 84 /** 85 * The default unit to use with properties that pass the RE_DEFAULT_UNIT test. 86 * 87 * @property DEFAULT_UNIT 88 * @static 89 */ 90 Y.Anim.DEFAULT_UNIT = 'px'; 91 92 Y.Anim.DEFAULT_EASING = function (t, b, c, d) { 93 return c * t / d + b; // linear easing 94 }; 95 96 /** 97 * Time in milliseconds passed to setInterval for frame processing 98 * 99 * @property intervalTime 100 * @default 20 101 * @static 102 */ 103 Y.Anim._intervalTime = 20; 104 105 /** 106 * Bucket for custom getters and setters 107 * 108 * @property behaviors 109 * @static 110 */ 111 Y.Anim.behaviors = { 112 left: { 113 get: function(anim, attr) { 114 return anim._getOffset(attr); 115 } 116 } 117 }; 118 119 Y.Anim.behaviors.top = Y.Anim.behaviors.left; 120 121 /** 122 * The default setter to use when setting object properties. 123 * 124 * @property DEFAULT_SETTER 125 * @static 126 */ 127 Y.Anim.DEFAULT_SETTER = function(anim, att, from, to, elapsed, duration, fn, unit) { 128 var node = anim._node, 129 domNode = node._node, 130 val = fn(elapsed, NUM(from), NUM(to) - NUM(from), duration); 131 132 if (domNode) { 133 if ('style' in domNode && (att in domNode.style || att in Y.DOM.CUSTOM_STYLES)) { 134 unit = unit || ''; 135 node.setStyle(att, val + unit); 136 } else if ('attributes' in domNode && att in domNode.attributes) { 137 node.setAttribute(att, val); 138 } else if (att in domNode) { 139 domNode[att] = val; 140 } 141 } else if (node.set) { 142 node.set(att, val); 143 } else if (att in node) { 144 node[att] = val; 145 } 146 }; 147 148 /** 149 * The default getter to use when getting object properties. 150 * 151 * @property DEFAULT_GETTER 152 * @static 153 */ 154 Y.Anim.DEFAULT_GETTER = function(anim, att) { 155 var node = anim._node, 156 domNode = node._node, 157 val = ''; 158 159 if (domNode) { 160 if ('style' in domNode && (att in domNode.style || att in Y.DOM.CUSTOM_STYLES)) { 161 val = node.getComputedStyle(att); 162 } else if ('attributes' in domNode && att in domNode.attributes) { 163 val = node.getAttribute(att); 164 } else if (att in domNode) { 165 val = domNode[att]; 166 } 167 } else if (node.get) { 168 val = node.get(att); 169 } else if (att in node) { 170 val = node[att]; 171 } 172 173 return val; 174 }; 175 176 Y.Anim.ATTRS = { 177 /** 178 * The object to be animated. 179 * @attribute node 180 * @type Node 181 */ 182 node: { 183 setter: function(node) { 184 if (node) { 185 if (typeof node === 'string' || node.nodeType) { 186 node = Y.one(node); 187 } 188 } 189 190 this._node = node; 191 if (!node) { 192 Y.log(node + ' is not a valid node', 'warn', 'Anim'); 193 } 194 return node; 195 } 196 }, 197 198 /** 199 * The length of the animation. Defaults to "1" (second). 200 * @attribute duration 201 * @type NUM 202 */ 203 duration: { 204 value: 1 205 }, 206 207 /** 208 * The method that will provide values to the attribute(s) during the animation. 209 * Defaults to "Easing.easeNone". 210 * @attribute easing 211 * @type Function 212 */ 213 easing: { 214 value: Y.Anim.DEFAULT_EASING, 215 216 setter: function(val) { 217 if (typeof val === 'string' && Y.Easing) { 218 return Y.Easing[val]; 219 } 220 } 221 }, 222 223 /** 224 * The starting values for the animated properties. 225 * 226 * Fields may be strings, numbers, or functions. 227 * If a function is used, the return value becomes the from value. 228 * If no from value is specified, the DEFAULT_GETTER will be used. 229 * Supports any unit, provided it matches the "to" (or default) 230 * unit (e.g. `{width: '10em', color: 'rgb(0, 0, 0)', borderColor: '#ccc'}`). 231 * 232 * If using the default ('px' for length-based units), the unit may be omitted 233 * (e.g. `{width: 100}, borderColor: 'ccc'}`, which defaults to pixels 234 * and hex, respectively). 235 * 236 * @attribute from 237 * @type Object 238 */ 239 from: {}, 240 241 /** 242 * The ending values for the animated properties. 243 * 244 * Fields may be strings, numbers, or functions. 245 * Supports any unit, provided it matches the "from" (or default) 246 * unit (e.g. `{width: '50%', color: 'red', borderColor: '#ccc'}`). 247 * 248 * If using the default ('px' for length-based units), the unit may be omitted 249 * (e.g. `{width: 100, borderColor: 'ccc'}`, which defaults to pixels 250 * and hex, respectively). 251 * 252 * @attribute to 253 * @type Object 254 */ 255 to: {}, 256 257 /** 258 * Date stamp for the first frame of the animation. 259 * @attribute startTime 260 * @type Int 261 * @default 0 262 * @readOnly 263 */ 264 startTime: { 265 value: 0, 266 readOnly: true 267 }, 268 269 /** 270 * Current time the animation has been running. 271 * @attribute elapsedTime 272 * @type Int 273 * @default 0 274 * @readOnly 275 */ 276 elapsedTime: { 277 value: 0, 278 readOnly: true 279 }, 280 281 /** 282 * Whether or not the animation is currently running. 283 * @attribute running 284 * @type Boolean 285 * @default false 286 * @readOnly 287 */ 288 running: { 289 getter: function() { 290 return !!_running[Y.stamp(this)]; 291 }, 292 value: false, 293 readOnly: true 294 }, 295 296 /** 297 * The number of times the animation should run 298 * @attribute iterations 299 * @type Int 300 * @default 1 301 */ 302 iterations: { 303 value: 1 304 }, 305 306 /** 307 * The number of iterations that have occurred. 308 * Resets when an animation ends (reaches iteration count or stop() called). 309 * @attribute iterationCount 310 * @type Int 311 * @default 0 312 * @readOnly 313 */ 314 iterationCount: { 315 value: 0, 316 readOnly: true 317 }, 318 319 /** 320 * How iterations of the animation should behave. 321 * Possible values are "normal" and "alternate". 322 * Normal will repeat the animation, alternate will reverse on every other pass. 323 * 324 * @attribute direction 325 * @type String 326 * @default "normal" 327 */ 328 direction: { 329 value: 'normal' // | alternate (fwd on odd, rev on even per spec) 330 }, 331 332 /** 333 * Whether or not the animation is currently paused. 334 * @attribute paused 335 * @type Boolean 336 * @default false 337 * @readOnly 338 */ 339 paused: { 340 readOnly: true, 341 value: false 342 }, 343 344 /** 345 * If true, the `from` and `to` attributes are swapped, 346 * and the animation is then run starting from `from`. 347 * @attribute reverse 348 * @type Boolean 349 * @default false 350 */ 351 reverse: { 352 value: false 353 } 354 355 356 }; 357 358 /** 359 * Runs all animation instances. 360 * @method run 361 * @static 362 */ 363 Y.Anim.run = function() { 364 var instances = Y.Anim._instances, 365 i; 366 for (i in instances) { 367 if (instances[i].run) { 368 instances[i].run(); 369 } 370 } 371 }; 372 373 /** 374 * Pauses all animation instances. 375 * @method pause 376 * @static 377 */ 378 Y.Anim.pause = function() { 379 for (var i in _running) { // stop timer if nothing running 380 if (_running[i].pause) { 381 _running[i].pause(); 382 } 383 } 384 385 Y.Anim._stopTimer(); 386 }; 387 388 /** 389 * Stops all animation instances. 390 * @method stop 391 * @static 392 */ 393 Y.Anim.stop = function() { 394 for (var i in _running) { // stop timer if nothing running 395 if (_running[i].stop) { 396 _running[i].stop(); 397 } 398 } 399 Y.Anim._stopTimer(); 400 }; 401 402 Y.Anim._startTimer = function() { 403 if (!_timer) { 404 _timer = setInterval(Y.Anim._runFrame, Y.Anim._intervalTime); 405 } 406 }; 407 408 Y.Anim._stopTimer = function() { 409 clearInterval(_timer); 410 _timer = 0; 411 }; 412 413 /** 414 * Called per Interval to handle each animation frame. 415 * @method _runFrame 416 * @private 417 * @static 418 */ 419 Y.Anim._runFrame = function() { 420 var done = true, 421 anim; 422 for (anim in _running) { 423 if (_running[anim]._runFrame) { 424 done = false; 425 _running[anim]._runFrame(); 426 } 427 } 428 429 if (done) { 430 Y.Anim._stopTimer(); 431 } 432 }; 433 434 Y.Anim.RE_UNITS = /^(-?\d*\.?\d*){1}(em|ex|px|in|cm|mm|pt|pc|%)*$/; 435 436 var proto = { 437 /** 438 * Starts or resumes an animation. 439 * @method run 440 * @chainable 441 */ 442 run: function() { 443 if (this.get(PAUSED)) { 444 this._resume(); 445 } else if (!this.get(RUNNING)) { 446 this._start(); 447 } 448 return this; 449 }, 450 451 /** 452 * Pauses the animation and 453 * freezes it in its current state and time. 454 * Calling run() will continue where it left off. 455 * @method pause 456 * @chainable 457 */ 458 pause: function() { 459 if (this.get(RUNNING)) { 460 this._pause(); 461 } 462 return this; 463 }, 464 465 /** 466 * Stops the animation and resets its time. 467 * @method stop 468 * @param {Boolean} finish If true, the animation will move to the last frame 469 * @chainable 470 */ 471 stop: function(finish) { 472 if (this.get(RUNNING) || this.get(PAUSED)) { 473 this._end(finish); 474 } 475 return this; 476 }, 477 478 _added: false, 479 480 _start: function() { 481 this._set(START_TIME, new Date() - this.get(ELAPSED_TIME)); 482 this._actualFrames = 0; 483 if (!this.get(PAUSED)) { 484 this._initAnimAttr(); 485 } 486 _running[Y.stamp(this)] = this; 487 Y.Anim._startTimer(); 488 489 this.fire(START); 490 }, 491 492 _pause: function() { 493 this._set(START_TIME, null); 494 this._set(PAUSED, true); 495 delete _running[Y.stamp(this)]; 496 497 /** 498 * @event pause 499 * @description fires when an animation is paused. 500 * @param {Event} ev The pause event. 501 * @type Event.Custom 502 */ 503 this.fire('pause'); 504 }, 505 506 _resume: function() { 507 this._set(PAUSED, false); 508 _running[Y.stamp(this)] = this; 509 this._set(START_TIME, new Date() - this.get(ELAPSED_TIME)); 510 Y.Anim._startTimer(); 511 512 /** 513 * @event resume 514 * @description fires when an animation is resumed (run from pause). 515 * @param {Event} ev The pause event. 516 * @type Event.Custom 517 */ 518 this.fire('resume'); 519 }, 520 521 _end: function(finish) { 522 var duration = this.get('duration') * 1000; 523 if (finish) { // jump to last frame 524 this._runAttrs(duration, duration, this.get(REVERSE)); 525 } 526 527 this._set(START_TIME, null); 528 this._set(ELAPSED_TIME, 0); 529 this._set(PAUSED, false); 530 531 delete _running[Y.stamp(this)]; 532 this.fire(END, {elapsed: this.get(ELAPSED_TIME)}); 533 }, 534 535 _runFrame: function() { 536 var d = this._runtimeAttr.duration, 537 t = new Date() - this.get(START_TIME), 538 reverse = this.get(REVERSE), 539 done = (t >= d); 540 541 this._runAttrs(t, d, reverse); 542 this._actualFrames += 1; 543 this._set(ELAPSED_TIME, t); 544 545 this.fire(TWEEN); 546 if (done) { 547 this._lastFrame(); 548 } 549 }, 550 551 _runAttrs: function(t, d, reverse) { 552 var attr = this._runtimeAttr, 553 customAttr = Y.Anim.behaviors, 554 easing = attr.easing, 555 lastFrame = d, 556 done = false, 557 attribute, 558 setter, 559 i; 560 561 if (t >= d) { 562 done = true; 563 } 564 565 if (reverse) { 566 t = d - t; 567 lastFrame = 0; 568 } 569 570 for (i in attr) { 571 if (attr[i].to) { 572 attribute = attr[i]; 573 setter = (i in customAttr && 'set' in customAttr[i]) ? 574 customAttr[i].set : Y.Anim.DEFAULT_SETTER; 575 576 if (!done) { 577 setter(this, i, attribute.from, attribute.to, t, d, easing, attribute.unit); 578 } else { 579 setter(this, i, attribute.from, attribute.to, lastFrame, d, easing, attribute.unit); 580 } 581 } 582 } 583 584 585 }, 586 587 _lastFrame: function() { 588 var iter = this.get('iterations'), 589 iterCount = this.get(ITERATION_COUNT); 590 591 iterCount += 1; 592 if (iter === 'infinite' || iterCount < iter) { 593 if (this.get('direction') === 'alternate') { 594 this.set(REVERSE, !this.get(REVERSE)); // flip it 595 } 596 /** 597 * @event iteration 598 * @description fires when an animation begins an iteration. 599 * @param {Event} ev The iteration event. 600 * @type Event.Custom 601 */ 602 this.fire('iteration'); 603 } else { 604 iterCount = 0; 605 this._end(); 606 } 607 608 this._set(START_TIME, new Date()); 609 this._set(ITERATION_COUNT, iterCount); 610 }, 611 612 _initAnimAttr: function() { 613 var from = this.get('from') || {}, 614 to = this.get('to') || {}, 615 attr = { 616 duration: this.get('duration') * 1000, 617 easing: this.get('easing') 618 }, 619 customAttr = Y.Anim.behaviors, 620 node = this.get(NODE), // implicit attr init 621 unit, begin, end; 622 623 Y.each(to, function(val, name) { 624 if (typeof val === 'function') { 625 val = val.call(this, node); 626 } 627 628 begin = from[name]; 629 if (begin === undefined) { 630 begin = (name in customAttr && 'get' in customAttr[name]) ? 631 customAttr[name].get(this, name) : Y.Anim.DEFAULT_GETTER(this, name); 632 } else if (typeof begin === 'function') { 633 begin = begin.call(this, node); 634 } 635 636 var mFrom = Y.Anim.RE_UNITS.exec(begin), 637 mTo = Y.Anim.RE_UNITS.exec(val); 638 639 begin = mFrom ? mFrom[1] : begin; 640 end = mTo ? mTo[1] : val; 641 unit = mTo ? mTo[2] : mFrom ? mFrom[2] : ''; // one might be zero TODO: mixed units 642 643 if (!unit && Y.Anim.RE_DEFAULT_UNIT.test(name)) { 644 unit = Y.Anim.DEFAULT_UNIT; 645 } 646 647 if (!begin || !end) { 648 Y.error('invalid "from" or "to" for "' + name + '"', 'Anim'); 649 return; 650 } 651 652 attr[name] = { 653 from: Y.Lang.isObject(begin) ? Y.clone(begin) : begin, 654 to: end, 655 unit: unit 656 }; 657 658 }, this); 659 660 this._runtimeAttr = attr; 661 }, 662 663 664 // TODO: move to computedStyle? (browsers dont agree on default computed offsets) 665 _getOffset: function(attr) { 666 var node = this._node, 667 val = node.getComputedStyle(attr), 668 get = (attr === 'left') ? 'getX': 'getY', 669 set = (attr === 'left') ? 'setX': 'setY', 670 position; 671 672 if (val === 'auto') { 673 position = node.getStyle('position'); 674 if (position === 'absolute' || position === 'fixed') { 675 val = node[get](); 676 node[set](val); 677 } else { 678 val = 0; 679 } 680 } 681 682 return val; 683 }, 684 685 destructor: function() { 686 delete Y.Anim._instances[Y.stamp(this)]; 687 } 688 }; 689 690 Y.extend(Y.Anim, Y.Base, proto); 691 692 693 }, '3.17.2', {"requires": ["base-base", "node-style", "color-base"]});
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |