vendor: 3,594 bytes, lines 1-88
1/******/ (function(modules) { // webpackBootstrap 2/******/ // The module cache 3/******/ var installedModules = {}; 4/******/ 5/******/ // The require function 6/******/ function __webpack_require__(moduleId) { 7/******/ 8/******/ // Check if module is in cache 9/******/ if(installedModules[moduleId]) { 10/******/ return installedModules[moduleId].exports; 11/******/ } 12/******/ // Create a new module (and put it into the cache) 13/******/ var module = installedModules[moduleId] = { 14/******/ i: moduleId, 15/******/ l: false, 16/******/ exports: {} 17/******/ }; 18/******/ 19/******/ // Execute the module function 20/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 21/******/ 22/******/ // Flag the module as loaded 23/******/ module.l = true; 24/******/ 25/******/ // Return the exports of the module 26/******/ return module.exports; 27/******/ } 28/******/ 29/******/ 30/******/ // expose the modules object (__webpack_modules__) 31/******/ __webpack_require__.m = modules; 32/******/ 33/******/ // expose the module cache 34/******/ __webpack_require__.c = installedModules; 35/******/ 36/******/ // define getter function for harmony exports 37/******/ __webpack_require__.d = function(exports, name, getter) { 38/******/ if(!__webpack_require__.o(exports, name)) { 39/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); 40/******/ } 41/******/ }; 42/******/ 43/******/ // define __esModule on exports 44/******/ __webpack_require__.r = function(exports) { 45/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { 46/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); 47/******/ } 48/******/ Object.defineProperty(exports, '__esModule', { value: true }); 49/******/ }; 50/******/ 51/******/ // create a fake namespace object 52/******/ // mode & 1: value is a module id, require it 53/******/ // mode & 2: merge all properties of value into the ns 54/******/ // mode & 4: return value when already ns object 55/******/ // mode & 8|1: behave like require 56/******/ __webpack_require__.t = function(value, mode) { 57/******/ if(mode & 1) value = __webpack_require__(value); 58/******/ if(mode & 8) return value; 59/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; 60/******/ var ns = Object.create(null); 61/******/ __webpack_require__.r(ns); 62/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); 63/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); 64/******/ return ns; 65/******/ }; 66/******/ 67/******/ // getDefaultExport function for compatibility with non-harmony modules 68/******/ __webpack_require__.n = function(module) { 69/******/ var getter = module && module.__esModule ? 70/******/ function getDefault() { return module['default']; } : 71/******/ function getModuleExports() { return module; }; 72/******/ __webpack_require__.d(getter, 'a', getter); 73/******/ return getter; 74/******/ }; 75/******/ 76/******/ // Object.prototype.hasOwnProperty.call 77/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 78/******/ 79/******/ // __webpack_public_path__ 80/******/ __webpack_require__.p = ""; 81/******/ 82/******/ 83/******/ // Load entry module and return exports 84/******/ return __webpack_require__(__webpack_require__.s = 2); 85/******/ }) 86/************************************************************************/ 87/******/ ({ 88
89/***/ "../../../upup-baseline/js/src/content-rotator/contentRotator.jsx": 90/*!*************************************************************************************************************************************!*\ 91 !*** /Applications/XAMPP/xamppfiles/htdocs/gwu-wordpress/wp-content/themes/upup-baseline/js/src/content-rotator/contentRotator.jsx ***! 92 \*************************************************************************************************************************************/ 93/*! exports provided: default */ 94/***/ (function(module, __webpack_exports__, __webpack_require__) { 95 96"use strict"; 97__webpack_require__.r(__webpack_exports__); 98/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return contentRotator; }); 99/* harmony import */ var regenerator_runtime__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! regenerator-runtime */ "../../../upup-baseline/node_modules/regenerator-runtime/runtime.js"); 100/* harmony import */ var regenerator_runtime__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(regenerator_runtime__WEBPACK_IMPORTED_MODULE_0__); 101/* harmony import */ var hammerjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! hammerjs */ "../../../upup-baseline/node_modules/hammerjs/hammer.js"); 102/* harmony import */ var hammerjs__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(hammerjs__WEBPACK_IMPORTED_MODULE_1__); 103/* harmony import */ var _utility__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../utility */ "../../../upup-baseline/js/src/utility.js"); 104function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 105 106function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } 107 108function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } 109 110function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 111 112 113 114 115/** 116 * Drive content rotators on the page 117 * Must register controls and subcomponents with this driver 118 */ 119 120var contentRotator = /*#__PURE__*/function () { 121 /** 122 * Pick up on all the parts of the rotator: Images, Content, Controls 123 * @param rotatorContainer 124 */ 125 function contentRotator(rotatorContainer) { 126 var _this = this; 127 128 _classCallCheck(this, contentRotator); 129 130 _defineProperty(this, "handleControlAction", function (action, goToIndex, e) { 131 switch (action) { 132 case 'goTo': 133 _this.goTo(goToIndex); 134 135 break; 136 137 case 'prev': 138 _this.previous(e); 139 140 break; 141 142 case 'next': 143 _this.next(e); 144 145 break; 146 147 default: 148 console.error('The content rotator does not have a handler for the method: ' + action); 149 break; 150 } 151 }); 152 153 _defineProperty(this, "next", function (e) { 154 if (_this.count === 1) { 155 return; 156 } 157 158 if (_this.activeIndex >= _this.count - 1) { 159 _this.goTo(0); 160 } else { 161 _this.goTo(_this.activeIndex + 1); 162 } 163 }); 164 165 _defineProperty(this, "previous", function (e) { 166 if (_this.count === 1) { 167 return; 168 } 169 170 if (_this.activeIndex <= 0) { 171 _this.goTo(_this.count - 1); 172 } else { 173 _this.goTo(_this.activeIndex - 1); 174 } 175 }); 176 177 _defineProperty(this, "goTo", function (index) { 178 // transition all subcomponents to new index 179 try { 180 if (_this.subComponents.length > 0) { 181 _this.subComponents.forEach(function (subComponent) { 182 subComponent.transitionTo(index); 183 }); 184 } 185 } catch (e) { 186 console.error(e); 187 } 188 189 _this.activeIndex = index; 190 }); 191 192 this.activeIndex = 0; 193 this.count = 0; 194 this.subComponents = []; 195 this.controlElements = []; // Swipe controls are built in for the rotator! 196 197 this.swipeController = new hammerjs__WEBPACK_IMPORTED_MODULE_1___default.a.Manager(rotatorContainer); 198 this.swipeController.add(new hammerjs__WEBPACK_IMPORTED_MODULE_1___default.a.Swipe({ 199 direction: hammerjs__WEBPACK_IMPORTED_MODULE_1___default.a.DIRECTION_HORIZONTAL 200 })); 201 this.swipeController.on('swipeleft', this.next); 202 this.swipeController.on('swiperight', this.previous);
203 Object(_utility__WEBPACK_IMPORTED_MODULE_2__["preventClickOnDrag"])(rotatorContainer); 204 } 205 /** 206 * Controls are inputs that issue actions 207 * Could be left/ right or other buttons 208 * @param controlElement 209 * @param action - allowable are: [next, prev, goto] 210 * @param goToIndex - what index to go to - only relevant if this is a goto action 211 */ 212 213 214 _createClass(contentRotator, [{ 215 key: "registerControl", 216 value: function registerControl(controlElement, action) { 217 var goToIndex = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; 218 // add listeners to this control 219 controlElement.addEventListener('click', this.handleControlAction.bind(this, action, parseInt(goToIndex))); 220 this.controlElements.push(controlElement); 221 } 222 /** 223 * Subcomponents react to actions issued by the rotator 224 * @param SubComponentInstance - expect this instance to have a transitionTo function 225 */ 226 227 }, { 228 key: "registerSubComponent", 229 value: function registerSubComponent(SubComponentInstance) { 230 this.subComponents.push(SubComponentInstance); 231 232 if (typeof SubComponentInstance.getCount === 'function') { 233 this.count = SubComponentInstance.getCount(); 234 } 235 } 236 }]); 237 238 return contentRotator; 239}(); 240 241 242 243/***/ }), 244
245/***/ "../../../upup-baseline/js/src/content-rotator/slideRotator.jsx": 246/*!***********************************************************************************************************************************!*\ 247 !*** /Applications/XAMPP/xamppfiles/htdocs/gwu-wordpress/wp-content/themes/upup-baseline/js/src/content-rotator/slideRotator.jsx ***! 248 \***********************************************************************************************************************************/ 249/*! exports provided: default */ 250/***/ (function(module, __webpack_exports__, __webpack_require__) { 251 252"use strict"; 253__webpack_require__.r(__webpack_exports__); 254/* harmony import */ var velocity_animate__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! velocity-animate */ "../../../upup-baseline/node_modules/velocity-animate/velocity.js"); 255/* harmony import */ var velocity_animate__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(velocity_animate__WEBPACK_IMPORTED_MODULE_0__); 256/* harmony import */ var _utility__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../utility */ "../../../upup-baseline/js/src/utility.js"); 257function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } 258 259function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } 260 261function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 262 263function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } 264 265function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } 266 267 268 269/** 270 * Manage one set of slides 271 * Receive the slide container 272 */ 273 274var slideRotator = /*#__PURE__*/function () { 275 function slideRotator(slideContainer) { 276 _classCallCheck(this, slideRotator); 277 278 this.slideContainer = slideContainer; 279 this.slides = []; 280 this.slideCount = 0; 281 this.isAnimating = false; 282 this.activeIndex = 0; 283 this.setUpSlides(); 284 } 285 286 _createClass(slideRotator, [{ 287 key: "getCount", 288 value: function getCount() { 289 return this.slideCount; 290 } 291 /** 292 * Sets up the slides with images 293 * Hide images with aria-hidden - this is to preserve the triggers/ fire lines 294 */ 295 296 }, { 297 key: "setUpSlides", 298 value: function setUpSlides() { 299 var slideSelector = this.slideContainer.dataset.imageClass, 300 slides = []; 301 302 if (slideSelector) { 303 slides = Array.prototype.slice.call(this.slideContainer.querySelectorAll('.' + slideSelector)); 304 } else { 305 slides = Array.prototype.slice.call(this.slideContainer.querySelectorAll('img')); 306 } 307 308 this.slides = slides; 309 this.slideCount = slides.length; // hide all but current slide 310 311 this.slides.forEach(function (slide, index) { 312 if (index > 0) { 313 slide.setAttribute('aria-hidden', true); 314 } 315 }); 316 } 317 /** 318 * Handle Transition for the slide 319 */ 320 321 }, { 322 key: "transitionTo", 323 value: function () { 324 var _transitionTo = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(index) { 325 var _this = this; 326 327 var currentSlide, nextSlide; 328 return regeneratorRuntime.wrap(function _callee$(_context) { 329 while (1) { 330 switch (_context.prev = _context.next) { 331 case 0: 332 currentSlide = this.slides[this.activeIndex], nextSlide = this.slides[index]; 333 334 if (!(this.activeIndex === index)) { 335 _context.next = 4; 336 break; 337 } 338 339 nextSlide.setAttribute('aria-hidden', false); 340 return _context.abrupt("return"); 341 342 case 4: 343 this.isAnimating = true; // set the current image to opacity 1 z-index 0 344 345 Object(_utility__WEBPACK_IMPORTED_MODULE_1__["css"])(currentSlide, { 346 'z-index': 1 347 }); // set the next slide to display block 348 349 Object(_utility__WEBPACK_IMPORTED_MODULE_1__["css"])(nextSlide, { 350 'display': 'none' 351 }); // this is a REALLY sneaky way to trigger the screen reader's aria-live attribute. 352 // by inserting a brief pause, the SR picks up the change b/w none and block on the incoming item. 353 // with no pause, this does not work as the change is nearly instantaneous 354 355 _context.next = 9; 356 return Object(_utility__WEBPACK_IMPORTED_MODULE_1__["sleep"])(1); 357 358 case 9: 359 Object(_utility__WEBPACK_IMPORTED_MODULE_1__["css"])(nextSlide, { 360 'opacity': 0, 361 'z-index': 2, 362 'transition': 'none', 363 'display': 'block' 364 }); 365 nextSlide.setAttribute('aria-hidden', false); 366 currentSlide.setAttribute('aria-hidden', true); // transition the next slide in. 367 // hide the current slide once complete to hide it from the screen reader 368 369 velocity_animate__WEBPACK_IMPORTED_MODULE_0___default()(nextSlide, { 370 opacity: [1, 0], 371 scale: [1, 1.2], 372 zIndex: [2, 2] 373 }, { 374 // when complete, hide the old slide 375 complete: function complete() { 376 Object(_utility__WEBPACK_IMPORTED_MODULE_1__["css"])(currentSlide, { 377 'z-index': 0 378 }); // drop any transform or transitions from the style attribute 379 380 Object(_utility__WEBPACK_IMPORTED_MODULE_1__["css"])(nextSlide, { 381 transform: '', 382 transition: '' 383 }); 384 _this.isAnimating = false;
385 } 386 }); 387 this.activeIndex = index; 388 389 case 14: 390 case "end": 391 return _context.stop(); 392 } 393 } 394 }, _callee, this); 395 })); 396 397 function transitionTo(_x) { 398 return _transitionTo.apply(this, arguments); 399 } 400 401 return transitionTo; 402 }() 403 }]); 404 405 return slideRotator; 406}(); 407 408/* harmony default export */ __webpack_exports__["default"] = (slideRotator); 409 410/***/ }), 411
412/***/ "../../../upup-baseline/js/src/utility.js": 413/*!*************************************************************************************************************!*\ 414 !*** /Applications/XAMPP/xamppfiles/htdocs/gwu-wordpress/wp-content/themes/upup-baseline/js/src/utility.js ***! 415 \*************************************************************************************************************/ 416/*! exports provided: setPageHeight, setHeaderHeight, closestPolyfill, trackHeaderBottom, debounce, throttle, containScroll, allowScrollWithinContainedScroll, sleep, preventGhosts, preventClickOnDrag, css, getAttributeStyles, merge, getElOffset, manageClipboardLinks, copyToClipboard */ 417/***/ (function(module, __webpack_exports__, __webpack_require__) { 418 419"use strict"; 420__webpack_require__.r(__webpack_exports__); 421/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "setPageHeight", function() { return setPageHeight; }); 422/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "setHeaderHeight", function() { return setHeaderHeight; }); 423/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "closestPolyfill", function() { return closestPolyfill; }); 424/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "trackHeaderBottom", function() { return trackHeaderBottom; }); 425/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "debounce", function() { return debounce; }); 426/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "throttle", function() { return throttle; }); 427/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "containScroll", function() { return containScroll; }); 428/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "allowScrollWithinContainedScroll", function() { return allowScrollWithinContainedScroll; }); 429/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "sleep", function() { return sleep; }); 430/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "preventGhosts", function() { return preventGhosts; }); 431/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "preventClickOnDrag", function() { return preventClickOnDrag; }); 432/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "css", function() { return css; }); 433/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getAttributeStyles", function() { return getAttributeStyles; }); 434/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "merge", function() { return merge; }); 435/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getElOffset", function() { return getElOffset; }); 436/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "manageClipboardLinks", function() { return manageClipboardLinks; }); 437/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "copyToClipboard", function() { return copyToClipboard; }); 438function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } 439 440function setPageHeight() { 441 var vh = window.innerHeight * 0.01; // Then we set the value in the --vh custom property to the root of the document 442 443 document.documentElement.style.setProperty('--vh', vh + 'px'); 444} 445/** 446 * Set a variable to reflect the height of the header 447 */ 448 449function setHeaderHeight() { 450 var header = document.getElementById('site-header'), 451 headerHeight = header.offsetHeight, 452 originalHeight = header.dataset.originalHeight; 453 454 if (originalHeight) { 455 headerHeight = originalHeight; 456 } 457 458 document.documentElement.style.setProperty('--headerHeight', headerHeight + 'px'); 459} 460function closestPolyfill() { 461 if (!Element.prototype.matches) { 462 Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector; 463 } 464 465 if (!Element.prototype.closest) { 466 Element.prototype.closest = function (s) { 467 var el = this; 468 469 do { 470 if (el.matches(s)) return el; 471 el = el.parentElement || el.parentNode; 472 } while (el !== null && el.nodeType === 1); 473 474 return null; 475 }; 476 } 477} 478/** 479 * Track the bottom of the header offset from the window 480 */ 481 482function trackHeaderBottom() { 483 var header = document.getElementById('site-header'), 484 headerWrap = header.querySelector('.site-header__wrap'), 485 headerHeight = 0, 486 headerOffset = null, 487 headerBottom; 488 489 if (headerWrap) { 490 headerHeight = headerWrap.offsetHeight; 491 headerOffset = headerWrap.getBoundingClientRect(); 492 } else { 493 headerHeight = header.offsetHeight; 494 headerOffset = header.getBoundingClientRect(); 495 } 496 497 headerBottom = headerOffset.top + headerHeight; 498 document.documentElement.style.setProperty('--headerBottom', headerBottom + 'px'); 499} 500function debounce(callback, threshold, execAsap) { 501 var timeout; 502 return function () { 503 var obj = this, 504 args = arguments; 505 506 function delayed() { 507 if (!execAsap) callback.apply(obj, args); 508 clearTimeout(timeout); 509 timeout = null; 510 } 511 512 if (timeout) clearTimeout(timeout);else if (execAsap) callback.apply(obj, args); 513 timeout = setTimeout(delayed, threshold || 100); 514 }; 515} 516function throttle(callback) { 517 var interval = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 100; 518 var fire_last = arguments.length > 2 ? arguments[2] : undefined; 519 var last = Date.now(), 520 timeout = null; 521 return function () { 522 var obj = this, 523 args = arguments, 524 now = Date.now(); 525 526 function delayed() { 527 callback.apply(obj, args); 528 timeout = null; 529 } //this event is new enough 530 531 532 if (now - last > interval) { 533 callback.apply(obj, args); 534 last = now; //can be set up to call the callback one more time at the end of the throttle 535 536 if (fire_last) { 537 clearTimeout(timeout); 538 timeout = setTimeout(delayed, interval || 100); 539 } 540 } 541 }; 542} 543/** 544 * TODO: improve handling for widthGreaterThan logic - really only relevant if a container should not scroll at a given size 545 * Handle scrolling issue on iOS where background can be scrolled while menu is open 546 * @param element 547 * @param screenSize 548 */ 549 550function containScroll(element) { 551 var screenSize = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { 552 x: function x(w) { 553 return w > 0; 554 }, 555 y: function y(h) { 556 return h > 0; 557 } 558 }; 559 560 var initialClientY = null, 561 cancelIfAtBoundary = function cancelIfAtBoundary(deltaY, e) { 562 if (element.scrollHeight - element.scrollTop <= element.clientHeight && deltaY > 0 || element.scrollTop === 0 && deltaY < 0) { 563 e.preventDefault(); 564 } 565 }, 566 567 /** 568 * Check screen size constraints 569 * @param e 570 */ 571 isScreenCorrectSize = function isScreenCorrectSize() { 572 return screenSize.x(window.innerWidth) && screenSize.y(window.innerHeight); 573 }, 574 handleTouchStart = function handleTouchStart(e) { 575 if (!isScreenCorrectSize()) { 576 return false;
577 } 578 579 if (e.targetTouches.length === 1) { 580 // detect single touch 581 initialClientY = e.targetTouches[0].clientY; 582 } 583 }, 584 handleTouchMove = function handleTouchMove(e) { 585 if (!isScreenCorrectSize()) { 586 return false; 587 } 588 589 var deltaY = e.targetTouches[0].clientY - initialClientY; 590 591 if (e.targetTouches.length !== 1) { 592 return e; 593 } // invert delat Y here for same logic to work 594 595 596 cancelIfAtBoundary(-deltaY, e); 597 e.stopPropagation(); 598 e.stopImmediatePropagation(); 599 }, 600 handleWheel = function handleWheel(e) { 601 var deltaY = e.deltaY; 602 603 if (!isScreenCorrectSize()) { 604 return false; 605 } 606 607 cancelIfAtBoundary(deltaY, e); 608 e.stopPropagation(); 609 e.stopImmediatePropagation(); 610 }; 611 612 element.addEventListener('touchstart', handleTouchStart); 613 element.addEventListener('touchmove', handleTouchMove, { 614 passive: false 615 }); 616 element.addEventListener('wheel', handleWheel, { 617 passive: false 618 }); 619} 620/** 621 * way that scrolling can be stopped from propagating if not at boundary, but prop
621agate up if hits boundary 622 */ 623 624function allowScrollWithinContainedScroll(element) { 625 var initialClientY = null, 626 stopPropagationIfWithinBoundary = function stopPropagationIfWithinBoundary(deltaY, e) { 627 if (element.scrollHeight - element.offsetHeight >= element.scrollTop && !(element.scrollTop === 0 && deltaY < 0 || element.scrollHeight - element.offsetHeight === element.scrollTop && deltaY > 0)) { 628 e.stopPropagation(); 629 e.stopImmediatePropagation(); 630 } 631 }, 632 handleTouchStart = function handleTouchStart(e) { 633 if (e.targetTouches.length === 1) { 634 // detect single touch 635 initialClientY = e.targetTouches[0].clientY; 636 } 637 }, 638 handleTouchMove = function handleTouchMove(e) { 639 var deltaY = e.targetTouches[0].clientY - initialClientY; 640 641 if (e.targetTouches.length !== 1) { 642 return e; 643 } // invert delat Y here for same logic to work 644 645 646 stopPropagationIfWithinBoundary(-deltaY, e); 647 }, 648 handleWheel = function handleWheel(e) { 649 var deltaY = e.deltaY; 650 stopPropagationIfWithinBoundary(deltaY, e); 651 }; 652 653 element.addEventListener('touchstart', handleTouchStart); 654 element.addEventListener('touchmove', handleTouchMove, { 655 passive: false 656 }); 657 element.addEventListener('wheel', handleWheel, { 658 passive: false 659 }); 660} 661function sleep(ms) { 662 return new Promise(function (resolve) { 663 return setTimeout(resolve, ms); 664 }); 665} 666/** 667 * Props: https://gist.github.com/kosich/23188dd86633b6c2efb7 668 * @param element 669 */ 670 671function preventGhosts(element) { 672 var POINTER_TYPE = { 673 MOUSE: 0, 674 TOUCH: 1 675 }, 676 ANTI_GHOST_DELAY = 2000, 677 latestInteractionType, 678 latestInteractionTime, 679 mouseEvents = ['mousedown', 'mouseup', 'mousemove'], 680 touchEvents = ['touchstart', 'touchend']; 681 682 function handleTap(type, e) { 683 var now = Date.now(); 684 685 if (type !== latestInteractionType) { 686 if (now - latestInteractionTime <= ANTI_GHOST_DELAY) { 687 // console.log('!prevented!'); 688 e.preventDefault(); 689 e.stopPropagation(); 690 e.stopImmediatePropagation(); 691 return false; 692 } 693 694 latestInteractionType = type; 695 } 696 697 latestInteractionTime = now; 698 } 699 700 function attachEvents(eventList, interactionType) { 701 eventList.forEach(function (eventName) { 702 element.addEventListener(eventName, handleTap.bind(null, interactionType), true); 703 }); 704 } 705 706 attachEvents(mouseEvents, POINTER_TYPE.MOUSE); 707 attachEvents(touchEvents, POINTER_TYPE.TOUCH); 708} 709/** 710 * Prevent a click event on drag 711 */ 712 713function preventClickOnDrag(element) { 714 var downX = 0, 715 downY = 0; 716 717 function handleDown(e) { 718 downX = e.screenX; 719 downY = e.screenY; 720 } 721 722 function handleUp(e) { 723 var releaseX = e.screenX, 724 releaseY = e.screenY, 725 dist = Math.sqrt(Math.pow(releaseX - downX, 2) + Math.pow(releaseY - downY, 2)); 726 727 if (dist > 10) { 728 e.preventDefault(); 729 e.stopPropagation(); 730 } 731 } 732 733 element.addEventListener('mousedown', handleDown); 734 element.addEventListener('mouseup', handleUp); 735 element.addEventListener('click', handleUp); 736} 737/** 738 * Set the CSS style attribute of an element 739 * @param el - the element to manipulate 740 * @param props_to - the properties and values to set 741 */ 742 743function css(el, props_to) { 744 var styles = getAttributeStyles(el), 745 updated = merge(styles, props_to), 746 style_string = ''; 747 748 for (var prop in updated) { 749 if (updated[prop] === null || updated[prop] === '') continue; 750 style_string += prop + ':' + updated[prop] + '; '; 751 } 752 753 style_string = style_string.replace(/;\s?$/, ''); 754 el.setAttribute('style', style_string); 755} 756function getAttributeStyles(el) { 757 var string = el.getAttribute('style'), 758 pairs = string ? string.split(';') : [], 759 _tmp, 760 styles = {}; 761 762 if (pairs.length <= 0) return styles; 763 764 for (var i = 0, il = pairs.length; i < il; i++) { 765 _tmp = pairs[i].trim().split(/:(.+)?/); //split on first occuence 766 767 if (_tmp[0] == '') continue; 768 styles[_tmp[0].trim()] = _tmp[1].trim(); 769 } 770 771 return styles; 772} 773function merge(o1, o2, flat) { 774 var o3 = {}; 775 flat = flat === true; 776 777 for (var prop in o1) { 778 if (!o1.hasOwnProperty(prop)) continue; 779 o3[prop] = o1[prop]; 780 } 781 782 for (prop in o2) { 783 if (!o2.hasOwnProperty(prop)) continue; 784 785 if (_typeof(o2[prop]) == 'object' && _typeof(o3[prop]) == 'object') { 786 if (!flat) { 787 o3[prop] = merge(o3[prop], o2[prop]); 788 } else { 789 o3[prop] = o2[prop]; 790 } 791 } else { 792 o3[prop] = o2[prop]; 793 } 794 } 795 796 return o3; 797} 798function getElOffset(el) { 799 var rect = el.getBoundingClientRect(), 800 width = el.offsetWidth, 801 height = el.offsetHeight; 802 return { 803 left: rect.left + window.scrollX, 804 top: rect.top + window.pageYOffset, 805 right: window.innerWidth - rect.left - width, 806 bottom: rect.top + window.pageYOffset + height 807 }; 808} 809/** 810 * Find and manage links/ buttons that allow text to be copied to the clipboard 811 */ 812 813function manageClipboardLinks() { 814 var _this = this; 815 816 var clipboardLinks = document.querySelectorAll('.js-clipboard-copy'); 817 clipboardLinks.forEach(function (link) { 818 link.addEventListener('click', copyToClipboard.bind(_this, link)); 819 }); 820} 821/** 822 * Copy some text to the clipboard 823 * The target needs to carry the specific text as a data attribute 824 */ 825 826function copyToClipboard(link, e) { 827 var copyable = link.getAttribute('data-copy'); 828 e.preventDefault(); 829 830 if (!navigator || !navigator.clipboard) { 831 console.error("Could not copy - navigator object not available"); 832 return false;
833 } 834 835 navigator.clipboard.writeText(copyable).then(function () { 836 link.classList.add('copied'); 837 setTimeout(function () { 838 link.classList.remove('copied'); 839 }, 2000); 840 }); 841} 842 843/***/ }), 844
vendor: 74,397 bytes, lines 845-3495
845/***/ "../../../upup-baseline/node_modules/hammerjs/hammer.js": 846/*!***************************************************************************************************************************!*\ 847 !*** /Applications/XAMPP/xamppfiles/htdocs/gwu-wordpress/wp-content/themes/upup-baseline/node_modules/hammerjs/hammer.js ***! 848 \***************************************************************************************************************************/ 849/*! no static exports found */ 850/***/ (function(module, exports, __webpack_require__) { 851 852var __WEBPACK_AMD_DEFINE_RESULT__;/*! Hammer.JS - v2.0.7 - 2016-04-22 853 * http://hammerjs.github.io/ 854 * 855 * Copyright (c) 2016 Jorik Tangelder; 856 * Licensed under the MIT license */ 857(function(window, document, exportName, undefined) { 858 'use strict'; 859 860var VENDOR_PREFIXES = ['', 'webkit', 'Moz', 'MS', 'ms', 'o']; 861var TEST_ELEMENT = document.createElement('div'); 862 863var TYPE_FUNCTION = 'function'; 864 865var round = Math.round; 866var abs = Math.abs; 867var now = Date.now; 868 869/** 870 * set a timeout with a given scope 871 * @param {Function} fn 872 * @param {Number} timeout 873 * @param {Object} context 874 * @returns {number} 875 */ 876function setTimeoutContext(fn, timeout, context) { 877 return setTimeout(bindFn(fn, context), timeout); 878} 879 880/** 881 * if the argument is an array, we want to execute the fn on each entry 882 * if it aint an array we don't want to do a thing. 883 * this is used by all the methods that accept a single and array argument. 884 * @param {*|Array} arg 885 * @param {String} fn 886 * @param {Object} [context] 887 * @returns {Boolean} 888 */ 889function invokeArrayArg(arg, fn, context) { 890 if (Array.isArray(arg)) { 891 each(arg, context[fn], context); 892 return true; 893 } 894 return false; 895} 896 897/** 898 * walk objects and arrays 899 * @param {Object} obj 900 * @param {Function} iterator 901 * @param {Object} context 902 */ 903function each(obj, iterator, context) { 904 var i; 905 906 if (!obj) { 907 return; 908 } 909 910 if (obj.forEach) { 911 obj.forEach(iterator, context); 912 } else if (obj.length !== undefined) { 913 i = 0; 914 while (i < obj.length) { 915 iterator.call(context, obj[i], i, obj); 916 i++; 917 } 918 } else { 919 for (i in obj) { 920 obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj); 921 } 922 } 923} 924 925/** 926 * wrap a method with a deprecation warning and stack trace 927 * @param {Function} method 928 * @param {String} name 929 * @param {String} message 930 * @returns {Function} A new function wrapping the supplied method. 931 */ 932function deprecate(method, name, message) { 933 var deprecationMessage = 'DEPRECATED METHOD: ' + name + '\n' + message + ' AT \n'; 934 return function() { 935 var e = new Error('get-stack-trace'); 936 var stack = e && e.stack ? e.stack.replace(/^[^\(]+?[\n$]/gm, '') 937 .replace(/^\s+at\s+/gm, '') 938 .replace(/^Object.<anonymous>\s*\(/gm, '{anonymous}()@') : 'Unknown Stack Trace'; 939 940 var log = window.console && (window.console.warn || window.console.log); 941 if (log) { 942 log.call(window.console, deprecationMessage, stack); 943 } 944 return method.apply(this, arguments); 945 }; 946} 947 948/** 949 * extend object. 950 * means that properties in dest will be overwritten by the ones in src. 951 * @param {Object} target 952 * @param {...Object} objects_to_assign 953 * @returns {Object} target 954 */ 955var assign; 956if (typeof Object.assign !== 'function') { 957 assign = function assign(target) { 958 if (target === undefined || target === null) { 959 throw new TypeError('Cannot convert undefined or null to object'); 960 } 961 962 var output = Object(target); 963 for (var index = 1; index < arguments.length; index++) { 964 var source = arguments[index]; 965 if (source !== undefined && source !== null) { 966 for (var nextKey in source) { 967 if (source.hasOwnProperty(nextKey)) { 968 output[nextKey] = source[nextKey]; 969 } 970 } 971 } 972 } 973 return output; 974 }; 975} else { 976 assign = Object.assign; 977} 978 979/** 980 * extend object. 981 * means that properties in dest will be overwritten by the ones in src. 982 * @param {Object} dest 983 * @param {Object} src 984 * @param {Boolean} [merge=false] 985 * @returns {Object} dest 986 */ 987var extend = deprecate(function extend(dest, src, merge) { 988 var keys = Object.keys(src); 989 var i = 0; 990 while (i < keys.length) { 991 if (!merge || (merge && dest[keys[i]] === undefined)) { 992 dest[keys[i]] = src[keys[i]]; 993 } 994 i++; 995 } 996 return dest; 997}, 'extend', 'Use `assign`.'); 998 999/** 1000 * merge the values from src in the dest. 1001 * means that properties that exist in dest will not be overwritten by src 1002 * @param {Object} dest 1003 * @param {Object} src 1004 * @returns {Object} dest 1005 */ 1006var merge = deprecate(function merge(dest, src) { 1007 return extend(dest, src, true); 1008}, 'merge', 'Use `assign`.'); 1009 1010/** 1011 * simple class inheritance 1012 * @param {Function} child 1013 * @param {Function} base 1014 * @param {Object} [properties] 1015 */ 1016function inherit(child, base, properties) { 1017 var baseP = base.prototype, 1018 childP; 1019 1020 childP = child.prototype = Object.create(baseP); 1021 childP.constructor = child; 1022 childP._super = baseP; 1023 1024 if (properties) { 1025 assign(childP, properties); 1026 } 1027} 1028 1029/** 1030 * simple function bind 1031 * @param {Function} fn 1032 * @param {Object} context 1033 * @returns {Function} 1034 */ 1035function bindFn(fn, context) { 1036 return function boundFn() { 1037 return fn.apply(context, arguments); 1038 }; 1039} 1040 1041/** 1042 * let a boolean value also be a function that must return a boolean 1043 * this first item in args will be used as the context 1044 * @param {Boolean|Function} val 1045 * @param {Array} [args] 1046 * @returns {Boolean} 1047 */ 1048function boolOrFn(val, args) { 1049 if (typeof val == TYPE_FUNCTION) { 1050 return val.apply(args ? args[0] || undefined : undefined, args); 1051 } 1052 return val; 1053} 1054 1055/** 1056 * use the val2 when val1 is undefined 1057 * @param {*} val1 1058 * @param {*} val2 1059 * @returns {*} 1060 */ 1061function ifUndefined(val1, val2) { 1062 return (val1 === undefined) ? val2 : val1; 1063} 1064 1065/** 1066 * addEventListener with multiple events at once 1067 * @param {EventTarget} target 1068 * @param {String} types 1069 * @param {Function} handler 1070 */ 1071function addEventListeners(target, types, handler) { 1072 each(splitStr(types), function(type) { 1073 target.addEventListener(type, handler, false); 1074 }); 1075} 1076 1077/** 1078 * removeEventListener with multiple events at once 1079 * @param {EventTarget} target 1080 * @param {String} types 1081 * @param {Function} handler 1082 */ 1083function removeEventListeners(target, types, handler) { 1084 each(splitStr(types), function(type) { 1085 target.removeEventListener(type, handler, false); 1086 }); 1087} 1088 1089/** 1090 * find if a node is in the given parent 1091 * @method hasParent 1092 * @param {HTMLElement} node 1093 * @param {HTMLElement} parent 1094 * @return {Boolean} found 1095 */ 1096function hasParent(node, parent) { 1097 while (node) { 1098 if (node == parent) { 1099 return true; 1100 } 1101 node = node.parentNode; 1102 } 1103 return false; 1104} 1105 1106/** 1107 * small indexOf wrapper 1108 * @param {String} str 1109 * @param {String} find 1110 * @returns {Boolean} found 1111 */ 1112function inStr(str, find) { 1113 return str.indexOf(find) > -1; 1114} 1115 1116/** 1117 * split string on whitespace 1118 * @param {String} str 1119 * @returns {Array} words 1120 */ 1121function splitStr(str) { 1122 return str.trim().split(/\s+/g); 1123} 1124 1125/** 1126 * find if a array contains the object using indexOf or a simple polyFill 1127 * @param {Array} src 1128 * @param {String} find 1129 * @param {String} [findByKey] 1130 * @return {Boolean|Number} false when not found, or the index 1131 */ 1132function inArray(src, find, findByKey) { 1133 if (src.indexOf && !findByKey) { 1134 return src.indexOf(find); 1135 } else { 1136 var i = 0; 1137 while (i < src.length) { 1138 if ((findByKey && src[i][findByKey] == find) || (!findByKey && src[i] === find)) { 1139 return i; 1140 } 1141 i++; 1142 } 1143 return -1; 1144 } 1145} 1146 1147/** 1148 * convert array-like objects to real arrays 1149 * @param {Object} obj 1150 * @returns {Array} 1151 */ 1152function toArray(obj) { 1153 return Array.prototype.slice.call(obj, 0); 1154} 1155 1156/** 1157 * unique array with objects based on a key (like 'id') or just by the array's value 1158 * @param {Array} src [{id:1},{id:2},{id:1}] 1159 * @param {String} [key] 1160 * @param {Boolean} [sort=False] 1161 * @returns {Array} [{id:1},{id:2}] 1162 */ 1163function uniqueArray(src, key, sort) { 1164 var results = []; 1165 var values = []; 1166 var i = 0; 1167 1168 while (i < src.length) { 1169 var val = key ? src[i][key] : src[i]; 1170 if (inArray(values, val) < 0) { 1171 results.push(src[i]); 1172 } 1173 values[i] = val; 1174 i++; 1175 } 1176 1177 if (sort) { 1178 if (!key) { 1179 results = results.sort(); 1180 } else { 1181 results = results.sort(function sortUniqueArray(a, b) { 1182 return a[key] > b[key]; 1183 }); 1184 } 1185 } 1186 1187 return results; 1188} 1189 1190/** 1191 * get the prefixed property 1192 * @param {Object} obj 1193 * @param {String} property 1194 * @returns {String|Undefined} prefixed 1195 */ 1196function prefixed(obj, property) { 1197 var prefix, prop; 1198 var camelProp = property[0].toUpperCase() + property.slice(1); 1199 1200 var i = 0; 1201 while (i < VENDOR_PREFIXES.length) { 1202 prefix = VENDOR_PREFIXES[i]; 1203 prop = (prefix) ? prefix + camelProp : property; 1204 1205 if (prop in obj) { 1206 return prop; 1207 } 1208 i++; 1209 } 1210 return undefined; 1211} 1212 1213/** 1214 * get a unique id 1215 * @returns {number} uniqueId 1216 */ 1217var _uniqueId = 1; 1218function uniqueId() { 1219 return _uniqueId++; 1220} 1221 1222/** 1223 * get the window object of an element 1224 * @param {HTMLElement} element 1225 * @returns {DocumentView|Window} 1226 */ 1227function getWindowForElement(element) { 1228 var doc = element.ownerDocument || element; 1229 return (doc.defaultView || doc.parentWindow || window); 1230} 1231 1232var MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i; 1233 1234var SUPPORT_TOUCH = ('ontouchstart' in window); 1235var SUPPORT_POINTER_EVENTS = prefixed(window, 'PointerEvent') !== undefined; 1236var SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent); 1237 1238var INPUT_TYPE_TOUCH = 'touch'; 1239var INPUT_TYPE_PEN = 'pen'; 1240var INPUT_TYPE_MOUSE = 'mouse'; 1241var INPUT_TYPE_KINECT = 'kinect'; 1242 1243var COMPUTE_INTERVAL = 25; 1244 1245var INPUT_START = 1; 1246var INPUT_MOVE = 2; 1247var INPUT_END = 4; 1248var INPUT_CANCEL = 8; 1249 1250var DIRECTION_NONE = 1; 1251var DIRECTION_LEFT = 2; 1252var DIRECTION_RIGHT = 4; 1253var DIRECTION_UP = 8; 1254var DIRECTION_DOWN = 16; 1255 1256var DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT; 1257var DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN; 1258var DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL; 1259 1260var PROPS_XY = ['x', 'y']; 1261var PROPS_CLIENT_XY = ['clientX', 'clientY']; 1262 1263/** 1264 * create new input type manager 1265 * @param {Manager} manager 1266 * @param {Function} callback 1267 * @returns {Input} 1268 * @constructor 1269 */ 1270function Input(manager, callback) { 1271 var self = this; 1272 this.manager = manager; 1273 this.callback = callback; 1274 this.element = manager.element; 1275 this.target = manager.options.inputTarget; 1276 1277 // smaller wrapper around the handler, for the scope and the enabled state of the manager, 1278 // so when disabled the input events are completely bypassed. 1279 this.domHandler = function(ev) { 1280 if (boolOrFn(manager.options.enable, [manager])) { 1281 self.handler(ev); 1282 } 1283 }; 1284 1285 this.init(); 1286 1287} 1288 1289Input.prototype = { 1290 /** 1291 * should handle the inputEvent data and trigger the callback 1292 * @virtual 1293 */ 1294 handler: function() { }, 1295 1296 /** 1297 * bind the events 1298 */ 1299 init: function() { 1300 this.evEl && addEventListeners(this.element, this.evEl, this.domHandler); 1301 this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler); 1302 this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); 1303 }, 1304 1305 /** 1306 * unbind the events 1307 */ 1308 destroy: function() { 1309 this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler); 1310 this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler); 1311 this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); 1312 } 1313}; 1314 1315/** 1316 * create new input type manager 1317 * called by the Manager constructor 1318 * @param {Hammer} manager 1319 * @returns {Input} 1320 */ 1321function createInputInstance(manager) { 1322 var Type; 1323 var inputClass = manager.options.inputClass; 1324 1325 if (inputClass) { 1326 Type = inputClass; 1327 } else if (SUPPORT_POINTER_EVENTS) { 1328 Type = PointerEventInput; 1329 } else if (SUPPORT_ONLY_TOUCH) { 1330 Type = TouchInput; 1331 } else if (!SUPPORT_TOUCH) { 1332 Type = MouseInput; 1333 } else { 1334 Type = TouchMouseInput; 1335 } 1336 return new (Type)(manager, inputHandler); 1337} 1338 1339/** 1340 * handle input events 1341 * @param {Manager} manager 1342 * @param {String} eventType 1343 * @param {Object} input 1344 */ 1345function inputHandler(manager, eventType, input) { 1346 var pointersLen = input.pointers.length; 1347 var changedPointersLen = input.changedPointers.length; 1348 var isFirst = (eventType & INPUT_START && (pointersLen - changedPointersLen === 0)); 1349 var isFinal = (eventType & (INPUT_END | INPUT_CANCEL) && (pointersLen - changedPointersLen === 0)); 1350 1351 input.isFirst = !!isFirst; 1352 input.isFinal = !!isFinal; 1353 1354 if (isFirst) { 1355 manager.session = {}; 1356 } 1357 1358 // source event is the normalized value of the domEvents 1359 // like 'touchstart, mouseup, pointerdown' 1360 input.eventType = eventType; 1361 1362 // compute scale, rotation etc 1363 computeInputData(manager, input); 1364 1365 // emit secret event 1366 manager.emit('hammer.input', input); 1367 1368 manager.recognize(input); 1369 manager.session.prevInput = input; 1370} 1371 1372/** 1373 * extend the data with some usable properties like scale, rotate, velocity etc 1374 * @param {Object} manager 1375 * @param {Object} input 1376 */ 1377function computeInputData(manager, input) { 1378 var session = manager.session; 1379 var pointers = input.pointers; 1380 var pointersLength = pointers.length; 1381 1382 // store the first input to calculate the distance and direction 1383 if (!session.firstInput) { 1384 session.firstInput = simpleCloneInputData(input); 1385 } 1386 1387 // to compute scale and rotation we need to store the multiple touches 1388 if (pointersLength > 1 && !session.firstMultiple) { 1389 session.firstMultiple = simpleCloneInputData(input); 1390 } else if (pointersLength === 1) { 1391 session.firstMultiple = false; 1392 } 1393 1394 var firstInput = session.firstInput; 1395 var firstMultiple = session.firstMultiple; 1396 var offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center; 1397 1398 var center = input.center = getCenter(pointers); 1399 input.timeStamp = now(); 1400 input.deltaTime = input.timeStamp - firstInput.timeStamp; 1401 1402 input.angle = getAngle(offsetCenter, center); 1403 input.distance = getDistance(offsetCenter, center); 1404 1405 computeDeltaXY(session, input); 1406 input.offsetDirection = getDirection(input.deltaX, input.deltaY); 1407 1408 var overallVelocity = getVelocity(input.deltaTime, input.deltaX, input.deltaY); 1409 input.overallVelocityX = overallVelocity.x; 1410 input.overallVelocityY = overallVelocity.y; 1411 input.overallVelocity = (abs(overallVelocity.x) > abs(overallVelocity.y)) ? overallVelocity.x : overallVelocity.y; 1412 1413 input.scale = firstMultiple ? getScale(firstMultiple.pointers, pointers) : 1; 1414 input.rotation = firstMultiple ? getRotation(firstMultiple.pointers, pointers) : 0; 1415 1416 input.maxPointers = !session.prevInput ? input.pointers.length : ((input.pointers.length > 1417 session.prevInput.maxPointers) ? input.pointers.length : session.prevInput.maxPointers); 1418 1419 computeIntervalInputData(session, input); 1420 1421 // find the correct target 1422 var target = manager.element; 1423 if (hasParent(input.srcEvent.target, target)) { 1424 target = input.srcEvent.target; 1425 } 1426 input.target = target; 1427} 1428 1429function computeDeltaXY(session, input) { 1430 var center = input.center; 1431 var offset = session.offsetDelta || {}; 1432 var prevDelta = session.prevDelta || {}; 1433 var prevInput = session.prevInput || {}; 1434 1435 if (input.eventType === INPUT_START || prevInput.eventType === INPUT_END) { 1436 prevDelta = session.prevDelta = { 1437 x: prevInput.deltaX || 0, 1438 y: prevInput.deltaY || 0 1439 }; 1440 1441 offset = session.offsetDelta = { 1442 x: center.x, 1443 y: center.y 1444 }; 1445 } 1446 1447 input.deltaX = prevDelta.x + (center.x - offset.x); 1448 input.deltaY = prevDelta.y + (center.y - offset.y); 1449} 1450 1451/** 1452 * velocity is calculated every x ms 1453 * @param {Object} session 1454 * @param {Object} input 1455 */ 1456function computeIntervalInputData(session, input) { 1457 var last = session.lastInterval || input, 1458 deltaTime = input.timeStamp - last.timeStamp, 1459 velocity, velocityX, velocityY, direction; 1460 1461 if (input.eventType != INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined)) { 1462 var deltaX = input.deltaX - last.deltaX; 1463 var deltaY = input.deltaY - last.deltaY; 1464 1465 var v = getVelocity(deltaTime, deltaX, deltaY); 1466 velocityX = v.x; 1467 velocityY = v.y; 1468 velocity = (abs(v.x) > abs(v.y)) ? v.x : v.y; 1469 direction = getDirection(deltaX, deltaY); 1470 1471 session.lastInterval = input; 1472 } else { 1473 // use latest velocity info if it doesn't overtake a minimum period 1474 velocity = last.velocity; 1475 velocityX = last.velocityX; 1476 velocityY = last.velocityY; 1477 direction = last.direction; 1478 } 1479 1480 input.velocity = velocity; 1481 input.velocityX = velocityX; 1482 input.velocityY = velocityY; 1483 input.direction = direction; 1484} 1485 1486/** 1487 * create a simple clone from the input used for storage of firstInput and firstMultiple 1488 * @param {Object} input 1489 * @returns {Object} clonedInputData 1490 */ 1491function simpleCloneInputData(input) { 1492 // make a simple copy of the pointers because we will get a reference if we don't 1493 // we only need clientXY for the calculations 1494 var pointers = []; 1495 var i = 0; 1496 while (i < input.pointers.length) { 1497 pointers[i] = { 1498 clientX: round(input.pointers[i].clientX), 1499 clientY: round(input.pointers[i].clientY) 1500 }; 1501 i++; 1502 } 1503 1504 return { 1505 timeStamp: now(), 1506 pointers: pointers, 1507 center: getCenter(pointers), 1508 deltaX: input.deltaX, 1509 deltaY: input.deltaY 1510 }; 1511} 1512 1513/** 1514 * get the center of all the pointers 1515 * @param {Array} pointers 1516 * @return {Object} center contains `x` and `y` properties 1517 */ 1518function getCenter(pointers) { 1519 var pointersLength = pointers.length; 1520 1521 // no need to loop when only one touch 1522 if (pointersLength === 1) { 1523 return { 1524 x: round(pointers[0].clientX), 1525 y: round(pointers[0].clientY) 1526 }; 1527 } 1528 1529 var x = 0, y = 0, i = 0; 1530 while (i < pointersLength) { 1531 x += pointers[i].clientX; 1532 y += pointers[i].clientY; 1533 i++; 1534 } 1535 1536 return { 1537 x: round(x / pointersLength), 1538 y: round(y / pointersLength) 1539 }; 1540} 1541 1542/** 1543 * calculate the velocity between two points. unit is in px per ms. 1544 * @param {Number} deltaTime 1545 * @param {Number} x 1546 * @param {Number} y 1547 * @return {Object} velocity `x` and `y` 1548 */ 1549function getVelocity(deltaTime, x, y) { 1550 return { 1551 x: x / deltaTime || 0, 1552 y: y / deltaTime || 0 1553 }; 1554} 1555 1556/** 1557 * get the direction between two points 1558 * @param {Number} x 1559 * @param {Number} y 1560 * @return {Number} direction 1561 */ 1562function getDirection(x, y) { 1563 if (x === y) { 1564 return DIRECTION_NONE; 1565 } 1566 1567 if (abs(x) >= abs(y)) { 1568 return x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT; 1569 } 1570 return y < 0 ? DIRECTION_UP : DIRECTION_DOWN; 1571} 1572 1573/** 1574 * calculate the absolute distance between two points 1575 * @param {Object} p1 {x, y} 1576 * @param {Object} p2 {x, y} 1577 * @param {Array} [props] containing x and y keys 1578 * @return {Number} distance 1579 */ 1580function getDistance(p1, p2, props) { 1581 if (!props) { 1582 props = PROPS_XY; 1583 } 1584 var x = p2[props[0]] - p1[props[0]], 1585 y = p2[props[1]] - p1[props[1]]; 1586 1587 return Math.sqrt((x * x) + (y * y)); 1588} 1589 1590/** 1591 * calculate the angle between two coordinates 1592 * @param {Object} p1 1593 * @param {Object} p2 1594 * @param {Array} [props] containing x and y keys 1595 * @return {Number} angle 1596 */ 1597function getAngle(p1, p2, props) { 1598 if (!props) { 1599 props = PROPS_XY; 1600 } 1601 var x = p2[props[0]] - p1[props[0]], 1602 y = p2[props[1]] - p1[props[1]]; 1603 return Math.atan2(y, x) * 180 / Math.PI; 1604} 1605 1606/** 1607 * calculate the rotation degrees between two pointersets 1608 * @param {Array} start array of pointers 1609 * @param {Array} end array of pointers 1610 * @return {Number} rotation 1611 */ 1612function getRotation(start, end) { 1613 return getAngle(end[1], end[0], PROPS_CLIENT_XY) + getAngle(start[1], start[0], PROPS_CLIENT_XY); 1614} 1615 1616/** 1617 * calculate the scale factor between two pointersets 1618 * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out 1619 * @param {Array} start array of pointers 1620 * @param {Array} end array of pointers 1621 * @return {Number} scale 1622 */ 1623function getScale(start, end) { 1624 return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY); 1625} 1626 1627var MOUSE_INPUT_MAP = { 1628 mousedown: INPUT_START, 1629 mousemove: INPUT_MOVE, 1630 mouseup: INPUT_END 1631}; 1632 1633var MOUSE_ELEMENT_EVENTS = 'mousedown'; 1634var MOUSE_WINDOW_EVENTS = 'mousemove mouseup'; 1635 1636/** 1637 * Mouse events input 1638 * @constructor 1639 * @extends Input 1640 */ 1641function MouseInput() { 1642 this.evEl = MOUSE_ELEMENT_EVENTS; 1643 this.evWin = MOUSE_WINDOW_EVENTS; 1644 1645 this.pressed = false; // mousedown state 1646 1647 Input.apply(this, arguments); 1648} 1649 1650inherit(MouseInput, Input, { 1651 /** 1652 * handle mouse events 1653 * @param {Object} ev 1654 */ 1655 handler: function MEhandler(ev) { 1656 var eventType = MOUSE_INPUT_MAP[ev.type]; 1657 1658 // on start we want to have the left mouse button down 1659 if (eventType & INPUT_START && ev.button === 0) { 1660 this.pressed = true; 1661 } 1662 1663 if (eventType & INPUT_MOVE && ev.which !== 1) { 1664 eventType = INPUT_END; 1665 } 1666 1667 // mouse must be down 1668 if (!this.pressed) { 1669 return; 1670 } 1671 1672 if (eventType & INPUT_END) { 1673 this.pressed = false; 1674 } 1675 1676 this.callback(this.manager, eventType, { 1677 pointers: [ev], 1678 changedPointers: [ev], 1679 pointerType: INPUT_TYPE_MOUSE, 1680 srcEvent: ev 1681 }); 1682 } 1683}); 1684 1685var POINTER_INPUT_MAP = { 1686 pointerdown: INPUT_START, 1687 pointermove: INPUT_MOVE, 1688 pointerup: INPUT_END, 1689 pointercancel: INPUT_CANCEL, 1690 pointerout: INPUT_CANCEL 1691}; 1692 1693// in IE10 the pointer types is defined as an enum 1694var IE10_POINTER_TYPE_ENUM = { 1695 2: INPUT_TYPE_TOUCH, 1696 3: INPUT_TYPE_PEN, 1697 4: INPUT_TYPE_MOUSE, 1698 5: INPUT_TYPE_KINECT // see https://twitter.com/jacobrossi/status/480596438489890816 1699}; 1700 1701var POINTER_ELEMENT_EVENTS = 'pointerdown'; 1702var POINTER_WINDOW_EVENTS = 'pointermove pointerup pointercancel'; 1703 1704// IE10 has prefixed support, and case-sensitive 1705if (window.MSPointerEvent && !window.PointerEvent) { 1706 POINTER_ELEMENT_EVENTS = 'MSPointerDown'; 1707 POINTER_WINDOW_EVENTS = 'MSPointerMove MSPointerUp MSPointerCancel'; 1708} 1709 1710/** 1711 * Pointer events input 1712 * @constructor 1713 * @extends Input 1714 */ 1715function PointerEventInput() { 1716 this.evEl = POINTER_ELEMENT_EVENTS; 1717 this.evWin = POINTER_WINDOW_EVENTS; 1718 1719 Input.apply(this, arguments); 1720 1721 this.store = (this.manager.session.pointerEvents = []); 1722} 1723 1724inherit(PointerEventInput, Input, { 1725 /** 1726 * handle mouse events 1727 * @param {Object} ev 1728 */ 1729 handler: function PEhandler(ev) { 1730 var store = this.store; 1731 var removePointer = false; 1732 1733 var eventTypeNormalized = ev.type.toLowerCase().replace('ms', ''); 1734 var eventType = POINTER_INPUT_MAP[eventTypeNormalized]; 1735 var pointerType = IE10_POINTER_TYPE_ENUM[ev.pointerType] || ev.pointerType; 1736 1737 var isTouch = (pointerType == INPUT_TYPE_TOUCH); 1738 1739 // get index of the event in the store 1740 var storeIndex = inArray(store, ev.pointerId, 'pointerId'); 1741 1742 // start and mouse must be down 1743 if (eventType & INPUT_START && (ev.button === 0 || isTouch)) { 1744 if (storeIndex < 0) { 1745 store.push(ev); 1746 storeIndex = store.length - 1; 1747 } 1748 } else if (eventType & (INPUT_END | INPUT_CANCEL)) { 1749 removePointer = true; 1750 } 1751 1752 // it not found, so the pointer hasn't been down (so it's probably a hover) 1753 if (storeIndex < 0) { 1754 return; 1755 } 1756 1757 // update the event in the store 1758 store[storeIndex] = ev; 1759 1760 this.callback(this.manager, eventType, { 1761 pointers: store, 1762 changedPointers: [ev], 1763 pointerType: pointerType, 1764 srcEvent: ev 1765 }); 1766 1767 if (removePointer) { 1768 // remove from the store 1769 store.splice(storeIndex, 1); 1770 } 1771 } 1772}); 1773 1774var SINGLE_TOUCH_INPUT_MAP = { 1775 touchstart: INPUT_START, 1776 touchmove: INPUT_MOVE, 1777 touchend: INPUT_END, 1778 touchcancel: INPUT_CANCEL 1779}; 1780 1781var SINGLE_TOUCH_TARGET_EVENTS = 'touchstart'; 1782var SINGLE_TOUCH_WINDOW_EVENTS = 'touchstart touchmove touchend touchcancel'; 1783 1784/** 1785 * Touch events input 1786 * @constructor 1787 * @extends Input 1788 */ 1789function SingleTouchInput() { 1790 this.evTarget = SINGLE_TOUCH_TARGET_EVENTS; 1791 this.evWin = SINGLE_TOUCH_WINDOW_EVENTS; 1792 this.started = false; 1793 1794 Input.apply(this, arguments); 1795} 1796 1797inherit(SingleTouchInput, Input, { 1798 handler: function TEhandler(ev) { 1799 var type = SINGLE_TOUCH_INPUT_MAP[ev.type]; 1800 1801 // should we handle the touch events? 1802 if (type === INPUT_START) { 1803 this.started = true; 1804 } 1805 1806 if (!this.started) { 1807 return; 1808 } 1809 1810 var touches = normalizeSingleTouches.call(this, ev, type); 1811 1812 // when done, reset the started state 1813 if (type & (INPUT_END | INPUT_CANCEL) && touches[0].length - touches[1].length === 0) { 1814 this.started = false; 1815 } 1816 1817 this.callback(this.manager, type, { 1818 pointers: touches[0], 1819 changedPointers: touches[1], 1820 pointerType: INPUT_TYPE_TOUCH, 1821 srcEvent: ev 1822 }); 1823 } 1824}); 1825 1826/** 1827 * @this {TouchInput} 1828 * @param {Object} ev 1829 * @param {Number} type flag 1830 * @returns {undefined|Array} [all, changed] 1831 */ 1832function normalizeSingleTouches(ev, type) { 1833 var all = toArray(ev.touches); 1834 var changed = toArray(ev.changedTouches); 1835 1836 if (type & (INPUT_END | INPUT_CANCEL)) { 1837 all = uniqueArray(all.concat(changed), 'identifier', true); 1838 } 1839 1840 return [all, changed]; 1841} 1842 1843var TOUCH_INPUT_MAP = { 1844 touchstart: INPUT_START, 1845 touchmove: INPUT_MOVE, 1846 touchend: INPUT_END, 1847 touchcancel: INPUT_CANCEL 1848}; 1849 1850var TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel'; 1851 1852/** 1853 * Multi-user touch events input 1854 * @constructor 1855 * @extends Input 1856 */ 1857function TouchInput() { 1858 this.evTarget = TOUCH_TARGET_EVENTS; 1859 this.targetIds = {}; 1860 1861 Input.apply(this, arguments); 1862} 1863 1864inherit(TouchInput, Input, { 1865 handler: function MTEhandler(ev) { 1866 var type = TOUCH_INPUT_MAP[ev.type]; 1867 var touches = getTouches.call(this, ev, type); 1868 if (!touches) { 1869 return; 1870 } 1871 1872 this.callback(this.manager, type, { 1873 pointers: touches[0], 1874 changedPointers: touches[1], 1875 pointerType: INPUT_TYPE_TOUCH, 1876 srcEvent: ev 1877 }); 1878 } 1879}); 1880 1881/** 1882 * @this {TouchInput} 1883 * @param {Object} ev 1884 * @param {Number} type flag 1885 * @returns {undefined|Array} [all, changed] 1886 */ 1887function getTouches(ev, type) { 1888 var allTouches = toArray(ev.touches); 1889 var targetIds = this.targetIds; 1890 1891 // when there is only one touch, the process can be simplified 1892 if (type & (INPUT_START | INPUT_MOVE) && allTouches.length === 1) { 1893 targetIds[allTouches[0].identifier] = true; 1894 return [allTouches, allTouches]; 1895 } 1896 1897 var i, 1898 targetTouches, 1899 changedTouches = toArray(ev.changedTouches), 1900 changedTargetTouches = [], 1901 target = this.target; 1902 1903 // get target touches from touches 1904 targetTouches = allTouches.filter(function(touch) { 1905 return hasParent(touch.target, target); 1906 }); 1907 1908 // collect touches 1909 if (type === INPUT_START) { 1910 i = 0; 1911 while (i < targetTouches.length) { 1912 targetIds[targetTouches[i].identifier] = true; 1913 i++; 1914 } 1915 } 1916 1917 // filter changed touches to only contain touches that exist in the collected target ids 1918 i = 0; 1919 while (i < changedTouches.length) { 1920 if (targetIds[changedTouches[i].identifier]) { 1921 changedTargetTouches.push(changedTouches[i]); 1922 } 1923 1924 // cleanup removed touches 1925 if (type & (INPUT_END | INPUT_CANCEL)) { 1926 delete targetIds[changedTouches[i].identifier]; 1927 } 1928 i++; 1929 } 1930 1931 if (!changedTargetTouches.length) { 1932 return; 1933 } 1934 1935 return [ 1936 // merge targetTouches with changedTargetTouches so it contains ALL touches, including 'end' and 'cancel' 1937 uniqueArray(targetTouches.concat(changedTargetTouches), 'identifier', true), 1938 changedTargetTouches 1939 ]; 1940} 1941 1942/** 1943 * Combined touch and mouse input 1944 * 1945 * Touch has a higher priority then mouse, and while touching no mouse events are allowed. 1946 * This because touch devices also emit mouse events while doing a touch. 1947 * 1948 * @constructor 1949 * @extends Input 1950 */ 1951 1952var DEDUP_TIMEOUT = 2500; 1953var DEDUP_DISTANCE = 25; 1954 1955function TouchMouseInput() { 1956 Input.apply(this, arguments); 1957 1958 var handler = bindFn(this.handler, this); 1959 this.touch = new TouchInput(this.manager, handler); 1960 this.mouse = new MouseInput(this.manager, handler); 1961 1962 this.primaryTouch = null; 1963 this.lastTouches = []; 1964} 1965 1966inherit(TouchMouseInput, Input, { 1967 /** 1968 * handle mouse and touch events 1969 * @param {Hammer} manager 1970 * @param {String} inputEvent 1971 * @param {Object} inputData 1972 */ 1973 handler: function TMEhandler(manager, inputEvent, inputData) { 1974 var isTouch = (inputData.pointerType == INPUT_TYPE_TOUCH), 1975 isMouse = (inputData.pointerType == INPUT_TYPE_MOUSE); 1976 1977 if (isMouse && inputData.sourceCapabilities && inputData.sourceCapabilities.firesTouchEvents) { 1978 return; 1979 } 1980 1981 // when we're in a touch event, record touches to de-dupe synthetic mouse event 1982 if (isTouch) { 1983 recordTouches.call(this, inputEvent, inputData); 1984 } else if (isMouse && isSyntheticEvent.call(this, inputData)) { 1985 return; 1986 } 1987 1988 this.callback(manager, inputEvent, inputData); 1989 }, 1990 1991 /** 1992 * remove the event listeners 1993 */ 1994 destroy: function destroy() { 1995 this.touch.destroy(); 1996 this.mouse.destroy(); 1997 } 1998}); 1999 2000function recordTouches(eventType, eventData) { 2001 if (eventType & INPUT_START) { 2002 this.primaryTouch = eventData.changedPointers[0].identifier; 2003 setLastTouch.call(this, eventData); 2004 } else if (eventType & (INPUT_END | INPUT_CANCEL)) { 2005 setLastTouch.call(this, eventData); 2006 } 2007} 2008 2009function setLastTouch(eventData) { 2010 var touch = eventData.changedPointers[0]; 2011 2012 if (touch.identifier === this.primaryTouch) { 2013 var lastTouch = {x: touch.clientX, y: touch.clientY}; 2014 this.lastTouches.push(lastTouch); 2015 var lts = this.lastTouches; 2016 var removeLastTouch = function() { 2017 var i = lts.indexOf(lastTouch); 2018 if (i > -1) { 2019 lts.splice(i, 1); 2020 } 2021 }; 2022 setTimeout(removeLastTouch, DEDUP_TIMEOUT); 2023 } 2024} 2025 2026function isSyntheticEvent(eventData) { 2027 var x = eventData.srcEvent.clientX, y = eventData.srcEvent.clientY; 2028 for (var i = 0; i < this.lastTouches.length; i++) { 2029 var t = this.lastTouches[i]; 2030 var dx = Math.abs(x - t.x), dy = Math.abs(y - t.y); 2031 if (dx <= DEDUP_DISTANCE && dy <= DEDUP_DISTANCE) { 2032 return true; 2033 } 2034 } 2035 return false; 2036} 2037 2038var PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction'); 2039var NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined; 2040 2041// magical touchAction value 2042var TOUCH_ACTION_COMPUTE = 'compute'; 2043var TOUCH_ACTION_AUTO = 'auto'; 2044var TOUCH_ACTION_MANIPULATION = 'manipulation'; // not implemented 2045var TOUCH_ACTION_NONE = 'none'; 2046var TOUCH_ACTION_PAN_X = 'pan-x'; 2047var TOUCH_ACTION_PAN_Y = 'pan-y'; 2048var TOUCH_ACTION_MAP = getTouchActionProps(); 2049 2050/** 2051 * Touch Action 2052 * sets the touchAction property or uses the js alternative 2053 * @param {Manager} manager 2054 * @param {String} value 2055 * @constructor 2056 */ 2057function TouchAction(manager, value) { 2058 this.manager = manager; 2059 this.set(value); 2060} 2061 2062TouchAction.prototype = { 2063 /** 2064 * set the touchAction value on the element or enable the polyfill 2065 * @param {String} value 2066 */ 2067 set: function(value) { 2068 // find out the touch-action by the event handlers 2069 if (value == TOUCH_ACTION_COMPUTE) { 2070 value = this.compute(); 2071 } 2072 2073 if (NATIVE_TOUCH_ACTION && this.manager.element.style && TOUCH_ACTION_MAP[value]) { 2074 this.manager.element.style[PREFIXED_TOUCH_ACTION] = value; 2075 } 2076 this.actions = value.toLowerCase().trim(); 2077 }, 2078 2079 /** 2080 * just re-set the touchAction value 2081 */ 2082 update: function() { 2083 this.set(this.manager.options.touchAction); 2084 }, 2085 2086 /** 2087 * compute the value for the touchAction property based on the recognizer's settings 2088 * @returns {String} value 2089 */ 2090 compute: function() { 2091 var actions = []; 2092 each(this.manager.recognizers, function(recognizer) { 2093 if (boolOrFn(recognizer.options.enable, [recognizer])) { 2094 actions = actions.concat(recognizer.getTouchAction()); 2095 } 2096 }); 2097 return cleanTouchActions(actions.join(' ')); 2098 }, 2099 2100 /** 2101 * this method is called on each input cycle and provides the preventing of the browser behavior 2102 * @param {Object} input 2103 */ 2104 preventDefaults: function(input) { 2105 var srcEvent = input.srcEvent; 2106 var direction = input.offsetDirection; 2107 2108 // if the touch action did prevented once this session 2109 if (this.manager.session.prevented) { 2110 srcEvent.preventDefault(); 2111 return; 2112 } 2113 2114 var actions = this.actions; 2115 var hasNone = inStr(actions, TOUCH_ACTION_NONE) && !TOUCH_ACTION_MAP[TOUCH_ACTION_NONE]; 2116 var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_Y]; 2117 var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_X]; 2118 2119 if (hasNone) { 2120 //do not prevent defaults if this is a tap gesture 2121 2122 var isTapPointer = input.pointers.length === 1; 2123 var isTapMovement = input.distance < 2; 2124 var isTapTouchTime = input.deltaTime < 250; 2125 2126 if (isTapPointer && isTapMovement && isTapTouchTime) { 2127 return; 2128 } 2129 } 2130 2131 if (hasPanX && hasPanY) { 2132 // `pan-x pan-y` means browser handles all scrolling/panning, do not prevent 2133 return; 2134 } 2135 2136 if (hasNone || 2137 (hasPanY && direction & DIRECTION_HORIZONTAL) || 2138 (hasPanX && direction & DIRECTION_VERTICAL)) { 2139 return this.preventSrc(srcEvent); 2140 } 2141 }, 2142 2143 /** 2144 * call preventDefault to prevent the browser's default behavior (scrolling in most cases) 2145 * @param {Object} srcEvent 2146 */ 2147 preventSrc: function(srcEvent) { 2148 this.manager.session.prevented = true; 2149 srcEvent.preventDefault(); 2150 } 2151}; 2152 2153/** 2154 * when the touchActions are collected they are not a valid value, so we need to clean things up. * 2155 * @param {String} actions 2156 * @returns {*} 2157 */ 2158function cleanTouchActions(actions) { 2159 // none 2160 if (inStr(actions, TOUCH_ACTION_NONE)) { 2161 return TOUCH_ACTION_NONE; 2162 } 2163 2164 var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X); 2165 var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y); 2166 2167 // if both pan-x and pan-y are set (different recognizers 2168 // for different directions, e.g. horizontal pan but vertical swipe?) 2169 // we need none (as otherwise with pan-x pan-y combined none of these 2170 // recognizers will work, since the browser would handle all panning 2171 if (hasPanX && hasPanY) { 2172 return TOUCH_ACTION_NONE; 2173 } 2174 2175 // pan-x OR pan-y 2176 if (hasPanX || hasPanY) { 2177 return hasPanX ? TOUCH_ACTION_PAN_X : TOUCH_ACTION_PAN_Y; 2178 } 2179 2180 // manipulation 2181 if (inStr(actions, TOUCH_ACTION_MANIPULATION)) { 2182 return TOUCH_ACTION_MANIPULATION; 2183 } 2184 2185 return TOUCH_ACTION_AUTO; 2186} 2187 2188function getTouchActionProps() { 2189 if (!NATIVE_TOUCH_ACTION) { 2190 return false; 2191 } 2192 var touchMap = {}; 2193 var cssSupports = window.CSS && window.CSS.supports; 2194 ['auto', 'manipulation', 'pan-y', 'pan-x', 'pan-x pan-y', 'none'].forEach(function(val) { 2195 2196 // If css.supports is not supported but there is native touch-action assume it supports 2197 // all values. This is the case for IE 10 and 11. 2198 touchMap[val] = cssSupports ? window.CSS.supports('touch-action', val) : true; 2199 }); 2200 return touchMap; 2201} 2202 2203/** 2204 * Recognizer flow explained; * 2205 * All recognizers have the initial state of POSSIBLE when a input session starts. 2206 * The definition of a input session is from the first input until the last input, with all it's movement in it. * 2207 * Example session for mouse-input: mousedown -> mousemove -> mouseup 2208 * 2209 * On each recognizing cycle (see Manager.recognize) the .recognize() method is executed 2210 * which determines with state it should be. 2211 * 2212 * If the recognizer has the state FAILED, CANCELLED or RECOGNIZED (equals ENDED), it is reset to 2213 * POSSIBLE to give it another change on the next cycle. 2214 * 2215 * Possible 2216 * | 2217 * +-----+---------------+ 2218 * | | 2219 * +-----+-----+ | 2220 * | | | 2221 * Failed Cancelled | 2222 * +-------+------+ 2223 * | | 2224 * Recognized Began 2225 * | 2226 * Changed 2227 * | 2228 * Ended/Recognized 2229 */ 2230var STATE_POSSIBLE = 1; 2231var STATE_BEGAN = 2; 2232var STATE_CHANGED = 4; 2233var STATE_ENDED = 8; 2234var STATE_RECOGNIZED = STATE_ENDED; 2235var STATE_CANCELLED = 16; 2236var STATE_FAILED = 32; 2237 2238/** 2239 * Recognizer 2240 * Every recognizer needs to extend from this class. 2241 * @constructor 2242 * @param {Object} options 2243 */ 2244function Recognizer(options) { 2245 this.options = assign({}, this.defaults, options || {}); 2246 2247 this.id = uniqueId(); 2248 2249 this.manager = null; 2250 2251 // default is enable true 2252 this.options.enable = ifUndefined(this.options.enable, true); 2253 2254 this.state = STATE_POSSIBLE; 2255 2256 this.simultaneous = {}; 2257 this.requireFail = []; 2258} 2259 2260Recognizer.prototype = { 2261 /** 2262 * @virtual 2263 * @type {Object} 2264 */ 2265 defaults: {}, 2266 2267 /** 2268 * set options 2269 * @param {Object} options 2270 * @return {Recognizer} 2271 */ 2272 set: function(options) { 2273 assign(this.options, options); 2274 2275 // also update the touchAction, in case something changed about the directions/enabled state 2276 this.manager && this.manager.touchAction.update(); 2277 return this; 2278 }, 2279 2280 /** 2281 * recognize simultaneous with an other recognizer. 2282 * @param {Recognizer} otherRecognizer 2283 * @returns {Recognizer} this 2284 */ 2285 recognizeWith: function(otherRecognizer) { 2286 if (invokeArrayArg(otherRecognizer, 'recognizeWith', this)) { 2287 return this; 2288 } 2289 2290 var simultaneous = this.simultaneous; 2291 otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); 2292 if (!simultaneous[otherRecognizer.id]) { 2293 simultaneous[otherRecognizer.id] = otherRecognizer; 2294 otherRecognizer.recognizeWith(this); 2295 } 2296 return this; 2297 }, 2298 2299 /** 2300 * drop the simultaneous link. it doesnt remove the link on the other recognizer. 2301 * @param {Recognizer} otherRecognizer 2302 * @returns {Recognizer} this 2303 */ 2304 dropRecognizeWith: function(otherRecognizer) { 2305 if (invokeArrayArg(otherRecognizer, 'dropRecognizeWith', this)) { 2306 return this; 2307 } 2308 2309 otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); 2310 delete this.simultaneous[otherRecognizer.id]; 2311 return this; 2312 }, 2313 2314 /** 2315 * recognizer can only run when an other is failing 2316 * @param {Recognizer} otherRecognizer 2317 * @returns {Recognizer} this 2318 */ 2319 requireFailure: function(otherRecognizer) { 2320 if (invokeArrayArg(otherRecognizer, 'requireFailure', this)) { 2321 return this; 2322 } 2323 2324 var requireFail = this.requireFail; 2325 otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); 2326 if (inArray(requireFail, otherRecognizer) === -1) { 2327 requireFail.push(otherRecognizer); 2328 otherRecognizer.requireFailure(this); 2329 } 2330 return this; 2331 }, 2332 2333 /** 2334 * drop the requireFailure link. it does not remove the link on the other recognizer. 2335 * @param {Recognizer} otherRecognizer 2336 * @returns {Recognizer} this 2337 */ 2338 dropRequireFailure: function(otherRecognizer) { 2339 if (invokeArrayArg(otherRecognizer, 'dropRequireFailure', this)) { 2340 return this; 2341 } 2342 2343 otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); 2344 var index = inArray(this.requireFail, otherRecognizer); 2345 if (index > -1) { 2346 this.requireFail.splice(index, 1); 2347 } 2348 return this; 2349 }, 2350 2351 /** 2352 * has require failures boolean 2353 * @returns {boolean} 2354 */ 2355 hasRequireFailures: function() { 2356 return this.requireFail.length > 0; 2357 }, 2358 2359 /** 2360 * if the recognizer can recognize simultaneous with an other recognizer 2361 * @param {Recognizer} otherRecognizer 2362 * @returns {Boolean} 2363 */ 2364 canRecognizeWith: function(otherRecognizer) { 2365 return !!this.simultaneous[otherRecognizer.id]; 2366 }, 2367 2368 /** 2369 * You should use `tryEmit` instead of `emit` directly to check 2370 * that all the needed recognizers has failed before emitting. 2371 * @param {Object} input 2372 */ 2373 emit: function(input) { 2374 var self = this; 2375 var state = this.state; 2376 2377 function emit(event) { 2378 self.manager.emit(event, input); 2379 } 2380 2381 // 'panstart' and 'panmove' 2382 if (state < STATE_ENDED) { 2383 emit(self.options.event + stateStr(state)); 2384 } 2385 2386 emit(self.options.event); // simple 'eventName' events 2387 2388 if (input.additionalEvent) { // additional event(panleft, panright, pinchin, pinchout...) 2389 emit(input.additionalEvent); 2390 } 2391 2392 // panend and pancancel 2393 if (state >= STATE_ENDED) { 2394 emit(self.options.event + stateStr(state)); 2395 } 2396 }, 2397 2398 /** 2399 * Check that all the require failure recognizers has failed, 2400 * if true, it emits a gesture event, 2401 * otherwise, setup the state to FAILED. 2402 * @param {Object} input 2403 */ 2404 tryEmit: function(input) { 2405 if (this.canEmit()) { 2406 return this.emit(input); 2407 } 2408 // it's failing anyway 2409 this.state = STATE_FAILED; 2410 }, 2411 2412 /** 2413 * can we emit? 2414 * @returns {boolean} 2415 */ 2416 canEmit: function() { 2417 var i = 0; 2418 while (i < this.requireFail.length) { 2419 if (!(this.requireFail[i].state & (STATE_FAILED | STATE_POSSIBLE))) { 2420 return false; 2421 } 2422 i++; 2423 } 2424 return true; 2425 }, 2426 2427 /** 2428 * update the recognizer 2429 * @param {Object} inputData 2430 */ 2431 recognize: function(inputData) { 2432 // make a new copy of the inputData 2433 // so we can change the inputData without messing up the other recognizers 2434 var inputDataClone = assign({}, inputData); 2435 2436 // is is enabled and allow recognizing? 2437 if (!boolOrFn(this.options.enable, [this, inputDataClone])) { 2438 this.reset(); 2439 this.state = STATE_FAILED; 2440 return; 2441 } 2442 2443 // reset when we've reached the end 2444 if (this.state & (STATE_RECOGNIZED | STATE_CANCELLED | STATE_FAILED)) { 2445 this.state = STATE_POSSIBLE; 2446 } 2447 2448 this.state = this.process(inputDataClone); 2449 2450 // the recognizer has recognized a gesture 2451 // so trigger an event 2452 if (this.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED | STATE_CANCELLED)) { 2453 this.tryEmit(inputDataClone); 2454 } 2455 }, 2456 2457 /** 2458 * return the state of the recognizer 2459 * the actual recognizing happens in this method 2460 * @virtual 2461 * @param {Object} inputData 2462 * @returns {Const} STATE 2463 */ 2464 process: function(inputData) { }, // jshint ignore:line 2465 2466 /** 2467 * return the preferred touch-action 2468 * @virtual 2469 * @returns {Array} 2470 */ 2471 getTouchAction: function() { }, 2472 2473 /** 2474 * called when the gesture isn't allowed to recognize 2475 * like when another is being recognized or it is disabled 2476 * @virtual 2477 */ 2478 reset: function() { } 2479}; 2480 2481/** 2482 * get a usable string, used as event postfix 2483 * @param {Const} state 2484 * @returns {String} state 2485 */ 2486function stateStr(state) { 2487 if (state & STATE_CANCELLED) { 2488 return 'cancel'; 2489 } else if (state & STATE_ENDED) { 2490 return 'end'; 2491 } else if (state & STATE_CHANGED) { 2492 return 'move'; 2493 } else if (state & STATE_BEGAN) { 2494 return 'start'; 2495 } 2496 return ''; 2497} 2498 2499/** 2500 * direction cons to string 2501 * @param {Const} direction 2502 * @returns {String} 2503 */ 2504function directionStr(direction) { 2505 if (direction == DIRECTION_DOWN) { 2506 return 'down'; 2507 } else if (direction == DIRECTION_UP) { 2508 return 'up'; 2509 } else if (direction == DIRECTION_LEFT) { 2510 return 'left'; 2511 } else if (direction == DIRECTION_RIGHT) { 2512 return 'right'; 2513 } 2514 return ''; 2515} 2516 2517/** 2518 * get a recognizer by name if it is bound to a manager 2519 * @param {Recognizer|String} otherRecognizer 2520 * @param {Recognizer} recognizer 2521 * @returns {Recognizer} 2522 */ 2523function getRecognizerByNameIfManager(otherRecognizer, recognizer) { 2524 var manager = recognizer.manager; 2525 if (manager) { 2526 return manager.get(otherRecognizer); 2527 } 2528 return otherRecognizer; 2529} 2530 2531/** 2532 * This recognizer is just used as a base for the simple attribute recognizers. 2533 * @constructor 2534 * @extends Recognizer 2535 */ 2536function AttrRecognizer() { 2537 Recognizer.apply(this, arguments); 2538} 2539 2540inherit(AttrRecognizer, Recognizer, { 2541 /** 2542 * @namespace 2543 * @memberof AttrRecognizer 2544 */ 2545 defaults: { 2546 /** 2547 * @type {Number} 2548 * @default 1 2549 */ 2550 pointers: 1 2551 }, 2552 2553 /** 2554 * Used to check if it the recognizer receives valid input, like input.distance > 10. 2555 * @memberof AttrRecognizer 2556 * @param {Object} input 2557 * @returns {Boolean} recognized 2558 */ 2559 attrTest: function(input) { 2560 var optionPointers = this.options.pointers; 2561 return optionPointers === 0 || input.pointers.length === optionPointers; 2562 }, 2563 2564 /** 2565 * Process the input and return the state for the recognizer 2566 * @memberof AttrRecognizer 2567 * @param {Object} input 2568 * @returns {*} State 2569 */ 2570 process: function(input) { 2571 var state = this.state; 2572 var eventType = input.eventType; 2573 2574 var isRecognized = state & (STATE_BEGAN | STATE_CHANGED); 2575 var isValid = this.attrTest(input); 2576 2577 // on cancel input and we've recognized before, return STATE_CANCELLED 2578 if (isRecognized && (eventType & INPUT_CANCEL || !isValid)) { 2579 return state | STATE_CANCELLED; 2580 } else if (isRecognized || isValid) { 2581 if (eventType & INPUT_END) { 2582 return state | STATE_ENDED; 2583 } else if (!(state & STATE_BEGAN)) { 2584 return STATE_BEGAN; 2585 } 2586 return state | STATE_CHANGED; 2587 } 2588 return STATE_FAILED; 2589 } 2590}); 2591 2592/** 2593 * Pan 2594 * Recognized when the pointer is down and moved in the allowed direction. 2595 * @constructor 2596 * @extends AttrRecognizer 2597 */ 2598function PanRecognizer() { 2599 AttrRecognizer.apply(this, arguments); 2600 2601 this.pX = null; 2602 this.pY = null; 2603} 2604 2605inherit(PanRecognizer, AttrRecognizer, { 2606 /** 2607 * @namespace 2608 * @memberof PanRecognizer 2609 */ 2610 defaults: { 2611 event: 'pan', 2612 threshold: 10, 2613 pointers: 1, 2614 direction: DIRECTION_ALL 2615 }, 2616 2617 getTouchAction: function() { 2618 var direction = this.options.direction; 2619 var actions = []; 2620 if (direction & DIRECTION_HORIZONTAL) { 2621 actions.push(TOUCH_ACTION_PAN_Y); 2622 } 2623 if (direction & DIRECTION_VERTICAL) { 2624 actions.push(TOUCH_ACTION_PAN_X); 2625 } 2626 return actions; 2627 }, 2628 2629 directionTest: function(input) { 2630 var options = this.options; 2631 var hasMoved = true; 2632 var distance = input.distance; 2633 var direction = input.direction; 2634 var x = input.deltaX; 2635 var y = input.deltaY; 2636 2637 // lock to axis? 2638 if (!(direction & options.direction)) { 2639 if (options.direction & DIRECTION_HORIZONTAL) { 2640 direction = (x === 0) ? DIRECTION_NONE : (x < 0) ? DIRECTION_LEFT : DIRECTION_RIGHT; 2641 hasMoved = x != this.pX; 2642 distance = Math.abs(input.deltaX); 2643 } else { 2644 direction = (y === 0) ? DIRECTION_NONE : (y < 0) ? DIRECTION_UP : DIRECTION_DOWN; 2645 hasMoved = y != this.pY; 2646 distance = Math.abs(input.deltaY); 2647 } 2648 } 2649 input.direction = direction; 2650 return hasMoved && distance > options.threshold && direction & options.direction; 2651 }, 2652 2653 attrTest: function(input) { 2654 return AttrRecognizer.prototype.attrTest.call(this, input) && 2655 (this.state & STATE_BEGAN || (!(this.state & STATE_BEGAN) && this.directionTest(input))); 2656 }, 2657 2658 emit: function(input) { 2659 2660 this.pX = input.deltaX; 2661 this.pY = input.deltaY; 2662 2663 var direction = directionStr(input.direction); 2664 2665 if (direction) { 2666 input.additionalEvent = this.options.event + direction; 2667 } 2668 this._super.emit.call(this, input); 2669 } 2670}); 2671 2672/** 2673 * Pinch 2674 * Recognized when two or more pointers are moving toward (zoom-in) or away from each other (zoom-out). 2675 * @constructor 2676 * @extends AttrRecognizer 2677 */ 2678function PinchRecognizer() { 2679 AttrRecognizer.apply(this, arguments); 2680} 2681 2682inherit(PinchRecognizer, AttrRecognizer, { 2683 /** 2684 * @namespace 2685 * @memberof PinchRecognizer 2686 */ 2687 defaults: { 2688 event: 'pinch', 2689 threshold: 0, 2690 pointers: 2 2691 }, 2692 2693 getTouchAction: function() { 2694 return [TOUCH_ACTION_NONE]; 2695 }, 2696 2697 attrTest: function(input) { 2698 return this._super.attrTest.call(this, input) && 2699 (Math.abs(input.scale - 1) > this.options.threshold || this.state & STATE_BEGAN); 2700 }, 2701 2702 emit: function(input) { 2703 if (input.scale !== 1) { 2704 var inOut = input.scale < 1 ? 'in' : 'out'; 2705 input.additionalEvent = this.options.event + inOut; 2706 } 2707 this._super.emit.call(this, input); 2708 } 2709}); 2710 2711/** 2712 * Press 2713 * Recognized when the pointer is down for x ms without any movement. 2714 * @constructor 2715 * @extends Recognizer 2716 */ 2717function PressRecognizer() { 2718 Recognizer.apply(this, arguments); 2719 2720 this._timer = null; 2721 this._input = null; 2722} 2723 2724inherit(PressRecognizer, Recognizer, { 2725 /** 2726 * @namespace 2727 * @memberof PressRecognizer 2728 */ 2729 defaults: { 2730 event: 'press', 2731 pointers: 1, 2732 time: 251, // minimal time of the pointer to be pressed 2733 threshold: 9 // a minimal movement is ok, but keep it low 2734 }, 2735 2736 getTouchAction: function() { 2737 return [TOUCH_ACTION_AUTO]; 2738 }, 2739 2740 process: function(input) { 2741 var options = this.options; 2742 var validPointers = input.pointers.length === options.pointers; 2743 var validMovement = input.distance < options.threshold; 2744 var validTime = input.deltaTime > options.time; 2745 2746 this._input = input; 2747 2748 // we only allow little movement 2749 // and we've reached an end event, so a tap is possible 2750 if (!validMovement || !validPointers || (input.eventType & (INPUT_END | INPUT_CANCEL) && !validTime)) { 2751 this.reset(); 2752 } else if (input.eventType & INPUT_START) { 2753 this.reset(); 2754 this._timer = setTimeoutContext(function() { 2755 this.state = STATE_RECOGNIZED; 2756 this.tryEmit(); 2757 }, options.time, this); 2758 } else if (input.eventType & INPUT_END) { 2759 return STATE_RECOGNIZED; 2760 } 2761 return STATE_FAILED; 2762 }, 2763 2764 reset: function() { 2765 clearTimeout(this._timer); 2766 }, 2767 2768 emit: function(input) { 2769 if (this.state !== STATE_RECOGNIZED) { 2770 return; 2771 } 2772 2773 if (input && (input.eventType & INPUT_END)) { 2774 this.manager.emit(this.options.event + 'up', input); 2775 } else { 2776 this._input.timeStamp = now(); 2777 this.manager.emit(this.options.event, this._input); 2778 } 2779 } 2780}); 2781 2782/** 2783 * Rotate 2784 * Recognized when two or more pointer are moving in a circular motion. 2785 * @constructor 2786 * @extends AttrRecognizer 2787 */ 2788function RotateRecognizer() { 2789 AttrRecognizer.apply(this, arguments); 2790} 2791 2792inherit(RotateRecognizer, AttrRecognizer, { 2793 /** 2794 * @namespace 2795 * @memberof RotateRecognizer 2796 */ 2797 defaults: { 2798 event: 'rotate', 2799 threshold: 0, 2800 pointers: 2 2801 }, 2802 2803 getTouchAction: function() { 2804 return [TOUCH_ACTION_NONE]; 2805 }, 2806 2807 attrTest: function(input) { 2808 return this._super.attrTest.call(this, input) && 2809 (Math.abs(input.rotation) > this.options.threshold || this.state & STATE_BEGAN); 2810 } 2811}); 2812 2813/** 2814 * Swipe 2815 * Recognized when the pointer is moving fast (velocity), with enough distance in the allowed direction. 2816 * @constructor 2817 * @extends AttrRecognizer 2818 */ 2819function SwipeRecognizer() { 2820 AttrRecognizer.apply(this, arguments); 2821} 2822 2823inherit(SwipeRecognizer, AttrRecognizer, { 2824 /** 2825 * @namespace 2826 * @memberof SwipeRecognizer 2827 */ 2828 defaults: { 2829 event: 'swipe', 2830 threshold: 10, 2831 velocity: 0.3, 2832 direction: DIRECTION_HORIZONTAL | DIRECTION_VERTICAL, 2833 pointers: 1 2834 }, 2835 2836 getTouchAction: function() { 2837 return PanRecognizer.prototype.getTouchAction.call(this); 2838 }, 2839 2840 attrTest: function(input) { 2841 var direction = this.options.direction; 2842 var velocity; 2843 2844 if (direction & (DIRECTION_HORIZONTAL | DIRECTION_VERTICAL)) { 2845 velocity = input.overallVelocity; 2846 } else if (direction & DIRECTION_HORIZONTAL) { 2847 velocity = input.overallVelocityX; 2848 } else if (direction & DIRECTION_VERTICAL) { 2849 velocity = input.overallVelocityY; 2850 } 2851 2852 return this._super.attrTest.call(this, input) && 2853 direction & input.offsetDirection && 2854 input.distance > this.options.threshold && 2855 input.maxPointers == this.options.pointers && 2856 abs(velocity) > this.options.velocity && input.eventType & INPUT_END; 2857 }, 2858 2859 emit: function(input) { 2860 var direction = directionStr(input.offsetDirection); 2861 if (direction) { 2862 this.manager.emit(this.options.event + direction, input); 2863 } 2864 2865 this.manager.emit(this.options.event, input); 2866 } 2867}); 2868 2869/** 2870 * A tap is ecognized when the pointer is doing a small tap/click. Multiple taps are recognized if they occur 2871 * between the given interval and position. The delay option can be used to recognize multi-taps without firing 2872 * a single tap. 2873 * 2874 * The eventData from the emitted event contains the property `tapCount`, which contains the amount of 2875 * multi-taps being recognized. 2876 * @constructor 2877 * @extends Recognizer 2878 */ 2879function TapRecognizer() { 2880 Recognizer.apply(this, arguments); 2881 2882 // previous time and center, 2883 // used for tap counting 2884 this.pTime = false; 2885 this.pCenter = false; 2886 2887 this._timer = null; 2888 this._input = null; 2889 this.count = 0; 2890} 2891 2892inherit(TapRecognizer, Recognizer, { 2893 /** 2894 * @namespace 2895 * @memberof PinchRecognizer 2896 */ 2897 defaults: { 2898 event: 'tap', 2899 pointers: 1, 2900 taps: 1, 2901 interval: 300, // max time between the multi-tap taps 2902 time: 250, // max time of the pointer to be down (like finger on the screen) 2903 threshold: 9, // a minimal movement is ok, but keep it low 2904 posThreshold: 10 // a multi-tap can be a bit off the initial position 2905 }, 2906 2907 getTouchAction: function() { 2908 return [TOUCH_ACTION_MANIPULATION]; 2909 }, 2910 2911 process: function(input) { 2912 var options = this.options; 2913 2914 var validPointers = input.pointers.length === options.pointers; 2915 var validMovement = input.distance < options.threshold; 2916 var validTouchTime = input.deltaTime < options.time; 2917 2918 this.reset(); 2919 2920 if ((input.eventType & INPUT_START) && (this.count === 0)) { 2921 return this.failTimeout(); 2922 } 2923 2924 // we only allow little movement 2925 // and we've reached an end event, so a tap is possible 2926 if (validMovement && validTouchTime && validPointers) { 2927 if (input.eventType != INPUT_END) { 2928 return this.failTimeout(); 2929 } 2930 2931 var validInterval = this.pTime ? (input.timeStamp - this.pTime < options.interval) : true; 2932 var validMultiTap = !this.pCenter || getDistance(this.pCenter, input.center) < options.posThreshold; 2933 2934 this.pTime = input.timeStamp; 2935 this.pCenter = input.center; 2936 2937 if (!validMultiTap || !validInterval) { 2938 this.count = 1; 2939 } else { 2940 this.count += 1; 2941 } 2942 2943 this._input = input; 2944 2945 // if tap count matches we have recognized it, 2946 // else it has began recognizing... 2947 var tapCount = this.count % options.taps; 2948 if (tapCount === 0) { 2949 // no failing requirements, immediately trigger the tap event 2950 // or wait as long as the multitap interval to trigger 2951 if (!this.hasRequireFailures()) { 2952 return STATE_RECOGNIZED; 2953 } else { 2954 this._timer = setTimeoutContext(function() { 2955 this.state = STATE_RECOGNIZED; 2956 this.tryEmit(); 2957 }, options.interval, this); 2958 return STATE_BEGAN; 2959 } 2960 } 2961 } 2962 return STATE_FAILED; 2963 }, 2964 2965 failTimeout: function() { 2966 this._timer = setTimeoutContext(function() { 2967 this.state = STATE_FAILED; 2968 }, this.options.interval, this); 2969 return STATE_FAILED; 2970 }, 2971 2972 reset: function() { 2973 clearTimeout(this._timer); 2974 }, 2975 2976 emit: function() { 2977 if (this.state == STATE_RECOGNIZED) { 2978 this._input.tapCount = this.count; 2979 this.manager.emit(this.options.event, this._input); 2980 } 2981 } 2982}); 2983 2984/** 2985 * Simple way to create a manager with a default set of recognizers. 2986 * @param {HTMLElement} element 2987 * @param {Object} [options] 2988 * @constructor 2989 */ 2990function Hammer(element, options) { 2991 options = options || {}; 2992 options.recognizers = ifUndefined(options.recognizers, Hammer.defaults.preset); 2993 return new Manager(element, options); 2994} 2995 2996/** 2997 * @const {string} 2998 */ 2999Hammer.VERSION = '2.0.7'; 3000 3001/** 3002 * default settings 3003 * @namespace 3004 */ 3005Hammer.defaults = { 3006 /** 3007 * set if DOM events are being triggered. 3008 * But this is slower and unused by simple implementations, so disabled by default. 3009 * @type {Boolean} 3010 * @default false 3011 */ 3012 domEvents: false, 3013 3014 /** 3015 * The value for the touchAction property/fallback. 3016 * When set to `compute` it will magically set the correct value based on the added recognizers. 3017 * @type {String} 3018 * @default compute 3019 */ 3020 touchAction: TOUCH_ACTION_COMPUTE, 3021 3022 /** 3023 * @type {Boolean} 3024 * @default true 3025 */ 3026 enable: true, 3027 3028 /** 3029 * EXPERIMENTAL FEATURE -- can be removed/changed 3030 * Change the parent input target element. 3031 * If Null, then it is being set the to main element. 3032 * @type {Null|EventTarget} 3033 * @default null 3034 */ 3035 inputTarget: null, 3036 3037 /** 3038 * force an input class 3039 * @type {Null|Function} 3040 * @default null 3041 */ 3042 inputClass: null, 3043 3044 /** 3045 * Default recognizer setup when calling `Hammer()` 3046 * When creating a new Manager these will be skipped. 3047 * @type {Array} 3048 */ 3049 preset: [ 3050 // RecognizerClass, options, [recognizeWith, ...], [requireFailure, ...] 3051 [RotateRecognizer, {enable: false}], 3052 [PinchRecognizer, {enable: false}, ['rotate']], 3053 [SwipeRecognizer, {direction: DIRECTION_HORIZONTAL}], 3054 [PanRecognizer, {direction: DIRECTION_HORIZONTAL}, ['swipe']], 3055 [TapRecognizer], 3056 [TapRecognizer, {event: 'doubletap', taps: 2}, ['tap']], 3057 [PressRecognizer] 3058 ], 3059 3060 /** 3061 * Some CSS properties can be used to improve the working of Hammer. 3062 * Add them to this method and they will be set when creating a new Manager. 3063 * @namespace 3064 */ 3065 cssProps: { 3066 /** 3067 * Disables text selection to improve the dragging gesture. Mainly for desktop browsers. 3068 * @type {String} 3069 * @default 'none' 3070 */ 3071 userSelect: 'none', 3072 3073 /** 3074 * Disable the Windows Phone grippers when pressing an element. 3075 * @type {String} 3076 * @default 'none' 3077 */ 3078 touchSelect: 'none', 3079 3080 /** 3081 * Disables the default callout shown when you touch and hold a touch target. 3082 * On iOS, when you touch and hold a touch target such as a link, Safari displays 3083 * a callout containing information about the link. This property allows you to disable that callout. 3084 * @type {String} 3085 * @default 'none' 3086 */ 3087 touchCallout: 'none', 3088 3089 /** 3090 * Specifies whether zooming is enabled. Used by IE10> 3091 * @type {String} 3092 * @default 'none' 3093 */ 3094 contentZooming: 'none', 3095 3096 /** 3097 * Specifies that an entire element should be draggable instead of its contents. Mainly for desktop browsers. 3098 * @type {String} 3099 * @default 'none' 3100 */ 3101 userDrag: 'none', 3102 3103 /** 3104 * Overrides the highlight color shown when the user taps a link or a JavaScript 3105 * clickable element in iOS. This property obeys the alpha value, if specified. 3106 * @type {String} 3107 * @default 'rgba(0,0,0,0)' 3108 */ 3109 tapHighlightColor: 'rgba(0,0,0,0)' 3110 } 3111}; 3112 3113var STOP = 1; 3114var FORCED_STOP = 2; 3115 3116/** 3117 * Manager 3118 * @param {HTMLElement} element 3119 * @param {Object} [options] 3120 * @constructor 3121 */ 3122function Manager(element, options) { 3123 this.options = assign({}, Hammer.defaults, options || {}); 3124 3125 this.options.inputTarget = this.options.inputTarget || element; 3126 3127 this.handlers = {}; 3128 this.session = {}; 3129 this.recognizers = []; 3130 this.oldCssProps = {}; 3131 3132 this.element = element; 3133 this.input = createInputInstance(this); 3134 this.touchAction = new TouchAction(this, this.options.touchAction); 3135 3136 toggleCssProps(this, true); 3137 3138 each(this.options.recognizers, function(item) { 3139 var recognizer = this.add(new (item[0])(item[1])); 3140 item[2] && recognizer.recognizeWith(item[2]); 3141 item[3] && recognizer.requireFailure(item[3]); 3142 }, this); 3143} 3144 3145Manager.prototype = { 3146 /** 3147 * set options 3148 * @param {Object} options 3149 * @returns {Manager} 3150 */ 3151 set: function(options) { 3152 assign(this.options, options); 3153 3154 // Options that need a little more setup 3155 if (options.touchAction) { 3156 this.touchAction.update(); 3157 } 3158 if (options.inputTarget) { 3159 // Clean up existing event listeners and reinitialize 3160 this.input.destroy(); 3161 this.input.target = options.inputTarget; 3162 this.input.init(); 3163 } 3164 return this; 3165 }, 3166 3167 /** 3168 * stop recognizing for this session. 3169 * This session will be discarded, when a new [input]start event is fired. 3170 * When forced, the recognizer cycle is stopped immediately. 3171 * @param {Boolean} [force] 3172 */ 3173 stop: function(force) { 3174 this.session.stopped = force ? FORCED_STOP : STOP; 3175 }, 3176 3177 /** 3178 * run the recognizers! 3179 * called by the inputHandler function on every movement of the pointers (touches) 3180 * it walks through all the recognizers and tries to detect the gesture that is being made 3181 * @param {Object} inputData 3182 */ 3183 recognize: function(inputData) { 3184 var session = this.session; 3185 if (session.stopped) { 3186 return; 3187 } 3188 3189 // run the touch-action polyfill 3190 this.touchAction.preventDefaults(inputData); 3191 3192 var recognizer; 3193 var recognizers = this.recognizers; 3194 3195 // this holds the recognizer that is being recognized. 3196 // so the recognizer's state needs to be BEGAN, CHANGED, ENDED or RECOGNIZED 3197 // if no recognizer is detecting a thing, it is set to `null` 3198 var curRecognizer = session.curRecognizer; 3199 3200 // reset when the last recognizer is recognized 3201 // or when we're in a new session 3202 if (!curRecognizer || (curRecognizer && curRecognizer.state & STATE_RECOGNIZED)) { 3203 curRecognizer = session.curRecognizer = null; 3204 } 3205 3206 var i = 0; 3207 while (i < recognizers.length) { 3208 recognizer = recognizers[i]; 3209 3210 // find out if we are allowed try to recognize the input for this one. 3211 // 1. allow if the session is NOT forced stopped (see the .stop() method) 3212 // 2. allow if we still haven't recognized a gesture in this session, or the this recognizer is the one 3213 // that is being recognized. 3214 // 3. allow if the recognizer is allowed to run simultaneous with the current recognized recognizer. 3215 // this can be setup with the `recognizeWith()` method on the recognizer. 3216 if (session.stopped !== FORCED_STOP && ( // 1 3217 !curRecognizer || recognizer == curRecognizer || // 2 3218 recognizer.canRecognizeWith(curRecognizer))) { // 3 3219 recognizer.recognize(inputData); 3220 } else { 3221 recognizer.reset(); 3222 } 3223 3224 // if the recognizer has been recognizing the input as a valid gesture, we want to store this one as the 3225 // current active recognizer. but only if we don't already have an active recognizer 3226 if (!curRecognizer && recognizer.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED)) { 3227 curRecognizer = session.curRecognizer = recognizer; 3228 } 3229 i++; 3230 } 3231 }, 3232 3233 /** 3234 * get a recognizer by its event name. 3235 * @param {Recognizer|String} recognizer 3236 * @returns {Recognizer|Null} 3237 */ 3238 get: function(recognizer) { 3239 if (recognizer instanceof Recognizer) { 3240 return recognizer; 3241 } 3242 3243 var recognizers = this.recognizers; 3244 for (var i = 0; i < recognizers.length; i++) { 3245 if (recognizers[i].options.event == recognizer) { 3246 return recognizers[i]; 3247 } 3248 } 3249 return null; 3250 }, 3251 3252 /** 3253 * add a recognizer to the manager 3254 * existing recognizers with the same event name will be removed 3255 * @param {Recognizer} recognizer 3256 * @returns {Recognizer|Manager} 3257 */ 3258 add: function(recognizer) { 3259 if (invokeArrayArg(recognizer, 'add', this)) { 3260 return this; 3261 } 3262 3263 // remove existing 3264 var existing = this.get(recognizer.options.event); 3265 if (existing) { 3266 this.remove(existing); 3267 } 3268 3269 this.recognizers.push(recognizer); 3270 recognizer.manager = this; 3271 3272 this.touchAction.update(); 3273 return recognizer; 3274 }, 3275 3276 /** 3277 * remove a recognizer by name or instance 3278 * @param {Recognizer|String} recognizer 3279 * @returns {Manager} 3280 */ 3281 remove: function(recognizer) { 3282 if (invokeArrayArg(recognizer, 'remove', this)) { 3283 return this; 3284 } 3285 3286 recognizer = this.get(recognizer); 3287 3288 // let's make sure this recognizer exists 3289 if (recognizer) { 3290 var recognizers = this.recognizers; 3291 var index = inArray(recognizers, recognizer); 3292 3293 if (index !== -1) { 3294 recognizers.splice(index, 1); 3295 this.touchAction.update(); 3296 } 3297 } 3298 3299 return this; 3300 }, 3301 3302 /** 3303 * bind event 3304 * @param {String} events 3305 * @param {Function} handler 3306 * @returns {EventEmitter} this 3307 */ 3308 on: function(events, handler) { 3309 if (events === undefined) { 3310 return; 3311 } 3312 if (handler === undefined) { 3313 return; 3314 } 3315 3316 var handlers = this.handlers; 3317 each(splitStr(events), function(event) { 3318 handlers[event] = handlers[event] || []; 3319 handlers[event].push(handler); 3320 }); 3321 return this; 3322 }, 3323 3324 /** 3325 * unbind event, leave emit blank to remove all handlers 3326 * @param {String} events 3327 * @param {Function} [handler] 3328 * @returns {EventEmitter} this 3329 */ 3330 off: function(events, handler) { 3331 if (events === undefined) { 3332 return; 3333 } 3334 3335 var handlers = this.handlers; 3336 each(splitStr(events), function(event) { 3337 if (!handler) { 3338 delete handlers[event]; 3339 } else { 3340 handlers[event] && handlers[event].splice(inArray(handlers[event], handler), 1); 3341 } 3342 }); 3343 return this; 3344 }, 3345 3346 /** 3347 * emit event to the listeners 3348 * @param {String} event 3349 * @param {Object} data 3350 */ 3351 emit: function(event, data) { 3352 // we also want to trigger dom events 3353 if (this.options.domEvents) { 3354 triggerDomEvent(event, data); 3355 } 3356 3357 // no handlers, so skip it all 3358 var handlers = this.handlers[event] && this.handlers[event].slice(); 3359 if (!handlers || !handlers.length) { 3360 return; 3361 } 3362 3363 data.type = event; 3364 data.preventDefault = function() { 3365 data.srcEvent.preventDefault(); 3366 }; 3367 3368 var i = 0; 3369 while (i < handlers.length) { 3370 handlers[i](data); 3371 i++; 3372 } 3373 }, 3374 3375 /** 3376 * destroy the manager and unbinds all events 3377 * it doesn't unbind dom events, that is the user own responsibility 3378 */ 3379 destroy: function() { 3380 this.element && toggleCssProps(this, false); 3381 3382 this.handlers = {}; 3383 this.session = {}; 3384 this.input.destroy(); 3385 this.element = null; 3386 } 3387}; 3388 3389/** 3390 * add/remove the css properties as defined in manager.options.cssProps 3391 * @param {Manager} manager 3392 * @param {Boolean} add 3393 */ 3394function toggleCssProps(manager, add) { 3395 var element = manager.element; 3396 if (!element.style) { 3397 return; 3398 } 3399 var prop; 3400 each(manager.options.cssProps, function(value, name) { 3401 prop = prefixed(element.style, name); 3402 if (add) { 3403 manager.oldCssProps[prop] = element.style[prop]; 3404 element.style[prop] = value; 3405 } else { 3406 element.style[prop] = manager.oldCssProps[prop] || ''; 3407 } 3408 }); 3409 if (!add) { 3410 manager.oldCssProps = {}; 3411 } 3412} 3413 3414/** 3415 * trigger dom event 3416 * @param {String} event 3417 * @param {Object} data 3418 */ 3419function triggerDomEvent(event, data) { 3420 var gestureEvent = document.createEvent('Event'); 3421 gestureEvent.initEvent(event, true, true); 3422 gestureEvent.gesture = data; 3423 data.target.dispatchEvent(gestureEvent); 3424} 3425 3426assign(Hammer, { 3427 INPUT_START: INPUT_START, 3428 INPUT_MOVE: INPUT_MOVE, 3429 INPUT_END: INPUT_END, 3430 INPUT_CANCEL: INPUT_CANCEL, 3431 3432 STATE_POSSIBLE: STATE_POSSIBLE, 3433 STATE_BEGAN: STATE_BEGAN, 3434 STATE_CHANGED: STATE_CHANGED, 3435 STATE_ENDED: STATE_ENDED, 3436 STATE_RECOGNIZED: STATE_RECOGNIZED, 3437 STATE_CANCELLED: STATE_CANCELLED, 3438 STATE_FAILED: STATE_FAILED, 3439 3440 DIRECTION_NONE: DIRECTION_NONE, 3441 DIRECTION_LEFT: DIRECTION_LEFT, 3442 DIRECTION_RIGHT: DIRECTION_RIGHT, 3443 DIRECTION_UP: DIRECTION_UP, 3444 DIRECTION_DOWN: DIRECTION_DOWN, 3445 DIRECTION_HORIZONTAL: DIRECTION_HORIZONTAL, 3446 DIRECTION_VERTICAL: DIRECTION_VERTICAL, 3447 DIRECTION_ALL: DIRECTION_ALL, 3448 3449 Manager: Manager, 3450 Input: Input, 3451 TouchAction: TouchAction, 3452 3453 TouchInput: TouchInput, 3454 MouseInput: MouseInput, 3455 PointerEventInput: PointerEventInput, 3456 TouchMouseInput: TouchMouseInput, 3457 SingleTouchInput: SingleTouchInput, 3458 3459 Recognizer: Recognizer, 3460 AttrRecognizer: AttrRecognizer, 3461 Tap: TapRecognizer, 3462 Pan: PanRecognizer, 3463 Swipe: SwipeRecognizer, 3464 Pinch: PinchRecognizer, 3465 Rotate: RotateRecognizer, 3466 Press: PressRecognizer, 3467 3468 on: addEventListeners, 3469 off: removeEventListeners, 3470 each: each, 3471 merge: merge, 3472 extend: extend, 3473 assign: assign, 3474 inherit: inherit, 3475 bindFn: bindFn, 3476 prefixed: prefixed 3477}); 3478 3479// this prevents errors when Hammer is loaded in the presence of an AMD 3480// style loader but by script tag, not by the loader. 3481var freeGlobal = (typeof window !== 'undefined' ? window : (typeof self !== 'undefined' ? self : {})); // jshint ignore:line 3482freeGlobal.Hammer = Hammer; 3483 3484if (true) { 3485 !(__WEBPACK_AMD_DEFINE_RESULT__ = (function() { 3486 return Hammer; 3487 }).call(exports, __webpack_require__, exports, module), 3488 __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); 3489} else {} 3490 3491})(window, document, 'Hammer'); 3492 3493 3494/***/ }), 3495
vendor: 24,774 bytes, lines 3496-4235
3496/***/ "../../../upup-baseline/node_modules/regenerator-runtime/runtime.js": 3497/*!***************************************************************************************************************************************!*\ 3498 !*** /Applications/XAMPP/xamppfiles/htdocs/gwu-wordpress/wp-content/themes/upup-baseline/node_modules/regenerator-runtime/runtime.js ***! 3499 \***************************************************************************************************************************************/ 3500/*! no static exports found */ 3501/***/ (function(module, exports, __webpack_require__) { 3502 3503/** 3504 * Copyright (c) 2014-present, Facebook, Inc. 3505 * 3506 * This source code is licensed under the MIT license found in the 3507 * LICENSE file in the root directory of this source tree. 3508 */ 3509 3510var runtime = (function (exports) { 3511 "use strict"; 3512 3513 var Op = Object.prototype; 3514 var hasOwn = Op.hasOwnProperty; 3515 var undefined; // More compressible than void 0. 3516 var $Symbol = typeof Symbol === "function" ? Symbol : {}; 3517 var iteratorSymbol = $Symbol.iterator || "@@iterator"; 3518 var asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator"; 3519 var toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag"; 3520 3521 function wrap(innerFn, outerFn, self, tryLocsList) { 3522 // If outerFn provided and outerFn.prototype is a Generator, then outerFn.prototype instanceof Generator. 3523 var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator; 3524 var generator = Object.create(protoGenerator.prototype); 3525 var context = new Context(tryLocsList || []); 3526 3527 // The ._invoke method unifies the implementations of the .next, 3528 // .throw, and .return methods. 3529 generator._invoke = makeInvokeMethod(innerFn, self, context); 3530 3531 return generator; 3532 } 3533 exports.wrap = wrap; 3534 3535 // Try/catch helper to minimize deoptimizations. Returns a completion 3536 // record like context.tryEntries[i].completion. This interface could 3537 // have been (and was previously) designed to take a closure to be 3538 // invoked without arguments, but in all the cases we care about we 3539 // already have an existing method we want to call, so there's no need 3540 // to create a new function object. We can even get away with assuming 3541 // the method takes exactly one argument, since that happens to be true 3542 // in every case, so we don't have to touch the arguments object. The 3543 // only additional allocation required is the completion record, which 3544 // has a stable shape and so hopefully should be cheap to allocate. 3545 function tryCatch(fn, obj, arg) { 3546 try { 3547 return { type: "normal", arg: fn.call(obj, arg) }; 3548 } catch (err) { 3549 return { type: "throw", arg: err }; 3550 } 3551 } 3552 3553 var GenStateSuspendedStart = "suspendedStart"; 3554 var GenStateSuspendedYield = "suspendedYield"; 3555 var GenStateExecuting = "executing"; 3556 var GenStateCompleted = "completed"; 3557 3558 // Returning this object from the innerFn has the same effect as 3559 // breaking out of the dispatch switch statement. 3560 var ContinueSentinel = {}; 3561 3562 // Dummy constructor functions that we use as the .constructor and 3563 // .constructor.prototype properties for functions that return Generator 3564 // objects. For full spec compliance, you may wish to configure your 3565 // minifier not to mangle the names of these two functions. 3566 function Generator() {} 3567 function GeneratorFunction() {} 3568 function GeneratorFunctionPrototype() {} 3569 3570 // This is a polyfill for %IteratorPrototype% for environments that 3571 // don't natively support it. 3572 var IteratorPrototype = {}; 3573 IteratorPrototype[iteratorSymbol] = function () { 3574 return this; 3575 }; 3576 3577 var getProto = Object.getPrototypeOf; 3578 var NativeIteratorPrototype = getProto && getProto(getProto(values([]))); 3579 if (NativeIteratorPrototype && 3580 NativeIteratorPrototype !== Op && 3581 hasOwn.call(NativeIteratorPrototype, iteratorSymbol)) { 3582 // This environment has a native %IteratorPrototype%; use it instead 3583 // of the polyfill. 3584 IteratorPrototype = NativeIteratorPrototype; 3585 } 3586 3587 var Gp = GeneratorFunctionPrototype.prototype = 3588 Generator.prototype = Object.create(IteratorPrototype); 3589 GeneratorFunction.prototype = Gp.constructor = GeneratorFunctionPrototype; 3590 GeneratorFunctionPrototype.constructor = GeneratorFunction; 3591 GeneratorFunctionPrototype[toStringTagSymbol] = 3592 GeneratorFunction.displayName = "GeneratorFunction"; 3593 3594 // Helper for defining the .next, .throw, and .return methods of the 3595 // Iterator interface in terms of a single ._invoke method. 3596 function defineIteratorMethods(prototype) { 3597 ["next", "throw", "return"].forEach(function(method) { 3598 prototype[method] = function(arg) { 3599 return this._invoke(method, arg); 3600 }; 3601 }); 3602 } 3603 3604 exports.isGeneratorFunction = function(genFun) { 3605 var ctor = typeof genFun === "function" && genFun.constructor; 3606 return ctor 3607 ? ctor === GeneratorFunction || 3608 // For the native GeneratorFunction constructor, the best we can 3609 // do is to check its .name property. 3610 (ctor.displayName || ctor.name) === "GeneratorFunction" 3611 : false; 3612 }; 3613 3614 exports.mark = function(genFun) { 3615 if (Object.setPrototypeOf) { 3616 Object.setPrototypeOf(genFun, GeneratorFunctionPrototype); 3617 } else { 3618 genFun.__proto__ = GeneratorFunctionPrototype; 3619 if (!(toStringTagSymbol in genFun)) { 3620 genFun[toStringTagSymbol] = "GeneratorFunction"; 3621 } 3622 } 3623 genFun.prototype = Object.create(Gp); 3624 return genFun; 3625 }; 3626 3627 // Within the body of any async function, `await x` is transformed to 3628 // `yield regeneratorRuntime.awrap(x)`, so that the runtime can test 3629 // `hasOwn.call(value, "__await")` to determine if the yielded value is 3630 // meant to be awaited. 3631 exports.awrap = function(arg) { 3632 return { __await: arg }; 3633 }; 3634 3635 function AsyncIterator(generator, PromiseImpl) { 3636 function invoke(method, arg, resolve, reject) { 3637 var record = tryCatch(generator[method], generator, arg); 3638 if (record.type === "throw") { 3639 reject(record.arg); 3640 } else { 3641 var result = record.arg; 3642 var value = result.value; 3643 if (value && 3644 typeof value === "object" && 3645 hasOwn.call(value, "__await")) { 3646 return PromiseImpl.resolve(value.__await).then(function(value) { 3647 invoke("next", value, resolve, reject); 3648 }, function(err) { 3649 invoke("throw", err, resolve, reject); 3650 }); 3651 } 3652 3653 return PromiseImpl.resolve(value).then(function(unwrapped) { 3654 // When a yielded Promise is resolved, its final value becomes 3655 // the .value of the Promise<{value,done}> result for the 3656 // current iteration. 3657 result.value = unwrapped; 3658 resolve(result); 3659 }, function(error) { 3660 // If a rejected Promise was yielded, throw the rejection back 3661 // into the async generator function so it can be handled there. 3662 return invoke("throw", error, resolve, reject); 3663 }); 3664 } 3665 } 3666 3667 var previousPromise; 3668 3669 function enqueue(method, arg) { 3670 function callInvokeWithMethodAndArg() { 3671 return new PromiseImpl(function(resolve, reject) { 3672 invoke(method, arg, resolve, reject); 3673 }); 3674 } 3675 3676 return previousPromise = 3677 // If enqueue has been called before, then we want to wait until 3678 // all previous Promises have been resolved before calling invoke, 3679 // so that results are always delivered in the correct order. If 3680 // enqueue has not been called before, then it is important to 3681 // call invoke immediately, without waiting on a callback to fire, 3682 // so that the async generator function has the opportunity to do 3683 // any necessary setup in a predictable way. This predictability 3684 // is why the Promise constructor synchronously invokes its 3685 // executor callback, and why async functions synchronously 3686 // execute code before the first await. Since we implement simple 3687 // async functions in terms of async generators, it is especially 3688 // important to get this right, even though it requires care. 3689 previousPromise ? previousPromise.then( 3690 callInvokeWithMethodAndArg, 3691 // Avoid propagating failures to Promises returned by later 3692 // invocations of the iterator. 3693 callInvokeWithMethodAndArg 3694 ) : callInvokeWithMethodAndArg(); 3695 } 3696 3697 // Define the unified helper method that is used to implement .next, 3698 // .throw, and .return (see defineIteratorMethods). 3699 this._invoke = enqueue; 3700 } 3701 3702 defineIteratorMethods(AsyncIterator.prototype); 3703 AsyncIterator.prototype[asyncIteratorSymbol] = function () { 3704 return this; 3705 }; 3706 exports.AsyncIterator = AsyncIterator; 3707 3708 // Note that simple async functions are implemented on top of 3709 // AsyncIterator objects; they just return a Promise for the value of 3710 // the final result produced by the iterator. 3711 exports.async = function(innerFn, outerFn, self, tryLocsList, PromiseImpl) { 3712 if (PromiseImpl === void 0) PromiseImpl = Promise; 3713 3714 var iter = new AsyncIterator( 3715 wrap(innerFn, outerFn, self, tryLocsList), 3716 PromiseImpl 3717 ); 3718 3719 return exports.isGeneratorFunction(outerFn) 3720 ? iter // If outerFn is a generator, return the full iterator. 3721 : iter.next().then(function(result) { 3722 return result.done ? result.value : iter.next(); 3723 }); 3724 }; 3725 3726 function makeInvokeMethod(innerFn, self, context) { 3727 var state = GenStateSuspendedStart; 3728 3729 return function invoke(method, arg) { 3730 if (state === GenStateExecuting) { 3731 throw new Error("Generator is already running"); 3732 } 3733 3734 if (state === GenStateCompleted) { 3735 if (method === "throw") { 3736 throw arg; 3737 } 3738 3739 // Be forgiving, per 25.3.3.3.3 of the spec: 3740 // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresume 3741 return doneResult(); 3742 } 3743 3744 context.method = method; 3745 context.arg = arg; 3746 3747 while (true) { 3748 var delegate = context.delegate; 3749 if (delegate) { 3750 var delegateResult = maybeInvokeDelegate(delegate, context); 3751 if (delegateResult) { 3752 if (delegateResult === ContinueSentinel) continue; 3753 return delegateResult; 3754 } 3755 } 3756 3757 if (context.method === "next") { 3758 // Setting context._sent for legacy support of Babel's 3759 // function.sent implementation. 3760 context.sent = context._sent = context.arg; 3761 3762 } else if (context.method === "throw") { 3763 if (state === GenStateSuspendedStart) { 3764 state = GenStateCompleted; 3765 throw context.arg; 3766 } 3767 3768 context.dispatchException(context.arg); 3769 3770 } else if (context.method === "return") { 3771 context.abrupt("return", context.arg); 3772 } 3773 3774 state = GenStateExecuting; 3775 3776 var record = tryCatch(innerFn, self, context); 3777 if (record.type === "normal") { 3778 // If an exception is thrown from innerFn, we leave state === 3779 // GenStateExecuting and loop back for another invocation. 3780 state = context.done 3781 ? GenStateCompleted 3782 : GenStateSuspendedYield; 3783 3784 if (record.arg === ContinueSentinel) { 3785 continue; 3786 } 3787 3788 return { 3789 value: record.arg, 3790 done: context.done 3791 }; 3792 3793 } else if (record.type === "throw") { 3794 state = GenStateCompleted; 3795 // Dispatch the exception by looping back around to the 3796 // context.dispatchException(context.arg) call above. 3797 context.method = "throw"; 3798 context.arg = record.arg; 3799 } 3800 } 3801 }; 3802 } 3803 3804 // Call delegate.iterator[context.method](context.arg) and handle the 3805 // result, either by returning a { value, done } result from the 3806 // delegate iterator, or by modifying context.method and context.arg, 3807 // setting context.delegate to null, and returning the ContinueSentinel. 3808 function maybeInvokeDelegate(delegate, context) { 3809 var method = delegate.iterator[context.method]; 3810 if (method === undefined) { 3811 // A .throw or .return when the delegate iterator has no .throw 3812 // method always terminates the yield* loop. 3813 context.delegate = null; 3814 3815 if (context.method === "throw") { 3816 // Note: ["return"] must be used for ES3 parsing compatibility. 3817 if (delegate.iterator["return"]) { 3818 // If the delegate iterator has a return method, give it a 3819 // chance to clean up. 3820 context.method = "return"; 3821 context.arg = undefined; 3822 maybeInvokeDelegate(delegate, context); 3823 3824 if (context.method === "throw") { 3825 // If maybeInvokeDelegate(context) changed context.method from 3826 // "return" to "throw", let that override the TypeError below. 3827 return ContinueSentinel; 3828 } 3829 } 3830 3831 context.method = "throw"; 3832 context.arg = new TypeError( 3833 "The iterator does not provide a 'throw' method"); 3834 } 3835 3836 return ContinueSentinel; 3837 } 3838 3839 var record = tryCatch(method, delegate.iterator, context.arg); 3840 3841 if (record.type === "throw") { 3842 context.method = "throw"; 3843 context.arg = record.arg; 3844 context.delegate = null; 3845 return ContinueSentinel; 3846 } 3847 3848 var info = record.arg; 3849 3850 if (! info) { 3851 context.method = "throw"; 3852 context.arg = new TypeError("iterator result is not an object"); 3853 context.delegate = null; 3854 return ContinueSentinel; 3855 } 3856 3857 if (info.done) { 3858 // Assign the result of the finished delegate to the temporary 3859 // variable specified by delegate.resultName (see delegateYield). 3860 context[delegate.resultName] = info.value; 3861 3862 // Resume execution at the desired location (see delegateYield). 3863 context.next = delegate.nextLoc; 3864 3865 // If context.method was "throw" but the delegate handled the 3866 // exception, let the outer generator proceed normally. If 3867 // context.method was "next", forget context.arg since it has been 3868 // "consumed" by the delegate iterator. If context.method was 3869 // "return", allow the original .return call to continue in the 3870 // outer generator. 3871 if (context.method !== "return") { 3872 context.method = "next"; 3873 context.arg = undefined; 3874 } 3875 3876 } else { 3877 // Re-yield the result returned by the delegate method. 3878 return info; 3879 } 3880 3881 // The delegate iterator is finished, so forget it and continue with 3882 // the outer generator. 3883 context.delegate = null; 3884 return ContinueSentinel; 3885 } 3886 3887 // Define Generator.prototype.{next,throw,return} in terms of the 3888 // unified ._invoke helper method. 3889 defineIteratorMethods(Gp); 3890 3891 Gp[toStringTagSymbol] = "Generator"; 3892 3893 // A Generator should always return itself as the iterator object when the 3894 // @@iterator function is called on it. Some browsers' implementations of the 3895 // iterator prototype chain incorrectly implement this, causing the Generator 3896 // object to not be returned from this call. This ensures that doesn't happen. 3897 // See https://github.com/facebook/regenerator/issues/274 for more details. 3898 Gp[iteratorSymbol] = function() { 3899 return this; 3900 }; 3901 3902 Gp.toString = function() { 3903 return "[object Generator]"; 3904 }; 3905 3906 function pushTryEntry(locs) { 3907 var entry = { tryLoc: locs[0] }; 3908 3909 if (1 in locs) { 3910 entry.catchLoc = locs[1]; 3911 } 3912 3913 if (2 in locs) { 3914 entry.finallyLoc = locs[2]; 3915 entry.afterLoc = locs[3]; 3916 } 3917 3918 this.tryEntries.push(entry); 3919 } 3920 3921 function resetTryEntry(entry) { 3922 var record = entry.completion || {}; 3923 record.type = "normal"; 3924 delete record.arg; 3925 entry.completion = record; 3926 } 3927 3928 function Context(tryLocsList) { 3929 // The root entry object (effectively a try statement without a catch 3930 // or a finally block) gives us a place to store values thrown from 3931 // locations where there is no enclosing try statement. 3932 this.tryEntries = [{ tryLoc: "root" }]; 3933 tryLocsList.forEach(pushTryEntry, this); 3934 this.reset(true); 3935 } 3936 3937 exports.keys = function(object) { 3938 var keys = []; 3939 for (var key in object) { 3940 keys.push(key); 3941 } 3942 keys.reverse(); 3943 3944 // Rather than returning an object with a next method, we keep 3945 // things simple and return the next function itself. 3946 return function next() { 3947 while (keys.length) { 3948 var key = keys.pop(); 3949 if (key in object) { 3950 next.value = key; 3951 next.done = false; 3952 return next; 3953 } 3954 } 3955 3956 // To avoid creating an additional object, we just hang the .value 3957 // and .done properties off the next function object itself. This 3958 // also ensures that the minifier will not anonymize the function. 3959 next.done = true; 3960 return next; 3961 }; 3962 }; 3963 3964 function values(iterable) { 3965 if (iterable) { 3966 var iteratorMethod = iterable[iteratorSymbol]; 3967 if (iteratorMethod) { 3968 return iteratorMethod.call(iterable); 3969 } 3970 3971 if (typeof iterable.next === "function") { 3972 return iterable; 3973 } 3974 3975 if (!isNaN(iterable.length)) { 3976 var i = -1, next = function next() { 3977 while (++i < iterable.length) { 3978 if (hasOwn.call(iterable, i)) { 3979 next.value = iterable[i]; 3980 next.done = false; 3981 return next; 3982 } 3983 } 3984 3985 next.value = undefined; 3986 next.done = true; 3987 3988 return next; 3989 }; 3990 3991 return next.next = next; 3992 } 3993 } 3994 3995 // Return an iterator with no values. 3996 return { next: doneResult }; 3997 } 3998 exports.values = values; 3999 4000 function doneResult() { 4001 return { value: undefined, done: true }; 4002 } 4003 4004 Context.prototype = { 4005 constructor: Context, 4006 4007 reset: function(skipTempReset) { 4008 this.prev = 0; 4009 this.next = 0; 4010 // Resetting context._sent for legacy support of Babel's 4011 // function.sent implementation. 4012 this.sent = this._sent = undefined; 4013 this.done = false; 4014 this.delegate = null; 4015 4016 this.method = "next"; 4017 this.arg = undefined; 4018 4019 this.tryEntries.forEach(resetTryEntry); 4020 4021 if (!skipTempReset) { 4022 for (var name in this) { 4023 // Not sure about the optimal order of these conditions: 4024 if (name.charAt(0) === "t" && 4025 hasOwn.call(this, name) && 4026 !isNaN(+name.slice(1))) { 4027 this[name] = undefined; 4028 } 4029 } 4030 } 4031 }, 4032 4033 stop: function() { 4034 this.done = true; 4035 4036 var rootEntry = this.tryEntries[0]; 4037 var rootRecord = rootEntry.completion; 4038 if (rootRecord.type === "throw") { 4039 throw rootRecord.arg; 4040 } 4041 4042 return this.rval; 4043 }, 4044 4045 dispatchException: function(exception) { 4046 if (this.done) { 4047 throw exception; 4048 } 4049 4050 var context = this; 4051 function handle(loc, caught) { 4052 record.type = "throw"; 4053 record.arg = exception; 4054 context.next = loc; 4055 4056 if (caught) { 4057 // If the dispatched exception was caught by a catch block, 4058 // then let that catch block handle the exception normally. 4059 context.method = "next"; 4060 context.arg = undefined; 4061 } 4062 4063 return !! caught; 4064 } 4065 4066 for (var i = this.tryEntries.length - 1; i >= 0; --i) { 4067 var entry = this.tryEntries[i]; 4068 var record = entry.completion; 4069 4070 if (entry.tryLoc === "root") { 4071 // Exception thrown outside of any try block that could handle 4072 // it, so set the completion value of the entire function to 4073 // throw the exception. 4074 return handle("end"); 4075 } 4076 4077 if (entry.tryLoc <= this.prev) { 4078 var hasCatch = hasOwn.call(entry, "catchLoc"); 4079 var hasFinally = hasOwn.call(entry, "finallyLoc"); 4080 4081 if (hasCatch && hasFinally) { 4082 if (this.prev < entry.catchLoc) { 4083 return handle(entry.catchLoc, true); 4084 } else if (this.prev < entry.finallyLoc) { 4085 return handle(entry.finallyLoc); 4086 } 4087 4088 } else if (hasCatch) { 4089 if (this.prev < entry.catchLoc) { 4090 return handle(entry.catchLoc, true); 4091 } 4092 4093 } else if (hasFinally) { 4094 if (this.prev < entry.finallyLoc) { 4095 return handle(entry.finallyLoc); 4096 } 4097 4098 } else { 4099 throw new Error("try statement without catch or finally"); 4100 } 4101 } 4102 } 4103 }, 4104 4105 abrupt: function(type, arg) { 4106 for (var i = this.tryEntries.length - 1; i >= 0; --i) { 4107 var entry = this.tryEntries[i]; 4108 if (entry.tryLoc <= this.prev && 4109 hasOwn.call(entry, "finallyLoc") && 4110 this.prev < entry.finallyLoc) { 4111 var finallyEntry = entry; 4112 break; 4113 } 4114 } 4115 4116 if (finallyEntry && 4117 (type === "break" || 4118 type === "continue") && 4119 finallyEntry.tryLoc <= arg && 4120 arg <= finallyEntry.finallyLoc) { 4121 // Ignore the finally entry if control is not jumping to a 4122 // location outside the try/catch block. 4123 finallyEntry = null; 4124 } 4125 4126 var record = finallyEntry ? finallyEntry.completion : {}; 4127 record.type = type; 4128 record.arg = arg; 4129 4130 if (finallyEntry) { 4131 this.method = "next"; 4132 this.next = finallyEntry.finallyLoc; 4133 return ContinueSentinel; 4134 } 4135 4136 return this.complete(record); 4137 }, 4138 4139 complete: function(record, afterLoc) { 4140 if (record.type === "throw") { 4141 throw record.arg; 4142 } 4143 4144 if (record.type === "break" || 4145 record.type === "continue") { 4146 this.next = record.arg; 4147 } else if (record.type === "return") { 4148 this.rval = this.arg = record.arg; 4149 this.method = "return"; 4150 this.next = "end"; 4151 } else if (record.type === "normal" && afterLoc) { 4152 this.next = afterLoc; 4153 } 4154 4155 return ContinueSentinel; 4156 }, 4157 4158 finish: function(finallyLoc) { 4159 for (var i = this.tryEntries.length - 1; i >= 0; --i) { 4160 var entry = this.tryEntries[i]; 4161 if (entry.finallyLoc === finallyLoc) { 4162 this.complete(entry.completion, entry.afterLoc); 4163 resetTryEntry(entry); 4164 return ContinueSentinel; 4165 } 4166 } 4167 }, 4168 4169 "catch": function(tryLoc) { 4170 for (var i = this.tryEntries.length - 1; i >= 0; --i) { 4171 var entry = this.tryEntries[i]; 4172 if (entry.tryLoc === tryLoc) { 4173 var record = entry.completion; 4174 if (record.type === "throw") { 4175 var thrown = record.arg; 4176 resetTryEntry(entry); 4177 } 4178 return thrown; 4179 } 4180 } 4181 4182 // The context.catch method must only be called with a location 4183 // argument that corresponds to a known catch block. 4184 throw new Error("illegal catch attempt"); 4185 }, 4186 4187 delegateYield: function(iterable, resultName, nextLoc) { 4188 this.delegate = { 4189 iterator: values(iterable), 4190 resultName: resultName, 4191 nextLoc: nextLoc 4192 }; 4193 4194 if (this.method === "next") { 4195 // Deliberately forget the last sent value so that we don't 4196 // accidentally pass it on to the delegate. 4197 this.arg = undefined; 4198 } 4199 4200 return ContinueSentinel; 4201 } 4202 }; 4203 4204 // Regardless of whether this script is executing as a CommonJS module 4205 // or not, return the runtime object so that we can declare the variable 4206 // regeneratorRuntime in the outer scope, which allows this module to be 4207 // injected easily by `bin/regenerator --include-runtime script.js`. 4208 return exports; 4209 4210}( 4211 // If this script is executing as a CommonJS module, use module.exports 4212 // as the regeneratorRuntime namespace. Otherwise create a new empty 4213 // object. Either way, the resulting object will be used to initialize 4214 // the regeneratorRuntime variable at the top of this file. 4215 true ? module.exports : undefined 4216)); 4217 4218try { 4219 regeneratorRuntime = runtime; 4220} catch (accidentalStrictMode) { 4221 // This module should not be running in strict mode, so the above 4222 // assignment should always work unless something is misconfigured. Just 4223 // in case runtime.js accidentally runs in strict mode, we can escape 4224 // strict mode using a global Function call. This could conceivably fail 4225 // if a Content Security Policy forbids using Function, but in that case 4226 // the proper solution is to fix the accidental strict mode problem. If 4227 // you've misconfigured your bundler to force strict mode and applied a 4228 // CSP to forbid Function, and you're not willing to fix either of those 4229 // problems, please detail your unique predicament in a GitHub issue. 4230 Function("r", "regeneratorRuntime = r")(runtime); 4231} 4232 4233 4234/***/ }), 4235
vendor: 207,337 bytes, lines 4236-9021
4236/***/ "../../../upup-baseline/node_modules/velocity-animate/velocity.js": 4237/*!*************************************************************************************************************************************!*\ 4238 !*** /Applications/XAMPP/xamppfiles/htdocs/gwu-wordpress/wp-content/themes/upup-baseline/node_modules/velocity-animate/velocity.js ***! 4239 \*************************************************************************************************************************************/ 4240/*! no static exports found */ 4241/***/ (function(module, exports, __webpack_require__) { 4242 4243var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! VelocityJS.org (1.5.2). (C) 2014 Julian Shapiro. MIT @license: en.wikipedia.org/wiki/MIT_License */ 4244 4245/************************* 4246 Velocity jQuery Shim 4247 *************************/ 4248 4249/*! VelocityJS.org jQuery Shim (1.0.1). (C) 2014 The jQuery Foundation. MIT @license: en.wikipedia.org/wiki/MIT_License. */ 4250 4251/* This file contains the jQuery functions that Velocity relies on, thereby removing Velocity's dependency on a full copy of jQuery, and allowing it to work in any environment. */ 4252/* These shimmed functions are only used if jQuery isn't present. If both this shim and jQuery are loaded, Velocity defaults to jQuery proper. */ 4253/* Browser support: Using this shim instead of jQuery proper removes support for IE8. */ 4254 4255(function(window) { 4256 "use strict"; 4257 /*************** 4258 Setup 4259 ***************/ 4260 4261 /* If jQuery is already loaded, there's no point in loading this shim. */ 4262 if (window.jQuery) { 4263 return; 4264 } 4265 4266 /* jQuery base. */ 4267 var $ = function(selector, context) { 4268 return new $.fn.init(selector, context); 4269 }; 4270 4271 /******************** 4272 Private Methods 4273 ********************/ 4274 4275 /* jQuery */ 4276 $.isWindow = function(obj) { 4277 /* jshint eqeqeq: false */ 4278 return obj && obj === obj.window; 4279 }; 4280 4281 /* jQuery */ 4282 $.type = function(obj) { 4283 if (!obj) { 4284 return obj + ""; 4285 } 4286 4287 return typeof obj === "object" || typeof obj === "function" ? 4288 class2type[toString.call(obj)] || "object" : 4289 typeof obj; 4290 }; 4291 4292 /* jQuery */ 4293 $.isArray = Array.isArray || function(obj) { 4294 return $.type(obj) === "array"; 4295 }; 4296 4297 /* jQuery */ 4298 function isArraylike(obj) { 4299 var length = obj.length, 4300 type = $.type(obj); 4301 4302 if (type === "function" || $.isWindow(obj)) { 4303 return false; 4304 } 4305 4306 if (obj.nodeType === 1 && length) { 4307 return true; 4308 } 4309 4310 return type === "array" || length === 0 || typeof length === "number" && length > 0 && (length - 1) in obj; 4311 } 4312 4313 /*************** 4314 $ Methods 4315 ***************/ 4316 4317 /* jQuery: Support removed for IE<9. */ 4318 $.isPlainObject = function(obj) { 4319 var key; 4320 4321 if (!obj || $.type(obj) !== "object" || obj.nodeType || $.isWindow(obj)) { 4322 return false; 4323 } 4324 4325 try { 4326 if (obj.constructor && 4327 !hasOwn.call(obj, "constructor") && 4328 !hasOwn.call(obj.constructor.prototype, "isPrototypeOf")) { 4329 return false; 4330 } 4331 } catch (e) { 4332 return false; 4333 } 4334 4335 for (key in obj) { 4336 } 4337 4338 return key === undefined || hasOwn.call(obj, key); 4339 }; 4340 4341 /* jQuery */ 4342 $.each = function(obj, callback, args) { 4343 var value, 4344 i = 0, 4345 length = obj.length, 4346 isArray = isArraylike(obj); 4347 4348 if (args) { 4349 if (isArray) { 4350 for (; i < length; i++) { 4351 value = callback.apply(obj[i], args); 4352 4353 if (value === false) { 4354 break; 4355 } 4356 } 4357 } else { 4358 for (i in obj) { 4359 if (!obj.hasOwnProperty(i)) { 4360 continue; 4361 } 4362 value = callback.apply(obj[i], args); 4363 4364 if (value === false) { 4365 break; 4366 } 4367 } 4368 } 4369 4370 } else { 4371 if (isArray) { 4372 for (; i < length; i++) { 4373 value = callback.call(obj[i], i, obj[i]); 4374 4375 if (value === false) { 4376 break; 4377 } 4378 } 4379 } else { 4380 for (i in obj) { 4381 if (!obj.hasOwnProperty(i)) { 4382 continue; 4383 } 4384 value = callback.call(obj[i], i, obj[i]); 4385 4386 if (value === false) { 4387 break; 4388 } 4389 } 4390 } 4391 } 4392 4393 return obj; 4394 }; 4395 4396 /* Custom */ 4397 $.data = function(node, key, value) { 4398 /* $.getData() */ 4399 if (value === undefined) { 4400 var getId = node[$.expando], 4401 store = getId && cache[getId]; 4402 4403 if (key === undefined) { 4404 return store; 4405 } else if (store) { 4406 if (key in store) { 4407 return store[key]; 4408 } 4409 } 4410 /* $.setData() */ 4411 } else if (key !== undefined) { 4412 var setId = node[$.expando] || (node[$.expando] = ++$.uuid); 4413 4414 cache[setId] = cache[setId] || {}; 4415 cache[setId][key] = value; 4416 4417 return value; 4418 } 4419 }; 4420 4421 /* Custom */ 4422 $.removeData = function(node, keys) { 4423 var id = node[$.expando], 4424 store = id && cache[id]; 4425 4426 if (store) { 4427 // Cleanup the entire store if no keys are provided. 4428 if (!keys) { 4429 delete cache[id]; 4430 } else { 4431 $.each(keys, function(_, key) { 4432 delete store[key]; 4433 }); 4434 } 4435 } 4436 }; 4437 4438 /* jQuery */ 4439 $.extend = function() { 4440 var src, copyIsArray, copy, name, options, clone, 4441 target = arguments[0] || {}, 4442 i = 1, 4443 length = arguments.length, 4444 deep = false; 4445 4446 if (typeof target === "boolean") { 4447 deep = target; 4448 4449 target = arguments[i] || {}; 4450 i++; 4451 } 4452 4453 if (typeof target !== "object" && $.type(target) !== "function") { 4454 target = {}; 4455 } 4456 4457 if (i === length) { 4458 target = this; 4459 i--; 4460 } 4461 4462 for (; i < length; i++) { 4463 if ((options = arguments[i])) { 4464 for (name in options) { 4465 if (!options.hasOwnProperty(name)) { 4466 continue; 4467 } 4468 src = target[name]; 4469 copy = options[name]; 4470 4471 if (target === copy) { 4472 continue; 4473 } 4474 4475 if (deep && copy && ($.isPlainObject(copy) || (copyIsArray = $.isArray(copy)))) { 4476 if (copyIsArray) { 4477 copyIsArray = false; 4478 clone = src && $.isArray(src) ? src : []; 4479 4480 } else { 4481 clone = src && $.isPlainObject(src) ? src : {}; 4482 } 4483 4484 target[name] = $.extend(deep, clone, copy); 4485 4486 } else if (copy !== undefined) { 4487 target[name] = copy; 4488 } 4489 } 4490 } 4491 } 4492 4493 return target; 4494 }; 4495 4496 /* jQuery 1.4.3 */ 4497 $.queue = function(elem, type, data) { 4498 function $makeArray(arr, results) { 4499 var ret = results || []; 4500 4501 if (arr) { 4502 if (isArraylike(Object(arr))) { 4503 /* $.merge */ 4504 (function(first, second) { 4505 var len = +second.length, 4506 j = 0, 4507 i = first.length; 4508 4509 while (j < len) { 4510 first[i++] = second[j++]; 4511 } 4512 4513 if (len !== len) { 4514 while (second[j] !== undefined) { 4515 first[i++] = second[j++]; 4516 } 4517 } 4518 4519 first.length = i; 4520 4521 return first; 4522 })(ret, typeof arr === "string" ? [arr] : arr); 4523 } else { 4524 [].push.call(ret, arr); 4525 } 4526 } 4527 4528 return ret; 4529 } 4530 4531 if (!elem) { 4532 return; 4533 } 4534 4535 type = (type || "fx") + "queue"; 4536 4537 var q = $.data(elem, type); 4538 4539 if (!data) { 4540 return q || []; 4541 } 4542 4543 if (!q || $.isArray(data)) { 4544 q = $.data(elem, type, $makeArray(data)); 4545 } else { 4546 q.push(data); 4547 } 4548 4549 return q; 4550 }; 4551 4552 /* jQuery 1.4.3 */ 4553 $.dequeue = function(elems, type) { 4554 /* Custom: Embed element iteration. */ 4555 $.each(elems.nodeType ? [elems] : elems, function(i, elem) { 4556 type = type || "fx"; 4557 4558 var queue = $.queue(elem, type), 4559 fn = queue.shift(); 4560 4561 if (fn === "inprogress") { 4562 fn = queue.shift(); 4563 } 4564 4565 if (fn) { 4566 if (type === "fx") { 4567 queue.unshift("inprogress"); 4568 } 4569 4570 fn.call(elem, function() { 4571 $.dequeue(elem, type); 4572 }); 4573 } 4574 }); 4575 }; 4576 4577 /****************** 4578 $.fn Methods 4579 ******************/ 4580 4581 /* jQuery */ 4582 $.fn = $.prototype = { 4583 init: function(selector) { 4584 /* Just return the element wrapped inside an array; don't proceed with the actual jQuery node wrapping process. */ 4585 if (selector.nodeType) { 4586 this[0] = selector; 4587 4588 return this; 4589 } else { 4590 throw new Error("Not a DOM node."); 4591 } 4592 }, 4593 offset: function() { 4594 /* jQuery altered code: Dropped disconnected DOM node checking. */ 4595 var box = this[0].getBoundingClientRect ? this[0].getBoundingClientRect() : {top: 0, left: 0}; 4596 4597 return { 4598 top: box.top + (window.pageYOffset || document.scrollTop || 0) - (document.clientTop || 0), 4599 left: box.left + (window.pageXOffset || document.scrollLeft || 0) - (document.clientLeft || 0) 4600 }; 4601 }, 4602 position: function() { 4603 /* jQuery */ 4604 function offsetParentFn(elem) { 4605 var offsetParent = elem.offsetParent; 4606 4607 while (offsetParent && (offsetParent.nodeName.toLowerCase() !== "html" && offsetParent.style && offsetParent.style.position.toLowerCase() === "static")) { 4608 offsetParent = offsetParent.offsetParent; 4609 } 4610 4611 return offsetParent || document; 4612 } 4613 4614 /* Zepto */ 4615 var elem = this[0], 4616 offsetParent = offsetParentFn(elem), 4617 offset = this.offset(), 4618 parentOffset = /^(?:body|html)$/i.test(offsetParent.nodeName) ? {top: 0, left: 0} : $(offsetParent).offset(); 4619 4620 offset.top -= parseFloat(elem.style.marginTop) || 0; 4621 offset.left -= parseFloat(elem.style.marginLeft) || 0; 4622 4623 if (offsetParent.style) { 4624 parentOffset.top += parseFloat(offsetParent.style.borderTopWidth) || 0; 4625 parentOffset.left += parseFloat(offsetParent.style.borderLeftWidth) || 0; 4626 } 4627 4628 return { 4629 top: offset.top - parentOffset.top, 4630 left: offset.left - parentOffset.left 4631 }; 4632 } 4633 }; 4634 4635 /********************** 4636 Private Variables 4637 **********************/ 4638 4639 /* For $.data() */ 4640 var cache = {}; 4641 $.expando = "velocity" + (new Date().getTime()); 4642 $.uuid = 0; 4643 4644 /* For $.queue() */ 4645 var class2type = {}, 4646 hasOwn = class2type.hasOwnProperty, 4647 toString = class2type.toString; 4648 4649 var types = "Boolean Number String Function Array Date RegExp Object Error".split(" "); 4650 for (var i = 0; i < types.length; i++) { 4651 class2type["[object " + types[i] + "]"] = types[i].toLowerCase(); 4652 } 4653 4654 /* Makes $(node) possible, without having to call init. */ 4655 $.fn.init.prototype = $.fn; 4656 4657 /* Globalize Velocity onto the window, and assign its Utilities property. */ 4658 window.Velocity = {Utilities: $}; 4659})(window); 4660 4661/****************** 4662 Velocity.js 4663 ******************/ 4664 4665(function(factory) { 4666 "use strict"; 4667 /* CommonJS module. */ 4668 if ( true && typeof module.exports === "object") { 4669 module.exports = factory(); 4670 /* AMD module. */ 4671 } else if (true) { 4672 !(__WEBPACK_AMD_DEFINE_FACTORY__ = (factory), 4673 __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? 4674 (__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) : 4675 __WEBPACK_AMD_DEFINE_FACTORY__), 4676 __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); 4677 /* Browser globals. */ 4678 } else {} 4679}(function() { 4680 "use strict"; 4681 return function(global, window, document, undefined) { 4682 4683 /*************** 4684 Summary 4685 ***************/ 4686 4687 /* 4688 - CSS: CSS stack that works independently from the rest of Velocity. 4689 - animate(): Core animation method that iterates over the targeted elements and queues the incoming call onto each element individually. 4690 - Pre-Queueing: Prepare the element for animation by instantiating its data cache and processing the call's options. 4691 - Queueing: The logic that runs once the call has reached its point of execution in the element's $.queue() stack. 4692 Most logic is placed here to avoid risking it becoming stale (if the element's properties have changed). 4693 - Pushing: Consolidation of the tween data followed by its push onto the global in-progress calls container. 4694 - tick(): The single requestAnimationFrame loop responsible for tweening all in-progress calls. 4695 - completeCall(): Handles the cleanup process for each Velocity call. 4696 */ 4697 4698 /********************* 4699 Helper Functions 4700 *********************/ 4701 4702 /* IE detection. Gist: https://gist.github.com/julianshapiro/9098609 */ 4703 var IE = (function() { 4704 if (document.documentMode) { 4705 return document.documentMode; 4706 } else { 4707 for (var i = 7; i > 4; i--) { 4708 var div = document.createElement("div"); 4709 4710 div.innerHTML = "<!--[if IE " + i + "]><span></span><![endif]-->"; 4711 4712 if (div.getElementsByTagName("span").length) { 4713 div = null; 4714 4715 return i; 4716 } 4717 } 4718 } 4719 4720 return undefined; 4721 })(); 4722 4723 /* rAF shim. Gist: https://gist.github.com/julianshapiro/9497513 */ 4724 var rAFShim = (function() { 4725 var timeLast = 0; 4726 4727 return window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) { 4728 var timeCurrent = (new Date()).getTime(), 4729 timeDelta; 4730 4731 /* Dynamically set delay on a per-tick basis to match 60fps. */ 4732 /* Technique by Erik Moller. MIT license: https://gist.github.com/paulirish/1579671 */ 4733 timeDelta = Math.max(0, 16 - (timeCurrent - timeLast)); 4734 timeLast = timeCurrent + timeDelta; 4735 4736 return setTimeout(function() { 4737 callback(timeCurrent + timeDelta); 4738 }, timeDelta); 4739 }; 4740 })(); 4741 4742 var performance = (function() { 4743 var perf = window.performance || {}; 4744 4745 if (typeof perf.now !== "function") { 4746 var nowOffset = perf.timing && perf.timing.navigationStart ? perf.timing.navigationStart : (new Date()).getTime(); 4747 4748 perf.now = function() { 4749 return (new Date()).getTime() - nowOffset; 4750 }; 4751 } 4752 return perf; 4753 })(); 4754 4755 /* Array compacting. Copyright Lo-Dash. MIT License: https://github.com/lodash/lodash/blob/master/LICENSE.txt */ 4756 function compactSparseArray(array) { 4757 var index = -1, 4758 length = array ? array.length : 0, 4759 result = []; 4760 4761 while (++index < length) { 4762 var value = array[index]; 4763 4764 if (value) { 4765 result.push(value); 4766 } 4767 } 4768 4769 return result; 4770 } 4771 4772 /** 4773 * Shim for "fixing" IE's lack of support (IE < 9) for applying slice 4774 * on host objects like NamedNodeMap, NodeList, and HTMLCollection 4775 * (technically, since host objects have been implementation-dependent, 4776 * at least before ES2015, IE hasn't needed to work this way). 4777 * Also works on strings, fixes IE < 9 to allow an explicit undefined 4778 * for the 2nd argument (as in Firefox), and prevents errors when 4779 * called on other DOM objects. 4780 */ 4781 var _slice = (function() { 4782 var slice = Array.prototype.slice; 4783 4784 try { 4785 // Can't be used with DOM elements in IE < 9 4786 slice.call(document.documentElement); 4787 return slice; 4788 } catch (e) { // Fails in IE < 9 4789 4790 // This will work for genuine arrays, array-like objects, 4791 // NamedNodeMap (attributes, entities, notations), 4792 // NodeList (e.g., getElementsByTagName), HTMLCollection (e.g., childNodes), 4793 // and will not fail on other DOM objects (as do DOM elements in IE < 9) 4794 return function(begin, end) { 4795 var len = this.length; 4796 4797 if (typeof begin !== "number") { 4798 begin = 0; 4799 } 4800 // IE < 9 gets unhappy with an undefined end argument 4801 if (typeof end !== "number") { 4802 end = len; 4803 } 4804 // For native Array objects, we use the native slice function 4805 if (this.slice) { 4806 return slice.call(this, begin, end); 4807 } 4808 // For array like object we handle it ourselves. 4809 var i, 4810 cloned = [], 4811 // Handle negative value for "begin" 4812 start = (begin >= 0) ? begin : Math.max(0, len + begin), 4813 // Handle negative value for "end" 4814 upTo = end < 0 ? len + end : Math.min(end, len), 4815 // Actual expected size of the slice 4816 size = upTo - start; 4817 4818 if (size > 0) { 4819 cloned = new Array(size); 4820 if (this.charAt) { 4821 for (i = 0; i < size; i++) { 4822 cloned[i] = this.charAt(start + i); 4823 } 4824 } else { 4825 for (i = 0; i < size; i++) { 4826 cloned[i] = this[start + i]; 4827 } 4828 } 4829 } 4830 return cloned; 4831 }; 4832 } 4833 })(); 4834 4835 /* .indexOf doesn't exist in IE<9 */ 4836 var _inArray = (function() { 4837 if (Array.prototype.includes) { 4838 return function(arr, val) { 4839 return arr.includes(val); 4840 }; 4841 } 4842 if (Array.prototype.indexOf) { 4843 return function(arr, val) { 4844 return arr.indexOf(val) >= 0; 4845 }; 4846 } 4847 return function(arr, val) { 4848 for (var i = 0; i < arr.length; i++) { 4849 if (arr[i] === val) { 4850 return true; 4851 } 4852 } 4853 return false; 4854 }; 4855 }); 4856 4857 function sanitizeElements(elements) { 4858 /* Unwrap jQuery/Zepto objects. */ 4859 if (Type.isWrapped(elements)) { 4860 elements = _slice.call(elements); 4861 /* Wrap a single element in an array so that $.each() can iterate with the element instead of its node's children. */ 4862 } else if (Type.isNode(elements)) { 4863 elements = [elements]; 4864 } 4865 4866 return elements; 4867 } 4868 4869 var Type = { 4870 isNumber: function(variable) { 4871 return (typeof variable === "number"); 4872 }, 4873 isString: function(variable) { 4874 return (typeof variable === "string"); 4875 }, 4876 isArray: Array.isArray || function(variable) { 4877 return Object.prototype.toString.call(variable) === "[object Array]"; 4878 }, 4879 isFunction: function(variable) { 4880 return Object.prototype.toString.call(variable) === "[object Function]"; 4881 }, 4882 isNode: function(variable) { 4883 return variable && variable.nodeType; 4884 }, 4885 /* Determine if variable is an array-like wrapped jQuery, Zepto or similar element, or even a NodeList etc. */ 4886 /* NOTE: HTMLFormElements also have a length. */ 4887 isWrapped: function(variable) { 4888 return variable 4889 && variable !== window 4890 && Type.isNumber(variable.length) 4891 && !Type.isString(variable) 4892 && !Type.isFunction(variable) 4893 && !Type.isNode(variable) 4894 && (variable.length === 0 || Type.isNode(variable[0])); 4895 }, 4896 isSVG: function(variable) { 4897 return window.SVGElement && (variable instanceof window.SVGElement); 4898 }, 4899 isEmptyObject: function(variable) { 4900 for (var name in variable) { 4901 if (variable.hasOwnProperty(name)) { 4902 return false; 4903 } 4904 } 4905 4906 return true; 4907 } 4908 }; 4909 4910 /***************** 4911 Dependencies 4912 *****************/ 4913 4914 var $, 4915 isJQuery = false; 4916 4917 if (global.fn && global.fn.jquery) { 4918 $ = global; 4919 isJQuery = true; 4920 } else { 4921 $ = window.Velocity.Utilities; 4922 } 4923 4924 if (IE <= 8 && !isJQuery) { 4925 throw new Error("Velocity: IE8 and below require jQuery to be loaded before Velocity."); 4926 } else if (IE <= 7) { 4927 /* Revert to jQuery's $.animate(), and lose Velocity's extra features. */ 4928 jQuery.fn.velocity = jQuery.fn.animate; 4929 4930 /* Now that $.fn.velocity is aliased, abort this Velocity declaration. */ 4931 return; 4932 } 4933 4934 /***************** 4935 Constants 4936 *****************/ 4937 4938 var DURATION_DEFAULT = 400, 4939 EASING_DEFAULT = "swing"; 4940 4941 /************* 4942 State 4943 *************/ 4944 4945 var Velocity = { 4946 /* Container for page-wide Velocity state data. */ 4947 State: { 4948 /* Detect mobile devices to determine if mobileHA should be turned on. */ 4949 isMobile: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(window.navigator.userAgent), 4950 /* The mobileHA option's behavior changes on older Android devices (Gingerbread, versions 2.3.3-2.3.7). */ 4951 isAndroid: /Android/i.test(window.navigator.userAgent), 4952 isGingerbread: /Android 2\.3\.[3-7]/i.test(window.navigator.userAgent), 4953 isChrome: window.chrome, 4954 isFirefox: /Firefox/i.test(window.navigator.userAgent), 4955 /* Create a cached element for re-use when checking for CSS property prefixes. */ 4956 prefixElement: document.createElement("div"), 4957 /* Cache every prefix match to avoid repeating lookups. */ 4958 prefixMatches: {}, 4959 /* Cache the anchor used for animating window scrolling. */ 4960 scrollAnchor: null, 4961 /* Cache the browser-specific property names associated with the scroll anchor. */ 4962 scrollPropertyLeft: null, 4963 scrollPropertyTop: null, 4964 /* Keep track of whether our RAF tick is running. */ 4965 isTicking: false, 4966 /* Container for every in-progress call to Velocity. */ 4967 calls: [], 4968 delayedElements: { 4969 count: 0 4970 } 4971 }, 4972 /* Velocity's custom CSS stack. Made global for unit testing. */ 4973 CSS: {/* Defined below. */}, 4974 /* A shim of the jQuery utility functions used by Velocity -- provided by Velocity's optional jQuery shim. */ 4975 Utilities: $, 4976 /* Container for the user's custom animation redirects that are referenced by name in place of the properties map argument. */ 4977 Redirects: {/* Manually registered by the user. */}, 4978 Easings: {/* Defined below. */}, 4979 /* Attempt to use ES6 Promises by default. Users can override this with a third-party promises library. */ 4980 Promise: window.Promise, 4981 /* Velocity option defaults, which can be overriden by the user. */ 4982 defaults: { 4983 queue: "", 4984 duration: DURATION_DEFAULT, 4985 easing: EASING_DEFAULT, 4986 begin: undefined, 4987 complete: undefined, 4988 progress: undefined, 4989 display: undefined, 4990 visibility: undefined, 4991 loop: false, 4992 delay: false, 4993 mobileHA: true, 4994 /* Advanced: Set to false to prevent property values from being cached between consecutive Velocity-initiated chain calls. */ 4995 _cacheValues: true, 4996 /* Advanced: Set to false if the promise should always resolve on empty element lists. */ 4997 promiseRejectEmpty: true 4998 }, 4999 /* A design goal of Velocity is to cache data wherever possible in order to avoid DOM requerying. Accordingly, each element has a data cache. */ 5000 init: function(element) { 5001 $.data(element, "velocity", { 5002 /* Store whether this is an SVG element, since its properties are retrieved and updated differently than standard HTML elements. */ 5003 isSVG: Type.isSVG(element), 5004 /* Keep track of whether the element is currently being animated by Velocity. 5005 This is used to ensure that property values are not transferred between non-consecutive (stale) calls. */ 5006 isAnimating: false, 5007 /* A reference to the element's live computedStyle object. Learn more here: https://developer.mozilla.org/en/docs/Web/API/window.getComputedStyle */ 5008 computedStyle: null, 5009 /* Tween data is cached for each animation on the element so that data can be passed across calls -- 5010 in particular, end values are used as subsequent start values in consecutive Velocity calls. */ 5011 tweensContainer: null, 5012 /* The full root property values of each CSS hook being animated on this element are cached so that: 5013 1) Concurrently-animating hooks sharing the same root can have their root values' merged into one while tweening. 5014 2) Post-hook-injection root values can be transferred over to consecutively chained Velocity calls as starting root values. */ 5015 rootPropertyValueCache: {}, 5016 /* A cache for transform updates, which must be manually flushed via CSS.flushTransformCache(). */ 5017 transformCache: {} 5018 }); 5019 }, 5020 /* A parallel to jQuery's $.css(), used for getting/setting Velocity's hooked CSS properties. */ 5021 hook: null, /* Defined below. */ 5022 /* Velocity-wide animation time remapping for testing purposes. */ 5023 mock: false, 5024 version: {major: 1, minor: 5, patch: 2}, 5025 /* Set to 1 or 2 (most verbose) to output debug info to console. */ 5026 debug: false, 5027 /* Use rAF high resolution timestamp when available */ 5028 timestamp: true, 5029 /* Pause all animations */ 5030 pauseAll: function(queueName) { 5031 var currentTime = (new Date()).getTime(); 5032 5033 $.each(Velocity.State.calls, function(i, activeCall) { 5034 5035 if (activeCall) { 5036 5037 /* If we have a queueName and this call is not on that queue, skip */ 5038 if (queueName !== undefined && ((activeCall[2].queue !== queueName) || (activeCall[2].queue === false))) { 5039 return true; 5040 } 5041 5042 /* Set call to paused */ 5043 activeCall[5] = { 5044 resume: false 5045 }; 5046 } 5047 }); 5048 5049 /* Pause timers on any currently delayed calls */ 5050 $.each(Velocity.State.delayedElements, function(k, element) { 5051 if (!element) { 5052 return; 5053 } 5054 pauseDelayOnElement(element, currentTime); 5055 }); 5056 }, 5057 /* Resume all animations */ 5058 resumeAll: function(queueName) { 5059 var currentTime = (new Date()).getTime(); 5060 5061 $.each(Velocity.State.calls, function(i, activeCall) { 5062 5063 if (activeCall) { 5064 5065 /* If we have a queueName and this call is not on that queue, skip */ 5066 if (queueName !== undefined && ((activeCall[2].queue !== queueName) || (activeCall[2].queue === false))) { 5067 return true; 5068 } 5069 5070 /* Set call to resumed if it was paused */ 5071 if (activeCall[5]) { 5072 activeCall[5].resume = true; 5073 } 5074 } 5075 }); 5076 /* Resume timers on any currently delayed calls */ 5077 $.each(Velocity.State.delayedElements, function(k, element) { 5078 if (!element) { 5079 return; 5080 } 5081 resumeDelayOnElement(element, currentTime); 5082 }); 5083 } 5084 }; 5085 5086 /* Retrieve the appropriate scroll anchor and property name for the browser: https://developer.mozilla.org/en-US/docs/Web/API/Window.scrollY */ 5087 if (window.pageYOffset !== undefined) { 5088 Velocity.State.scrollAnchor = window; 5089 Velocity.State.scrollPropertyLeft = "pageXOffset"; 5090 Velocity.State.scrollPropertyTop = "pageYOffset"; 5091 } else { 5092 Velocity.State.scrollAnchor = document.documentElement || document.body.parentNode || document.body; 5093 Velocity.State.scrollPropertyLeft = "scrollLeft"; 5094 Velocity.State.scrollPropertyTop = "scrollTop"; 5095 } 5096 5097 /* Shorthand alias for jQuery's $.data() utility. */ 5098 function Data(element) { 5099 /* Hardcode a reference to the plugin name. */ 5100 var response = $.data(element, "velocity"); 5101 5102 /* jQuery <=1.4.2 returns null instead of undefined when no match is found. We normalize this behavior. */ 5103 return response === null ? undefined : response; 5104 } 5105 5106 /************** 5107 Delay Timer 5108 **************/ 5109 5110 function pauseDelayOnElement(element, currentTime) { 5111 /* Check for any delay timers, and pause the set timeouts (while preserving time data) 5112 to be resumed when the "resume" command is issued */ 5113 var data = Data(element); 5114 if (data && data.delayTimer && !data.delayPaused) { 5115 data.delayRemaining = data.delay - currentTime + data.delayBegin; 5116 data.delayPaused = true; 5117 clearTimeout(data.delayTimer.setTimeout); 5118 } 5119 } 5120 5121 function resumeDelayOnElement(element, currentTime) { 5122 /* Check for any paused timers and resume */ 5123 var data = Data(element); 5124 if (data && data.delayTimer && data.delayPaused) { 5125 /* If the element was mid-delay, re initiate the timeout with the remaining delay */ 5126 data.delayPaused = false; 5127 data.delayTimer.setTimeout = setTimeout(data.delayTimer.next, data.delayRemaining); 5128 } 5129 } 5130 5131 5132 5133 /************** 5134 Easing 5135 **************/ 5136 5137 /* Step easing generator. */ 5138 function generateStep(steps) { 5139 return function(p) { 5140 return Math.round(p * steps) * (1 / steps); 5141 }; 5142 } 5143 5144 /* Bezier curve function generator. Copyright Gaetan Renaudeau. MIT License: http://en.wikipedia.org/wiki/MIT_License */ 5145 function generateBezier(mX1, mY1, mX2, mY2) { 5146 var NEWTON_ITERATIONS = 4, 5147 NEWTON_MIN_SLOPE = 0.001, 5148 SUBDIVISION_PRECISION = 0.0000001, 5149 SUBDIVISION_MAX_ITERATIONS = 10, 5150 kSplineTableSize = 11, 5151 kSampleStepSize = 1.0 / (kSplineTableSize - 1.0), 5152 float32ArraySupported = "Float32Array" in window; 5153 5154 /* Must contain four arguments. */ 5155 if (arguments.length !== 4) { 5156 return false; 5157 } 5158 5159 /* Arguments must be numbers. */ 5160 for (var i = 0; i < 4; ++i) { 5161 if (typeof arguments[i] !== "number" || isNaN(arguments[i]) || !isFinite(arguments[i])) { 5162 return false; 5163 } 5164 } 5165 5166 /* X values must be in the [0, 1] range. */ 5167 mX1 = Math.min(mX1, 1); 5168 mX2 = Math.min(mX2, 1); 5169 mX1 = Math.max(mX1, 0); 5170 mX2 = Math.max(mX2, 0); 5171 5172 var mSampleValues = float32ArraySupported ? new Float32Array(kSplineTableSize) : new Array(kSplineTableSize); 5173 5174 function A(aA1, aA2) { 5175 return 1.0 - 3.0 * aA2 + 3.0 * aA1; 5176 } 5177 function B(aA1, aA2) { 5178 return 3.0 * aA2 - 6.0 * aA1; 5179 } 5180 function C(aA1) { 5181 return 3.0 * aA1; 5182 } 5183 5184 function calcBezier(aT, aA1, aA2) { 5185 return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT; 5186 } 5187 5188 function getSlope(aT, aA1, aA2) { 5189 return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1); 5190 } 5191 5192 function newtonRaphsonIterate(aX, aGuessT) { 5193 for (var i = 0; i < NEWTON_ITERATIONS; ++i) { 5194 var currentSlope = getSlope(aGuessT, mX1, mX2); 5195 5196 if (currentSlope === 0.0) { 5197 return aGuessT; 5198 } 5199 5200 var currentX = calcBezier(aGuessT, mX1, mX2) - aX; 5201 aGuessT -= currentX / currentSlope; 5202 } 5203 5204 return aGuessT; 5205 } 5206 5207 function calcSampleValues() { 5208 for (var i = 0; i < kSplineTableSize; ++i) { 5209 mSampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2); 5210 } 5211 } 5212 5213 function binarySubdivide(aX, aA, aB) { 5214 var currentX, currentT, i = 0; 5215 5216 do { 5217 currentT = aA + (aB - aA) / 2.0; 5218 currentX = calcBezier(currentT, mX1, mX2) - aX; 5219 if (currentX > 0.0) { 5220 aB = currentT; 5221 } else { 5222 aA = currentT; 5223 } 5224 } while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS); 5225 5226 return currentT; 5227 } 5228 5229 function getTForX(aX) { 5230 var intervalStart = 0.0, 5231 currentSample = 1, 5232 lastSample = kSplineTableSize - 1; 5233 5234 for (; currentSample !== lastSample && mSampleValues[currentSample] <= aX; ++currentSample) { 5235 intervalStart += kSampleStepSize; 5236 } 5237 5238 --currentSample; 5239 5240 var dist = (aX - mSampleValues[currentSample]) / (mSampleValues[currentSample + 1] - mSampleValues[currentSample]), 5241 guessForT = intervalStart + dist * kSampleStepSize, 5242 initialSlope = getSlope(guessForT, mX1, mX2); 5243 5244 if (initialSlope >= NEWTON_MIN_SLOPE) { 5245 return newtonRaphsonIterate(aX, guessForT); 5246 } else if (initialSlope === 0.0) { 5247 return guessForT; 5248 } else { 5249 return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize); 5250 } 5251 } 5252 5253 var _precomputed = false; 5254 5255 function precompute() { 5256 _precomputed = true; 5257 if (mX1 !== mY1 || mX2 !== mY2) { 5258 calcSampleValues(); 5259 } 5260 } 5261 5262 var f = function(aX) { 5263 if (!_precomputed) { 5264 precompute(); 5265 } 5266 if (mX1 === mY1 && mX2 === mY2) { 5267 return aX; 5268 } 5269 if (aX === 0) { 5270 return 0; 5271 } 5272 if (aX === 1) { 5273 return 1; 5274 } 5275 5276 return calcBezier(getTForX(aX), mY1, mY2); 5277 }; 5278 5279 f.getControlPoints = function() { 5280 return [{x: mX1, y: mY1}, {x: mX2, y: mY2}]; 5281 }; 5282 5283 var str = "generateBezier(" + [mX1, mY1, mX2, mY2] + ")"; 5284 f.toString = function() { 5285 return str; 5286 }; 5287 5288 return f; 5289 } 5290 5291 /* Runge-Kutta spring physics function generator. Adapted from Framer.js, copyright Koen Bok. MIT License: http://en.wikipedia.org/wiki/MIT_License */ 5292 /* Given a tension, friction, and duration, a simulation at 60FPS will first run without a defined duration in order to calculate the full path. A second pass 5293 then adjusts the time delta -- using the relation between actual time and duration -- to calculate the path for the duration-constrained animation. */ 5294 var generateSpringRK4 = (function() { 5295 function springAccelerationForState(state) { 5296 return (-state.tension * state.x) - (state.friction * state.v); 5297 } 5298 5299 function springEvaluateStateWithDerivative(initialState, dt, derivative) { 5300 var state = { 5301 x: initialState.x + derivative.dx * dt, 5302 v: initialState.v + derivative.dv * dt, 5303 tension: initialState.tension, 5304 friction: initialState.friction 5305 }; 5306 5307 return {dx: state.v, dv: springAccelerationForState(state)}; 5308 } 5309 5310 function springIntegrateState(state, dt) { 5311 var a = { 5312 dx: state.v, 5313 dv: springAccelerationForState(state) 5314 }, 5315 b = springEvaluateStateWithDerivative(state, dt * 0.5, a), 5316 c = springEvaluateStateWithDerivative(state, dt * 0.5, b), 5317 d = springEvaluateStateWithDerivative(state, dt, c), 5318 dxdt = 1.0 / 6.0 * (a.dx + 2.0 * (b.dx + c.dx) + d.dx), 5319 dvdt = 1.0 / 6.0 * (a.dv + 2.0 * (b.dv + c.dv) + d.dv); 5320 5321 state.x = state.x + dxdt * dt; 5322 state.v = state.v + dvdt * dt; 5323 5324 return state; 5325 } 5326 5327 return function springRK4Factory(tension, friction, duration) { 5328 5329 var initState = { 5330 x: -1, 5331 v: 0, 5332 tension: null, 5333 friction: null 5334 }, 5335 path = [0], 5336 time_lapsed = 0, 5337 tolerance = 1 / 10000, 5338 DT = 16 / 1000, 5339 have_duration, dt, last_state; 5340 5341 tension = parseFloat(tension) || 500; 5342 friction = parseFloat(friction) || 20; 5343 duration = duration || null; 5344 5345 initState.tension = tension; 5346 initState.friction = friction; 5347 5348 have_duration = duration !== null; 5349 5350 /* Calculate the actual time it takes for this animation to complete with the provided conditions. */ 5351 if (have_duration) { 5352 /* Run the simulation without a duration. */ 5353 time_lapsed = springRK4Factory(tension, friction); 5354 /* Compute the adjusted time delta. */ 5355 dt = time_lapsed / duration * DT; 5356 } else { 5357 dt = DT; 5358 } 5359 5360 while (true) { 5361 /* Next/step function .*/ 5362 last_state = springIntegrateState(last_state || initState, dt); 5363 /* Store the position. */ 5364 path.push(1 + last_state.x); 5365 time_lapsed += 16; 5366 /* If the change threshold is reached, break. */ 5367 if (!(Math.abs(last_state.x) > tolerance && Math.abs(last_state.v) > tolerance)) { 5368 break; 5369 } 5370 } 5371 5372 /* If duration is not defined, return the actual time required for completing this animation. Otherwise, return a closure that holds the 5373 computed path and returns a snapshot of the position according to a given percentComplete. */ 5374 return !have_duration ? time_lapsed : function(percentComplete) { 5375 return path[ (percentComplete * (path.length - 1)) | 0 ]; 5376 }; 5377 }; 5378 }()); 5379 5380 /* jQuery easings. */ 5381 Velocity.Easings = { 5382 linear: function(p) { 5383 return p; 5384 }, 5385 swing: function(p) { 5386 return 0.5 - Math.cos(p * Math.PI) / 2; 5387 }, 5388 /* Bonus "spring" easing, which is a less exaggerated version of easeInOutElastic. */ 5389 spring: function(p) { 5390 return 1 - (Math.cos(p * 4.5 * Math.PI) * Math.exp(-p * 6)); 5391 } 5392 }; 5393 5394 /* CSS3 and Robert Penner easings. */ 5395 $.each( 5396 [ 5397 ["ease", [0.25, 0.1, 0.25, 1.0]], 5398 ["ease-in", [0.42, 0.0, 1.00, 1.0]], 5399 ["ease-out", [0.00, 0.0, 0.58, 1.0]], 5400 ["ease-in-out", [0.42, 0.0, 0.58, 1.0]], 5401 ["easeInSine", [0.47, 0, 0.745, 0.715]], 5402 ["easeOutSine", [0.39, 0.575, 0.565, 1]], 5403 ["easeInOutSine", [0.445, 0.05, 0.55, 0.95]], 5404 ["easeInQuad", [0.55, 0.085, 0.68, 0.53]], 5405 ["easeOutQuad", [0.25, 0.46, 0.45, 0.94]], 5406 ["easeInOutQuad", [0.455, 0.03, 0.515, 0.955]], 5407 ["easeInCubic", [0.55, 0.055, 0.675, 0.19]], 5408 ["easeOutCubic", [0.215, 0.61, 0.355, 1]], 5409 ["easeInOutCubic", [0.645, 0.045, 0.355, 1]], 5410 ["easeInQuart", [0.895, 0.03, 0.685, 0.22]], 5411 ["easeOutQuart", [0.165, 0.84, 0.44, 1]], 5412 ["easeInOutQuart", [0.77, 0, 0.175, 1]], 5413 ["easeInQuint", [0.755, 0.05, 0.855, 0.06]], 5414 ["easeOutQuint", [0.23, 1, 0.32, 1]], 5415 ["easeInOutQuint", [0.86, 0, 0.07, 1]], 5416 ["easeInExpo", [0.95, 0.05, 0.795, 0.035]], 5417 ["easeOutExpo", [0.19, 1, 0.22, 1]], 5418 ["easeInOutExpo", [1, 0, 0, 1]], 5419 ["easeInCirc", [0.6, 0.04, 0.98, 0.335]], 5420 ["easeOutCirc", [0.075, 0.82, 0.165, 1]], 5421 ["easeInOutCirc", [0.785, 0.135, 0.15, 0.86]] 5422 ], function(i, easingArray) { 5423 Velocity.Easings[easingArray[0]] = generateBezier.apply(null, easingArray[1]); 5424 }); 5425 5426 /* Determine the appropriate easing type given an easing input. */ 5427 function getEasing(value, duration) { 5428 var easing = value; 5429 5430 /* The easing option can either be a string that references a pre-registered easing, 5431 or it can be a two-/four-item array of integers to be converted into a bezier/spring function. */ 5432 if (Type.isString(value)) { 5433 /* Ensure that the easing has been assigned to jQuery's Velocity.Easings object. */ 5434 if (!Velocity.Easings[value]) { 5435 easing = false; 5436 } 5437 } else if (Type.isArray(value) && value.length === 1) { 5438 easing = generateStep.apply(null, value); 5439 } else if (Type.isArray(value) && value.length === 2) { 5440 /* springRK4 must be passed the animation's duration. */ 5441 /* Note: If the springRK4 array contains non-numbers, generateSpringRK4() returns an easing 5442 function generated with default tension and friction values. */ 5443 easing = generateSpringRK4.apply(null, value.concat([duration])); 5444 } else if (Type.isArray(value) && value.length === 4) { 5445 /* Note: If the bezier array contains non-numbers, generateBezier() returns false. */ 5446 easing = generateBezier.apply(null, value); 5447 } else { 5448 easing = false; 5449 } 5450 5451 /* Revert to the Velocity-wide default easing type, or fall back to "swing" (which is also jQuery's default) 5452 if the Velocity-wide default has been incorrectly modified. */ 5453 if (easing === false) { 5454 if (Velocity.Easings[Velocity.defaults.easing]) { 5455 easing = Velocity.defaults.easing; 5456 } else { 5457 easing = EASING_DEFAULT; 5458 } 5459 } 5460 5461 return easing; 5462 } 5463 5464 /***************** 5465 CSS Stack 5466 *****************/ 5467 5468 /* The CSS object is a highly condensed and performant CSS stack that fully replaces jQuery's. 5469 It handles the validation, getting, and setting of both standard CSS properties and CSS property hooks. */ 5470 /* Note: A "CSS" shorthand is aliased so that our code is easier to read. */ 5471 var CSS = Velocity.CSS = { 5472 /************* 5473 RegEx 5474 *************/ 5475 5476 RegEx: { 5477 isHex: /^#([A-f\d]{3}){1,2}$/i, 5478 /* Unwrap a property value's surrounding text, e.g. "rgba(4, 3, 2, 1)" ==> "4, 3, 2, 1" and "rect(4px 3px 2px 1px)" ==> "4px 3px 2px 1px". */ 5479 valueUnwrap: /^[A-z]+\((.*)\)$/i, 5480 wrappedValueAlreadyExtracted: /[0-9.]+ [0-9.]+ [0-9.]+( [0-9.]+)?/, 5481 /* Split a multi-value property into an array of subvalues, e.g. "rgba(4, 3, 2, 1) 4px 3px 2px 1px" ==> [ "rgba(4, 3, 2, 1)", "4px", "3px", "2px", "1px" ]. */ 5482 valueSplit: /([A-z]+\(.+\))|(([A-z0-9#-.]+?)(?=\s|$))/ig 5483 }, 5484 /************ 5485 Lists 5486 ************/ 5487 5488 Lists: { 5489 colors: ["fill", "stroke", "stopColor", "color", "backgroundColor", "borderColor", "borderTopColor", "borderRightColor", "borderBottomColor", "borderLeftColor", "outlineColor"], 5490 transformsBase: ["translateX", "translateY", "scale", "scaleX", "scaleY", "skewX", "skewY", "rotateZ"], 5491 transforms3D: ["transformPerspective", "translateZ", "scaleZ", "rotateX", "rotateY"], 5492 units: [ 5493 "%", // relative 5494 "em", "ex", "ch", "rem", // font relative 5495 "vw", "vh", "vmin", "vmax", // viewport relative 5496 "cm", "mm", "Q", "in", "pc", "pt", "px", // absolute lengths 5497 "deg", "grad", "rad", "turn", // angles 5498 "s", "ms" // time 5499 ], 5500 colorNames: { 5501 "aliceblue": "240,248,255", 5502 "antiquewhite": "250,235,215", 5503 "aquamarine": "127,255,212", 5504 "aqua": "0,255,255", 5505 "azure": "240,255,255", 5506 "beige": "245,245,220", 5507 "bisque": "255,228,196", 5508 "black": "0,0,0", 5509 "blanchedalmond": "255,235,205", 5510 "blueviolet": "138,43,226", 5511 "blue": "0,0,255", 5512 "brown": "165,42,42", 5513 "burlywood": "222,184,135", 5514 "cadetblue": "95,158,160", 5515 "chartreuse": "127,255,0", 5516 "chocolate": "210,105,30", 5517 "coral": "255,127,80", 5518 "cornflowerblue": "100,149,237", 5519 "cornsilk": "255,248,220", 5520 "crimson": "220,20,60", 5521 "cyan": "0,255,255", 5522 "darkblue": "0,0,139", 5523 "darkcyan": "0,139,139", 5524 "darkgoldenrod": "184,134,11", 5525 "darkgray": "169,169,169", 5526 "darkgrey": "169,169,169", 5527 "darkgreen": "0,100,0", 5528 "darkkhaki": "189,183,107", 5529 "darkmagenta": "139,0,139", 5530 "darkolivegreen": "85,107,47", 5531 "darkorange": "255,140,0", 5532 "darkorchid": "153,50,204", 5533 "darkred": "139,0,0", 5534 "darksalmon": "233,150,122", 5535 "darkseagreen": "143,188,143", 5536 "darkslateblue": "72,61,139", 5537 "darkslategray": "47,79,79", 5538 "darkturquoise": "0,206,209", 5539 "darkviolet": "148,0,211", 5540 "deeppink": "255,20,147", 5541 "deepskyblue": "0,191,255", 5542 "dimgray": "105,105,105", 5543 "dimgrey": "105,105,105", 5544 "dodgerblue": "30,144,255", 5545 "firebrick": "178,34,34", 5546 "floralwhite": "255,250,240", 5547 "forestgreen": "34,139,34", 5548 "fuchsia": "255,0,255", 5549 "gainsboro": "220,220,220", 5550 "ghostwhite": "248,248,255", 5551 "gold": "255,215,0", 5552 "goldenrod": "218,165,32", 5553 "gray": "128,128,128", 5554 "grey": "128,128,128", 5555 "greenyellow": "173,255,47", 5556 "green": "0,128,0", 5557 "honeydew": "240,255,240", 5558 "hotpink": "255,105,180", 5559 "indianred": "205,92,92", 5560 "indigo": "75,0,130", 5561 "ivory": "255,255,240", 5562 "khaki": "240,230,140", 5563 "lavenderblush": "255,240,245", 5564 "lavender": "230,230,250", 5565 "lawngreen": "124,252,0", 5566 "lemonchiffon": "255,250,205", 5567 "lightblue": "173,216,230", 5568 "lightcoral": "240,128,128", 5569 "lightcyan": "224,255,255", 5570 "lightgoldenrodyellow": "250,250,210", 5571 "lightgray": "211,211,211", 5572 "lightgrey": "211,211,211", 5573 "lightgreen": "144,238,144", 5574 "lightpink": "255,182,193", 5575 "lightsalmon": "255,160,122", 5576 "lightseagreen": "32,178,170", 5577 "lightskyblue": "135,206,250", 5578 "lightslategray": "119,136,153", 5579 "lightsteelblue": "176,196,222", 5580 "lightyellow": "255,255,224", 5581 "limegreen": "50,205,50", 5582 "lime": "0,255,0", 5583 "linen": "250,240,230", 5584 "magenta": "255,0,255", 5585 "maroon": "128,0,0", 5586 "mediumaquamarine": "102,205,170", 5587 "mediumblue": "0,0,205", 5588 "mediumorchid": "186,85,211", 5589 "mediumpurple": "147,112,219", 5590 "mediumseagreen": "60,179,113", 5591 "mediumslateblue": "123,104,238", 5592 "mediumspringgreen": "0,250,154", 5593 "mediumturquoise": "72,209,204", 5594 "mediumvioletred": "199,21,133", 5595 "midnightblue": "25,25,112", 5596 "mintcream": "245,255,250", 5597 "mistyrose": "255,228,225", 5598 "moccasin": "255,228,181", 5599 "navajowhite": "255,222,173", 5600 "navy": "0,0,128", 5601 "oldlace": "253,245,230", 5602 "olivedrab": "107,142,35", 5603 "olive": "128,128,0", 5604 "orangered": "255,69,0", 5605 "orange": "255,165,0", 5606 "orchid": "218,112,214", 5607 "palegoldenrod": "238,232,170", 5608 "palegreen": "152,251,152", 5609 "paleturquoise": "175,238,238", 5610 "palevioletred": "219,112,147", 5611 "papayawhip": "255,239,213", 5612 "peachpuff": "255,218,185", 5613 "peru": "205,133,63", 5614 "pink": "255,192,203", 5615 "plum": "221,160,221", 5616 "powderblue": "176,224,230", 5617 "purple": "128,0,128", 5618 "red": "255,0,0", 5619 "rosybrown": "188,143,143", 5620 "royalblue": "65,105,225", 5621 "saddlebrown": "139,69,19", 5622 "salmon": "250,128,114", 5623 "sandybrown": "244,164,96", 5624 "seagreen": "46,139,87", 5625 "seashell": "255,245,238", 5626 "sienna": "160,82,45", 5627 "silver": "192,192,192", 5628 "skyblue": "135,206,235", 5629 "slateblue": "106,90,205", 5630 "slategray": "112,128,144", 5631 "snow": "255,250,250", 5632 "springgreen": "0,255,127", 5633 "steelblue": "70,130,180", 5634 "tan": "210,180,140", 5635 "teal": "0,128,128", 5636 "thistle": "216,191,216", 5637 "tomato": "255,99,71", 5638 "turquoise": "64,224,208", 5639 "violet": "238,130,238", 5640 "wheat": "245,222,179", 5641 "whitesmoke": "245,245,245", 5642 "white": "255,255,255", 5643 "yellowgreen": "154,205,50", 5644 "yellow": "255,255,0" 5645 } 5646 }, 5647 /************ 5648 Hooks 5649 ************/ 5650 5651 /* Hooks allow a subproperty (e.g. "boxShadowBlur") of a compound-value CSS property 5652 (e.g. "boxShadow: X Y Blur Spread Color") to be animated as if it were a discrete property. */ 5653 /* Note: Beyond enabling fine-grained property animation, hooking is necessary since Velocity only 5654 tweens properties with single numeric values; unlike CSS transitions, Velocity does not interpolate compound-values. */ 5655 Hooks: { 5656 /******************** 5657 Registration 5658 ********************/ 5659 5660 /* Templates are a concise way of indicating which subproperties must be individually registered for each compound-value CSS property. */ 5661 /* Each template consists of the compound-value's base name, its constituent subproperty names, and those subproperties' default values. */ 5662 templates: { 5663 "textShadow": ["Color X Y Blur", "black 0px 0px 0px"], 5664 "boxShadow": ["Color X Y Blur Spread", "black 0px 0px 0px 0px"], 5665 "clip": ["Top Right Bottom Left", "0px 0px 0px 0px"], 5666 "backgroundPosition": ["X Y", "0% 0%"], 5667 "transformOrigin": ["X Y Z", "50% 50% 0px"], 5668 "perspectiveOrigin": ["X Y", "50% 50%"] 5669 }, 5670 /* A "registered" hook is one that has been converted from its template form into a live, 5671 tweenable property. It contains data to associate it with its root property. */ 5672 registered: { 5673 /* Note: A registered hook looks like this ==> textShadowBlur: [ "textShadow", 3 ], 5674 which consists of the subproperty's name, the associated root property's name, 5675 and the subproperty's position in the root's value. */ 5676 }, 5677 /* Convert the templates into individual hooks then append them to the registered object above. */ 5678 register: function() { 5679 /* Color hooks registration: Colors are defaulted to white -- as opposed to black -- since colors that are 5680 currently set to "transparent" default to their respective template below when color-animated, 5681 and white is typically a closer match to transparent than black is. An exception is made for text ("color"), 5682 which is almost always set closer to black than white. */ 5683 for (var i = 0; i < CSS.Lists.colors.length; i++) { 5684 var rgbComponents = (CSS.Lists.colors[i] === "color") ? "0 0 0 1" : "255 255 255 1"; 5685 CSS.Hooks.templates[CSS.Lists.colors[i]] = ["Red Green Blue Alpha", rgbComponents]; 5686 } 5687 5688 var rootProperty, 5689 hookTemplate, 5690 hookNames; 5691 5692 /* In IE, color values inside compound-value properties are positioned at the end the value instead of at the beginning. 5693 Thus, we re-arrange the templates accordingly. */ 5694 if (IE) { 5695 for (rootProperty in CSS.Hooks.templates) { 5696 if (!CSS.Hooks.templates.hasOwnProperty(rootProperty)) { 5697 continue; 5698 } 5699 hookTemplate = CSS.Hooks.templates[rootProperty]; 5700 hookNames = hookTemplate[0].split(" "); 5701 5702 var defaultValues = hookTemplate[1].match(CSS.RegEx.valueSplit); 5703 5704 if (hookNames[0] === "Color") { 5705 /* Reposition both the hook's name and its default value to the end of their respective strings. */ 5706 hookNames.push(hookNames.shift()); 5707 defaultValues.push(defaultValues.shift()); 5708 5709 /* Replace the existing template for the hook's root property. */ 5710 CSS.Hooks.templates[rootProperty] = [hookNames.join(" "), defaultValues.join(" ")]; 5711 } 5712 } 5713 } 5714 5715 /* Hook registration. */ 5716 for (rootProperty in CSS.Hooks.templates) { 5717 if (!CSS.Hooks.templates.hasOwnProperty(rootProperty)) { 5718 continue; 5719 } 5720 hookTemplate = CSS.Hooks.templates[rootProperty]; 5721 hookNames = hookTemplate[0].split(" "); 5722 5723 for (var j in hookNames) { 5724 if (!hookNames.hasOwnProperty(j)) { 5725 continue; 5726 } 5727 var fullHookName = rootProperty + hookNames[j], 5728 hookPosition = j; 5729 5730 /* For each hook, register its full name (e.g. textShadowBlur) with its root property (e.g. textShadow) 5731 and the hook's position in its template's default value string. */ 5732 CSS.Hooks.registered[fullHookName] = [rootProperty, hookPosition]; 5733 } 5734 } 5735 }, 5736 /***************************** 5737 Injection and Extraction 5738 *****************************/ 5739 5740 /* Look up the root property associated with the hook (e.g. return "textShadow" for "textShadowBlur"). */ 5741 /* Since a hook cannot be set directly (the browser won't recognize it), style updating for hooks is routed through the hook's root property. */ 5742 getRoot: function(property) { 5743 var hookData = CSS.Hooks.registered[property]; 5744 5745 if (hookData) { 5746 return hookData[0]; 5747 } else { 5748 /* If there was no hook match, return the property name untouched. */ 5749 return property; 5750 } 5751 }, 5752 getUnit: function(str, start) { 5753 var unit = (str.substr(start || 0, 5).match(/^[a-z%]+/) || [])[0] || ""; 5754 5755 if (unit && _inArray(CSS.Lists.units, unit)) { 5756 return unit; 5757 } 5758 return ""; 5759 }, 5760 fixColors: function(str) { 5761 return str.replace(/(rgba?\(\s*)?(\b[a-z]+\b)/g, function($0, $1, $2) { 5762 if (CSS.Lists.colorNames.hasOwnProperty($2)) { 5763 return ($1 ? $1 : "rgba(") + CSS.Lists.colorNames[$2] + ($1 ? "" : ",1)"); 5764 } 5765 return $1 + $2; 5766 }); 5767 }, 5768 /* Convert any rootPropertyValue, null or otherwise, into a space-delimited list of hook values so that 5769 the targeted hook can be injected or extracted at its standard position. */ 5770 cleanRootPropertyValue: function(rootProperty, rootPropertyValue) { 5771 /* If the rootPropertyValue is wrapped with "rgb()", "clip()", etc., remove the wrapping to normalize the value before manipulation. */ 5772 if (CSS.RegEx.valueUnwrap.test(rootPropertyValue)) { 5773 rootPropertyValue = rootPropertyValue.match(CSS.RegEx.valueUnwrap)[1]; 5774 } 5775 5776 /* If rootPropertyValue is a CSS null-value (from which there's inherently no hook value to extract), 5777 default to the root's default value as defined in CSS.Hooks.templates. */ 5778 /* Note: CSS null-values include "none", "auto", and "transparent". They must be converted into their 5779 zero-values (e.g. textShadow: "none" ==> textShadow: "0px 0px 0px black") for hook manipulation to proceed. */ 5780 if (CSS.Values.isCSSNullValue(rootPropertyValue)) { 5781 rootPropertyValue = CSS.Hooks.templates[rootProperty][1]; 5782 } 5783 5784 return rootPropertyValue; 5785 }, 5786 /* Extracted the hook's value from its root property's value. This is used to get the starting value of an animating hook. */ 5787 extractValue: function(fullHookName, rootPropertyValue) { 5788 var hookData = CSS.Hooks.registered[fullHookName]; 5789 5790 if (hookData) { 5791 var hookRoot = hookData[0], 5792 hookPosition = hookData[1]; 5793 5794 rootPropertyValue = CSS.Hooks.cleanRootPropertyValue(hookRoot, rootPropertyValue); 5795 5796 /* Split rootPropertyValue into its constituent hook values then grab the desired hook at its standard position. */ 5797 return rootPropertyValue.toString().match(CSS.RegEx.valueSplit)[hookPosition]; 5798 } else { 5799 /* If the provided fullHookName isn't a registered hook, return the rootPropertyValue that was passed in. */ 5800 return rootPropertyValue; 5801 } 5802 }, 5803 /* Inject the hook's value into its root property's value. This is used to piece back together the root property 5804 once Velocity has updated one of its individually hooked values through tweening. */ 5805 injectValue: function(fullHookName, hookValue, rootPropertyValue) { 5806 var hookData = CSS.Hooks.registered[fullHookName]; 5807 5808 if (hookData) { 5809 var hookRoot = hookData[0], 5810 hookPosition = hookData[1], 5811 rootPropertyValueParts, 5812 rootPropertyValueUpdated; 5813 5814 rootPropertyValue = CSS.Hooks.cleanRootPropertyValue(hookRoot, rootPropertyValue); 5815 5816 /* Split rootPropertyValue into its individual hook values, replace the targeted value with hookValue, 5817 then reconstruct the rootPropertyValue string. */ 5818 rootPropertyValueParts = rootPropertyValue.toString().match(CSS.RegEx.valueSplit); 5819 rootPropertyValueParts[hookPosition] = hookValue; 5820 rootPropertyValueUpdated = rootPropertyValueParts.join(" "); 5821 5822 return rootPropertyValueUpdated; 5823 } else { 5824 /* If the provided fullHookName isn't a registered hook, return the rootPropertyValue that was passed in. */ 5825 return rootPropertyValue; 5826 } 5827 } 5828 }, 5829 /******************* 5830 Normalizations 5831 *******************/ 5832 5833 /* Normalizations standardize CSS property manipulation by pollyfilling browser-specific implementations (e.g. opacity) 5834 and reformatting special properties (e.g. clip, rgba) to look like standard ones. */ 5835 Normalizations: { 5836 /* Normalizations are passed a normalization target (either the property's name, its extracted value, or its injected value), 5837 the targeted element (which may need to be queried), and the targeted property value. */ 5838 registered: { 5839 clip: function(type, element, propertyValue) { 5840 switch (type) { 5841 case "name": 5842 return "clip"; 5843 /* Clip needs to be unwrapped and stripped of its commas during extraction. */ 5844 case "extract": 5845 var extracted; 5846 5847 /* If Velocity also extracted this value, skip extraction. */ 5848 if (CSS.RegEx.wrappedValueAlreadyExtracted.test(propertyValue)) { 5849 extracted = propertyValue; 5850 } else { 5851 /* Remove the "rect()" wrapper. */ 5852 extracted = propertyValue.toString().match(CSS.RegEx.valueUnwrap); 5853 5854 /* Strip off commas. */ 5855 extracted = extracted ? extracted[1].replace(/,(\s+)?/g, " ") : propertyValue; 5856 } 5857 5858 return extracted; 5859 /* Clip needs to be re-wrapped during injection. */ 5860 case "inject": 5861 return "rect(" + propertyValue + ")"; 5862 } 5863 }, 5864 blur: function(type, element, propertyValue) { 5865 switch (type) { 5866 case "name": 5867 return Velocity.State.isFirefox ? "filter" : "-webkit-filter"; 5868 case "extract": 5869 var extracted = parseFloat(propertyValue); 5870 5871 /* If extracted is NaN, meaning the value isn't already extracted. */ 5872 if (!(extracted || extracted === 0)) { 5873 var blurComponent = propertyValue.toString().match(/blur\(([0-9]+[A-z]+)\)/i); 5874 5875 /* If the filter string had a blur component, return just the blur value and unit type. */ 5876 if (blurComponent) { 5877 extracted = blurComponent[1]; 5878 /* If the component doesn't exist, default blur to 0. */ 5879 } else { 5880 extracted = 0; 5881 } 5882 } 5883 5884 return extracted; 5885 /* Blur needs to be re-wrapped during injection. */ 5886 case "inject": 5887 /* For the blur effect to be fully de-applied, it needs to be set to "none" instead of 0. */ 5888 if (!parseFloat(propertyValue)) { 5889 return "none"; 5890 } else { 5891 return "blur(" + propertyValue + ")"; 5892 } 5893 } 5894 }, 5895 /* <=IE8 do not support the standard opacity property. They use filter:alpha(opacity=INT) instead. */ 5896 opacity: function(type, element, propertyValue) { 5897 if (IE <= 8) { 5898 switch (type) { 5899 case "name": 5900 return "filter"; 5901 case "extract": 5902 /* <=IE8 return a "filter" value of "alpha(opacity=\d{1,3})". 5903 Extract the value and convert it to a decimal value to match the standard CSS opacity property's formatting. */ 5904 var extracted = propertyValue.toString().match(/alpha\(opacity=(.*)\)/i); 5905 5906 if (extracted) { 5907 /* Convert to decimal value. */ 5908 propertyValue = extracted[1] / 100; 5909 } else { 5910 /* When extracting opacity, default to 1 since a null value means opacity hasn't been set. */ 5911 propertyValue = 1; 5912 } 5913 5914 return propertyValue; 5915 case "inject": 5916 /* Opacified elements are required to have their zoom property set to a non-zero value. */ 5917 element.style.zoom = 1; 5918 5919 /* Setting the filter property on elements with certain font property combinations can result in a 5920 highly unappealing ultra-bolding effect. There's no way to remedy this throughout a tween, but dropping the 5921 value altogether (when opacity hits 1) at leasts ensures that the glitch is gone post-tweening. */ 5922 if (parseFloat(propertyValue) >= 1) { 5923 return ""; 5924 } else { 5925 /* As per the filter property's spec, convert the decimal value to a whole number and wrap the value. */ 5926 return "alpha(opacity=" + parseInt(parseFloat(propertyValue) * 100, 10) + ")"; 5927 } 5928 } 5929 /* With all other browsers, normalization is not required; return the same values that were passed in. */ 5930 } else { 5931 switch (type) { 5932 case "name": 5933 return "opacity"; 5934 case "extract": 5935 return propertyValue; 5936 case "inject": 5937 return propertyValue; 5938 } 5939 } 5940 } 5941 }, 5942 /***************************** 5943 Batched Registrations 5944 *****************************/ 5945 5946 /* Note: Batched normalizations extend the CSS.Normalizations.registered object. */ 5947 register: function() { 5948 5949 /***************** 5950 Transforms 5951 *****************/ 5952 5953 /* Transforms are the subproperties contained by the CSS "transform" property. Transforms must undergo normalization 5954 so that they can be referenced in a properties map by their individual names. */ 5955 /* Note: When transforms are "set", they are actually assigned to a per-element transformCache. When all transform 5956 setting is complete complete, CSS.flushTransformCache() must be manually called to flush the values to the DOM. 5957 Transform setting is batched in this way to improve performance: the transform style only needs to be updated 5958 once when multiple transform subproperties are being animated simultaneously. */ 5959 /* Note: IE9 and Android Gingerbread have support for 2D -- but not 3D -- transforms. Since animating unsupported 5960 transform properties results in the browser ignoring the *entire* transform string, we prevent these 3D values 5961 from being normalized for these browsers so that tweening skips these properties altogether 5962 (since it will ignore them as being unsupported by the browser.) */ 5963 if ((!IE || IE > 9) && !Velocity.State.isGingerbread) { 5964 /* Note: Since the standalone CSS "perspective" property and the CSS transform "perspective" subproperty 5965 share the same name, the latter is given a unique token within Velocity: "transformPerspective". */ 5966 CSS.Lists.transformsBase = CSS.Lists.transformsBase.concat(CSS.Lists.transforms3D); 5967 } 5968 5969 for (var i = 0; i < CSS.Lists.transformsBase.length; i++) { 5970 /* Wrap the dynamically generated normalization function in a new scope so that transformName's value is 5971 paired with its respective function. (Otherwise, all functions would take the final for loop's transformName.) */ 5972 (function() { 5973 var transformName = CSS.Lists.transformsBase[i]; 5974 5975 CSS.Normalizations.registered[transformName] = function(type, element, propertyValue) { 5976 switch (type) { 5977 /* The normalized property name is the parent "transform" property -- the property that is actually set in CSS. */ 5978 case "name": 5979 return "transform"; 5980 /* Transform values are cached onto a per-element transformCache object. */ 5981 case "extract": 5982 /* If this transform has yet to be assigned a value, return its null value. */ 5983 if (Data(element) === undefined || Data(element).transformCache[transformName] === undefined) { 5984 /* Scale CSS.Lists.transformsBase default to 1 whereas all other transform properties default to 0. */ 5985 return /^scale/i.test(transformName) ? 1 : 0; 5986 /* When transform values are set, they are wrapped in parentheses as per the CSS spec. 5987 Thus, when extracting their values (for tween calculations), we strip off the parentheses. */ 5988 } 5989 return Data(element).transformCache[transformName].replace(/[()]/g, ""); 5990 case "inject": 5991 var invalid = false; 5992 5993 /* If an individual transform property contains an unsupported unit type, the browser ignores the *entire* transform property. 5994 Thus, protect users from themselves by skipping setting for transform values supplied with invalid unit types. */ 5995 /* Switch on the base transform type; ignore the axis by removing the last letter from the transform's name. */ 5996 switch (transformName.substr(0, transformName.length - 1)) { 5997 /* Whitelist unit types for each transform. */ 5998 case "translate": 5999 invalid = !/(%|px|em|rem|vw|vh|\d)$/i.test(propertyValue); 6000 break; 6001 /* Since an axis-free "scale" property is supported as well, a little hack is used here to detect it by chopping off its last letter. */ 6002 case "scal": 6003 case "scale": 6004 /* Chrome on Android has a bug in which scaled elements blur if their initial scale 6005 value is below 1 (which can happen with forcefeeding). Thus, we detect a yet-unset scale property 6006 and ensure that its first value is always 1. More info: http://stackoverflow.com/questions/10417890/css3-animations-with-transform-causes-blurred-elements-on-webkit/10417962#10417962 */ 6007 if (Velocity.State.isAndroid && Data(element).transformCache[transformName] === undefined && propertyValue < 1) { 6008 propertyValue = 1; 6009 } 6010 6011 invalid = !/(\d)$/i.test(propertyValue); 6012 break; 6013 case "skew": 6014 invalid = !/(deg|\d)$/i.test(propertyValue); 6015 break; 6016 case "rotate": 6017 invalid = !/(deg|\d)$/i.test(propertyValue); 6018 break; 6019 } 6020 6021 if (!invalid) { 6022 /* As per the CSS spec, wrap the value in parentheses. */ 6023 Data(element).transformCache[transformName] = "(" + propertyValue + ")"; 6024 } 6025 6026 /* Although the value is set on the transformCache object, return the newly-updated value for the calling code to process as normal. */ 6027 return Data(element).transformCache[transformName]; 6028 } 6029 }; 6030 })(); 6031 } 6032 6033 /************* 6034 Colors 6035 *************/ 6036 6037 /* Since Velocity only animates a single numeric value per property, color animation is achieved by hooking the individual RGBA components of CSS color properties. 6038 Accordingly, color values must be normalized (e.g. "#ff0000", "red", and "rgb(255, 0, 0)" ==> "255 0 0 1") so that their components can be injected/extracted by CSS.Hooks logic. */ 6039 for (var j = 0; j < CSS.Lists.colors.length; j++) { 6040 /* Wrap the dynamically generated normalization function in a new scope so that colorName's value is paired with its respective function. 6041 (Otherwise, all functions would take the final for loop's colorName.) */ 6042 (function() { 6043 var colorName = CSS.Lists.colors[j]; 6044 6045 /* Note: In IE<=8, which support rgb but not rgba, color properties are reverted to rgb by stripping off the alpha component. */ 6046 CSS.Normalizations.registered[colorName] = function(type, element, propertyValue) { 6047 switch (type) { 6048 case "name": 6049 return colorName; 6050 /* Convert all color values into the rgb format. (Old IE can return hex values and color names instead of rgb/rgba.) */ 6051 case "extract": 6052 var extracted; 6053 6054 /* If the color is already in its hookable form (e.g. "255 255 255 1") due to having been previously extracted, skip extraction. */ 6055 if (CSS.RegEx.wrappedValueAlreadyExtracted.test(propertyValue)) { 6056 extracted = propertyValue; 6057 } else { 6058 var converted, 6059 colorNames = { 6060 black: "rgb(0, 0, 0)", 6061 blue: "rgb(0, 0, 255)", 6062 gray: "rgb(128, 128, 128)", 6063 green: "rgb(0, 128, 0)", 6064 red: "rgb(255, 0, 0)", 6065 white: "rgb(255, 255, 255)" 6066 }; 6067 6068 /* Convert color names to rgb. */ 6069 if (/^[A-z]+$/i.test(propertyValue)) { 6070 if (colorNames[propertyValue] !== undefined) { 6071 converted = colorNames[propertyValue]; 6072 } else { 6073 /* If an unmatched color name is provided, default to black. */ 6074 converted = colorNames.black; 6075 } 6076 /* Convert hex values to rgb. */ 6077 } else if (CSS.RegEx.isHex.test(propertyValue)) { 6078 converted = "rgb(" + CSS.Values.hexToRgb(propertyValue).join(" ") + ")"; 6079 /* If the provided color doesn't match any of the accepted color formats, default to black. */ 6080 } else if (!(/^rgba?\(/i.test(propertyValue))) { 6081 converted = colorNames.black; 6082 } 6083 6084 /* Remove the surrounding "rgb/rgba()" string then replace commas with spaces and strip 6085 repeated spaces (in case the value included spaces to begin with). */ 6086 extracted = (converted || propertyValue).toString().match(CSS.RegEx.valueUnwrap)[1].replace(/,(\s+)?/g, " "); 6087 } 6088 6089 /* So long as this isn't <=IE8, add a fourth (alpha) component if it's missing and default it to 1 (visible). */ 6090 if ((!IE || IE > 8) && extracted.split(" ").length === 3) { 6091 extracted += " 1"; 6092 } 6093 6094 return extracted; 6095 case "inject": 6096 /* If we have a pattern then it might already have the right values */ 6097 if (/^rgb/.test(propertyValue)) { 6098 return propertyValue; 6099 } 6100 6101 /* If this is IE<=8 and an alpha component exists, strip it off. */ 6102 if (IE <= 8) { 6103 if (propertyValue.split(" ").length === 4) { 6104 propertyValue = propertyValue.split(/\s+/).slice(0, 3).join(" "); 6105 } 6106 /* Otherwise, add a fourth (alpha) component if it's missing and default it to 1 (visible). */ 6107 } else if (propertyValue.split(" ").length === 3) { 6108 propertyValue += " 1"; 6109 } 6110 6111 /* Re-insert the browser-appropriate wrapper("rgb/rgba()"), insert commas, and strip off decimal units 6112 on all values but the fourth (R, G, and B only accept whole numbers). */ 6113 return (IE <= 8 ? "rgb" : "rgba") + "(" + propertyValue.replace(/\s+/g, ",").replace(/\.(\d)+(?=,)/g, "") + ")"; 6114 } 6115 }; 6116 })(); 6117 } 6118 6119 /************** 6120 Dimensions 6121 **************/ 6122 function augmentDimension(name, element, wantInner) { 6123 var isBorderBox = CSS.getPropertyValue(element, "boxSizing").toString().toLowerCase() === "border-box"; 6124 6125 if (isBorderBox === (wantInner || false)) { 6126 /* in box-sizing mode, the CSS width / height accessors already give the outerWidth / outerHeight. */ 6127 var i, 6128 value, 6129 augment = 0, 6130 sides = name === "width" ? ["Left", "Right"] : ["Top", "Bottom"], 6131 fields = ["padding" + sides[0], "padding" + sides[1], "border" + sides[0] + "Width", "border" + sides[1] + "Width"]; 6132 6133 for (i = 0; i < fields.length; i++) { 6134 value = parseFloat(CSS.getPropertyValue(element, fields[i])); 6135 if (!isNaN(value)) { 6136 augment += value; 6137 } 6138 } 6139 return wantInner ? -augment : augment; 6140 } 6141 return 0; 6142 } 6143 function getDimension(name, wantInner) { 6144 return function(type, element, propertyValue) { 6145 switch (type) { 6146 case "name": 6147 return name; 6148 case "extract": 6149 return parseFloat(propertyValue) + augmentDimension(name, element, wantInner); 6150 case "inject": 6151 return (parseFloat(propertyValue) - augmentDimension(name, element, wantInner)) + "px"; 6152 } 6153 }; 6154 } 6155 CSS.Normalizations.registered.innerWidth = getDimension("width", true); 6156 CSS.Normalizations.registered.innerHeight = getDimension("height", true); 6157 CSS.Normalizations.registered.outerWidth = getDimension("width"); 6158 CSS.Normalizations.registered.outerHeight = getDimension("height"); 6159 } 6160 }, 6161 /************************ 6162 CSS Property Names 6163 ************************/ 6164 6165 Names: { 6166 /* Camelcase a property name into its JavaScript notation (e.g. "background-color" ==> "backgroundColor"). 6167 Camelcasing is used to normalize property names between and across calls. */ 6168 camelCase: function(property) { 6169 return property.replace(/-(\w)/g, function(match, subMatch) { 6170 return subMatch.toUpperCase(); 6171 }); 6172 }, 6173 /* For SVG elements, some properties (namely, dimensional ones) are GET/SET via the element's HTML attributes (instead of via CSS styles). */ 6174 SVGAttribute: function(property) { 6175 var SVGAttributes = "width|height|x|y|cx|cy|r|rx|ry|x1|x2|y1|y2"; 6176 6177 /* Certain browsers require an SVG transform to be applied as an attribute. (Otherwise, application via CSS is preferable due to 3D support.) */ 6178 if (IE || (Velocity.State.isAndroid && !Velocity.State.isChrome)) { 6179 SVGAttributes += "|transform"; 6180 } 6181 6182 return new RegExp("^(" + SVGAttributes + ")$", "i").test(property); 6183 }, 6184 /* Determine whether a property should be set with a vendor prefix. */ 6185 /* If a prefixed version of the property exists, return it. Otherwise, return the original property name. 6186 If the property is not at all supported by the browser, return a false flag. */ 6187 prefixCheck: function(property) { 6188 /* If this property has already been checked, return the cached value. */ 6189 if (Velocity.State.prefixMatches[property]) { 6190 return [Velocity.State.prefixMatches[property], true]; 6191 } else { 6192 var vendors = ["", "Webkit", "Moz", "ms", "O"]; 6193 6194 for (var i = 0, vendorsLength = vendors.length; i < vendorsLength; i++) { 6195 var propertyPrefixed; 6196 6197 if (i === 0) { 6198 propertyPrefixed = property; 6199 } else { 6200 /* Capitalize the first letter of the property to conform to JavaScript vendor prefix notation (e.g. webkitFilter). */ 6201 propertyPrefixed = vendors[i] + property.replace(/^\w/, function(match) { 6202 return match.toUpperCase(); 6203 }); 6204 } 6205 6206 /* Check if the browser supports this property as prefixed. */ 6207 if (Type.isString(Velocity.State.prefixElement.style[propertyPrefixed])) { 6208 /* Cache the match. */ 6209 Velocity.State.prefixMatches[property] = propertyPrefixed; 6210 6211 return [propertyPrefixed, true]; 6212 } 6213 } 6214 6215 /* If the browser doesn't support this property in any form, include a false flag so that the caller can decide how to proceed. */ 6216 return [property, false]; 6217 } 6218 } 6219 }, 6220 /************************ 6221 CSS Property Values 6222 ************************/ 6223 6224 Values: { 6225 /* Hex to RGB conversion. Copyright Tim Down: http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb */ 6226 hexToRgb: function(hex) { 6227 var shortformRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i, 6228 longformRegex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i, 6229 rgbParts; 6230 6231 hex = hex.replace(shortformRegex, function(m, r, g, b) { 6232 return r + r + g + g + b + b; 6233 }); 6234 6235 rgbParts = longformRegex.exec(hex); 6236 6237 return rgbParts ? [parseInt(rgbParts[1], 16), parseInt(rgbParts[2], 16), parseInt(rgbParts[3], 16)] : [0, 0, 0]; 6238 }, 6239 isCSSNullValue: function(value) { 6240 /* The browser defaults CSS values that have not been set to either 0 or one of several possible null-value strings. 6241 Thus, we check for both falsiness and these special strings. */ 6242 /* Null-value checking is performed to default the special strings to 0 (for the sake of tweening) or their hook 6243 templates as defined as CSS.Hooks (for the sake of hook injection/extraction). */ 6244 /* Note: Chrome returns "rgba(0, 0, 0, 0)" for an undefined color whereas IE returns "transparent". */ 6245 return (!value || /^(none|auto|transparent|(rgba\(0, ?0, ?0, ?0\)))$/i.test(value)); 6246 }, 6247 /* Retrieve a property's default unit type. Used for assigning a unit type when one is not supplied by the user. */ 6248 getUnitType: function(property) { 6249 if (/^(rotate|skew)/i.test(property)) { 6250 return "deg"; 6251 } else if (/(^(scale|scaleX|scaleY|scaleZ|alpha|flexGrow|flexHeight|zIndex|fontWeight)$)|((opacity|red|green|blue|alpha)$)/i.test(property)) { 6252 /* The above properties are unitless. */ 6253 return ""; 6254 } else { 6255 /* Default to px for all other properties. */ 6256 return "px"; 6257 } 6258 }, 6259 /* HTML elements default to an associated display type when they're not set to display:none. */ 6260 /* Note: This function is used for correctly setting the non-"none" display value in certain Velocity redirects, such as fadeIn/Out. */ 6261 getDisplayType: function(element) { 6262 var tagName = element && element.tagName.toString().toLowerCase(); 6263 6264 if (/^(b|big|i|small|tt|abbr|acronym|cite|code|dfn|em|kbd|strong|samp|var|a|bdo|br|img|map|object|q|script|span|sub|sup|button|input|label|select|textarea)$/i.test(tagName)) { 6265 return "inline"; 6266 } else if (/^(li)$/i.test(tagName)) { 6267 return "list-item"; 6268 } else if (/^(tr)$/i.test(tagName)) { 6269 return "table-row"; 6270 } else if (/^(table)$/i.test(tagName)) { 6271 return "table"; 6272 } else if (/^(tbody)$/i.test(tagName)) { 6273 return "table-row-group"; 6274 /* Default to "block" when no match is found. */ 6275 } else { 6276 return "block"; 6277 } 6278 }, 6279 /* The class add/remove functions are used to temporarily apply a "velocity-animating" class to elements while they're animating. */ 6280 addClass: function(element, className) { 6281 if (element) { 6282 if (element.classList) { 6283 element.classList.add(className); 6284 } else if (Type.isString(element.className)) { 6285 // Element.className is around 15% faster then set/getAttribute 6286 element.className += (element.className.length ? " " : "") + className; 6287 } else { 6288 // Work around for IE strict mode animating SVG - and anything else that doesn't behave correctly - the same way jQuery does it 6289 var currentClass = element.getAttribute(IE <= 7 ? "className" : "class") || ""; 6290 6291 element.setAttribute("class", currentClass + (currentClass ? " " : "") + className); 6292 } 6293 } 6294 }, 6295 removeClass: function(element, className) { 6296 if (element) { 6297 if (element.classList) { 6298 element.classList.remove(className); 6299 } else if (Type.isString(element.className)) { 6300 // Element.className is around 15% faster then set/getAttribute 6301 // TODO: Need some jsperf tests on performance - can we get rid of the regex and maybe use split / array manipulation? 6302 element.className = element.className.toString().replace(new RegExp("(^|\\s)" + className.split(" ").join("|") + "(\\s|$)", "gi"), " "); 6303 } else { 6304 // Work around for IE strict mode animating SVG - and anything else that doesn't behave correctly - the same way jQuery does it 6305 var currentClass = element.getAttribute(IE <= 7 ? "className" : "class") || ""; 6306 6307 element.setAttribute("class", currentClass.replace(new RegExp("(^|\s)" + className.split(" ").join("|") + "(\s|$)", "gi"), " ")); 6308 } 6309 } 6310 } 6311 }, 6312 /**************************** 6313 Style Getting & Setting 6314 ****************************/ 6315 6316 /* The singular getPropertyValue, which routes the logic for all normalizations, hooks, and standard CSS properties. */ 6317 getPropertyValue: function(element, property, rootPropertyValue, forceStyleLookup) { 6318 /* Get an element's computed property value. */ 6319 /* Note: Retrieving the value of a CSS property cannot simply be performed by checking an element's 6320 style attribute (which only reflects user-defined values). Instead, the browser must be queried for a property's 6321 *computed* value. You can read more about getComputedStyle here: https://developer.mozilla.org/en/docs/Web/API/window.getComputedStyle */ 6322 function computePropertyValue(element, property) { 6323 /* When box-sizing isn't set to border-box, height and width style values are incorrectly computed when an 6324 element's scrollbars are visible (which expands the element's dimensions). Thus, we defer to the more accurate 6325 offsetHeight/Width property, which includes the total dimensions for interior, border, padding, and scrollbar. 6326 We subtract border and padding to get the sum of interior + scrollbar. */ 6327 var computedValue = 0; 6328 6329 /* IE<=8 doesn't support window.getComputedStyle, thus we defer to jQuery, which has an extensive array 6330 of hacks to accurately retrieve IE8 property values. Re-implementing that logic here is not worth bloating the 6331 codebase for a dying browser. The performance repercussions of using jQuery here are minimal since 6332 Velocity is optimized to rarely (and sometimes never) query the DOM. Further, the $.css() codepath isn't that slow. */ 6333 if (IE <= 8) { 6334 computedValue = $.css(element, property); /* GET */ 6335 /* All other browsers support getComputedStyle. The returned live object reference is cached onto its 6336 associated element so that it does not need to be refetched upon every GET. */ 6337 } else { 6338 /* Browsers do not return height and width values for elements that are set to display:"none". Thus, we temporarily 6339 toggle display to the element type's default value. */ 6340 var toggleDisplay = false; 6341 6342 if (/^(width|height)$/.test(property) && CSS.getPropertyValue(element, "display") === 0) { 6343 toggleDisplay = true; 6344 CSS.setPropertyValue(element, "display", CSS.Values.getDisplayType(element)); 6345 } 6346 6347 var revertDisplay = function() { 6348 if (toggleDisplay) { 6349 CSS.setPropertyValue(element, "display", "none"); 6350 } 6351 }; 6352 6353 if (!forceStyleLookup) { 6354 if (property === "height" && CSS.getPropertyValue(element, "boxSizing").toString().toLowerCase() !== "border-box") { 6355 var contentBoxHeight = element.offsetHeight - (parseFloat(CSS.getPropertyValue(element, "borderTopWidth")) || 0) - (parseFloat(CSS.getPropertyValue(element, "borderBottomWidth")) || 0) - (parseFloat(CSS.getPropertyValue(element, "paddingTop")) || 0) - (parseFloat(CSS.getPropertyValue(element, "paddingBottom")) || 0); 6356 revertDisplay(); 6357 6358 return contentBoxHeight; 6359 } else if (property === "width" && CSS.getPropertyValue(element, "boxSizing").toString().toLowerCase() !== "border-box") { 6360 var contentBoxWidth = element.offsetWidth - (parseFloat(CSS.getPropertyValue(element, "borderLeftWidth")) || 0) - (parseFloat(CSS.getPropertyValue(element, "borderRightWidth")) || 0) - (parseFloat(CSS.getPropertyValue(element, "paddingLeft")) || 0) - (parseFloat(CSS.getPropertyValue(element, "paddingRight")) || 0); 6361 revertDisplay(); 6362 6363 return contentBoxWidth; 6364 } 6365 } 6366 6367 var computedStyle; 6368 6369 /* For elements that Velocity hasn't been called on directly (e.g. when Velocity queries the DOM on behalf 6370 of a parent of an element its animating), perform a direct getComputedStyle lookup since the object isn't cached. */ 6371 if (Data(element) === undefined) { 6372 computedStyle = window.getComputedStyle(element, null); /* GET */ 6373 /* If the computedStyle object has yet to be cached, do so now. */ 6374 } else if (!Data(element).computedStyle) { 6375 computedStyle = Data(element).computedStyle = window.getComputedStyle(element, null); /* GET */ 6376 /* If computedStyle is cached, use it. */ 6377 } else { 6378 computedStyle = Data(element).computedStyle; 6379 } 6380 6381 /* IE and Firefox do not return a value for the generic borderColor -- they only return individual values for each border side's color. 6382 Also, in all browsers, when border colors aren't all the same, a compound value is returned that Velocity isn't setup to parse. 6383 So, as a polyfill for querying individual border side colors, we just return the top border's color and animate all borders from that value. */ 6384 if (property === "borderColor") { 6385 property = "borderTopColor"; 6386 } 6387 6388 /* IE9 has a bug in which the "filter" property must be accessed from computedStyle using the getPropertyValue method 6389 instead of a direct property lookup. The getPropertyValue method is slower than a direct lookup, which is why we avoid it by default. */ 6390 if (IE === 9 && property === "filter") { 6391 computedValue = computedStyle.getPropertyValue(property); /* GET */ 6392 } else { 6393 computedValue = computedStyle[property]; 6394 } 6395 6396 /* Fall back to the property's style value (if defined) when computedValue returns nothing, 6397 which can happen when the element hasn't been painted. */ 6398 if (computedValue === "" || computedValue === null) { 6399 computedValue = element.style[property]; 6400 } 6401 6402 revertDisplay(); 6403 } 6404 6405 /* For top, right, bottom, and left (TRBL) values that are set to "auto" on elements of "fixed" or "absolute" position, 6406 defer to jQuery for converting "auto" to a numeric value. (For elements with a "static" or "relative" position, "auto" has the same 6407 effect as being set to 0, so no conversion is necessary.) */ 6408 /* An example of why numeric conversion is necessary: When an element with "position:absolute" has an untouched "left" 6409 property, which reverts to "auto", left's value is 0 relative to its parent element, but is often non-zero relative 6410 to its *containing* (not parent) element, which is the nearest "position:relative" ancestor or the viewport (and always the viewport in the case of "position:fixed"). */ 6411 if (computedValue === "auto" && /^(top|right|bottom|left)$/i.test(property)) { 6412 var position = computePropertyValue(element, "position"); /* GET */ 6413 6414 /* For absolute positioning, jQuery's $.position() only returns values for top and left; 6415 right and bottom will have their "auto" value reverted to 0. */ 6416 /* Note: A jQuery object must be created here since jQuery doesn't have a low-level alias for $.position(). 6417 Not a big deal since we're currently in a GET batch anyway. */ 6418 if (position === "fixed" || (position === "absolute" && /top|left/i.test(property))) { 6419 /* Note: jQuery strips the pixel unit from its returned values; we re-add it here to conform with computePropertyValue's behavior. */ 6420 computedValue = $(element).position()[property] + "px"; /* GET */ 6421 } 6422 } 6423 6424 return computedValue; 6425 } 6426 6427 var propertyValue; 6428 6429 /* If this is a hooked property (e.g. "clipLeft" instead of the root property of "clip"), 6430 extract the hook's value from a normalized rootPropertyValue using CSS.Hooks.extractValue(). */ 6431 if (CSS.Hooks.registered[property]) { 6432 var hook = property, 6433 hookRoot = CSS.Hooks.getRoot(hook); 6434 6435 /* If a cached rootPropertyValue wasn't passed in (which Velocity always attempts to do in order to avoid requerying the DOM), 6436 query the DOM for the root property's value. */ 6437 if (rootPropertyValue === undefined) { 6438 /* Since the browser is now being directly queried, use the official post-prefixing property name for this lookup. */ 6439 rootPropertyValue = CSS.getPropertyValue(element, CSS.Names.prefixCheck(hookRoot)[0]); /* GET */ 6440 } 6441 6442 /* If this root has a normalization registered, peform the associated normalization extraction. */ 6443 if (CSS.Normalizations.registered[hookRoot]) { 6444 rootPropertyValue = CSS.Normalizations.registered[hookRoot]("extract", element, rootPropertyValue); 6445 } 6446 6447 /* Extract the hook's value. */ 6448 propertyValue = CSS.Hooks.extractValue(hook, rootPropertyValue); 6449 6450 /* If this is a normalized property (e.g. "opacity" becomes "filter" in <=IE8) or "translateX" becomes "transform"), 6451 normalize the property's name and value, and handle the special case of transforms. */ 6452 /* Note: Normalizing a property is mutually exclusive from hooking a property since hook-extracted values are strictly 6453 numerical and therefore do not require normalization extraction. */ 6454 } else if (CSS.Normalizations.registered[property]) { 6455 var normalizedPropertyName, 6456 normalizedPropertyValue; 6457 6458 normalizedPropertyName = CSS.Normalizations.registered[property]("name", element); 6459 6460 /* Transform values are calculated via normalization extraction (see below), which checks against the element's transformCache. 6461 At no point do transform GETs ever actually query the DOM; initial stylesheet values are never processed. 6462 This is because parsing 3D transform matrices is not always accurate and would bloat our codebase; 6463 thus, normalization extraction defaults initial transform values to their zero-values (e.g. 1 for scaleX and 0 for translateX). */ 6464 if (normalizedPropertyName !== "transform") { 6465 normalizedPropertyValue = computePropertyValue(element, CSS.Names.prefixCheck(normalizedPropertyName)[0]); /* GET */ 6466 6467 /* If the value is a CSS null-value and this property has a hook template, use that zero-value template so that hooks can be extracted from it. */ 6468 if (CSS.Values.isCSSNullValue(normalizedPropertyValue) && CSS.Hooks.templates[property]) { 6469 normalizedPropertyValue = CSS.Hooks.templates[property][1]; 6470 } 6471 } 6472 6473 propertyValue = CSS.Normalizations.registered[property]("extract", element, normalizedPropertyValue); 6474 } 6475 6476 /* If a (numeric) value wasn't produced via hook extraction or normalization, query the DOM. */ 6477 if (!/^[\d-]/.test(propertyValue)) { 6478 /* For SVG elements, dimensional properties (which SVGAttribute() detects) are tweened via 6479 their HTML attribute values instead of their CSS style values. */ 6480 var data = Data(element); 6481 6482 if (data && data.isSVG && CSS.Names.SVGAttribute(property)) { 6483 /* Since the height/width attribute values must be set manually, they don't reflect computed values. 6484 Thus, we use use getBBox() to ensure we always get values for elements with undefined height/width attributes. */ 6485 if (/^(height|width)$/i.test(property)) { 6486 /* Firefox throws an error if .getBBox() is called on an SVG that isn't attached to the DOM. */ 6487 try { 6488 propertyValue = element.getBBox()[property]; 6489 } catch (error) { 6490 propertyValue = 0; 6491 } 6492 /* Otherwise, access the attribute value directly. */ 6493 } else { 6494 propertyValue = element.getAttribute(property); 6495 } 6496 } else { 6497 propertyValue = computePropertyValue(element, CSS.Names.prefixCheck(property)[0]); /* GET */ 6498 } 6499 } 6500 6501 /* Since property lookups are for animation purposes (which entails computing the numeric delta between start and end values), 6502 convert CSS null-values to an integer of value 0. */ 6503 if (CSS.Values.isCSSNullValue(propertyValue)) { 6504 propertyValue = 0; 6505 } 6506 6507 if (Velocity.debug >= 2) { 6508 console.log("Get " + property + ": " + propertyValue); 6509 } 6510 6511 return propertyValue; 6512 }, 6513 /* The singular setPropertyValue, which routes the logic for all normalizations, hooks, and standard CSS properties. */ 6514 setPropertyValue: function(element, property, propertyValue, rootPropertyValue, scrollData) { 6515 var propertyName = property; 6516 6517 /* In order to be subjected to call options and element queueing, scroll animation is routed through Velocity as if it were a standard CSS property. */ 6518 if (property === "scroll") { 6519 /* If a container option is present, scroll the container instead of the browser window. */ 6520 if (scrollData.container) { 6521 scrollData.container["scroll" + scrollData.direction] = propertyValue; 6522 /* Otherwise, Velocity defaults to scrolling the browser window. */ 6523 } else { 6524 if (scrollData.direction === "Left") { 6525 window.scrollTo(propertyValue, scrollData.alternateValue); 6526 } else { 6527 window.scrollTo(scrollData.alternateValue, propertyValue); 6528 } 6529 } 6530 } else { 6531 /* Transforms (translateX, rotateZ, etc.) are applied to a per-element transformCache object, which is manually flushed via flushTransformCache(). 6532 Thus, for now, we merely cache transforms being SET. */ 6533 if (CSS.Normalizations.registered[property] && CSS.Normalizations.registered[property]("name", element) === "transform") { 6534 /* Perform a normalization injection. */ 6535 /* Note: The normalization logic handles the transformCache updating. */ 6536 CSS.Normalizations.registered[property]("inject", element, propertyValue); 6537 6538 propertyName = "transform"; 6539 propertyValue = Data(element).transformCache[property]; 6540 } else { 6541 /* Inject hooks. */ 6542 if (CSS.Hooks.registered[property]) { 6543 var hookName = property, 6544 hookRoot = CSS.Hooks.getRoot(property); 6545 6546 /* If a cached rootPropertyValue was not provided, query the DOM for the hookRoot's current value. */ 6547 rootPropertyValue = rootPropertyValue || CSS.getPropertyValue(element, hookRoot); /* GET */ 6548 6549 propertyValue = CSS.Hooks.injectValue(hookName, propertyValue, rootPropertyValue); 6550 property = hookRoot; 6551 } 6552 6553 /* Normalize names and values. */ 6554 if (CSS.Normalizations.registered[property]) { 6555 propertyValue = CSS.Normalizations.registered[property]("inject", element, propertyValue); 6556 property = CSS.Normalizations.registered[property]("name", element); 6557 } 6558 6559 /* Assign the appropriate vendor prefix before performing an official style update. */ 6560 propertyName = CSS.Names.prefixCheck(property)[0]; 6561 6562 /* A try/catch is used for IE<=8, which throws an error when "invalid" CSS values are set, e.g. a negative width. 6563 Try/catch is avoided for other browsers since it incurs a performance overhead. */ 6564 if (IE <= 8) { 6565 try { 6566 element.style[propertyName] = propertyValue; 6567 } catch (error) { 6568 if (Velocity.debug) { 6569 console.log("Browser does not support [" + propertyValue + "] for [" + propertyName + "]"); 6570 } 6571 } 6572 /* SVG elements have their dimensional properties (width, height, x, y, cx, etc.) applied directly as attributes instead of as styles. */ 6573 /* Note: IE8 does not support SVG elements, so it's okay that we skip it for SVG animation. */ 6574 } else { 6575 var data = Data(element); 6576 6577 if (data && data.isSVG && CSS.Names.SVGAttribute(property)) { 6578 /* Note: For SVG attributes, vendor-prefixed property names are never used. */ 6579 /* Note: Not all CSS properties can be animated via attributes, but the browser won't throw an error for unsupported properties. */ 6580 element.setAttribute(property, propertyValue); 6581 } else { 6582 element.style[propertyName] = propertyValue; 6583 } 6584 } 6585 6586 if (Velocity.debug >= 2) { 6587 console.log("Set " + property + " (" + propertyName + "): " + propertyValue); 6588 } 6589 } 6590 } 6591 6592 /* Return the normalized property name and value in case the caller wants to know how these values were modified before being applied to the DOM. */ 6593 return [propertyName, propertyValue]; 6594 }, 6595 /* To increase performance by batching transform updates into a single SET, transforms are not directly applied to an element until flushTransformCache() is called. */ 6596 /* Note: Velocity applies transform properties in the same order that they are chronogically introduced to the element's CSS styles. */ 6597 flushTransformCache: function(element) { 6598 var transformString = "", 6599 data = Data(element); 6600 6601 /* Certain browsers require that SVG transforms be applied as an attribute. However, the SVG transform attribute takes a modified version of CSS's transform string 6602 (units are dropped and, except for skewX/Y, subproperties are merged into their master property -- e.g. scaleX and scaleY are merged into scale(X Y). */ 6603 if ((IE || (Velocity.State.isAndroid && !Velocity.State.isChrome)) && data && data.isSVG) { 6604 /* Since transform values are stored in their parentheses-wrapped form, we use a helper function to strip out their numeric values. 6605 Further, SVG transform properties only take unitless (representing pixels) values, so it's okay that parseFloat() strips the unit suffixed to the float value. */ 6606 var getTransformFloat = function(transformProperty) { 6607 return parseFloat(CSS.getPropertyValue(element, transformProperty)); 6608 }; 6609 6610 /* Create an object to organize all the transforms that we'll apply to the SVG element. To keep the logic simple, 6611 we process *all* transform properties -- even those that may not be explicitly applied (since they default to their zero-values anyway). */ 6612 var SVGTransforms = { 6613 translate: [getTransformFloat("translateX"), getTransformFloat("translateY")], 6614 skewX: [getTransformFloat("skewX")], skewY: [getTransformFloat("skewY")], 6615 /* If the scale property is set (non-1), use that value for the scaleX and scaleY values 6616 (this behavior mimics the result of animating all these properties at once on HTML elements). */ 6617 scale: getTransformFloat("scale") !== 1 ? [getTransformFloat("scale"), getTransformFloat("scale")] : [getTransformFloat("scaleX"), getTransformFloat("scaleY")], 6618 /* Note: SVG's rotate transform takes three values: rotation degrees followed by the X and Y values 6619 defining the rotation's origin point. We ignore the origin values (default them to 0). */ 6620 rotate: [getTransformFloat("rotateZ"), 0, 0] 6621 }; 6622 6623 /* Iterate through the transform properties in the user-defined property map order. 6624 (This mimics the behavior of non-SVG transform animation.) */ 6625 $.each(Data(element).transformCache, function(transformName) { 6626 /* Except for with skewX/Y, revert the axis-specific transform subproperties to their axis-free master 6627 properties so that they match up with SVG's accepted transform properties. */ 6628 if (/^translate/i.test(transformName)) { 6629 transformName = "translate"; 6630 } else if (/^scale/i.test(transformName)) { 6631 transformName = "scale"; 6632 } else if (/^rotate/i.test(transformName)) { 6633 transformName = "rotate"; 6634 } 6635 6636 /* Check that we haven't yet deleted the property from the SVGTransforms container. */ 6637 if (SVGTransforms[transformName]) { 6638 /* Append the transform property in the SVG-supported transform format. As per the spec, surround the space-delimited values in parentheses. */ 6639 transformString += transformName + "(" + SVGTransforms[transformName].join(" ") + ")" + " "; 6640 6641 /* After processing an SVG transform property, delete it from the SVGTransforms container so we don't 6642 re-insert the same master property if we encounter another one of its axis-specific properties. */ 6643 delete SVGTransforms[transformName]; 6644 } 6645 }); 6646 } else { 6647 var transformValue, 6648 perspective; 6649 6650 /* Transform properties are stored as members of the transformCache object. Concatenate all the members into a string. */ 6651 $.each(Data(element).transformCache, function(transformName) { 6652 transformValue = Data(element).transformCache[transformName]; 6653 6654 /* Transform's perspective subproperty must be set first in order to take effect. Store it temporarily. */ 6655 if (transformName === "transformPerspective") { 6656 perspective = transformValue; 6657 return true; 6658 } 6659 6660 /* IE9 only supports one rotation type, rotateZ, which it refers to as "rotate". */ 6661 if (IE === 9 && transformName === "rotateZ") { 6662 transformName = "rotate"; 6663 } 6664 6665 transformString += transformName + transformValue + " "; 6666 }); 6667 6668 /* If present, set the perspective subproperty first. */ 6669 if (perspective) { 6670 transformString = "perspective" + perspective + " " + transformString; 6671 } 6672 } 6673 6674 CSS.setPropertyValue(element, "transform", transformString); 6675 } 6676 }; 6677 6678 /* Register hooks and normalizations. */ 6679 CSS.Hooks.register(); 6680 CSS.Normalizations.register(); 6681 6682 /* Allow hook setting in the same fashion as jQuery's $.css(). */ 6683 Velocity.hook = function(elements, arg2, arg3) { 6684 var value; 6685 6686 elements = sanitizeElements(elements); 6687 6688 $.each(elements, function(i, element) { 6689 /* Initialize Velocity's per-element data cache if this element hasn't previously been animated. */ 6690 if (Data(element) === undefined) { 6691 Velocity.init(element); 6692 } 6693 6694 /* Get property value. If an element set was passed in, only return the value for the first element. */ 6695 if (arg3 === undefined) { 6696 if (value === undefined) { 6697 value = CSS.getPropertyValue(element, arg2); 6698 } 6699 /* Set property value. */ 6700 } else { 6701 /* sPV returns an array of the normalized propertyName/propertyValue pair used to update the DOM. */ 6702 var adjustedSet = CSS.setPropertyValue(element, arg2, arg3); 6703 6704 /* Transform properties don't automatically set. They have to be flushed to the DOM. */ 6705 if (adjustedSet[0] === "transform") { 6706 Velocity.CSS.flushTransformCache(element); 6707 } 6708 6709 value = adjustedSet; 6710 } 6711 }); 6712 6713 return value; 6714 }; 6715 6716 /***************** 6717 Animation 6718 *****************/ 6719 6720 var animate = function() { 6721 var opts; 6722 6723 /****************** 6724 Call Chain 6725 ******************/ 6726 6727 /* Logic for determining what to return to the call stack when exiting out of Velocity. */ 6728 function getChain() { 6729 /* If we are using the utility function, attempt to return this call's promise. If no promise library was detected, 6730 default to null instead of returning the targeted elements so that utility function's return value is standardized. */ 6731 if (isUtility) { 6732 return promiseData.promise || null; 6733 /* Otherwise, if we're using $.fn, return the jQuery-/Zepto-wrapped element set. */ 6734 } else { 6735 return elementsWrapped; 6736 } 6737 } 6738 6739 /************************* 6740 Arguments Assignment 6741 *************************/ 6742 6743 /* To allow for expressive CoffeeScript code, Velocity supports an alternative syntax in which "elements" (or "e"), "properties" (or "p"), and "options" (or "o") 6744 objects are defined on a container object that's passed in as Velocity's sole argument. */ 6745 /* Note: Some browsers automatically populate arguments with a "properties" object. We detect it by checking for its default "names" property. */ 6746 var syntacticSugar = (arguments[0] && (arguments[0].p || (($.isPlainObject(arguments[0].properties) && !arguments[0].properties.names) || Type.isString(arguments[0].properties)))), 6747 /* Whether Velocity was called via the utility function (as opposed to on a jQuery/Zepto object). */ 6748 isUtility, 6749 /* When Velocity is called via the utility function ($.Velocity()/Velocity()), elements are explicitly 6750 passed in as the first parameter. Thus, argument positioning varies. We normalize them here. */ 6751 elementsWrapped, 6752 argumentIndex; 6753 6754 var elements, 6755 propertiesMap, 6756 options; 6757 6758 /* Detect jQuery/Zepto elements being animated via the $.fn method. */ 6759 if (Type.isWrapped(this)) { 6760 isUtility = false; 6761 6762 argumentIndex = 0; 6763 elements = this; 6764 elementsWrapped = this; 6765 /* Otherwise, raw elements are being animated via the utility function. */ 6766 } else { 6767 isUtility = true; 6768 6769 argumentIndex = 1; 6770 elements = syntacticSugar ? (arguments[0].elements || arguments[0].e) : arguments[0]; 6771 } 6772 6773 /*************** 6774 Promises 6775 ***************/ 6776 6777 var promiseData = { 6778 promise: null, 6779 resolver: null, 6780 rejecter: null 6781 }; 6782 6783 /* If this call was made via the utility function (which is the default method of invocation when jQuery/Zepto are not being used), and if 6784 promise support was detected, create a promise object for this call and store references to its resolver and rejecter methods. The resolve 6785 method is used when a call completes naturally or is prematurely stopped by the user. In both cases, completeCall() handles the associated 6786 call cleanup and promise resolving logic. The reject method is used when an invalid set of arguments is passed into a Velocity call. */ 6787 /* Note: Velocity employs a call-based queueing architecture, which means that stopping an animating element actually stops the full call that 6788 triggered it -- not that one element exclusively. Similarly, there is one promise per call, and all elements targeted by a Velocity call are 6789 grouped together for the purposes of resolving and rejecting a promise. */ 6790 if (isUtility && Velocity.Promise) { 6791 promiseData.promise = new Velocity.Promise(function(resolve, reject) { 6792 promiseData.resolver = resolve; 6793 promiseData.rejecter = reject; 6794 }); 6795 } 6796 6797 if (syntacticSugar) { 6798 propertiesMap = arguments[0].properties || arguments[0].p; 6799 options = arguments[0].options || arguments[0].o; 6800 } else { 6801 propertiesMap = arguments[argumentIndex]; 6802 options = arguments[argumentIndex + 1]; 6803 } 6804 6805 elements = sanitizeElements(elements); 6806 6807 if (!elements) { 6808 if (promiseData.promise) { 6809 if (!propertiesMap || !options || options.promiseRejectEmpty !== false) { 6810 promiseData.rejecter(); 6811 } else { 6812 promiseData.resolver(); 6813 } 6814 } 6815 return; 6816 } 6817 6818 /* The length of the element set (in the form of a nodeList or an array of elements) is defaulted to 1 in case a 6819 single raw DOM element is passed in (which doesn't contain a length property). */ 6820 var elementsLength = elements.length, 6821 elementsIndex = 0; 6822 6823 /*************************** 6824 Argument Overloading 6825 ***************************/ 6826 6827 /* Support is included for jQuery's argument overloading: $.animate(propertyMap [, duration] [, easing] [, complete]). 6828 Overloading is detected by checking for the absence of an object being passed into options. */ 6829 /* Note: The stop/finish/pause/resume actions do not accept animation options, and are therefore excluded from this check. */ 6830 if (!/^(stop|finish|finishAll|pause|resume)$/i.test(propertiesMap) && !$.isPlainObject(options)) { 6831 /* The utility function shifts all arguments one position to the right, so we adjust for that offset. */ 6832 var startingArgumentPosition = argumentIndex + 1; 6833 6834 options = {}; 6835 6836 /* Iterate through all options arguments */ 6837 for (var i = startingArgumentPosition; i < arguments.length; i++) { 6838 /* Treat a number as a duration. Parse it out. */ 6839 /* Note: The following RegEx will return true if passed an array with a number as its first item. 6840 Thus, arrays are skipped from this check. */ 6841 if (!Type.isArray(arguments[i]) && (/^(fast|normal|slow)$/i.test(arguments[i]) || /^\d/.test(arguments[i]))) { 6842 options.duration = arguments[i]; 6843 /* Treat strings and arrays as easings. */ 6844 } else if (Type.isString(arguments[i]) || Type.isArray(arguments[i])) { 6845 options.easing = arguments[i]; 6846 /* Treat a function as a complete callback. */ 6847 } else if (Type.isFunction(arguments[i])) { 6848 options.complete = arguments[i]; 6849 } 6850 } 6851 } 6852 6853 /********************* 6854 Action Detection 6855 *********************/ 6856 6857 /* Velocity's behavior is categorized into "actions": Elements can either be specially scrolled into view, 6858 or they can be started, stopped, paused, resumed, or reversed . If a literal or referenced properties map is passed in as Velocity's 6859 first argument, the associated action is "start". Alternatively, "scroll", "reverse", "pause", "resume" or "stop" can be passed in 6860 instead of a properties map. */ 6861 var action; 6862 6863 switch (propertiesMap) { 6864 case "scroll": 6865 action = "scroll"; 6866 break; 6867 6868 case "reverse": 6869 action = "reverse"; 6870 break; 6871 6872 case "pause": 6873 6874 /******************* 6875 Action: Pause 6876 *******************/ 6877 6878 var currentTime = (new Date()).getTime(); 6879 6880 /* Handle delay timers */ 6881 $.each(elements, function(i, element) { 6882 pauseDelayOnElement(element, currentTime); 6883 }); 6884 6885 /* Pause and Resume are call-wide (not on a per element basis). Thus, calling pause or resume on a 6886 single element will cause any calls that containt tweens for that element to be paused/resumed 6887 as well. */ 6888 6889 /* Iterate through all calls and pause any that contain any of our elements */ 6890 $.each(Velocity.State.calls, function(i, activeCall) { 6891 6892 var found = false; 6893 /* Inactive calls are set to false by the logic inside completeCall(). Skip them. */ 6894 if (activeCall) { 6895 /* Iterate through the active call's targeted elements. */ 6896 $.each(activeCall[1], function(k, activeElement) { 6897 var queueName = (options === undefined) ? "" : options; 6898 6899 if (queueName !== true && (activeCall[2].queue !== queueName) && !(options === undefined && activeCall[2].queue === false)) { 6900 return true; 6901 } 6902 6903 /* Iterate through the calls targeted by the stop command. */ 6904 $.each(elements, function(l, element) { 6905 /* Check that this call was applied to the target element. */ 6906 if (element === activeElement) { 6907 6908 /* Set call to paused */ 6909 activeCall[5] = { 6910 resume: false 6911 }; 6912 6913 /* Once we match an element, we can bounce out to the next call entirely */ 6914 found = true; 6915 return false; 6916 } 6917 }); 6918 6919 /* Proceed to check next call if we have already matched */ 6920 if (found) { 6921 return false; 6922 } 6923 }); 6924 } 6925 6926 }); 6927 6928 /* Since pause creates no new tweens, exit out of Velocity. */ 6929 return getChain(); 6930 6931 case "resume": 6932 6933 /******************* 6934 Action: Resume 6935 *******************/ 6936 6937 /* Handle delay timers */ 6938 $.each(elements, function(i, element) { 6939 resumeDelayOnElement(element, currentTime); 6940 }); 6941 6942 /* Pause and Resume are call-wide (not on a per elemnt basis). Thus, calling pause or resume on a 6943 single element will cause any calls that containt tweens for that element to be paused/resumed 6944 as well. */ 6945 6946 /* Iterate through all calls and pause any that contain any of our elements */ 6947 $.each(Velocity.State.calls, function(i, activeCall) { 6948 var found = false; 6949 /* Inactive calls are set to false by the logic inside completeCall(). Skip them. */ 6950 if (activeCall) { 6951 /* Iterate through the active call's targeted elements. */ 6952 $.each(activeCall[1], function(k, activeElement) { 6953 var queueName = (options === undefined) ? "" : options; 6954 6955 if (queueName !== true && (activeCall[2].queue !== queueName) && !(options === undefined && activeCall[2].queue === false)) { 6956 return true; 6957 } 6958 6959 /* Skip any calls that have never been paused */ 6960 if (!activeCall[5]) { 6961 return true; 6962 } 6963 6964 /* Iterate through the calls targeted by the stop command. */ 6965 $.each(elements, function(l, element) { 6966 /* Check that this call was applied to the target element. */ 6967 if (element === activeElement) { 6968 6969 /* Flag a pause object to be resumed, which will occur during the next tick. In 6970 addition, the pause object will at that time be deleted */ 6971 activeCall[5].resume = true; 6972 6973 /* Once we match an element, we can bounce out to the next call entirely */ 6974 found = true; 6975 return false; 6976 } 6977 }); 6978 6979 /* Proceed to check next call if we have already matched */ 6980 if (found) { 6981 return false; 6982 } 6983 }); 6984 } 6985 6986 }); 6987 6988 /* Since resume creates no new tweens, exit out of Velocity. */ 6989 return getChain(); 6990 6991 case "finish": 6992 case "finishAll": 6993 case "stop": 6994 /******************* 6995 Action: Stop 6996 *******************/ 6997 6998 /* Clear the currently-active delay on each targeted element. */ 6999 $.each(elements, function(i, element) { 7000 if (Data(element) && Data(element).delayTimer) { 7001 /* Stop the timer from triggering its cached next() function. */ 7002 clearTimeout(Data(element).delayTimer.setTimeout); 7003 7004 /* Manually call the next() function so that the subsequent queue items can progress. */ 7005 if (Data(element).delayTimer.next) { 7006 Data(element).delayTimer.next(); 7007 } 7008 7009 delete Data(element).delayTimer; 7010 } 7011 7012 /* If we want to finish everything in the queue, we have to iterate through it 7013 and call each function. This will make them active calls below, which will 7014 cause them to be applied via the duration setting. */ 7015 if (propertiesMap === "finishAll" && (options === true || Type.isString(options))) { 7016 /* Iterate through the items in the element's queue. */ 7017 $.each($.queue(element, Type.isString(options) ? options : ""), function(_, item) { 7018 /* The queue array can contain an "inprogress" string, which we skip. */ 7019 if (Type.isFunction(item)) { 7020 item(); 7021 } 7022 }); 7023 7024 /* Clearing the $.queue() array is achieved by resetting it to []. */ 7025 $.queue(element, Type.isString(options) ? options : "", []); 7026 } 7027 }); 7028 7029 var callsToStop = []; 7030 7031 /* When the stop action is triggered, the elements' currently active call is immediately stopped. The active call might have 7032 been applied to multiple elements, in which case all of the call's elements will be stopped. When an element 7033 is stopped, the next item in its animation queue is immediately triggered. */ 7034 /* An additional argument may be passed in to clear an element's remaining queued calls. Either true (which defaults to the "fx" queue) 7035 or a custom queue string can be passed in. */ 7036 /* Note: The stop command runs prior to Velocity's Queueing phase since its behavior is intended to take effect *immediately*, 7037 regardless of the element's current queue state. */ 7038 7039 /* Iterate through every active call. */ 7040 $.each(Velocity.State.calls, function(i, activeCall) { 7041 /* Inactive calls are set to false by the logic inside completeCall(). Skip them. */ 7042 if (activeCall) { 7043 /* Iterate through the active call's targeted elements. */ 7044 $.each(activeCall[1], function(k, activeElement) { 7045 /* If true was passed in as a secondary argument, clear absolutely all calls on this element. Otherwise, only 7046 clear calls associated with the relevant queue. */ 7047 /* Call stopping logic works as follows: 7048 - options === true --> stop current default queue calls (and queue:false calls), including remaining queued ones. 7049 - options === undefined --> stop current queue:"" call and all queue:false calls. 7050 - options === false --> stop only queue:false calls. 7051 - options === "custom" --> stop current queue:"custom" call, including remaining queued ones (there is no functionality to only clear the currently-running queue:"custom" call). */ 7052 var queueName = (options === undefined) ? "" : options; 7053 7054 if (queueName !== true && (activeCall[2].queue !== queueName) && !(options === undefined && activeCall[2].queue === false)) { 7055 return true; 7056 } 7057 7058 /* Iterate through the calls targeted by the stop command. */ 7059 $.each(elements, function(l, element) { 7060 /* Check that this call was applied to the target element. */ 7061 if (element === activeElement) { 7062 /* Optionally clear the remaining queued calls. If we're doing "finishAll" this won't find anything, 7063 due to the queue-clearing above. */ 7064 if (options === true || Type.isString(options)) { 7065 /* Iterate through the items in the element's queue. */ 7066 $.each($.queue(element, Type.isString(options) ? options : ""), function(_, item) { 7067 /* The queue array can contain an "inprogress" string, which we skip. */ 7068 if (Type.isFunction(item)) { 7069 /* Pass the item's callback a flag indicating that we want to abort from the queue call. 7070 (Specifically, the queue will resolve the call's associated promise then abort.) */ 7071 item(null, true); 7072 } 7073 }); 7074 7075 /* Clearing the $.queue() array is achieved by resetting it to []. */ 7076 $.queue(element, Type.isString(options) ? options : "", []); 7077 } 7078 7079 if (propertiesMap === "stop") { 7080 /* Since "reverse" uses cached start values (the previous call's endValues), these values must be 7081 changed to reflect the final value that the elements were actually tweened to. */ 7082 /* Note: If only queue:false/queue:"custom" animations are currently running on an element, it won't have a tweensContainer 7083 object. Also, queue:false/queue:"custom" animations can't be reversed. */ 7084 var data = Data(element); 7085 if (data && data.tweensContainer && (queueName === true || queueName === "")) { 7086 $.each(data.tweensContainer, function(m, activeTween) { 7087 activeTween.endValue = activeTween.currentValue; 7088 }); 7089 } 7090 7091 callsToStop.push(i); 7092 } else if (propertiesMap === "finish" || propertiesMap === "finishAll") { 7093 /* To get active tweens to finish immediately, we forcefully shorten their durations to 1ms so that 7094 they finish upon the next rAf tick then proceed with normal call completion logic. */ 7095 activeCall[2].duration = 1; 7096 } 7097 } 7098 }); 7099 }); 7100 } 7101 }); 7102 7103 /* Prematurely call completeCall() on each matched active call. Pass an additional flag for "stop" to indicate 7104 that the complete callback and display:none setting should be skipped since we're completing prematurely. */ 7105 if (propertiesMap === "stop") { 7106 $.each(callsToStop, function(i, j) { 7107 completeCall(j, true); 7108 }); 7109 7110 if (promiseData.promise) { 7111 /* Immediately resolve the promise associated with this stop call since stop runs synchronously. */ 7112 promiseData.resolver(elements); 7113 } 7114 } 7115 7116 /* Since we're stopping, and not proceeding with queueing, exit out of Velocity. */ 7117 return getChain(); 7118 7119 default: 7120 /* Treat a non-empty plain object as a literal properties map. */ 7121 if ($.isPlainObject(propertiesMap) && !Type.isEmptyObject(propertiesMap)) { 7122 action = "start"; 7123 7124 /**************** 7125 Redirects 7126 ****************/ 7127 7128 /* Check if a string matches a registered redirect (see Redirects above). */ 7129 } else if (Type.isString(propertiesMap) && Velocity.Redirects[propertiesMap]) { 7130 opts = $.extend({}, options); 7131 7132 var durationOriginal = opts.duration, 7133 delayOriginal = opts.delay || 0; 7134 7135 /* If the backwards option was passed in, reverse the element set so that elements animate from the last to the first. */ 7136 if (opts.backwards === true) { 7137 elements = $.extend(true, [], elements).reverse(); 7138 } 7139 7140 /* Individually trigger the redirect for each element in the set to prevent users from having to handle iteration logic in their redirect. */ 7141 $.each(elements, function(elementIndex, element) { 7142 /* If the stagger option was passed in, successively delay each element by the stagger value (in ms). Retain the original delay value. */ 7143 if (parseFloat(opts.stagger)) { 7144 opts.delay = delayOriginal + (parseFloat(opts.stagger) * elementIndex); 7145 } else if (Type.isFunction(opts.stagger)) { 7146 opts.delay = delayOriginal + opts.stagger.call(element, elementIndex, elementsLength); 7147 } 7148 7149 /* If the drag option was passed in, successively increase/decrease (depending on the presense of opts.backwards) 7150 the duration of each element's animation, using floors to prevent producing very short durations. */ 7151 if (opts.drag) { 7152 /* Default the duration of UI pack effects (callouts and transitions) to 1000ms instead of the usual default duration of 400ms. */ 7153 opts.duration = parseFloat(durationOriginal) || (/^(callout|transition)/.test(propertiesMap) ? 1000 : DURATION_DEFAULT); 7154 7155 /* For each element, take the greater duration of: A) animation completion percentage relative to the original duration, 7156 B) 75% of the original duration, or C) a 200ms fallback (in case duration is already set to a low value). 7157 The end result is a baseline of 75% of the redirect's duration that increases/decreases as the end of the element set is approached. */ 7158 opts.duration = Math.max(opts.duration * (opts.backwards ? 1 - elementIndex / elementsLength : (elementIndex + 1) / elementsLength), opts.duration * 0.75, 200); 7159 } 7160 7161 /* Pass in the call's opts object so that the redirect can optionally extend it. It defaults to an empty object instead of null to 7162 reduce the opts checking logic required inside the redirect. */ 7163 Velocity.Redirects[propertiesMap].call(element, element, opts || {}, elementIndex, elementsLength, elements, promiseData.promise ? promiseData : undefined); 7164 }); 7165 7166 /* Since the animation logic resides within the redirect's own code, abort the remainder of this call. 7167 (The performance overhead up to this point is virtually non-existant.) */ 7168 /* Note: The jQuery call chain is kept intact by returning the complete element set. */ 7169 return getChain(); 7170 } else { 7171 var abortError = "Velocity: First argument (" + propertiesMap + ") was not a property map, a known action, or a registered redirect. Aborting."; 7172 7173 if (promiseData.promise) { 7174 promiseData.rejecter(new Error(abortError)); 7175 } else if (window.console) { 7176 console.log(abortError); 7177 } 7178 7179 return getChain(); 7180 } 7181 } 7182 7183 /************************** 7184 Call-Wide Variables 7185 **************************/ 7186 7187 /* A container for CSS unit conversion ratios (e.g. %, rem, and em ==> px) that is used to cache ratios across all elements 7188 being animated in a single Velocity call. Calculating unit ratios necessitates DOM querying and updating, and is therefore 7189 avoided (via caching) wherever possible. This container is call-wide instead of page-wide to avoid the risk of using stale 7190 conversion metrics across Velocity animations that are not immediately consecutively chained. */ 7191 var callUnitConversionData = { 7192 lastParent: null, 7193 lastPosition: null, 7194 lastFontSize: null, 7195 lastPercentToPxWidth: null, 7196 lastPercentToPxHeight: null, 7197 lastEmToPx: null, 7198 remToPx: null, 7199 vwToPx: null, 7200 vhToPx: null 7201 }; 7202 7203 /* A container for all the ensuing tween data and metadata associated with this call. This container gets pushed to the page-wide 7204 Velocity.State.calls array that is processed during animation ticking. */ 7205 var call = []; 7206 7207 /************************ 7208 Element Processing 7209 ************************/ 7210 7211 /* Element processing consists of three parts -- data processing that cannot go stale and data processing that *can* go stale (i.e. third-party style modifications): 7212 1) Pre-Queueing: Element-wide variables, including the element's data storage, are instantiated. Call options are prepared. If triggered, the Stop action is executed. 7213 2) Queueing: The logic that runs once this call has reached its point of execution in the element's $.queue() stack. Most logic is placed here to avoid risking it becoming stale. 7214 3) Pushing: Consolidation of the tween data followed by its push onto the global in-progress calls container. 7215 `elementArrayIndex` allows passing index of the element in the original array to value functions. 7216 If `elementsIndex` were used instead the index would be determined by the elements' per-element queue. 7217 */ 7218 function processElement(element, elementArrayIndex) { 7219 7220 /************************* 7221 Part I: Pre-Queueing 7222 *************************/ 7223 7224 /*************************** 7225 Element-Wide Variables 7226 ***************************/ 7227 7228 var /* The runtime opts object is the extension of the current call's options and Velocity's page-wide option defaults. */ 7229 opts = $.extend({}, Velocity.defaults, options), 7230 /* A container for the processed data associated with each property in the propertyMap. 7231 (Each property in the map produces its own "tween".) */ 7232 tweensContainer = {}, 7233 elementUnitConversionData; 7234 7235 /****************** 7236 Element Init 7237 ******************/ 7238 7239 if (Data(element) === undefined) { 7240 Velocity.init(element); 7241 } 7242 7243 /****************** 7244 Option: Delay 7245 ******************/ 7246 7247 /* Since queue:false doesn't respect the item's existing queue, we avoid injecting its delay here (it's set later on). */ 7248 /* Note: Velocity rolls its own delay function since jQuery doesn't have a utility alias for $.fn.delay() 7249 (and thus requires jQuery element creation, which we avoid since its overhead includes DOM querying). */ 7250 if (parseFloat(opts.delay) && opts.queue !== false) { 7251 $.queue(element, opts.queue, function(next, clearQueue) { 7252 if (clearQueue === true) { 7253 /* Do not continue with animation queueing. */ 7254 return true; 7255 } 7256 7257 /* This is a flag used to indicate to the upcoming completeCall() function that this queue entry was initiated by Velocity. See completeCall() for further details. */ 7258 Velocity.velocityQueueEntryFlag = true; 7259 7260 /* The ensuing queue item (which is assigned to the "next" argument that $.queue() automatically passes in) will be triggered after a setTimeout delay. 7261 The setTimeout is stored so that it can be subjected to clearTimeout() if this animation is prematurely stopped via Velocity's "stop" command, and 7262 delayBegin/delayTime is used to ensure we can "pause" and "resume" a tween that is still mid-delay. */ 7263 7264 /* Temporarily store delayed elements to facilite access for global pause/resume */ 7265 var callIndex = Velocity.State.delayedElements.count++; 7266 Velocity.State.delayedElements[callIndex] = element; 7267 7268 var delayComplete = (function(index) { 7269 return function() { 7270 /* Clear the temporary element */ 7271 Velocity.State.delayedElements[index] = false; 7272 7273 /* Finally, issue the call */ 7274 next(); 7275 }; 7276 })(callIndex); 7277 7278 7279 Data(element).delayBegin = (new Date()).getTime(); 7280 Data(element).delay = parseFloat(opts.delay); 7281 Data(element).delayTimer = { 7282 setTimeout: setTimeout(next, parseFloat(opts.delay)), 7283 next: delayComplete 7284 }; 7285 }); 7286 } 7287 7288 /********************* 7289 Option: Duration 7290 *********************/ 7291 7292 /* Support for jQuery's named durations. */ 7293 switch (opts.duration.toString().toLowerCase()) { 7294 case "fast": 7295 opts.duration = 200; 7296 break; 7297 7298 case "normal": 7299 opts.duration = DURATION_DEFAULT; 7300 break; 7301 7302 case "slow": 7303 opts.duration = 600; 7304 break; 7305 7306 default: 7307 /* Remove the potential "ms" suffix and default to 1 if the user is attempting to set a duration of 0 (in order to produce an immediate style change). */ 7308 opts.duration = parseFloat(opts.duration) || 1; 7309 } 7310 7311 /************************ 7312 Global Option: Mock 7313 ************************/ 7314 7315 if (Velocity.mock !== false) { 7316 /* In mock mode, all animations are forced to 1ms so that they occur immediately upon the next rAF tick. 7317 Alternatively, a multiplier can be passed in to time remap all delays and durations. */ 7318 if (Velocity.mock === true) { 7319 opts.duration = opts.delay = 1; 7320 } else { 7321 opts.duration *= parseFloat(Velocity.mock) || 1; 7322 opts.delay *= parseFloat(Velocity.mock) || 1; 7323 } 7324 } 7325 7326 /******************* 7327 Option: Easing 7328 *******************/ 7329 7330 opts.easing = getEasing(opts.easing, opts.duration); 7331 7332 /********************** 7333 Option: Callbacks 7334 **********************/ 7335 7336 /* Callbacks must functions. Otherwise, default to null. */ 7337 if (opts.begin && !Type.isFunction(opts.begin)) { 7338 opts.begin = null; 7339 } 7340 7341 if (opts.progress && !Type.isFunction(opts.progress)) { 7342 opts.progress = null; 7343 } 7344 7345 if (opts.complete && !Type.isFunction(opts.complete)) { 7346 opts.complete = null; 7347 } 7348 7349 /********************************* 7350 Option: Display & Visibility 7351 *********************************/ 7352 7353 /* Refer to Velocity's documentation (VelocityJS.org/#displayAndVisibility) for a description of the display and visibility options' behavior. */ 7354 /* Note: We strictly check for undefined instead of falsiness because display accepts an empty string value. */ 7355 if (opts.display !== undefined && opts.display !== null) { 7356 opts.display = opts.display.toString().toLowerCase(); 7357 7358 /* Users can pass in a special "auto" value to instruct Velocity to set the element to its default display value. */ 7359 if (opts.display === "auto") { 7360 opts.display = Velocity.CSS.Values.getDisplayType(element); 7361 } 7362 } 7363 7364 if (opts.visibility !== undefined && opts.visibility !== null) { 7365 opts.visibility = opts.visibility.toString().toLowerCase(); 7366 } 7367 7368 /********************** 7369 Option: mobileHA 7370 **********************/ 7371 7372 /* When set to true, and if this is a mobile device, mobileHA automatically enables hardware acceleration (via a null transform hack) 7373 on animating elements. HA is removed from the element at the completion of its animation. */ 7374 /* Note: Android Gingerbread doesn't support HA. If a null transform hack (mobileHA) is in fact set, it will prevent other tranform subproperties from taking effect. */ 7375 /* Note: You can read more about the use of mobileHA in Velocity's documentation: VelocityJS.org/#mobileHA. */ 7376 opts.mobileHA = (opts.mobileHA && Velocity.State.isMobile && !Velocity.State.isGingerbread); 7377 7378 /*********************** 7379 Part II: Queueing 7380 ***********************/ 7381 7382 /* When a set of elements is targeted by a Velocity call, the set is broken up and each element has the current Velocity call individually queued onto it. 7383 In this way, each element's existing queue is respected; some elements may already be animating and accordingly should not have this current Velocity call triggered immediately. */ 7384 /* In each queue, tween data is processed for each animating property then pushed onto the call-wide calls array. When the last element in the set has had its tweens processed, 7385 the call array is pushed to Velocity.State.calls for live processing by the requestAnimationFrame tick. */ 7386 function buildQueue(next) { 7387 var data, lastTweensContainer; 7388 7389 /******************* 7390 Option: Begin 7391 *******************/ 7392 7393 /* The begin callback is fired once per call -- not once per elemenet -- and is passed the full raw DOM element set as both its context and its first argument. */ 7394 if (opts.begin && elementsIndex === 0) { 7395 /* We throw callbacks in a setTimeout so that thrown errors don't halt the execution of Velocity itself. */ 7396 try { 7397 opts.begin.call(elements, elements); 7398 } catch (error) { 7399 setTimeout(function() { 7400 throw error; 7401 }, 1); 7402 } 7403 } 7404 7405 /***************************************** 7406 Tween Data Construction (for Scroll) 7407 *****************************************/ 7408 7409 /* Note: In order to be subjected to chaining and animation options, scroll's tweening is routed through Velocity as if it were a standard CSS property animation. */ 7410 if (action === "scroll") { 7411 /* The scroll action uniquely takes an optional "offset" option -- specified in pixels -- that offsets the targeted scroll position. */ 7412 var scrollDirection = (/^x$/i.test(opts.axis) ? "Left" : "Top"), 7413 scrollOffset = parseFloat(opts.offset) || 0, 7414 scrollPositionCurrent, 7415 scrollPositionCurrentAlternate, 7416 scrollPositionEnd; 7417 7418 /* Scroll also uniquely takes an optional "container" option, which indicates the parent element that should be scrolled -- 7419 as opposed to the browser window itself. This is useful for scrolling toward an element that's inside an overflowing parent element. */ 7420 if (opts.container) { 7421 /* Ensure that either a jQuery object or a raw DOM element was passed in. */ 7422 if (Type.isWrapped(opts.container) || Type.isNode(opts.container)) { 7423 /* Extract the raw DOM element from the jQuery wrapper. */ 7424 opts.container = opts.container[0] || opts.container; 7425 /* Note: Unlike other properties in Velocity, the browser's scroll position is never cached since it so frequently changes 7426 (due to the user's natural interaction with the page). */ 7427 scrollPositionCurrent = opts.container["scroll" + scrollDirection]; /* GET */ 7428 7429 /* $.position() values are relative to the container's currently viewable area (without taking into account the container's true dimensions 7430 -- say, for example, if the container was not overflowing). Thus, the scroll end value is the sum of the child element's position *and* 7431 the scroll container's current scroll position. */ 7432 scrollPositionEnd = (scrollPositionCurrent + $(element).position()[scrollDirection.toLowerCase()]) + scrollOffset; /* GET */ 7433 /* If a value other than a jQuery object or a raw DOM element was passed in, default to null so that this option is ignored. */ 7434 } else { 7435 opts.container = null; 7436 } 7437 } else { 7438 /* If the window itself is being scrolled -- not a containing element -- perform a live scroll position lookup using 7439 the appropriate cached property names (which differ based on browser type). */ 7440 scrollPositionCurrent = Velocity.State.scrollAnchor[Velocity.State["scrollProperty" + scrollDirection]]; /* GET */ 7441 /* When scrolling the browser window, cache the alternate axis's current value since window.scrollTo() doesn't let us change only one value at a time. */ 7442 scrollPositionCurrentAlternate = Velocity.State.scrollAnchor[Velocity.State["scrollProperty" + (scrollDirection === "Left" ? "Top" : "Left")]]; /* GET */ 7443 7444 /* Unlike $.position(), $.offset() values are relative to the browser window's true dimensions -- not merely its currently viewable area -- 7445 and therefore end values do not need to be compounded onto current values. */ 7446 scrollPositionEnd = $(element).offset()[scrollDirection.toLowerCase()] + scrollOffset; /* GET */ 7447 } 7448 7449 /* Since there's only one format that scroll's associated tweensContainer can take, we create it manually. */ 7450 tweensContainer = { 7451 scroll: { 7452 rootPropertyValue: false, 7453 startValue: scrollPositionCurrent, 7454 currentValue: scrollPositionCurrent, 7455 endValue: scrollPositionEnd, 7456 unitType: "", 7457 easing: opts.easing, 7458 scrollData: { 7459 container: opts.container, 7460 direction: scrollDirection, 7461 alternateValue: scrollPositionCurrentAlternate 7462 } 7463 }, 7464 element: element 7465 }; 7466 7467 if (Velocity.debug) { 7468 console.log("tweensContainer (scroll): ", tweensContainer.scroll, element); 7469 } 7470 7471 /****************************************** 7472 Tween Data Construction (for Reverse) 7473 ******************************************/ 7474 7475 /* Reverse acts like a "start" action in that a property map is animated toward. The only difference is 7476 that the property map used for reverse is the inverse of the map used in the previous call. Thus, we manipulate 7477 the previous call to construct our new map: use the previous map's end values as our new map's start values. Copy over all other data. */ 7478 /* Note: Reverse can be directly called via the "reverse" parameter, or it can be indirectly triggered via the loop option. (Loops are composed of multiple reverses.) */ 7479 /* Note: Reverse calls do not need to be consecutively chained onto a currently-animating element in order to operate on cached values; 7480 there is no harm to reverse being called on a potentially stale data cache since reverse's behavior is simply defined 7481 as reverting to the element's values as they were prior to the previous *Velocity* call. */ 7482 } else if (action === "reverse") { 7483 data = Data(element); 7484 7485 /* Abort if there is no prior animation data to reverse to. */ 7486 if (!data) { 7487 return; 7488 } 7489 7490 if (!data.tweensContainer) { 7491 /* Dequeue the element so that this queue entry releases itself immediately, allowing subsequent queue entries to run. */ 7492 $.dequeue(element, opts.queue); 7493 7494 return; 7495 } else { 7496 /********************* 7497 Options Parsing 7498 *********************/ 7499 7500 /* If the element was hidden via the display option in the previous call, 7501 revert display to "auto" prior to reversal so that the element is visible again. */ 7502 if (data.opts.display === "none") { 7503 data.opts.display = "auto"; 7504 } 7505 7506 if (data.opts.visibility === "hidden") { 7507 data.opts.visibility = "visible"; 7508 } 7509 7510 /* If the loop option was set in the previous call, disable it so that "reverse" calls aren't recursively generated. 7511 Further, remove the previous call's callback options; typically, users do not want these to be refired. */ 7512 data.opts.loop = false; 7513 data.opts.begin = null; 7514 data.opts.complete = null; 7515 7516 /* Since we're extending an opts object that has already been extended with the defaults options object, 7517 we remove non-explicitly-defined properties that are auto-assigned values. */ 7518 if (!options.easing) { 7519 delete opts.easing; 7520 } 7521 7522 if (!options.duration) { 7523 delete opts.duration; 7524 } 7525 7526 /* The opts object used for reversal is an extension of the options object optionally passed into this 7527 reverse call plus the options used in the previous Velocity call. */ 7528 opts = $.extend({}, data.opts, opts); 7529 7530 /************************************* 7531 Tweens Container Reconstruction 7532 *************************************/ 7533 7534 /* Create a deepy copy (indicated via the true flag) of the previous call's tweensContainer. */ 7535 lastTweensContainer = $.extend(true, {}, data ? data.tweensContainer : null); 7536 7537 /* Manipulate the previous tweensContainer by replacing its end values and currentValues with its start values. */ 7538 for (var lastTween in lastTweensContainer) { 7539 /* In addition to tween data, tweensContainers contain an element property that we ignore here. */ 7540 if (lastTweensContainer.hasOwnProperty(lastTween) && lastTween !== "element") { 7541 var lastStartValue = lastTweensContainer[lastTween].startValue; 7542 7543 lastTweensContainer[lastTween].startValue = lastTweensContainer[lastTween].currentValue = lastTweensContainer[lastTween].endValue; 7544 lastTweensContainer[lastTween].endValue = lastStartValue; 7545 7546 /* Easing is the only option that embeds into the individual tween data (since it can be defined on a per-property basis). 7547 Accordingly, every property's easing value must be updated when an options object is passed in with a reverse call. 7548 The side effect of this extensibility is that all per-property easing values are forcefully reset to the new value. */ 7549 if (!Type.isEmptyObject(options)) { 7550 lastTweensContainer[lastTween].easing = opts.easing; 7551 } 7552 7553 if (Velocity.debug) { 7554 console.log("reverse tweensContainer (" + lastTween + "): " + JSON.stringify(lastTweensContainer[lastTween]), element); 7555 } 7556 } 7557 } 7558 7559 tweensContainer = lastTweensContainer; 7560 } 7561 7562 /***************************************** 7563 Tween Data Construction (for Start) 7564 *****************************************/ 7565 7566 } else if (action === "start") { 7567 7568 /************************* 7569 Value Transferring 7570 *************************/ 7571 7572 /* If this queue entry follows a previous Velocity-initiated queue entry *and* if this entry was created 7573 while the element was in the process of being animated by Velocity, then this current call is safe to use 7574 the end values from the prior call as its start values. Velocity attempts to perform this value transfer 7575 process whenever possible in order to avoid requerying the DOM. */ 7576 /* If values aren't transferred from a prior call and start values were not forcefed by the user (more on this below), 7577 then the DOM is queried for the element's current values as a last resort. */ 7578 /* Note: Conversely, animation reversal (and looping) *always* perform inter-call value transfers; they never requery the DOM. */ 7579 7580 data = Data(element); 7581 7582 /* The per-element isAnimating flag is used to indicate whether it's safe (i.e. the data isn't stale) 7583 to transfer over end values to use as start values. If it's set to true and there is a previous 7584 Velocity call to pull values from, do so. */ 7585 if (data && data.tweensContainer && data.isAnimating === true) { 7586 lastTweensContainer = data.tweensContainer; 7587 } 7588 7589 /*************************** 7590 Tween Data Calculation 7591 ***************************/ 7592 7593 /* This function parses property data and defaults endValue, easing, and startValue as appropriate. */ 7594 /* Property map values can either take the form of 1) a single value representing the end value, 7595 or 2) an array in the form of [ endValue, [, easing] [, startValue] ]. 7596 The optional third parameter is a forcefed startValue to be used instead of querying the DOM for 7597 the element's current value. Read Velocity's docmentation to learn more about forcefeeding: VelocityJS.org/#forcefeeding */ 7598 var parsePropertyValue = function(valueData, skipResolvingEasing) { 7599 var endValue, easing, startValue; 7600 7601 /* If we have a function as the main argument then resolve it first, in case it returns an array that needs to be split */ 7602 if (Type.isFunction(valueData)) { 7603 valueData = valueData.call(element, elementArrayIndex, elementsLength); 7604 } 7605 7606 /* Handle the array format, which can be structured as one of three potential overloads: 7607 A) [ endValue, easing, startValue ], B) [ endValue, easing ], or C) [ endValue, startValue ] */ 7608 if (Type.isArray(valueData)) { 7609 /* endValue is always the first item in the array. Don't bother validating endValue's value now 7610 since the ensuing property cycling logic does that. */ 7611 endValue = valueData[0]; 7612 7613 /* Two-item array format: If the second item is a number, function, or hex string, treat it as a 7614 start value since easings can only be non-hex strings or arrays. */ 7615 if ((!Type.isArray(valueData[1]) && /^[\d-]/.test(valueData[1])) || Type.isFunction(valueData[1]) || CSS.RegEx.isHex.test(valueData[1])) { 7616 startValue = valueData[1]; 7617 /* Two or three-item array: If the second item is a non-hex string easing name or an array, treat it as an easing. */ 7618 } else if ((Type.isString(valueData[1]) && !CSS.RegEx.isHex.test(valueData[1]) && Velocity.Easings[valueData[1]]) || Type.isArray(valueData[1])) { 7619 easing = skipResolvingEasing ? valueData[1] : getEasing(valueData[1], opts.duration); 7620 7621 /* Don't bother validating startValue's value now since the ensuing property cycling logic inherently does that. */ 7622 startValue = valueData[2]; 7623 } else { 7624 startValue = valueData[1] || valueData[2]; 7625 } 7626 /* Handle the single-value format. */ 7627 } else { 7628 endValue = valueData; 7629 } 7630 7631 /* Default to the call's easing if a per-property easing type was not defined. */ 7632 if (!skipResolvingEasing) { 7633 easing = easing || opts.easing; 7634 } 7635 7636 /* If functions were passed in as values, pass the function the current element as its context, 7637 plus the element's index and the element set's size as arguments. Then, assign the returned value. */ 7638 if (Type.isFunction(endValue)) { 7639 endValue = endValue.call(element, elementArrayIndex, elementsLength); 7640 } 7641 7642 if (Type.isFunction(startValue)) { 7643 startValue = startValue.call(element, elementArrayIndex, elementsLength); 7644 } 7645 7646 /* Allow startValue to be left as undefined to indicate to the ensuing code that its value was not forcefed. */ 7647 return [endValue || 0, easing, startValue]; 7648 }; 7649 7650 var fixPropertyValue = function(property, valueData) { 7651 /* In case this property is a hook, there are circumstances where we will intend to work on the hook's root property and not the hooked subproperty. */ 7652 var rootProperty = CSS.Hooks.getRoot(property), 7653 rootPropertyValue = false, 7654 /* Parse out endValue, easing, and startValue from the property's data. */ 7655 endValue = valueData[0], 7656 easing = valueData[1], 7657 startValue = valueData[2], 7658 pattern; 7659 7660 /************************** 7661 Start Value Sourcing 7662 **************************/ 7663 7664 /* Other than for the dummy tween property, properties that are not supported by the browser (and do not have an associated normalization) will 7665 inherently produce no style changes when set, so they are skipped in order to decrease animation tick overhead. 7666 Property support is determined via prefixCheck(), which returns a false flag when no supported is detected. */ 7667 /* Note: Since SVG elements have some of their properties directly applied as HTML attributes, 7668 there is no way to check for their explicit browser support, and so we skip skip this check for them. */ 7669 if ((!data || !data.isSVG) && rootProperty !== "tween" && CSS.Names.prefixCheck(rootProperty)[1] === false && CSS.Normalizations.registered[rootProperty] === undefined) { 7670 if (Velocity.debug) { 7671 console.log("Skipping [" + rootProperty + "] due to a lack of browser support."); 7672 } 7673 return; 7674 } 7675 7676 /* If the display option is being set to a non-"none" (e.g. "block") and opacity (filter on IE<=8) is being 7677 animated to an endValue of non-zero, the user's intention is to fade in from invisible, thus we forcefeed opacity 7678 a startValue of 0 if its startValue hasn't already been sourced by value transferring or prior forcefeeding. */ 7679 if (((opts.display !== undefined && opts.display !== null && opts.display !== "none") || (opts.visibility !== undefined && opts.visibility !== "hidden")) && /opacity|filter/.test(property) && !startValue && endValue !== 0) { 7680 startValue = 0; 7681 } 7682 7683 /* If values have been transferred from the previous Velocity call, extract the endValue and rootPropertyValue 7684 for all of the current call's properties that were *also* animated in the previous call. */ 7685 /* Note: Value transferring can optionally be disabled by the user via the _cacheValues option. */ 7686 if (opts._cacheValues && lastTweensContainer && lastTweensContainer[property]) { 7687 if (startValue === undefined) { 7688 startValue = lastTweensContainer[property].endValue + lastTweensContainer[property].unitType; 7689 } 7690 7691 /* The previous call's rootPropertyValue is extracted from the element's data cache since that's the 7692 instance of rootPropertyValue that gets freshly updated by the tweening process, whereas the rootPropertyValue 7693 attached to the incoming lastTweensContainer is equal to the root property's value prior to any tweening. */ 7694 rootPropertyValue = data.rootPropertyValueCache[rootProperty]; 7695 /* If values were not transferred from a previous Velocity call, query the DOM as needed. */ 7696 } else { 7697 /* Handle hooked properties. */ 7698 if (CSS.Hooks.registered[property]) { 7699 if (startValue === undefined) { 7700 rootPropertyValue = CSS.getPropertyValue(element, rootProperty); /* GET */ 7701 /* Note: The following getPropertyValue() call does not actually trigger a DOM query; 7702 getPropertyValue() will extract the hook from rootPropertyValue. */ 7703 startValue = CSS.getPropertyValue(element, property, rootPropertyValue); 7704 /* If startValue is already defined via forcefeeding, do not query the DOM for the root property's value; 7705 just grab rootProperty's zero-value template from CSS.Hooks. This overwrites the element's actual 7706 root property value (if one is set), but this is acceptable since the primary reason users forcefeed is 7707 to avoid DOM queries, and thus we likewise avoid querying the DOM for the root property's value. */ 7708 } else { 7709 /* Grab this hook's zero-value template, e.g. "0px 0px 0px black". */ 7710 rootPropertyValue = CSS.Hooks.templates[rootProperty][1]; 7711 } 7712 /* Handle non-hooked properties that haven't already been defined via forcefeeding. */ 7713 } else if (startValue === undefined) { 7714 startValue = CSS.getPropertyValue(element, property); /* GET */ 7715 } 7716 } 7717 7718 /************************** 7719 Value Data Extraction 7720 **************************/ 7721 7722 var separatedValue, 7723 endValueUnitType, 7724 startValueUnitType, 7725 operator = false; 7726 7727 /* Separates a property value into its numeric value and its unit type. */ 7728 var separateValue = function(property, value) { 7729 var unitType, 7730 numericValue; 7731 7732 numericValue = (value || "0") 7733 .toString() 7734 .toLowerCase() 7735 /* Match the unit type at the end of the value. */ 7736 .replace(/[%A-z]+$/, function(match) { 7737 /* Grab the unit type. */ 7738 unitType = match; 7739 7740 /* Strip the unit type off of value. */ 7741 return ""; 7742 }); 7743 7744 /* If no unit type was supplied, assign one that is appropriate for this property (e.g. "deg" for rotateZ or "px" for width). */ 7745 if (!unitType) { 7746 unitType = CSS.Values.getUnitType(property); 7747 } 7748 7749 return [numericValue, unitType]; 7750 }; 7751 7752 if (startValue !== endValue && Type.isString(startValue) && Type.isString(endValue)) { 7753 pattern = ""; 7754 var iStart = 0, // index in startValue 7755 iEnd = 0, // index in endValue 7756 aStart = [], // array of startValue numbers 7757 aEnd = [], // array of endValue numbers 7758 inCalc = 0, // Keep track of being inside a "calc()" so we don't duplicate it 7759 inRGB = 0, // Keep track of being inside an RGB as we can't use fractional values 7760 inRGBA = 0; // Keep track of being inside an RGBA as we must pass fractional for the alpha channel 7761 7762 startValue = CSS.Hooks.fixColors(startValue); 7763 endValue = CSS.Hooks.fixColors(endValue); 7764 while (iStart < startValue.length && iEnd < endValue.length) { 7765 var cStart = startValue[iStart], 7766 cEnd = endValue[iEnd]; 7767 7768 if (/[\d\.-]/.test(cStart) && /[\d\.-]/.test(cEnd)) { 7769 var tStart = cStart, // temporary character buffer 7770 tEnd = cEnd, // temporary character buffer 7771 dotStart = ".", // Make sure we can only ever match a single dot in a decimal 7772 dotEnd = "."; // Make sure we can only ever match a single dot in a decimal 7773 7774 while (++iStart < startValue.length) { 7775 cStart = startValue[iStart]; 7776 if (cStart === dotStart) { 7777 dotStart = ".."; // Can never match two characters 7778 } else if (!/\d/.test(cStart)) { 7779 break; 7780 } 7781 tStart += cStart; 7782 } 7783 while (++iEnd < endValue.length) { 7784 cEnd = endValue[iEnd]; 7785 if (cEnd === dotEnd) { 7786 dotEnd = ".."; // Can never match two characters 7787 } else if (!/\d/.test(cEnd)) { 7788 break; 7789 } 7790 tEnd += cEnd; 7791 } 7792 var uStart = CSS.Hooks.getUnit(startValue, iStart), // temporary unit type 7793 uEnd = CSS.Hooks.getUnit(endValue, iEnd); // temporary unit type 7794 7795 iStart += uStart.length; 7796 iEnd += uEnd.length; 7797 if (uStart === uEnd) { 7798 // Same units 7799 if (tStart === tEnd) { 7800 // Same numbers, so just copy over 7801 pattern += tStart + uStart; 7802 } else { 7803 // Different numbers, so store them 7804 pattern += "{" + aStart.length + (inRGB ? "!" : "") + "}" + uStart; 7805 aStart.push(parseFloat(tStart)); 7806 aEnd.push(parseFloat(tEnd)); 7807 } 7808 } else { 7809 // Different units, so put into a "calc(from + to)" and animate each side to/from zero 7810 var nStart = parseFloat(tStart), 7811 nEnd = parseFloat(tEnd); 7812 7813 pattern += (inCalc < 5 ? "calc" : "") + "(" 7814 + (nStart ? "{" + aStart.length + (inRGB ? "!" : "") + "}" : "0") + uStart 7815 + " + " 7816 + (nEnd ? "{" + (aStart.length + (nStart ? 1 : 0)) + (inRGB ? "!" : "") + "}" : "0") + uEnd 7817 + ")"; 7818 if (nStart) { 7819 aStart.push(nStart); 7820 aEnd.push(0); 7821 } 7822 if (nEnd) { 7823 aStart.push(0); 7824 aEnd.push(nEnd); 7825 } 7826 } 7827 } else if (cStart === cEnd) { 7828 pattern += cStart; 7829 iStart++; 7830 iEnd++; 7831 // Keep track of being inside a calc() 7832 if (inCalc === 0 && cStart === "c" 7833 || inCalc === 1 && cStart === "a" 7834 || inCalc === 2 && cStart === "l" 7835 || inCalc === 3 && cStart === "c" 7836 || inCalc >= 4 && cStart === "(" 7837 ) { 7838 inCalc++; 7839 } else if ((inCalc && inCalc < 5) 7840 || inCalc >= 4 && cStart === ")" && --inCalc < 5) { 7841 inCalc = 0; 7842 } 7843 // Keep track of being inside an rgb() / rgba() 7844 if (inRGB === 0 && cStart === "r" 7845 || inRGB === 1 && cStart === "g" 7846 || inRGB === 2 && cStart === "b" 7847 || inRGB === 3 && cStart === "a" 7848 || inRGB >= 3 && cStart === "(" 7849 ) { 7850 if (inRGB === 3 && cStart === "a") { 7851 inRGBA = 1; 7852 } 7853 inRGB++; 7854 } else if (inRGBA && cStart === ",") { 7855 if (++inRGBA > 3) { 7856 inRGB = inRGBA = 0; 7857 } 7858 } else if ((inRGBA && inRGB < (inRGBA ? 5 : 4)) 7859 || inRGB >= (inRGBA ? 4 : 3) && cStart === ")" && --inRGB < (inRGBA ? 5 : 4)) { 7860 inRGB = inRGBA = 0; 7861 } 7862 } else { 7863 inCalc = 0; 7864 // TODO: changing units, fixing colours 7865 break; 7866 } 7867 } 7868 if (iStart !== startValue.length || iEnd !== endValue.length) { 7869 if (Velocity.debug) { 7870 console.error("Trying to pattern match mis-matched strings [\"" + endValue + "\", \"" + startValue + "\"]"); 7871 } 7872 pattern = undefined; 7873 } 7874 if (pattern) { 7875 if (aStart.length) { 7876 if (Velocity.debug) { 7877 console.log("Pattern found \"" + pattern + "\" -> ", aStart, aEnd, "[" + startValue + "," + endValue + "]"); 7878 } 7879 startValue = aStart; 7880 endValue = aEnd; 7881 endValueUnitType = startValueUnitType = ""; 7882 } else { 7883 pattern = undefined; 7884 } 7885 } 7886 } 7887 7888 if (!pattern) { 7889 /* Separate startValue. */ 7890 separatedValue = separateValue(property, startValue); 7891 startValue = separatedValue[0]; 7892 startValueUnitType = separatedValue[1]; 7893 7894 /* Separate endValue, and extract a value operator (e.g. "+=", "-=") if one exists. */ 7895 separatedValue = separateValue(property, endValue); 7896 endValue = separatedValue[0].replace(/^([+-\/*])=/, function(match, subMatch) { 7897 operator = subMatch; 7898 7899 /* Strip the operator off of the value. */ 7900 return ""; 7901 }); 7902 endValueUnitType = separatedValue[1]; 7903 7904 /* Parse float values from endValue and startValue. Default to 0 if NaN is returned. */ 7905 startValue = parseFloat(startValue) || 0; 7906 endValue = parseFloat(endValue) || 0; 7907 7908 /*************************************** 7909 Property-Specific Value Conversion 7910 ***************************************/ 7911 7912 /* Custom support for properties that don't actually accept the % unit type, but where pollyfilling is trivial and relatively foolproof. */ 7913 if (endValueUnitType === "%") { 7914 /* A %-value fontSize/lineHeight is relative to the parent's fontSize (as opposed to the parent's dimensions), 7915 which is identical to the em unit's behavior, so we piggyback off of that. */ 7916 if (/^(fontSize|lineHeight)$/.test(property)) { 7917 /* Convert % into an em decimal value. */ 7918 endValue = endValue / 100; 7919 endValueUnitType = "em"; 7920 /* For scaleX and scaleY, convert the value into its decimal format and strip off the unit type. */ 7921 } else if (/^scale/.test(property)) { 7922 endValue = endValue / 100; 7923 endValueUnitType = ""; 7924 /* For RGB components, take the defined percentage of 255 and strip off the unit type. */ 7925 } else if (/(Red|Green|Blue)$/i.test(property)) { 7926 endValue = (endValue / 100) * 255; 7927 endValueUnitType = ""; 7928 } 7929 } 7930 } 7931 7932 /*************************** 7933 Unit Ratio Calculation 7934 ***************************/ 7935 7936 /* When queried, the browser returns (most) CSS property values in pixels. Therefore, if an endValue with a unit type of 7937 %, em, or rem is animated toward, startValue must be converted from pixels into the same unit type as endValue in order 7938 for value manipulation logic (increment/decrement) to proceed. Further, if the startValue was forcefed or transferred 7939 from a previous call, startValue may also not be in pixels. Unit conversion logic therefore consists of two steps: 7940 1) Calculating the ratio of %/em/rem/vh/vw relative to pixels 7941 2) Converting startValue into the same unit of measurement as endValue based on these ratios. */ 7942 /* Unit conversion ratios are calculated by inserting a sibling node next to the target node, copying over its position property, 7943 setting values with the target unit type then comparing the returned pixel value. */ 7944 /* Note: Even if only one of these unit types is being animated, all unit ratios are calculated at once since the overhead 7945 of batching the SETs and GETs together upfront outweights the potential overhead 7946 of layout thrashing caused by re-querying for uncalculated ratios for subsequently-processed properties. */ 7947 /* Todo: Shift this logic into the calls' first tick instance so that it's synced with RAF. */ 7948 var calculateUnitRatios = function() { 7949 7950 /************************ 7951 Same Ratio Checks 7952 ************************/ 7953 7954 /* The properties below are used to determine whether the element differs sufficiently from this call's 7955 previously iterated element to also differ in its unit conversion ratios. If the properties match up with those 7956 of the prior element, the prior element's conversion ratios are used. Like most optimizations in Velocity, 7957 this is done to minimize DOM querying. */ 7958 var sameRatioIndicators = { 7959 myParent: element.parentNode || document.body, /* GET */ 7960 position: CSS.getPropertyValue(element, "position"), /* GET */ 7961 fontSize: CSS.getPropertyValue(element, "fontSize") /* GET */ 7962 }, 7963 /* Determine if the same % ratio can be used. % is based on the element's position value and its parent's width and height dimensions. */ 7964 samePercentRatio = ((sameRatioIndicators.position === callUnitConversionData.lastPosition) && (sameRatioIndicators.myParent === callUnitConversionData.lastParent)), 7965 /* Determine if the same em ratio can be used. em is relative to the element's fontSize. */ 7966 sameEmRatio = (sameRatioIndicators.fontSize === callUnitConversionData.lastFontSize); 7967 7968 /* Store these ratio indicators call-wide for the next element to compare against. */ 7969 callUnitConversionData.lastParent = sameRatioIndicators.myParent; 7970 callUnitConversionData.lastPosition = sameRatioIndicators.position; 7971 callUnitConversionData.lastFontSize = sameRatioIndicators.fontSize; 7972 7973 /*************************** 7974 Element-Specific Units 7975 ***************************/ 7976 7977 /* Note: IE8 rounds to the nearest pixel when returning CSS values, thus we perform conversions using a measurement 7978 of 100 (instead of 1) to give our ratios a precision of at least 2 decimal values. */ 7979 var measurement = 100, 7980 unitRatios = {}; 7981 7982 if (!sameEmRatio || !samePercentRatio) { 7983 var dummy = data && data.isSVG ? document.createElementNS("http://www.w3.org/2000/svg", "rect") : document.createElement("div"); 7984 7985 Velocity.init(dummy); 7986 sameRatioIndicators.myParent.appendChild(dummy); 7987 7988 /* To accurately and consistently calculate conversion ratios, the element's cascaded overflow and box-sizing are stripped. 7989 Similarly, since width/height can be artificially constrained by their min-/max- equivalents, these are controlled for as well. */ 7990 /* Note: Overflow must be also be controlled for per-axis since the overflow property overwrites its per-axis values. */ 7991 $.each(["overflow", "overflowX", "overflowY"], function(i, property) { 7992 Velocity.CSS.setPropertyValue(dummy, property, "hidden"); 7993 }); 7994 Velocity.CSS.setPropertyValue(dummy, "position", sameRatioIndicators.position); 7995 Velocity.CSS.setPropertyValue(dummy, "fontSize", sameRatioIndicators.fontSize); 7996 Velocity.CSS.setPropertyValue(dummy, "boxSizing", "content-box"); 7997 7998 /* width and height act as our proxy properties for measuring the horizontal and vertical % ratios. */ 7999 $.each(["minWidth", "maxWidth", "width", "minHeight", "maxHeight", "height"], function(i, property) { 8000 Velocity.CSS.setPropertyValue(dummy, property, measurement + "%"); 8001 }); 8002 /* paddingLeft arbitrarily acts as our proxy property for the em ratio. */ 8003 Velocity.CSS.setPropertyValue(dummy, "paddingLeft", measurement + "em"); 8004 8005 /* Divide the returned value by the measurement to get the ratio between 1% and 1px. Default to 1 since working with 0 can produce Infinite. */ 8006 unitRatios.percentToPxWidth = callUnitConversionData.lastPercentToPxWidth = (parseFloat(CSS.getPropertyValue(dummy, "width", null, true)) || 1) / measurement; /* GET */ 8007 unitRatios.percentToPxHeight = callUnitConversionData.lastPercentToPxHeight = (parseFloat(CSS.getPropertyValue(dummy, "height", null, true)) || 1) / measurement; /* GET */ 8008 unitRatios.emToPx = callUnitConversionData.lastEmToPx = (parseFloat(CSS.getPropertyValue(dummy, "paddingLeft")) || 1) / measurement; /* GET */ 8009 8010 sameRatioIndicators.myParent.removeChild(dummy); 8011 } else { 8012 unitRatios.emToPx = callUnitConversionData.lastEmToPx; 8013 unitRatios.percentToPxWidth = callUnitConversionData.lastPercentToPxWidth; 8014 unitRatios.percentToPxHeight = callUnitConversionData.lastPercentToPxHeight; 8015 } 8016 8017 /*************************** 8018 Element-Agnostic Units 8019 ***************************/ 8020 8021 /* Whereas % and em ratios are determined on a per-element basis, the rem unit only needs to be checked 8022 once per call since it's exclusively dependant upon document.body's fontSize. If this is the first time 8023 that calculateUnitRatios() is being run during this call, remToPx will still be set to its default value of null, 8024 so we calculate it now. */ 8025 if (callUnitConversionData.remToPx === null) { 8026 /* Default to browsers' default fontSize of 16px in the case of 0. */ 8027 callUnitConversionData.remToPx = parseFloat(CSS.getPropertyValue(document.body, "fontSize")) || 16; /* GET */ 8028 } 8029 8030 /* Similarly, viewport units are %-relative to the window's inner dimensions. */ 8031 if (callUnitConversionData.vwToPx === null) { 8032 callUnitConversionData.vwToPx = parseFloat(window.innerWidth) / 100; /* GET */ 8033 callUnitConversionData.vhToPx = parseFloat(window.innerHeight) / 100; /* GET */ 8034 } 8035 8036 unitRatios.remToPx = callUnitConversionData.remToPx; 8037 unitRatios.vwToPx = callUnitConversionData.vwToPx; 8038 unitRatios.vhToPx = callUnitConversionData.vhToPx; 8039 8040 if (Velocity.debug >= 1) { 8041 console.log("Unit ratios: " + JSON.stringify(unitRatios), element); 8042 } 8043 return unitRatios; 8044 }; 8045 8046 /******************** 8047 Unit Conversion 8048 ********************/ 8049 8050 /* The * and / operators, which are not passed in with an associated unit, inherently use startValue's unit. Skip value and unit conversion. */ 8051 if (/[\/*]/.test(operator)) { 8052 endValueUnitType = startValueUnitType; 8053 /* If startValue and endValue differ in unit type, convert startValue into the same unit type as endValue so that if endValueUnitType 8054 is a relative unit (%, em, rem), the values set during tweening will continue to be accurately relative even if the metrics they depend 8055 on are dynamically changing during the course of the animation. Conversely, if we always normalized into px and used px for setting values, the px ratio 8056 would become stale if the original unit being animated toward was relative and the underlying metrics change during the animation. */ 8057 /* Since 0 is 0 in any unit type, no conversion is necessary when startValue is 0 -- we just start at 0 with endValueUnitType. */ 8058 } else if ((startValueUnitType !== endValueUnitType) && startValue !== 0) { 8059 /* Unit conversion is also skipped when endValue is 0, but *startValueUnitType* must be used for tween values to remain accurate. */ 8060 /* Note: Skipping unit conversion here means that if endValueUnitType was originally a relative unit, the animation won't relatively 8061 match the underlying metrics if they change, but this is acceptable since we're animating toward invisibility instead of toward visibility, 8062 which remains past the point of the animation's completion. */ 8063 if (endValue === 0) { 8064 endValueUnitType = startValueUnitType; 8065 } else { 8066 /* By this point, we cannot avoid unit conversion (it's undesirable since it causes layout thrashing). 8067 If we haven't already, we trigger calculateUnitRatios(), which runs once per element per call. */ 8068 elementUnitConversionData = elementUnitConversionData || calculateUnitRatios(); 8069 8070 /* The following RegEx matches CSS properties that have their % values measured relative to the x-axis. */ 8071 /* Note: W3C spec mandates that all of margin and padding's properties (even top and bottom) are %-relative to the *width* of the parent element. */ 8072 var axis = (/margin|padding|left|right|width|text|word|letter/i.test(property) || /X$/.test(property) || property === "x") ? "x" : "y"; 8073 8074 /* In order to avoid generating n^2 bespoke conversion functions, unit conversion is a two-step process: 8075 1) Convert startValue into pixels. 2) Convert this new pixel value into endValue's unit type. */ 8076 switch (startValueUnitType) { 8077 case "%": 8078 /* Note: translateX and translateY are the only properties that are %-relative to an element's own dimensions -- not its parent's dimensions. 8079 Velocity does not include a special conversion process to account for this behavior. Therefore, animating translateX/Y from a % value 8080 to a non-% value will produce an incorrect start value. Fortunately, this sort of cross-unit conversion is rarely done by users in practice. */ 8081 startValue *= (axis === "x" ? elementUnitConversionData.percentToPxWidth : elementUnitConversionData.percentToPxHeight); 8082 break; 8083 8084 case "px": 8085 /* px acts as our midpoint in the unit conversion process; do nothing. */ 8086 break; 8087 8088 default: 8089 startValue *= elementUnitConversionData[startValueUnitType + "ToPx"]; 8090 } 8091 8092 /* Invert the px ratios to convert into to the target unit. */ 8093 switch (endValueUnitType) { 8094 case "%": 8095 startValue *= 1 / (axis === "x" ? elementUnitConversionData.percentToPxWidth : elementUnitConversionData.percentToPxHeight); 8096 break; 8097 8098 case "px": 8099 /* startValue is already in px, do nothing; we're done. */ 8100 break; 8101 8102 default: 8103 startValue *= 1 / elementUnitConversionData[endValueUnitType + "ToPx"]; 8104 } 8105 } 8106 } 8107 8108 /********************* 8109 Relative Values 8110 *********************/ 8111 8112 /* Operator logic must be performed last since it requires unit-normalized start and end values. */ 8113 /* Note: Relative *percent values* do not behave how most people think; while one would expect "+=50%" 8114 to increase the property 1.5x its current value, it in fact increases the percent units in absolute terms: 8115 50 points is added on top of the current % value. */ 8116 switch (operator) { 8117 case "+": 8118 endValue = startValue + endValue; 8119 break; 8120 8121 case "-": 8122 endValue = startValue - endValue; 8123 break; 8124 8125 case "*": 8126 endValue = startValue * endValue; 8127 break; 8128 8129 case "/": 8130 endValue = startValue / endValue; 8131 break; 8132 } 8133 8134 /************************** 8135 tweensContainer Push 8136 **************************/ 8137 8138 /* Construct the per-property tween object, and push it to the element's tweensContainer. */ 8139 tweensContainer[property] = { 8140 rootPropertyValue: rootPropertyValue, 8141 startValue: startValue, 8142 currentValue: startValue, 8143 endValue: endValue, 8144 unitType: endValueUnitType, 8145 easing: easing 8146 }; 8147 if (pattern) { 8148 tweensContainer[property].pattern = pattern; 8149 } 8150 8151 if (Velocity.debug) { 8152 console.log("tweensContainer (" + property + "): " + JSON.stringify(tweensContainer[property]), element); 8153 } 8154 }; 8155 8156 /* Create a tween out of each property, and append its associated data to tweensContainer. */ 8157 for (var property in propertiesMap) { 8158 8159 if (!propertiesMap.hasOwnProperty(property)) { 8160 continue; 8161 } 8162 /* The original property name's format must be used for the parsePropertyValue() lookup, 8163 but we then use its camelCase styling to normalize it for manipulation. */ 8164 var propertyName = CSS.Names.camelCase(property), 8165 valueData = parsePropertyValue(propertiesMap[property]); 8166 8167 /* Find shorthand color properties that have been passed a hex string. */ 8168 /* Would be quicker to use CSS.Lists.colors.includes() if possible */ 8169 if (_inArray(CSS.Lists.colors, propertyName)) { 8170 /* Parse the value data for each shorthand. */ 8171 var endValue = valueData[0], 8172 easing = valueData[1], 8173 startValue = valueData[2]; 8174 8175 if (CSS.RegEx.isHex.test(endValue)) { 8176 /* Convert the hex strings into their RGB component arrays. */ 8177 var colorComponents = ["Red", "Green", "Blue"], 8178 endValueRGB = CSS.Values.hexToRgb(endValue), 8179 startValueRGB = startValue ? CSS.Values.hexToRgb(startValue) : undefined; 8180 8181 /* Inject the RGB component tweens into propertiesMap. */ 8182 for (var i = 0; i < colorComponents.length; i++) { 8183 var dataArray = [endValueRGB[i]]; 8184 8185 if (easing) { 8186 dataArray.push(easing); 8187 } 8188 8189 if (startValueRGB !== undefined) { 8190 dataArray.push(startValueRGB[i]); 8191 } 8192 8193 fixPropertyValue(propertyName + colorComponents[i], dataArray); 8194 } 8195 /* If we have replaced a shortcut color value then don't update the standard property name */ 8196 continue; 8197 } 8198 } 8199 fixPropertyValue(propertyName, valueData); 8200 } 8201 8202 /* Along with its property data, store a reference to the element itself onto tweensContainer. */ 8203 tweensContainer.element = element; 8204 } 8205 8206 /***************** 8207 Call Push 8208 *****************/ 8209 8210 /* Note: tweensContainer can be empty if all of the properties in this call's property map were skipped due to not 8211 being supported by the browser. The element property is used for checking that the tweensContainer has been appended to. */ 8212 if (tweensContainer.element) { 8213 /* Apply the "velocity-animating" indicator class. */ 8214 CSS.Values.addClass(element, "velocity-animating"); 8215 8216 /* The call array houses the tweensContainers for each element being animated in the current call. */ 8217 call.push(tweensContainer); 8218 8219 data = Data(element); 8220 8221 if (data) { 8222 /* Store the tweensContainer and options if we're working on the default effects queue, so that they can be used by the reverse command. */ 8223 if (opts.queue === "") { 8224 8225 data.tweensContainer = tweensContainer; 8226 data.opts = opts; 8227 } 8228 8229 /* Switch on the element's animating flag. */ 8230 data.isAnimating = true; 8231 } 8232 8233 /* Once the final element in this call's element set has been processed, push the call array onto 8234 Velocity.State.calls for the animation tick to immediately begin processing. */ 8235 if (elementsIndex === elementsLength - 1) { 8236 /* Add the current call plus its associated metadata (the element set and the call's options) onto the global call container. 8237 Anything on this call container is subjected to tick() processing. */ 8238 Velocity.State.calls.push([call, elements, opts, null, promiseData.resolver, null, 0]); 8239 8240 /* If the animation tick isn't running, start it. (Velocity shuts it off when there are no active calls to process.) */ 8241 if (Velocity.State.isTicking === false) { 8242 Velocity.State.isTicking = true; 8243 8244 /* Start the tick loop. */ 8245 tick(); 8246 } 8247 } else { 8248 elementsIndex++; 8249 } 8250 } 8251 } 8252 8253 /* When the queue option is set to false, the call skips the element's queue and fires immediately. */ 8254 if (opts.queue === false) { 8255 /* Since this buildQueue call doesn't respect the element's existing queue (which is where a delay option would have been appended), 8256 we manually inject the delay property here with an explicit setTimeout. */ 8257 if (opts.delay) { 8258 8259 /* Temporarily store delayed elements to facilitate access for global pause/resume */ 8260 var callIndex = Velocity.State.delayedElements.count++; 8261 Velocity.State.delayedElements[callIndex] = element; 8262 8263 var delayComplete = (function(index) { 8264 return function() { 8265 /* Clear the temporary element */ 8266 Velocity.State.delayedElements[index] = false; 8267 8268 /* Finally, issue the call */ 8269 buildQueue(); 8270 }; 8271 })(callIndex); 8272 8273 Data(element).delayBegin = (new Date()).getTime(); 8274 Data(element).delay = parseFloat(opts.delay); 8275 Data(element).delayTimer = { 8276 setTimeout: setTimeout(buildQueue, parseFloat(opts.delay)), 8277 next: delayComplete 8278 }; 8279 } else { 8280 buildQueue(); 8281 } 8282 /* Otherwise, the call undergoes element queueing as normal. */ 8283 /* Note: To interoperate with jQuery, Velocity uses jQuery's own $.queue() stack for queuing logic. */ 8284 } else { 8285 $.queue(element, opts.queue, function(next, clearQueue) { 8286 /* If the clearQueue flag was passed in by the stop command, resolve this call's promise. (Promises can only be resolved once, 8287 so it's fine if this is repeatedly triggered for each element in the associated call.) */ 8288 if (clearQueue === true) { 8289 if (promiseData.promise) { 8290 promiseData.resolver(elements); 8291 } 8292 8293 /* Do not continue with animation queueing. */ 8294 return true; 8295 } 8296 8297 /* This flag indicates to the upcoming completeCall() function that this queue entry was initiated by Velocity. 8298 See completeCall() for further details. */ 8299 Velocity.velocityQueueEntryFlag = true; 8300 8301 buildQueue(next); 8302 }); 8303 } 8304 8305 /********************* 8306 Auto-Dequeuing 8307 *********************/ 8308 8309 /* As per jQuery's $.queue() behavior, to fire the first non-custom-queue entry on an element, the element 8310 must be dequeued if its queue stack consists *solely* of the current call. (This can be determined by checking 8311 for the "inprogress" item that jQuery prepends to active queue stack arrays.) Regardless, whenever the element's 8312 queue is further appended with additional items -- including $.delay()'s or even $.animate() calls, the queue's 8313 first entry is automatically fired. This behavior contrasts that of custom queues, which never auto-fire. */ 8314 /* Note: When an element set is being subjected to a non-parallel Velocity call, the animation will not begin until 8315 each one of the elements in the set has reached the end of its individually pre-existing queue chain. */ 8316 /* Note: Unfortunately, most people don't fully grasp jQuery's powerful, yet quirky, $.queue() function. 8317 Lean more here: http://stackoverflow.com/questions/1058158/can-somebody-explain-jquery-queue-to-me */ 8318 if ((opts.queue === "" || opts.queue === "fx") && $.queue(element)[0] !== "inprogress") { 8319 $.dequeue(element); 8320 } 8321 } 8322 8323 /************************** 8324 Element Set Iteration 8325 **************************/ 8326 8327 /* If the "nodeType" property exists on the elements variable, we're animating a single element. 8328 Place it in an array so that $.each() can iterate over it. */ 8329 $.each(elements, function(i, element) { 8330 /* Ensure each element in a set has a nodeType (is a real element) to avoid throwing errors. */ 8331 if (Type.isNode(element)) { 8332 processElement(element, i); 8333 } 8334 }); 8335 8336 /****************** 8337 Option: Loop 8338 ******************/ 8339 8340 /* The loop option accepts an integer indicating how many times the element should loop between the values in the 8341 current call's properties map and the element's property values prior to this call. */ 8342 /* Note: The loop option's logic is performed here -- after element processing -- because the current call needs 8343 to undergo its queue insertion prior to the loop option generating its series of constituent "reverse" calls, 8344 which chain after the current call. Two reverse calls (two "alternations") constitute one loop. */ 8345 opts = $.extend({}, Velocity.defaults, options); 8346 opts.loop = parseInt(opts.loop, 10); 8347 var reverseCallsCount = (opts.loop * 2) - 1; 8348 8349 if (opts.loop) { 8350 /* Double the loop count to convert it into its appropriate number of "reverse" calls. 8351 Subtract 1 from the resulting value since the current call is included in the total alternation count. */ 8352 for (var x = 0; x < reverseCallsCount; x++) { 8353 /* Since the logic for the reverse action occurs inside Queueing and therefore this call's options object 8354 isn't parsed until then as well, the current call's delay option must be explicitly passed into the reverse 8355 call so that the delay logic that occurs inside *Pre-Queueing* can process it. */ 8356 var reverseOptions = { 8357 delay: opts.delay, 8358 progress: opts.progress 8359 }; 8360 8361 /* If a complete callback was passed into this call, transfer it to the loop redirect's final "reverse" call 8362 so that it's triggered when the entire redirect is complete (and not when the very first animation is complete). */ 8363 if (x === reverseCallsCount - 1) { 8364 reverseOptions.display = opts.display; 8365 reverseOptions.visibility = opts.visibility; 8366 reverseOptions.complete = opts.complete; 8367 } 8368 8369 animate(elements, "reverse", reverseOptions); 8370 } 8371 } 8372 8373 /*************** 8374 Chaining 8375 ***************/ 8376 8377 /* Return the elements back to the call chain, with wrapped elements taking precedence in case Velocity was called via the $.fn. extension. */ 8378 return getChain(); 8379 }; 8380 8381 /* Turn Velocity into the animation function, extended with the pre-existing Velocity object. */ 8382 Velocity = $.extend(animate, Velocity); 8383 /* For legacy support, also expose the literal animate method. */ 8384 Velocity.animate = animate; 8385 8386 /************** 8387 Timing 8388 **************/ 8389 8390 /* Ticker function. */ 8391 var ticker = window.requestAnimationFrame || rAFShim; 8392 8393 /* Inactive browser tabs pause rAF, which results in all active animations immediately sprinting to their completion states when the tab refocuses. 8394 To get around this, we dynamically switch rAF to setTimeout (which the browser *doesn't* pause) when the tab loses focus. We skip this for mobile 8395 devices to avoid wasting battery power on inactive tabs. */ 8396 /* Note: Tab focus detection doesn't work on older versions of IE, but that's okay since they don't support rAF to begin with. */ 8397 if (!Velocity.State.isMobile && document.hidden !== undefined) { 8398 var updateTicker = function() { 8399 /* Reassign the rAF function (which the global tick() function uses) based on the tab's focus state. */ 8400 if (document.hidden) { 8401 ticker = function(callback) { 8402 /* The tick function needs a truthy first argument in order to pass its internal timestamp check. */ 8403 return setTimeout(function() { 8404 callback(true); 8405 }, 16); 8406 }; 8407 8408 /* The rAF loop has been paused by the browser, so we manually restart the tick. */ 8409 tick(); 8410 } else { 8411 ticker = window.requestAnimationFrame || rAFShim; 8412 } 8413 }; 8414 8415 /* Page could be sitting in the background at this time (i.e. opened as new tab) so making sure we use correct ticker from the start */ 8416 updateTicker(); 8417 8418 /* And then run check again every time visibility changes */ 8419 document.addEventListener("visibilitychange", updateTicker); 8420 } 8421 8422 /************ 8423 Tick 8424 ************/ 8425 8426 /* Note: All calls to Velocity are pushed to the Velocity.State.calls array, which is fully iterated through upon each tick. */ 8427 function tick(timestamp) { 8428 /* An empty timestamp argument indicates that this is the first tick occurence since ticking was turned on. 8429 We leverage this metadata to fully ignore the first tick pass since RAF's initial pass is fired whenever 8430 the browser's next tick sync time occurs, which results in the first elements subjected to Velocity 8431 calls being animated out of sync with any elements animated immediately thereafter. In short, we ignore 8432 the first RAF tick pass so that elements being immediately consecutively animated -- instead of simultaneously animated 8433 by the same Velocity call -- are properly batched into the same initial RAF tick and consequently remain in sync thereafter. */ 8434 if (timestamp) { 8435 /* We normally use RAF's high resolution timestamp but as it can be significantly offset when the browser is 8436 under high stress we give the option for choppiness over allowing the browser to drop huge chunks of frames. 8437 We use performance.now() and shim it if it doesn't exist for when the tab is hidden. */ 8438 var timeCurrent = Velocity.timestamp && timestamp !== true ? timestamp : performance.now(); 8439 8440 /******************** 8441 Call Iteration 8442 ********************/ 8443 8444 var callsLength = Velocity.State.calls.length; 8445 8446 /* To speed up iterating over this array, it is compacted (falsey items -- calls that have completed -- are removed) 8447 when its length has ballooned to a point that can impact tick performance. This only becomes necessary when animation 8448 has been continuous with many elements over a long period of time; whenever all active calls are completed, completeCall() clears Velocity.State.calls. */ 8449 if (callsLength > 10000) { 8450 Velocity.State.calls = compactSparseArray(Velocity.State.calls); 8451 callsLength = Velocity.State.calls.length; 8452 } 8453 8454 /* Iterate through each active call. */ 8455 for (var i = 0; i < callsLength; i++) { 8456 /* When a Velocity call is completed, its Velocity.State.calls entry is set to false. Continue on to the next call. */ 8457 if (!Velocity.State.calls[i]) { 8458 continue; 8459 } 8460 8461 /************************ 8462 Call-Wide Variables 8463 ************************/ 8464 8465 var callContainer = Velocity.State.calls[i], 8466 call = callContainer[0], 8467 opts = callContainer[2], 8468 timeStart = callContainer[3], 8469 firstTick = !timeStart, 8470 tweenDummyValue = null, 8471 pauseObject = callContainer[5], 8472 millisecondsEllapsed = callContainer[6]; 8473 8474 8475 8476 /* If timeStart is undefined, then this is the first time that this call has been processed by tick(). 8477 We assign timeStart now so that its value is as close to the real animation start time as possible. 8478 (Conversely, had timeStart been defined when this call was added to Velocity.State.calls, the delay 8479 between that time and now would cause the first few frames of the tween to be skipped since 8480 percentComplete is calculated relative to timeStart.) */ 8481 /* Further, subtract 16ms (the approximate resolution of RAF) from the current time value so that the 8482 first tick iteration isn't wasted by animating at 0% tween completion, which would produce the 8483 same style value as the element's current value. */ 8484 if (!timeStart) { 8485 timeStart = Velocity.State.calls[i][3] = timeCurrent - 16; 8486 } 8487 8488 /* If a pause object is present, skip processing unless it has been set to resume */ 8489 if (pauseObject) { 8490 if (pauseObject.resume === true) { 8491 /* Update the time start to accomodate the paused completion amount */ 8492 timeStart = callContainer[3] = Math.round(timeCurrent - millisecondsEllapsed - 16); 8493 8494 /* Remove pause object after processing */ 8495 callContainer[5] = null; 8496 } else { 8497 continue; 8498 } 8499 } 8500 8501 millisecondsEllapsed = callContainer[6] = timeCurrent - timeStart; 8502 8503 /* The tween's completion percentage is relative to the tween's start time, not the tween's start value 8504 (which would result in unpredictable tween durations since JavaScript's timers are not particularly accurate). 8505 Accordingly, we ensure that percentComplete does not exceed 1. */ 8506 var percentComplete = Math.min((millisecondsEllapsed) / opts.duration, 1); 8507 8508 /********************** 8509 Element Iteration 8510 **********************/ 8511 8512 /* For every call, iterate through each of the elements in its set. */ 8513 for (var j = 0, callLength = call.length; j < callLength; j++) { 8514 var tweensContainer = call[j], 8515 element = tweensContainer.element; 8516 8517 /* Check to see if this element has been deleted midway through the animation by checking for the 8518 continued existence of its data cache. If it's gone, or the element is currently paused, skip animating this element. */ 8519 if (!Data(element)) { 8520 continue; 8521 } 8522 8523 var transformPropertyExists = false; 8524 8525 /********************************** 8526 Display & Visibility Toggling 8527 **********************************/ 8528 8529 /* If the display option is set to non-"none", set it upfront so that the element can become visible before tweening begins. 8530 (Otherwise, display's "none" value is set in completeCall() once the animation has completed.) */ 8531 if (opts.display !== undefined && opts.display !== null && opts.display !== "none") { 8532 if (opts.display === "flex") { 8533 var flexValues = ["-webkit-box", "-moz-box", "-ms-flexbox", "-webkit-flex"]; 8534 8535 $.each(flexValues, function(i, flexValue) { 8536 CSS.setPropertyValue(element, "display", flexValue); 8537 }); 8538 } 8539 8540 CSS.setPropertyValue(element, "display", opts.display); 8541 } 8542 8543 /* Same goes with the visibility option, but its "none" equivalent is "hidden". */ 8544 if (opts.visibility !== undefined && opts.visibility !== "hidden") { 8545 CSS.setPropertyValue(element, "visibility", opts.visibility); 8546 } 8547 8548 /************************ 8549 Property Iteration 8550 ************************/ 8551 8552 /* For every element, iterate through each property. */ 8553 for (var property in tweensContainer) { 8554 /* Note: In addition to property tween data, tweensContainer contains a reference to its associated element. */ 8555 if (tweensContainer.hasOwnProperty(property) && property !== "element") { 8556 var tween = tweensContainer[property], 8557 currentValue, 8558 /* Easing can either be a pre-genereated function or a string that references a pre-registered easing 8559 on the Velocity.Easings object. In either case, return the appropriate easing *function*. */ 8560 easing = Type.isString(tween.easing) ? Velocity.Easings[tween.easing] : tween.easing; 8561 8562 /****************************** 8563 Current Value Calculation 8564 ******************************/ 8565 8566 if (Type.isString(tween.pattern)) { 8567 var patternReplace = percentComplete === 1 ? 8568 function($0, index, round) { 8569 var result = tween.endValue[index]; 8570 8571 return round ? Math.round(result) : result; 8572 } : 8573 function($0, index, round) { 8574 var startValue = tween.startValue[index], 8575 tweenDelta = tween.endValue[index] - startValue, 8576 result = startValue + (tweenDelta * easing(percentComplete, opts, tweenDelta)); 8577 8578 return round ? Math.round(result) : result; 8579 }; 8580 8581 currentValue = tween.pattern.replace(/{(\d+)(!)?}/g, patternReplace); 8582 } else if (percentComplete === 1) { 8583 /* If this is the last tick pass (if we've reached 100% completion for this tween), 8584 ensure that currentValue is explicitly set to its target endValue so that it's not subjected to any rounding. */ 8585 currentValue = tween.endValue; 8586 } else { 8587 /* Otherwise, calculate currentValue based on the current delta from startValue. */ 8588 var tweenDelta = tween.endValue - tween.startValue; 8589 8590 currentValue = tween.startValue + (tweenDelta * easing(percentComplete, opts, tweenDelta)); 8591 /* If no value change is occurring, don't proceed with DOM updating. */ 8592 } 8593 if (!firstTick && (currentValue === tween.currentValue)) { 8594 continue; 8595 } 8596 8597 tween.currentValue = currentValue; 8598 8599 /* If we're tweening a fake 'tween' property in order to log transition values, update the one-per-call variable so that 8600 it can be passed into the progress callback. */ 8601 if (property === "tween") { 8602 tweenDummyValue = currentValue; 8603 } else { 8604 /****************** 8605 Hooks: Part I 8606 ******************/ 8607 var hookRoot; 8608 8609 /* For hooked properties, the newly-updated rootPropertyValueCache is cached onto the element so that it can be used 8610 for subsequent hooks in this call that are associated with the same root property. If we didn't cache the updated 8611 rootPropertyValue, each subsequent update to the root property in this tick pass would reset the previous hook's 8612 updates to rootPropertyValue prior to injection. A nice performance byproduct of rootPropertyValue caching is that 8613 subsequently chained animations using the same hookRoot but a different hook can use this cached rootPropertyValue. */ 8614 if (CSS.Hooks.registered[property]) { 8615 hookRoot = CSS.Hooks.getRoot(property); 8616 8617 var rootPropertyValueCache = Data(element).rootPropertyValueCache[hookRoot]; 8618 8619 if (rootPropertyValueCache) { 8620 tween.rootPropertyValue = rootPropertyValueCache; 8621 } 8622 } 8623 8624 /***************** 8625 DOM Update 8626 *****************/ 8627 8628 /* setPropertyValue() returns an array of the property name and property value post any normalization that may have been performed. */ 8629 /* Note: To solve an IE<=8 positioning bug, the unit type is dropped when setting a property value of 0. */ 8630 var adjustedSetData = CSS.setPropertyValue(element, /* SET */ 8631 property, 8632 tween.currentValue + (IE < 9 && parseFloat(currentValue) === 0 ? "" : tween.unitType), 8633 tween.rootPropertyValue, 8634 tween.scrollData); 8635 8636 /******************* 8637 Hooks: Part II 8638 *******************/ 8639 8640 /* Now that we have the hook's updated rootPropertyValue (the post-processed value provided by adjustedSetData), cache it onto the element. */ 8641 if (CSS.Hooks.registered[property]) { 8642 /* Since adjustedSetData contains normalized data ready for DOM updating, the rootPropertyValue needs to be re-extracted from its normalized form. ?? */ 8643 if (CSS.Normalizations.registered[hookRoot]) { 8644 Data(element).rootPropertyValueCache[hookRoot] = CSS.Normalizations.registered[hookRoot]("extract", null, adjustedSetData[1]); 8645 } else { 8646 Data(element).rootPropertyValueCache[hookRoot] = adjustedSetData[1]; 8647 } 8648 } 8649 8650 /*************** 8651 Transforms 8652 ***************/ 8653 8654 /* Flag whether a transform property is being animated so that flushTransformCache() can be triggered once this tick pass is complete. */ 8655 if (adjustedSetData[0] === "transform") { 8656 transformPropertyExists = true; 8657 } 8658 8659 } 8660 } 8661 } 8662 8663 /**************** 8664 mobileHA 8665 ****************/ 8666 8667 /* If mobileHA is enabled, set the translate3d transform to null to force hardware acceleration. 8668 It's safe to override this property since Velocity doesn't actually support its animation (hooks are used in its place). */ 8669 if (opts.mobileHA) { 8670 /* Don't set the null transform hack if we've already done so. */ 8671 if (Data(element).transformCache.translate3d === undefined) { 8672 /* All entries on the transformCache object are later concatenated into a single transform string via flushTransformCache(). */ 8673 Data(element).transformCache.translate3d = "(0px, 0px, 0px)"; 8674 8675 transformPropertyExists = true; 8676 } 8677 } 8678 8679 if (transformPropertyExists) { 8680 CSS.flushTransformCache(element); 8681 } 8682 } 8683 8684 /* The non-"none" display value is only applied to an element once -- when its associated call is first ticked through. 8685 Accordingly, it's set to false so that it isn't re-processed by this call in the next tick. */ 8686 if (opts.display !== undefined && opts.display !== "none") { 8687 Velocity.State.calls[i][2].display = false; 8688 } 8689 if (opts.visibility !== undefined && opts.visibility !== "hidden") { 8690 Velocity.State.calls[i][2].visibility = false; 8691 } 8692 8693 /* Pass the elements and the timing data (percentComplete, msRemaining, timeStart, tweenDummyValue) into the progress callback. */ 8694 if (opts.progress) { 8695 opts.progress.call(callContainer[1], 8696 callContainer[1], 8697 percentComplete, 8698 Math.max(0, (timeStart + opts.duration) - timeCurrent), 8699 timeStart, 8700 tweenDummyValue); 8701 } 8702 8703 /* If this call has finished tweening, pass its index to completeCall() to handle call cleanup. */ 8704 if (percentComplete === 1) { 8705 completeCall(i); 8706 } 8707 } 8708 } 8709 8710 /* Note: completeCall() sets the isTicking flag to false when the last call on Velocity.State.calls has completed. */ 8711 if (Velocity.State.isTicking) { 8712 ticker(tick); 8713 } 8714 } 8715 8716 /********************** 8717 Call Completion 8718 **********************/ 8719 8720 /* Note: Unlike tick(), which processes all active calls at once, call completion is handled on a per-call basis. */ 8721 function completeCall(callIndex, isStopped) { 8722 /* Ensure the call exists. */ 8723 if (!Velocity.State.calls[callIndex]) { 8724 return false; 8725 } 8726 8727 /* Pull the metadata from the call. */ 8728 var call = Velocity.State.calls[callIndex][0], 8729 elements = Velocity.State.calls[callIndex][1], 8730 opts = Velocity.State.calls[callIndex][2], 8731 resolver = Velocity.State.calls[callIndex][4]; 8732 8733 var remainingCallsExist = false; 8734 8735 /************************* 8736 Element Finalization 8737 *************************/ 8738 8739 for (var i = 0, callLength = call.length; i < callLength; i++) { 8740 var element = call[i].element; 8741 8742 /* If the user set display to "none" (intending to hide the element), set it now that the animation has completed. */ 8743 /* Note: display:none isn't set when calls are manually stopped (via Velocity("stop"). */ 8744 /* Note: Display gets ignored with "reverse" calls and infinite loops, since this behavior would be undesirable. */ 8745 if (!isStopped && !opts.loop) { 8746 if (opts.display === "none") { 8747 CSS.setPropertyValue(element, "display", opts.display); 8748 } 8749 8750 if (opts.visibility === "hidden") { 8751 CSS.setPropertyValue(element, "visibility", opts.visibility); 8752 } 8753 } 8754 8755 /* If the element's queue is empty (if only the "inprogress" item is left at position 0) or if its queue is about to run 8756 a non-Velocity-initiated entry, turn off the isAnimating flag. A non-Velocity-initiatied queue entry's logic might alter 8757 an element's CSS values and thereby cause Velocity's cached value data to go stale. To detect if a queue entry was initiated by Velocity, 8758 we check for the existence of our special Velocity.queueEntryFlag declaration, which minifiers won't rename since the flag 8759 is assigned to jQuery's global $ object and thus exists out of Velocity's own scope. */ 8760 var data = Data(element); 8761 8762 if (opts.loop !== true && ($.queue(element)[1] === undefined || !/\.velocityQueueEntryFlag/i.test($.queue(element)[1]))) { 8763 /* The element may have been deleted. Ensure that its data cache still exists before acting on it. */ 8764 if (data) { 8765 data.isAnimating = false; 8766 /* Clear the element's rootPropertyValueCache, which will become stale. */ 8767 data.rootPropertyValueCache = {}; 8768 8769 var transformHAPropertyExists = false; 8770 /* If any 3D transform subproperty is at its default value (regardless of unit type), remove it. */ 8771 $.each(CSS.Lists.transforms3D, function(i, transformName) { 8772 var defaultValue = /^scale/.test(transformName) ? 1 : 0, 8773 currentValue = data.transformCache[transformName]; 8774 8775 if (data.transformCache[transformName] !== undefined && new RegExp("^\\(" + defaultValue + "[^.]").test(currentValue)) { 8776 transformHAPropertyExists = true; 8777 8778 delete data.transformCache[transformName]; 8779 } 8780 }); 8781 8782 /* Mobile devices have hardware acceleration removed at the end of the animation in order to avoid hogging the GPU's memory. */ 8783 if (opts.mobileHA) { 8784 transformHAPropertyExists = true; 8785 delete data.transformCache.translate3d; 8786 } 8787 8788 /* Flush the subproperty removals to the DOM. */ 8789 if (transformHAPropertyExists) { 8790 CSS.flushTransformCache(element); 8791 } 8792 8793 /* Remove the "velocity-animating" indicator class. */ 8794 CSS.Values.removeClass(element, "velocity-animating"); 8795 } 8796 } 8797 8798 /********************* 8799 Option: Complete 8800 *********************/ 8801 8802 /* Complete is fired once per call (not once per element) and is passed the full raw DOM element set as both its context and its first argument. */ 8803 /* Note: Callbacks aren't fired when calls are manually stopped (via Velocity("stop"). */ 8804 if (!isStopped && opts.complete && !opts.loop && (i === callLength - 1)) { 8805 /* We throw callbacks in a setTimeout so that thrown errors don't halt the execution of Velocity itself. */ 8806 try { 8807 opts.complete.call(elements, elements); 8808 } catch (error) { 8809 setTimeout(function() { 8810 throw error; 8811 }, 1); 8812 } 8813 } 8814 8815 /********************** 8816 Promise Resolving 8817 **********************/ 8818 8819 /* Note: Infinite loops don't return promises. */ 8820 if (resolver && opts.loop !== true) { 8821 resolver(elements); 8822 } 8823 8824 /**************************** 8825 Option: Loop (Infinite) 8826 ****************************/ 8827 8828 if (data && opts.loop === true && !isStopped) { 8829 /* If a rotateX/Y/Z property is being animated by 360 deg with loop:true, swap tween start/end values to enable 8830 continuous iterative rotation looping. (Otherise, the element would just rotate back and forth.) */ 8831 $.each(data.tweensContainer, function(propertyName, tweenContainer) { 8832 if (/^rotate/.test(propertyName) && ((parseFloat(tweenContainer.startValue) - parseFloat(tweenContainer.endValue)) % 360 === 0)) { 8833 var oldStartValue = tweenContainer.startValue; 8834 8835 tweenContainer.startValue = tweenContainer.endValue; 8836 tweenContainer.endValue = oldStartValue; 8837 } 8838 8839 if (/^backgroundPosition/.test(propertyName) && parseFloat(tweenContainer.endValue) === 100 && tweenContainer.unitType === "%") { 8840 tweenContainer.endValue = 0; 8841 tweenContainer.startValue = 100; 8842 } 8843 }); 8844 8845 Velocity(element, "reverse", {loop: true, delay: opts.delay}); 8846 } 8847 8848 /*************** 8849 Dequeueing 8850 ***************/ 8851 8852 /* Fire the next call in the queue so long as this call's queue wasn't set to false (to trigger a parallel animation), 8853 which would have already caused the next call to fire. Note: Even if the end of the animation queue has been reached, 8854 $.dequeue() must still be called in order to completely clear jQuery's animation queue. */ 8855 if (opts.queue !== false) { 8856 $.dequeue(element, opts.queue); 8857 } 8858 } 8859 8860 /************************ 8861 Calls Array Cleanup 8862 ************************/ 8863 8864 /* Since this call is complete, set it to false so that the rAF tick skips it. This array is later compacted via compactSparseArray(). 8865 (For performance reasons, the call is set to false instead of being deleted from the array: http://www.html5rocks.com/en/tutorials/speed/v8/) */ 8866 Velocity.State.calls[callIndex] = false; 8867 8868 /* Iterate through the calls array to determine if this was the final in-progress animation. 8869 If so, set a flag to end ticking and clear the calls array. */ 8870 for (var j = 0, callsLength = Velocity.State.calls.length; j < callsLength; j++) { 8871 if (Velocity.State.calls[j] !== false) { 8872 remainingCallsExist = true; 8873 8874 break; 8875 } 8876 } 8877 8878 if (remainingCallsExist === false) { 8879 /* tick() will detect this flag upon its next iteration and subsequently turn itself off. */ 8880 Velocity.State.isTicking = false; 8881 8882 /* Clear the calls array so that its length is reset. */ 8883 delete Velocity.State.calls; 8884 Velocity.State.calls = []; 8885 } 8886 } 8887 8888 /****************** 8889 Frameworks 8890 ******************/ 8891 8892 /* Both jQuery and Zepto allow their $.fn object to be extended to allow wrapped elements to be subjected to plugin calls. 8893 If either framework is loaded, register a "velocity" extension pointing to Velocity's core animate() method. Velocity 8894 also registers itself onto a global container (window.jQuery || window.Zepto || window) so that certain features are 8895 accessible beyond just a per-element scope. This master object contains an .animate() method, which is later assigned to $.fn 8896 (if jQuery or Zepto are present). Accordingly, Velocity can both act on wrapped DOM elements and stand alone for targeting raw DOM elements. */ 8897 global.Velocity = Velocity; 8898 8899 if (global !== window) { 8900 /* Assign the element function to Velocity's core animate() method. */ 8901 global.fn.velocity = animate; 8902 /* Assign the object function's defaults to Velocity's global defaults object. */ 8903 global.fn.velocity.defaults = Velocity.defaults; 8904 } 8905 8906 /*********************** 8907 Packaged Redirects 8908 ***********************/ 8909 8910 /* slideUp, slideDown */ 8911 $.each(["Down", "Up"], function(i, direction) { 8912 Velocity.Redirects["slide" + direction] = function(element, options, elementsIndex, elementsSize, elements, promiseData) { 8913 var opts = $.extend({}, options), 8914 begin = opts.begin, 8915 complete = opts.complete, 8916 inlineValues = {}, 8917 computedValues = {height: "", marginTop: "", marginBottom: "", paddingTop: "", paddingBottom: ""}; 8918 8919 if (opts.display === undefined) { 8920 /* Show the element before slideDown begins and hide the element after slideUp completes. */ 8921 /* Note: Inline elements cannot have dimensions animated, so they're reverted to inline-block. */ 8922 opts.display = (direction === "Down" ? (Velocity.CSS.Values.getDisplayType(element) === "inline" ? "inline-block" : "block") : "none"); 8923 } 8924 8925 opts.begin = function() { 8926 /* If the user passed in a begin callback, fire it now. */ 8927 if (elementsIndex === 0 && begin) { 8928 begin.call(elements, elements); 8929 } 8930 8931 /* Cache the elements' original vertical dimensional property values so that we can animate back to them. */ 8932 for (var property in computedValues) { 8933 if (!computedValues.hasOwnProperty(property)) { 8934 continue; 8935 } 8936 inlineValues[property] = element.style[property]; 8937 8938 /* For slideDown, use forcefeeding to animate all vertical properties from 0. For slideUp, 8939 use forcefeeding to start from computed values and animate down to 0. */ 8940 var propertyValue = CSS.getPropertyValue(element, property); 8941 computedValues[property] = (direction === "Down") ? [propertyValue, 0] : [0, propertyValue]; 8942 } 8943 8944 /* Force vertical overflow content to clip so that sliding works as expected. */ 8945 inlineValues.overflow = element.style.overflow; 8946 element.style.overflow = "hidden"; 8947 }; 8948 8949 opts.complete = function() { 8950 /* Reset element to its pre-slide inline values once its slide animation is complete. */ 8951 for (var property in inlineValues) { 8952 if (inlineValues.hasOwnProperty(property)) { 8953 element.style[property] = inlineValues[property]; 8954 } 8955 } 8956 8957 /* If the user passed in a complete callback, fire it now. */ 8958 if (elementsIndex === elementsSize - 1) { 8959 if (complete) { 8960 complete.call(elements, elements); 8961 } 8962 if (promiseData) { 8963 promiseData.resolver(elements); 8964 } 8965 } 8966 }; 8967 8968 Velocity(element, computedValues, opts); 8969 }; 8970 }); 8971 8972 /* fadeIn, fadeOut */ 8973 $.each(["In", "Out"], function(i, direction) { 8974 Velocity.Redirects["fade" + direction] = function(element, options, elementsIndex, elementsSize, elements, promiseData) { 8975 var opts = $.extend({}, options), 8976 complete = opts.complete, 8977 propertiesMap = {opacity: (direction === "In") ? 1 : 0}; 8978 8979 /* Since redirects are triggered individually for each element in the animated set, avoid repeatedly triggering 8980 callbacks by firing them only when the final element has been reached. */ 8981 if (elementsIndex !== 0) { 8982 opts.begin = null; 8983 } 8984 if (elementsIndex !== elementsSize - 1) { 8985 opts.complete = null; 8986 } else { 8987 opts.complete = function() { 8988 if (complete) { 8989 complete.call(elements, elements); 8990 } 8991 if (promiseData) { 8992 promiseData.resolver(elements); 8993 } 8994 }; 8995 } 8996 8997 /* If a display was passed in, use it. Otherwise, default to "none" for fadeOut or the element-specific default for fadeIn. */ 8998 /* Note: We allow users to pass in "null" to skip display setting altogether. */ 8999 if (opts.display === undefined) { 9000 opts.display = (direction === "In" ? "auto" : "none"); 9001 } 9002 9003 Velocity(this, propertiesMap, opts); 9004 }; 9005 }); 9006 9007 return Velocity; 9008 }((window.jQuery || window.Zepto || window), window, (window ? window.document : undefined)); 9009})); 9010 9011/****************** 9012 Known Issues 9013 ******************/ 9014 9015/* The CSS spec mandates that the translateX/Y/Z transforms are %-relative to the element itself -- not its parent. 9016 Velocity, however, doesn't make this distinction. Thus, converting to or from the % unit with these subproperties 9017 will produce an inaccurate conversion value. The same issue exists with the cx/cy attributes of SVG circles and ellipses. */ 9018 9019 9020/***/ }), 9021
9022/***/ "./gallery-slider/gallery-slider.js": 9023/*!******************************************!*\ 9024 !*** ./gallery-slider/gallery-slider.js ***! 9025 \******************************************/ 9026/*! no exports provided */ 9027/***/ (function(module, __webpack_exports__, __webpack_require__) { 9028 9029"use strict"; 9030__webpack_require__.r(__webpack_exports__); 9031/* harmony import */ var _upup_baseline_js_src_content_rotator_contentRotator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../upup-baseline/js/src/content-rotator/contentRotator */ "../../../upup-baseline/js/src/content-rotator/contentRotator.jsx"); 9032/* harmony import */ var _upup_baseline_js_src_content_rotator_slideRotator__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../upup-baseline/js/src/content-rotator/slideRotator */ "../../../upup-baseline/js/src/content-rotator/slideRotator.jsx"); 9033/* harmony import */ var _group_description_rotator__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./group-description-rotator */ "./gallery-slider/group-description-rotator.js"); 9034function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 9035 9036 9037 9038 9039/** 9040 * Pick up on multiple instances of the manager 9041 */ 9042 9043var gallerySliderManager = function gallerySliderManager() { 9044 _classCallCheck(this, gallerySliderManager); 9045 9046 // find all instances of gallery slider 9047 // manage these instances individually 9048 var gallerySliders = document.querySelectorAll('.group-gallery'); 9049 gallerySliders.forEach(function (gallery) { 9050 new gallerySlider(gallery); 9051 }); 9052}; 9053/** 9054 * Run one instance of the gallery slider 9055 * Set up slides, controls, etc. 9056 */ 9057 9058 9059var gallerySlider = function gallerySlider(galleryContainer) { 9060 var _this = this; 9061 9062 _classCallCheck(this, gallerySlider); 9063 9064 // set up controls and subcomponents to respond to those controls 9065 var slideContainer = galleryContainer.querySelector('.group-gallery__slider-images'); // CONTROLS 9066 // left/ right controls 9067 9068 var leftControl = galleryContainer.querySelector('.group-gallery__control--left'); 9069 var rightControl = galleryContainer.querySelector('.group-gallery__control--right'); // buttons for slide groups 9070 9071 var slideGroupButtons = Array.from(galleryContainer.querySelectorAll('.group-gallery__group-block')); // Subcomponents 9072 // Slide Rotator 9073 9074 this.slideRotator = new _upup_baseline_js_src_content_rotator_slideRotator__WEBPACK_IMPORTED_MODULE_1__["default"](slideContainer); // Description rotator - set active/ inactive when a certain slide index is reached - set these limits as data attributes 9075 9076 this.groupDescriptionRotator = new _group_description_rotator__WEBPACK_IMPORTED_MODULE_2__["default"](galleryContainer); // manage the content rotation - accounting for all controls and subcomponents 9077 9078 this.contentRotator = new _upup_baseline_js_src_content_rotator_contentRotator__WEBPACK_IMPORTED_MODULE_0__["default"](galleryContainer); 9079 this.contentRotator.registerSubComponent(this.slideRotator); 9080 this.contentRotator.registerSubComponent(this.groupDescriptionRotator); 9081 this.contentRotator.registerControl(leftControl, 'prev'); 9082 this.contentRotator.registerControl(rightControl, 'next'); 9083 9084 if (slideGroupButtons.length > 0) { 9085 slideGroupButtons.forEach(function (button, index) { 9086 var goToIndex = button.dataset.startingIndex; 9087 9088 _this.contentRotator.registerControl(button, 'goTo', goToIndex); 9089 }); 9090 } // start up at index 0 9091 9092 9093 this.contentRotator.goTo(0); 9094}; 9095 9096new gallerySliderManager(); 9097 9098/***/ }), 9099
9100/***/ "./gallery-slider/group-description-rotator.js": 9101/*!*****************************************************!*\ 9102 !*** ./gallery-slider/group-description-rotator.js ***! 9103 \*****************************************************/ 9104/*! exports provided: default */ 9105/***/ (function(module, __webpack_exports__, __webpack_require__) { 9106 9107"use strict"; 9108__webpack_require__.r(__webpack_exports__); 9109function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } 9110 9111function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } 9112 9113function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 9114 9115function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } 9116 9117function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } 9118 9119function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 9120 9121/** 9122 * Rotate through the group description blocks in the gallery slider 9123 * One block will apply for a subset of slides 9124 */ 9125var groupDescriptionRotator = /*#__PURE__*/function () { 9126 function groupDescriptionRotator(galleryContainer) { 9127 var _this = this; 9128 9129 _classCallCheck(this, groupDescriptionRotator); 9130 9131 _defineProperty(this, "handleResize", function (e) { 9132 _this.calculateContainerHeight(); 9133 9134 _this.calculateTitleHeight(); 9135 }); 9136 9137 this.blockRow = galleryContainer.querySelector('.group-gallery__groups-row'); 9138 this.blocks = Array.from(galleryContainer.querySelectorAll('.group-gallery__group-block')); // these objects will help us determine which block to make active 9139 9140 this.blockObjects = this.blocks.map(function (block) { 9141 return { 9142 el: block, 9143 contentContainer: block.querySelector('.group-gallery__group-block-content'), 9144 startingIndex: parseInt(block.dataset.startingIndex), 9145 endingIndex: parseInt(block.dataset.startingIndex) + parseInt(block.dataset.slideCount) - 1 9146 }; 9147 }); 9148 this.setup(); 9149 this.listen(); 9150 } 9151 9152 _createClass(groupDescriptionRotator, [{ 9153 key: "setup", 9154 value: function setup() { 9155 this.calculateContainerHeight(); 9156 this.calculateTitleHeight(); 9157 } 9158 }, { 9159 key: "listen", 9160 value: function listen() { 9161 window.addEventListener('resize', this.handleResize); 9162 } 9163 /** 9164 * On resize, adjust the height of the content row 9165 * Do this via a CSS variable 9166 * @param e 9167 */ 9168 9169 }, { 9170 key: "transitionTo", 9171 9172 /** 9173 * Receive an index to move to from the content rotator 9174 * @param index 9175 * @returns {Promise<void>} 9176 */ 9177 value: function () { 9178 var _transitionTo = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(index) { 9179 return regeneratorRuntime.wrap(function _callee$(_context) { 9180 while (1) { 9181 switch (_context.prev = _context.next) { 9182 case 0: 9183 if (!(this.blockObjects.length <= 0)) { 9184 _context.next = 3; 9185 break; 9186 } 9187 9188 console.error('No block objects were created - the group description rotator will not be doing anything...'); 9189 return _context.abrupt("return"); 9190 9191 case 3: 9192 // activate/ deactivate text blocks 9193 // set aria-hidden on content to trigger aria live section
9194 this.blockObjects.forEach(function (object) { 9195 if (index >= object.startingIndex && index <= object.endingIndex) { 9196 object.el.classList.add('active'); 9197 object.contentContainer.setAttribute('aria-hidden', false); 9198 } else { 9199 object.el.classList.remove('active'); 9200 object.contentContainer.setAttribute('aria-hidden', true); 9201 } 9202 }); 9203 9204 case 4: 9205 case "end": 9206 return _context.stop(); 9207 } 9208 } 9209 }, _callee, this); 9210 })); 9211 9212 function transitionTo(_x) { 9213 return _transitionTo.apply(this, arguments); 9214 } 9215 9216 return transitionTo; 9217 }() 9218 /** 9219 * Determine height of the content container needed to hold the tallest of the slider elements 9220 */ 9221 9222 }, { 9223 key: "calculateContainerHeight", 9224 value: function calculateContainerHeight() { 9225 var heightMax = 0; 9226 this.blocks.forEach(function (block) { 9227 var blockHeight = 0, 9228 isCurrentlyActive = block.classList.contains('active'); 9229 block.classList.add('active'); 9230 blockHeight = block.offsetHeight; 9231 9232 if (!isCurrentlyActive) { 9233 block.classList.remove('active'); 9234 } 9235 9236 if (blockHeight > heightMax) { 9237 heightMax = blockHeight; 9238 } 9239 }); 9240 this.blockRow.style.setProperty('--blockMinHeight', heightMax + 'px'); 9241 } 9242 /** 9243 * Determine the height of each block title 9244 */ 9245 9246 }, { 9247 key: "calculateTitleHeight", 9248 value: function calculateTitleHeight() { 9249 this.blocks.forEach(function (block) { 9250 var title = block.querySelector('.group-gallery__group-title'), 9251 titleHeight = title.offsetHeight; // this is set as a negative for its use in the css (Edge compat) 9252 9253 block.style.setProperty('--titleHeight', -titleHeight + 'px'); 9254 }); 9255 } 9256 }]); 9257 9258 return groupDescriptionRotator; 9259}(); 9260 9261/* harmony default export */ __webpack_exports__["default"] = (groupDescriptionRotator); 9262 9263/***/ })
9263, 9264 9265/***/ 2: 9266/*!*********************************************!*\ 9267 !*** multi ./gallery-slider/gallery-slider ***! 9268 \*********************************************/ 9269/*! no static exports found */ 9270/***/ (function(module, exports, __webpack_require__) { 9271 9272module.exports = __webpack_require__(/*! ./gallery-slider/gallery-slider */"./gallery-slider/gallery-slider.js"); 9273 9274 9275/***/ }) 9276 9277/******/ });
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.