[ 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 } 193 return node; 194 } 195 }, 196 197 /** 198 * The length of the animation. Defaults to "1" (second). 199 * @attribute duration 200 * @type NUM 201 */ 202 duration: { 203 value: 1 204 }, 205 206 /** 207 * The method that will provide values to the attribute(s) during the animation. 208 * Defaults to "Easing.easeNone". 209 * @attribute easing 210 * @type Function 211 */ 212 easing: { 213 value: Y.Anim.DEFAULT_EASING, 214 215 setter: function(val) { 216 if (typeof val === 'string' && Y.Easing) { 217 return Y.Easing[val]; 218 } 219 } 220 }, 221 222 /** 223 * The starting values for the animated properties. 224 * 225 * Fields may be strings, numbers, or functions. 226 * If a function is used, the return value becomes the from value. 227 * If no from value is specified, the DEFAULT_GETTER will be used. 228 * Supports any unit, provided it matches the "to" (or default) 229 * unit (e.g. `{width: '10em', color: 'rgb(0, 0, 0)', borderColor: '#ccc'}`). 230 * 231 * If using the default ('px' for length-based units), the unit may be omitted 232 * (e.g. `{width: 100}, borderColor: 'ccc'}`, which defaults to pixels 233 * and hex, respectively). 234 * 235 * @attribute from 236 * @type Object 237 */ 238 from: {}, 239 240 /** 241 * The ending values for the animated properties. 242 * 243 * Fields may be strings, numbers, or functions. 244 * Supports any unit, provided it matches the "from" (or default) 245 * unit (e.g. `{width: '50%', color: 'red', borderColor: '#ccc'}`). 246 * 247 * If using the default ('px' for length-based units), the unit may be omitted 248 * (e.g. `{width: 100, borderColor: 'ccc'}`, which defaults to pixels 249 * and hex, respectively). 250 * 251 * @attribute to 252 * @type Object 253 */ 254 to: {}, 255 256 /** 257 * Date stamp for the first frame of the animation. 258 * @attribute startTime 259 * @type Int 260 * @default 0 261 * @readOnly 262 */ 263 startTime: { 264 value: 0, 265 readOnly: true 266 }, 267 268 /** 269 * Current time the animation has been running. 270 * @attribute elapsedTime 271 * @type Int 272 * @default 0 273 * @readOnly 274 */ 275 elapsedTime: { 276 value: 0, 277 readOnly: true 278 }, 279 280 /** 281 * Whether or not the animation is currently running. 282 * @attribute running 283 * @type Boolean 284 * @default false 285 * @readOnly 286 */ 287 running: { 288 getter: function() { 289 return !!_running[Y.stamp(this)]; 290 }, 291 value: false, 292 readOnly: true 293 }, 294 295 /** 296 * The number of times the animation should run 297 * @attribute iterations 298 * @type Int 299 * @default 1 300 */ 301 iterations: { 302 value: 1 303 }, 304 305 /** 306 * The number of iterations that have occurred. 307 * Resets when an animation ends (reaches iteration count or stop() called). 308 * @attribute iterationCount 309 * @type Int 310 * @default 0 311 * @readOnly 312 */ 313 iterationCount: { 314 value: 0, 315 readOnly: true 316 }, 317 318 /** 319 * How iterations of the animation should behave. 320 * Possible values are "normal" and "alternate". 321 * Normal will repeat the animation, alternate will reverse on every other pass. 322 * 323 * @attribute direction 324 * @type String 325 * @default "normal" 326 */ 327 direction: { 328 value: 'normal' // | alternate (fwd on odd, rev on even per spec) 329 }, 330 331 /** 332 * Whether or not the animation is currently paused. 333 * @attribute paused 334 * @type Boolean 335 * @default false 336 * @readOnly 337 */ 338 paused: { 339 readOnly: true, 340 value: false 341 }, 342 343 /** 344 * If true, the `from` and `to` attributes are swapped, 345 * and the animation is then run starting from `from`. 346 * @attribute reverse 347 * @type Boolean 348 * @default false 349 */ 350 reverse: { 351 value: false 352 } 353 354 355 }; 356 357 /** 358 * Runs all animation instances. 359 * @method run 360 * @static 361 */ 362 Y.Anim.run = function() { 363 var instances = Y.Anim._instances, 364 i; 365 for (i in instances) { 366 if (instances[i].run) { 367 instances[i].run(); 368 } 369 } 370 }; 371 372 /** 373 * Pauses all animation instances. 374 * @method pause 375 * @static 376 */ 377 Y.Anim.pause = function() { 378 for (var i in _running) { // stop timer if nothing running 379 if (_running[i].pause) { 380 _running[i].pause(); 381 } 382 } 383 384 Y.Anim._stopTimer(); 385 }; 386 387 /** 388 * Stops all animation instances. 389 * @method stop 390 * @static 391 */ 392 Y.Anim.stop = function() { 393 for (var i in _running) { // stop timer if nothing running 394 if (_running[i].stop) { 395 _running[i].stop(); 396 } 397 } 398 Y.Anim._stopTimer(); 399 }; 400 401 Y.Anim._startTimer = function() { 402 if (!_timer) { 403 _timer = setInterval(Y.Anim._runFrame, Y.Anim._intervalTime); 404 } 405 }; 406 407 Y.Anim._stopTimer = function() { 408 clearInterval(_timer); 409 _timer = 0; 410 }; 411 412 /** 413 * Called per Interval to handle each animation frame. 414 * @method _runFrame 415 * @private 416 * @static 417 */ 418 Y.Anim._runFrame = function() { 419 var done = true, 420 anim; 421 for (anim in _running) { 422 if (_running[anim]._runFrame) { 423 done = false; 424 _running[anim]._runFrame(); 425 } 426 } 427 428 if (done) { 429 Y.Anim._stopTimer(); 430 } 431 }; 432 433 Y.Anim.RE_UNITS = /^(-?\d*\.?\d*){1}(em|ex|px|in|cm|mm|pt|pc|%)*$/; 434 435 var proto = { 436 /** 437 * Starts or resumes an animation. 438 * @method run 439 * @chainable 440 */ 441 run: function() { 442 if (this.get(PAUSED)) { 443 this._resume(); 444 } else if (!this.get(RUNNING)) { 445 this._start(); 446 } 447 return this; 448 }, 449 450 /** 451 * Pauses the animation and 452 * freezes it in its current state and time. 453 * Calling run() will continue where it left off. 454 * @method pause 455 * @chainable 456 */ 457 pause: function() { 458 if (this.get(RUNNING)) { 459 this._pause(); 460 } 461 return this; 462 }, 463 464 /** 465 * Stops the animation and resets its time. 466 * @method stop 467 * @param {Boolean} finish If true, the animation will move to the last frame 468 * @chainable 469 */ 470 stop: function(finish) { 471 if (this.get(RUNNING) || this.get(PAUSED)) { 472 this._end(finish); 473 } 474 return this; 475 }, 476 477 _added: false, 478 479 _start: function() { 480 this._set(START_TIME, new Date() - this.get(ELAPSED_TIME)); 481 this._actualFrames = 0; 482 if (!this.get(PAUSED)) { 483 this._initAnimAttr(); 484 } 485 _running[Y.stamp(this)] = this; 486 Y.Anim._startTimer(); 487 488 this.fire(START); 489 }, 490 491 _pause: function() { 492 this._set(START_TIME, null); 493 this._set(PAUSED, true); 494 delete _running[Y.stamp(this)]; 495 496 /** 497 * @event pause 498 * @description fires when an animation is paused. 499 * @param {Event} ev The pause event. 500 * @type Event.Custom 501 */ 502 this.fire('pause'); 503 }, 504 505 _resume: function() { 506 this._set(PAUSED, false); 507 _running[Y.stamp(this)] = this; 508 this._set(START_TIME, new Date() - this.get(ELAPSED_TIME)); 509 Y.Anim._startTimer(); 510 511 /** 512 * @event resume 513 * @description fires when an animation is resumed (run from pause). 514 * @param {Event} ev The pause event. 515 * @type Event.Custom 516 */ 517 this.fire('resume'); 518 }, 519 520 _end: function(finish) { 521 var duration = this.get('duration') * 1000; 522 if (finish) { // jump to last frame 523 this._runAttrs(duration, duration, this.get(REVERSE)); 524 } 525 526 this._set(START_TIME, null); 527 this._set(ELAPSED_TIME, 0); 528 this._set(PAUSED, false); 529 530 delete _running[Y.stamp(this)]; 531 this.fire(END, {elapsed: this.get(ELAPSED_TIME)}); 532 }, 533 534 _runFrame: function() { 535 var d = this._runtimeAttr.duration, 536 t = new Date() - this.get(START_TIME), 537 reverse = this.get(REVERSE), 538 done = (t >= d); 539 540 this._runAttrs(t, d, reverse); 541 this._actualFrames += 1; 542 this._set(ELAPSED_TIME, t); 543 544 this.fire(TWEEN); 545 if (done) { 546 this._lastFrame(); 547 } 548 }, 549 550 _runAttrs: function(t, d, reverse) { 551 var attr = this._runtimeAttr, 552 customAttr = Y.Anim.behaviors, 553 easing = attr.easing, 554 lastFrame = d, 555 done = false, 556 attribute, 557 setter, 558 i; 559 560 if (t >= d) { 561 done = true; 562 } 563 564 if (reverse) { 565 t = d - t; 566 lastFrame = 0; 567 } 568 569 for (i in attr) { 570 if (attr[i].to) { 571 attribute = attr[i]; 572 setter = (i in customAttr && 'set' in customAttr[i]) ? 573 customAttr[i].set : Y.Anim.DEFAULT_SETTER; 574 575 if (!done) { 576 setter(this, i, attribute.from, attribute.to, t, d, easing, attribute.unit); 577 } else { 578 setter(this, i, attribute.from, attribute.to, lastFrame, d, easing, attribute.unit); 579 } 580 } 581 } 582 583 584 }, 585 586 _lastFrame: function() { 587 var iter = this.get('iterations'), 588 iterCount = this.get(ITERATION_COUNT); 589 590 iterCount += 1; 591 if (iter === 'infinite' || iterCount < iter) { 592 if (this.get('direction') === 'alternate') { 593 this.set(REVERSE, !this.get(REVERSE)); // flip it 594 } 595 /** 596 * @event iteration 597 * @description fires when an animation begins an iteration. 598 * @param {Event} ev The iteration event. 599 * @type Event.Custom 600 */ 601 this.fire('iteration'); 602 } else { 603 iterCount = 0; 604 this._end(); 605 } 606 607 this._set(START_TIME, new Date()); 608 this._set(ITERATION_COUNT, iterCount); 609 }, 610 611 _initAnimAttr: function() { 612 var from = this.get('from') || {}, 613 to = this.get('to') || {}, 614 attr = { 615 duration: this.get('duration') * 1000, 616 easing: this.get('easing') 617 }, 618 customAttr = Y.Anim.behaviors, 619 node = this.get(NODE), // implicit attr init 620 unit, begin, end; 621 622 Y.each(to, function(val, name) { 623 if (typeof val === 'function') { 624 val = val.call(this, node); 625 } 626 627 begin = from[name]; 628 if (begin === undefined) { 629 begin = (name in customAttr && 'get' in customAttr[name]) ? 630 customAttr[name].get(this, name) : Y.Anim.DEFAULT_GETTER(this, name); 631 } else if (typeof begin === 'function') { 632 begin = begin.call(this, node); 633 } 634 635 var mFrom = Y.Anim.RE_UNITS.exec(begin), 636 mTo = Y.Anim.RE_UNITS.exec(val); 637 638 begin = mFrom ? mFrom[1] : begin; 639 end = mTo ? mTo[1] : val; 640 unit = mTo ? mTo[2] : mFrom ? mFrom[2] : ''; // one might be zero TODO: mixed units 641 642 if (!unit && Y.Anim.RE_DEFAULT_UNIT.test(name)) { 643 unit = Y.Anim.DEFAULT_UNIT; 644 } 645 646 if (!begin || !end) { 647 Y.error('invalid "from" or "to" for "' + name + '"', 'Anim'); 648 return; 649 } 650 651 attr[name] = { 652 from: Y.Lang.isObject(begin) ? Y.clone(begin) : begin, 653 to: end, 654 unit: unit 655 }; 656 657 }, this); 658 659 this._runtimeAttr = attr; 660 }, 661 662 663 // TODO: move to computedStyle? (browsers dont agree on default computed offsets) 664 _getOffset: function(attr) { 665 var node = this._node, 666 val = node.getComputedStyle(attr), 667 get = (attr === 'left') ? 'getX': 'getY', 668 set = (attr === 'left') ? 'setX': 'setY', 669 position; 670 671 if (val === 'auto') { 672 position = node.getStyle('position'); 673 if (position === 'absolute' || position === 'fixed') { 674 val = node[get](); 675 node[set](val); 676 } else { 677 val = 0; 678 } 679 } 680 681 return val; 682 }, 683 684 destructor: function() { 685 delete Y.Anim._instances[Y.stamp(this)]; 686 } 687 }; 688 689 Y.extend(Y.Anim, Y.Base, proto); 690 691 692 }, '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 |