PageSourceSearch

https://gardner-webb.edu/wp-content/themes/gardnerwebb-twenty/js/dist/gallerySlider.bundle.js?ver=1790854316

js gardner-webb.edu collected 2026-10-01 11:33:49 UTC 348,016 bytes, 9,277 lines download raw bytes

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.