PageSourceSearch

https://dehaakfabriekwebshop.nl/wp-content/themes/uncode/library/js/plugins.js?ver=566701535

js dehaakfabriekwebshop.nl collected 2026-09-27 02:05:15 UTC 1,868,865 bytes, 56,599 lines download raw bytes

vendor: 4,970 bytes, lines 1-161
1/* ----------------------------------------------------------
2 * Plugins
3 * ---------------------------------------------------------- */
4
5(function (global, factory) {
6  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
7  typeof define === 'function' && define.amd ? define(['exports'], factory) :
8  (global = global || self, factory(global.window = global.window || {}));
9}(this, (function (exports) { 'use strict';
10
11  function _inheritsLoose(subClass, superClass) {
12    subClass.prototype = Object.create(superClass.prototype);
13    subClass.prototype.constructor = subClass;
14    subClass.__proto__ = superClass;
15  }
16
17  function _assertThisInitialized(self) {
18    if (self === void 0) {
19      throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
20    }
21
22    return self;
23  }
24
25  /*!
26   * GSAP 3.12.5
27   * https://gsap.com
28   *
29   * @license Copyright 2008-2024, GreenSock. All rights reserved.
30   * Subject to the terms at https://gsap.com/standard-license or for
31   * Club GSAP members, the agreement issued with that membership.
32   * @author: Jack Doyle, [email protected]
33  */
34  var _config = {
35    autoSleep: 120,
36    force3D: "auto",
37    nullTargetWarn: 1,
38    units: {
39      lineHeight: ""
40    }
41  },
42      _defaults = {
43    duration: .5,
44    overwrite: false,
45    delay: 0
46  },
47      _suppressOverwrites,
48      _reverting,
49      _context,
50      _bigNum = 1e8,
51      _tinyNum = 1 / _bigNum,
52      _2PI = Math.PI * 2,
53      _HALF_PI = _2PI / 4,
54      _gsID = 0,
55      _sqrt = Math.sqrt,
56      _cos = Math.cos,
57      _sin = Math.sin,
58      _isString = function _isString(value) {
59    return typeof value === "string";
60  },
61      _isFunction = function _isFunction(value) {
62    return typeof value === "function";
63  },
64      _isNumber = function _isNumber(value) {
65    return typeof value === "number";
66  },
67      _isUndefined = function _isUndefined(value) {
68    return typeof value === "undefined";
69  },
70      _isObject = function _isObject(value) {
71    return typeof value === "object";
72  },
73      _isNotFalse = function _isNotFalse(value) {
74    return value !== false;
75  },
76      _windowExists = function _windowExists() {
77    return typeof window !== "undefined";
78  },
79      _isFuncOrString = function _isFuncOrString(value) {
80    return _isFunction(value) || _isString(value);
81  },
82      _isTypedArray = typeof ArrayBuffer === "function" && ArrayBuffer.isView || function () {},
83      _isArray = Array.isArray,
84      _strictNumExp = /(?:-?\.?\d|\.)+/gi,
85      _numExp = /[-+=.]*\d+[.e\-+]*\d*[e\-+]*\d*/g,
86      _numWithUnitExp = /[-+=.]*\d+[.e-]*\d*[a-z%]*/g,
87      _complexStringNumExp = /[-+=.]*\d+\.?\d*(?:e-|e\+)?\d*/gi,
88      _relExp = /[+-]=-?[.\d]+/,
89      _delimitedValueExp = /[^,'"\[\]\s]+/gi,
90      _unitExp = /^[+\-=e\s\d]*\d+[.\d]*([a-z]*|%)\s*$/i,
91      _globalTimeline,
92      _win,
93      _coreInitted,
94      _doc,
95      _globals = {},
96      _installScope = {},
97      _coreReady,
98      _install = function _install(scope) {
99    return (_installScope = _merge(scope, _globals)) && gsap;
100  },
101      _missingPlugin = function _missingPlugin(property, value) {
102    return console.warn("Invalid property", property, "set to", value, "Missing plugin? gsap.registerPlugin()");
103  },
104      _warn = function _warn(message, suppress) {
105    return !suppress && console.warn(message);
106  },
107      _addGlobal = function _addGlobal(name, obj) {
108    return name && (_globals[name] = obj) && _installScope && (_installScope[name] = obj) || _globals;
109  },
110      _emptyFunc = function _emptyFunc() {
111    return 0;
112  },
113      _startAtRevertConfig = {
114    suppressEvents: true,
115    isStart: true,
116    kill: false
117  },
118      _revertConfigNoKill = {
119    suppressEvents: true,
120    kill: false
121  },
122      _revertConfig = {
123    suppressEvents: true
124  },
125      _reservedProps = {},
126      _lazyTweens = [],
127      _lazyLookup = {},
128      _lastRenderedFrame,
129      _plugins = {},
130      _effects = {},
131      _nextGCFrame = 30,
132      _harnessPlugins = [],
133      _callbackNames = "",
134      _harness = function _harness(targets) {
135    var target = targets[0],
136        harnessPlugin,
137        i;
138    _isObject(target) || _isFunction(target) || (targets = [targets]);
139
140    if (!(harnessPlugin = (target._gsap || {}).harness)) {
141      i = _harnessPlugins.length;
142
143      while (i-- && !_harnessPlugins[i].targetTest(target)) {}
144
145      harnessPlugin = _harnessPlugins[i];
146    }
147
148    i = targets.length;
149
150    while (i--) {
151      targets[i] && (targets[i]._gsap || (targets[i]._gsap = new GSCache(targets[i], harnessPlugin))) || targets.splice(i, 1);
152    }
153
154    return targets;
155  },
156      _getCache = function _getCache(target) {
157    return target._gsap || _harness(toArray(target))[0]._gsap;
158  },
159      _getProperty = function _getProperty(target, property, v) {
160    return (v = target[property]) && _isFunction(v) ? target[property]() : _isUndefined(v) && target.getAttribute && target.getAttribute(property) || v;
161  },
vendor: 6,338 bytes, lines 162-371
162      _forEachName = function _forEachName(names, func) {
163    return (names = names.split(",")).forEach(func) || names;
164  },
165      _round = function _round(value) {
166    return Math.round(value * 100000) / 100000 || 0;
167  },
168      _roundPrecise = function _roundPrecise(value) {
169    return Math.round(value * 10000000) / 10000000 || 0;
170  },
171      _parseRelative = function _parseRelative(start, value) {
172    var operator = value.charAt(0),
173        end = parseFloat(value.substr(2));
174    start = parseFloat(start);
175    return operator === "+" ? start + end : operator === "-" ? start - end : operator === "*" ? start * end : start / end;
176  },
177      _arrayContainsAny = function _arrayContainsAny(toSearch, toFind) {
178    var l = toFind.length,
179        i = 0;
180
181    for (; toSearch.indexOf(toFind[i]) < 0 && ++i < l;) {}
182
183    return i < l;
184  },
185      _lazyRender = function _lazyRender() {
186    var l = _lazyTweens.length,
187        a = _lazyTweens.slice(0),
188        i,
189        tween;
190
191    _lazyLookup = {};
192    _lazyTweens.length = 0;
193
194    for (i = 0; i < l; i++) {
195      tween = a[i];
196      tween && tween._lazy && (tween.render(tween._lazy[0], tween._lazy[1], true)._lazy = 0);
197    }
198  },
199      _lazySafeRender = function _lazySafeRender(animation, time, suppressEvents, force) {
200    _lazyTweens.length && !_reverting && _lazyRender();
201    animation.render(time, suppressEvents, force || _reverting && time < 0 && (animation._initted || animation._startAt));
202    _lazyTweens.length && !_reverting && _lazyRender();
203  },
204      _numericIfPossible = function _numericIfPossible(value) {
205    var n = parseFloat(value);
206    return (n || n === 0) && (value + "").match(_delimitedValueExp).length < 2 ? n : _isString(value) ? value.trim() : value;
207  },
208      _passThrough = function _passThrough(p) {
209    return p;
210  },
211      _setDefaults = function _setDefaults(obj, defaults) {
212    for (var p in defaults) {
213      p in obj || (obj[p] = defaults[p]);
214    }
215
216    return obj;
217  },
218      _setKeyframeDefaults = function _setKeyframeDefaults(excludeDuration) {
219    return function (obj, defaults) {
220      for (var p in defaults) {
221        p in obj || p === "duration" && excludeDuration || p === "ease" || (obj[p] = defaults[p]);
222      }
223    };
224  },
225      _merge = function _merge(base, toMerge) {
226    for (var p in toMerge) {
227      base[p] = toMerge[p];
228    }
229
230    return base;
231  },
232      _mergeDeep = function _mergeDeep(base, toMerge) {
233    for (var p in toMerge) {
234      p !== "__proto__" && p !== "constructor" && p !== "prototype" && (base[p] = _isObject(toMerge[p]) ? _mergeDeep(base[p] || (base[p] = {}), toMerge[p]) : toMerge[p]);
235    }
236
237    return base;
238  },
239      _copyExcluding = function _copyExcluding(obj, excluding) {
240    var copy = {},
241        p;
242
243    for (p in obj) {
244      p in excluding || (copy[p] = obj[p]);
245    }
246
247    return copy;
248  },
249      _inheritDefaults = function _inheritDefaults(vars) {
250    var parent = vars.parent || _globalTimeline,
251        func = vars.keyframes ? _setKeyframeDefaults(_isArray(vars.keyframes)) : _setDefaults;
252
253    if (_isNotFalse(vars.inherit)) {
254      while (parent) {
255        func(vars, parent.vars.defaults);
256        parent = parent.parent || parent._dp;
257      }
258    }
259
260    return vars;
261  },
262      _arraysMatch = function _arraysMatch(a1, a2) {
263    var i = a1.length,
264        match = i === a2.length;
265
266    while (match && i-- && a1[i] === a2[i]) {}
267
268    return i < 0;
269  },
270      _addLinkedListItem = function _addLinkedListItem(parent, child, firstProp, lastProp, sortBy) {
271    if (firstProp === void 0) {
272      firstProp = "_first";
273    }
274
275    if (lastProp === void 0) {
276      lastProp = "_last";
277    }
278
279    var prev = parent[lastProp],
280        t;
281
282    if (sortBy) {
283      t = child[sortBy];
284
285      while (prev && prev[sortBy] > t) {
286        prev = prev._prev;
287      }
288    }
289
290    if (prev) {
291      child._next = prev._next;
292      prev._next = child;
293    } else {
294      child._next = parent[firstProp];
295      parent[firstProp] = child;
296    }
297
298    if (child._next) {
299      child._next._prev = child;
300    } else {
301      parent[lastProp] = child;
302    }
303
304    child._prev = prev;
305    child.parent = child._dp = parent;
306    return child;
307  },
308      _removeLinkedListItem = function _removeLinkedListItem(parent, child, firstProp, lastProp) {
309    if (firstProp === void 0) {
310      firstProp = "_first";
311    }
312
313    if (lastProp === void 0) {
314      lastProp = "_last";
315    }
316
317    var prev = child._prev,
318        next = child._next;
319
320    if (prev) {
321      prev._next = next;
322    } else if (parent[firstProp] === child) {
323      parent[firstProp] = next;
324    }
325
326    if (next) {
327      next._prev = prev;
328    } else if (parent[lastProp] === child) {
329      parent[lastProp] = prev;
330    }
331
332    child._next = child._prev = child.parent = null;
333  },
334      _removeFromParent = function _removeFromParent(child, onlyIfParentHasAutoRemove) {
335    child.parent && (!onlyIfParentHasAutoRemove || child.parent.autoRemoveChildren) && child.parent.remove && child.parent.remove(child);
336    child._act = 0;
337  },
338      _uncache = function _uncache(animation, child) {
339    if (animation && (!child || child._end > animation._dur || child._start < 0)) {
340      var a = animation;
341
342      while (a) {
343        a._dirty = 1;
344        a = a.parent;
345      }
346    }
347
348    return animation;
349  },
350      _recacheAncestors = function _recacheAncestors(animation) {
351    var parent = animation.parent;
352
353    while (parent && parent.parent) {
354      parent._dirty = 1;
355      parent.totalDuration();
356      parent = parent.parent;
357    }
358
359    return animation;
360  },
361      _rewindStartAt = function _rewindStartAt(tween, totalTime, suppressEvents, force) {
362    return tween._startAt && (_reverting ? tween._startAt.revert(_revertConfigNoKill) : tween.vars.immediateRender && !tween.vars.autoRevert || tween._startAt.render(totalTime, true, force));
363  },
364      _hasNoPausedAncestors = function _hasNoPausedAncestors(animation) {
365    return !animation || animation._ts && _hasNoPausedAncestors(animation.parent);
366  },
367      _elapsedCycleDuration = function _elapsedCycleDuration(animation) {
368    return animation._repeat ? _animationCycle(animation._tTime, animation = animation.duration() + animation._rDelay) * animation : 0;
369  },
370      _animationCycle = function _animationCycle(tTime, cycleDuration) {
371    var whole = Math.floor(tTime /= cycleDuration
vendor: 17,487 bytes, lines 371-839
371);
372    return tTime && whole === tTime ? whole - 1 : whole;
373  },
374      _parentToChildTotalTime = function _parentToChildTotalTime(parentTime, child) {
375    return (parentTime - child._start) * child._ts + (child._ts >= 0 ? 0 : child._dirty ? child.totalDuration() : child._tDur);
376  },
377      _setEnd = function _setEnd(animation) {
378    return animation._end = _roundPrecise(animation._start + (animation._tDur / Math.abs(animation._ts || animation._rts || _tinyNum) || 0));
379  },
380      _alignPlayhead = function _alignPlayhead(animation, totalTime) {
381    var parent = animation._dp;
382
383    if (parent && parent.smoothChildTiming && animation._ts) {
384      animation._start = _roundPrecise(parent._time - (animation._ts > 0 ? totalTime / animation._ts : ((animation._dirty ? animation.totalDuration() : animation._tDur) - totalTime) / -animation._ts));
385
386      _setEnd(animation);
387
388      parent._dirty || _uncache(parent, animation);
389    }
390
391    return animation;
392  },
393      _postAddChecks = function _postAddChecks(timeline, child) {
394    var t;
395
396    if (child._time || !child._dur && child._initted || child._start < timeline._time && (child._dur || !child.add)) {
397      t = _parentToChildTotalTime(timeline.rawTime(), child);
398
399      if (!child._dur || _clamp(0, child.totalDuration(), t) - child._tTime > _tinyNum) {
400        child.render(t, true);
401      }
402    }
403
404    if (_uncache(timeline, child)._dp && timeline._initted && timeline._time >= timeline._dur && timeline._ts) {
405      if (timeline._dur < timeline.duration()) {
406        t = timeline;
407
408        while (t._dp) {
409          t.rawTime() >= 0 && t.totalTime(t._tTime);
410          t = t._dp;
411        }
412      }
413
414      timeline._zTime = -_tinyNum;
415    }
416  },
417      _addToTimeline = function _addToTimeline(timeline, child, position, skipChecks) {
418    child.parent && _removeFromParent(child);
419    child._start = _roundPrecise((_isNumber(position) ? position : position || timeline !== _globalTimeline ? _parsePosition(timeline, position, child) : timeline._time) + child._delay);
420    child._end = _roundPrecise(child._start + (child.totalDuration() / Math.abs(child.timeScale()) || 0));
421
422    _addLinkedListItem(timeline, child, "_first", "_last", timeline._sort ? "_start" : 0);
423
424    _isFromOrFromStart(child) || (timeline._recent = child);
425    skipChecks || _postAddChecks(timeline, child);
426    timeline._ts < 0 && _alignPlayhead(timeline, timeline._tTime);
427    return timeline;
428  },
429      _scrollTrigger = function _scrollTrigger(animation, trigger) {
430    return (_globals.ScrollTrigger || _missingPlugin("scrollTrigger", trigger)) && _globals.ScrollTrigger.create(trigger, animation);
431  },
432      _attemptInitTween = function _attemptInitTween(tween, time, force, suppressEvents, tTime) {
433    _initTween(tween, time, tTime);
434
435    if (!tween._initted) {
436      return 1;
437    }
438
439    if (!force && tween._pt && !_reverting && (tween._dur && tween.vars.lazy !== false || !tween._dur && tween.vars.lazy) && _lastRenderedFrame !== _ticker.frame) {
440      _lazyTweens.push(tween);
441
442      tween._lazy = [tTime, suppressEvents];
443      return 1;
444    }
445  },
446      _parentPlayheadIsBeforeStart = function _parentPlayheadIsBeforeStart(_ref) {
447    var parent = _ref.parent;
448    return parent && parent._ts && parent._initted && !parent._lock && (parent.rawTime() < 0 || _parentPlayheadIsBeforeStart(parent));
449  },
450      _isFromOrFromStart = function _isFromOrFromStart(_ref2) {
451    var data = _ref2.data;
452    return data === "isFromStart" || data === "isStart";
453  },
454      _renderZeroDurationTween = function _renderZeroDurationTween(tween, totalTime, suppressEvents, force) {
455    var prevRatio = tween.ratio,
456        ratio = totalTime < 0 || !totalTime && (!tween._start && _parentPlayheadIsBeforeStart(tween) && !(!tween._initted && _isFromOrFromStart(tween)) || (tween._ts < 0 || tween._dp._ts < 0) && !_isFromOrFromStart(tween)) ? 0 : 1,
457        repeatDelay = tween._rDelay,
458        tTime = 0,
459        pt,
460        iteration,
461        prevIteration;
462
463    if (repeatDelay && tween._repeat) {
464      tTime = _clamp(0, tween._tDur, totalTime);
465      iteration = _animationCycle(tTime, repeatDelay);
466      tween._yoyo && iteration & 1 && (ratio = 1 - ratio);
467
468      if (iteration !== _animationCycle(tween._tTime, repeatDelay)) {
469        prevRatio = 1 - ratio;
470        tween.vars.repeatRefresh && tween._initted && tween.invalidate();
471      }
472    }
473
474    if (ratio !== prevRatio || _reverting || force || tween._zTime === _tinyNum || !totalTime && tween._zTime) {
475      if (!tween._initted && _attemptInitTween(tween, totalTime, force, suppressEvents, tTime)) {
476        return;
477      }
478
479      prevIteration = tween._zTime;
480      tween._zTime = totalTime || (suppressEvents ? _tinyNum : 0);
481      suppressEvents || (suppressEvents = totalTime && !prevIteration);
482      tween.ratio = ratio;
483      tween._from && (ratio = 1 - ratio);
484      tween._time = 0;
485      tween._tTime = tTime;
486      pt = tween._pt;
487
488      while (pt) {
489        pt.r(ratio, pt.d);
490        pt = pt._next;
491      }
492
493      totalTime < 0 && _rewindStartAt(tween, totalTime, suppressEvents, true);
494      tween._onUpdate && !suppressEvents && _callback(tween, "onUpdate");
495      tTime && tween._repeat && !suppressEvents && tween.parent && _callback(tween, "onRepeat");
496
497      if ((totalTime >= tween._tDur || totalTime < 0) && tween.ratio === ratio) {
498        ratio && _removeFromParent(tween, 1);
499
500        if (!suppressEvents && !_reverting) {
501          _callback(tween, ratio ? "onComplete" : "onReverseComplete", true);
502
503          tween._prom && tween._prom();
504        }
505      }
506    } else if (!tween._zTime) {
507      tween._zTime = totalTime;
508    }
509  },
510      _findNextPauseTween = function _findNextPauseTween(animation, prevTime, time) {
511    var child;
512
513    if (time > prevTime) {
514      child = animation._first;
515
516      while (child && child._start <= time) {
517        if (child.data === "isPause" && child._start > prevTime) {
518          return child;
519        }
520
521        child = child._next;
522      }
523    } else {
524      child = animation._last;
525
526      while (child && child._start >= time) {
527        if (child.data === "isPause" && child._start < prevTime) {
528          return child;
529        }
530
531        child = child._prev;
532      }
533    }
534  },
535      _setDuration = function _setDuration(animation, duration, skipUncache, leavePlayhead) {
536    var repeat = animation._repeat,
537        dur = _roundPrecise(duration) || 0,
538        totalProgress = animation._tTime / animation._tDur;
539    totalProgress && !leavePlayhead && (animation._time *= dur / animation._dur);
540    animation._dur = dur;
541    animation._tDur = !repeat ? dur : repeat < 0 ? 1e10 : _roundPrecise(dur * (repeat + 1) + animation._rDelay * repeat);
542    totalProgress > 0 && !leavePlayhead && _alignPlayhead(animation, animation._tTime = animation._tDur * totalProgress);
543    animation.parent && _setEnd(animation);
544    skipUncache || _uncache(animation.parent, animation);
545    return animation;
546  },
547      _onUpdateTotalDuration = function _onUpdateTotalDuration(animation) {
548    return animation instanceof Timeline ? _uncache(animation) : _setDuration(animation, animation._dur);
549  },
550      _zeroPosition = {
551    _start: 0,
552    endTime: _emptyFunc,
553    totalDuration: _emptyFunc
554  },
555      _parsePosition = function _parsePosition(animation, position, percentAnimation) {
556    var labels = animation.labels,
557        recent = animation._recent || _zeroPosition,
558        clippedDuration = animation.duration() >= _bigNum ? recent.endTime(false) : animation._dur,
559        i,
560        offset,
561        isPercent;
562
563    if (_isString(position) && (isNaN(position) || position in labels)) {
564      offset = position.charAt(0);
565      isPercent = position.substr(-1) === "%";
566      i = position.indexOf("=");
567
568      if (offset === "<" || offset === ">") {
569        i >= 0 && (position = position.replace(/=/, ""));
570        return (offset === "<" ? recent._start : recent.endTime(recent._repeat >= 0)) + (parseFloat(position.substr(1)) || 0) * (isPercent ? (i < 0 ? recent : percentAnimation).totalDuration() / 100 : 1);
571      }
572
573      if (i < 0) {
574        position in labels || (labels[position] = clippedDuration);
575        return labels[position];
576      }
577
578      offset = parseFloat(position.charAt(i - 1) + position.substr(i + 1));
579
580      if (isPercent && percentAnimation) {
581        offset = offset / 100 * (_isArray(percentAnimation) ? percentAnimation[0] : percentAnimation).totalDuration();
582      }
583
584      return i > 1 ? _parsePosition(animation, position.substr(0, i - 1), percentAnimation) + offset : clippedDuration + offset;
585    }
586
587    return position == null ? clippedDuration : +position;
588  },
589      _createTweenType = function _createTweenType(type, params, timeline) {
590    var isLegacy = _isNumber(params[1]),
591        varsIndex = (isLegacy ? 2 : 1) + (type < 2 ? 0 : 1),
592        vars = params[varsIndex],
593        irVars,
594        parent;
595
596    isLegacy && (vars.duration = params[1]);
597    vars.parent = timeline;
598
599    if (type) {
600      irVars = vars;
601      parent = timeline;
602
603      while (parent && !("immediateRender" in irVars)) {
604        irVars = parent.vars.defaults || {};
605        parent = _isNotFalse(parent.vars.inherit) && parent.parent;
606      }
607
608      vars.immediateRender = _isNotFalse(irVars.immediateRender);
609      type < 2 ? vars.runBackwards = 1 : vars.startAt = params[varsIndex - 1];
610    }
611
612    return new Tween(params[0], vars, params[varsIndex + 1]);
613  },
614      _conditionalReturn = function _conditionalReturn(value, func) {
615    return value || value === 0 ? func(value) : func;
616  },
617      _clamp = function _clamp(min, max, value) {
618    return value < min ? min : value > max ? max : value;
619  },
620      getUnit = function getUnit(value, v) {
621    return !_isString(value) || !(v = _unitExp.exec(value)) ? "" : v[1];
622  },
623      clamp = function clamp(min, max, value) {
624    return _conditionalReturn(value, function (v) {
625      return _clamp(min, max, v);
626    });
627  },
628      _slice = [].slice,
629      _isArrayLike = function _isArrayLike(value, nonEmpty) {
630    return value && _isObject(value) && "length" in value && (!nonEmpty && !value.length || value.length - 1 in value && _isObject(value[0])) && !value.nodeType && value !== _win;
631  },
632      _flatten = function _flatten(ar, leaveStrings, accumulator) {
633    if (accumulator === void 0) {
634      accumulator = [];
635    }
636
637    return ar.forEach(function (value) {
638      var _accumulator;
639
640      return _isString(value) && !leaveStrings || _isArrayLike(value, 1) ? (_accumulator = accumulator).push.apply(_accumulator, toArray(value)) : accumulator.push(value);
641    }) || accumulator;
642  },
643      toArray = function toArray(value, scope, leaveStrings) {
644    return _context && !scope && _context.selector ? _context.selector(value) : _isString(value) && !leaveStrings && (_coreInitted || !_wake()) ? _slice.call((scope || _doc).querySelectorAll(value), 0) : _isArray(value) ? _flatten(value, leaveStrings) : _isArrayLike(value) ? _slice.call(value, 0) : value ? [value] : [];
645  },
646      selector = function selector(value) {
647    value = toArray(value)[0] || _warn("Invalid scope") || {};
648    return function (v) {
649      var el = value.current || value.nativeElement || value;
650      return toArray(v, el.querySelectorAll ? el : el === value ? _warn("Invalid scope") || _doc.createElement("div") : value);
651    };
652  },
653      shuffle = function shuffle(a) {
654    return a.sort(function () {
655      return .5 - Math.random();
656    });
657  },
658      distribute = function distribute(v) {
659    if (_isFunction(v)) {
660      return v;
661    }
662
663    var vars = _isObject(v) ? v : {
664      each: v
665    },
666        ease = _parseEase(vars.ease),
667        from = vars.from || 0,
668        base = parseFloat(vars.base) || 0,
669        cache = {},
670        isDecimal = from > 0 && from < 1,
671        ratios = isNaN(from) || isDecimal,
672        axis = vars.axis,
673        ratioX = from,
674        ratioY = from;
675
676    if (_isString(from)) {
677      ratioX = ratioY = {
678        center: .5,
679        edges: .5,
680        end: 1
681      }[from] || 0;
682    } else if (!isDecimal && ratios) {
683      ratioX = from[0];
684      ratioY = from[1];
685    }
686
687    return function (i, target, a) {
688      var l = (a || vars).length,
689          distances = cache[l],
690          originX,
691          originY,
692          x,
693          y,
694          d,
695          j,
696          max,
697          min,
698          wrapAt;
699
700      if (!distances) {
701        wrapAt = vars.grid === "auto" ? 0 : (vars.grid || [1, _bigNum])[1];
702
703        if (!wrapAt) {
704          max = -_bigNum;
705
706          while (max < (max = a[wrapAt++].getBoundingClientRect().left) && wrapAt < l) {}
707
708          wrapAt < l && wrapAt--;
709        }
710
711        distances = cache[l] = [];
712        originX = ratios ? Math.min(wrapAt, l) * ratioX - .5 : from % wrapAt;
713        originY = wrapAt === _bigNum ? 0 : ratios ? l * ratioY / wrapAt - .5 : from / wrapAt | 0;
714        max = 0;
715        min = _bigNum;
716
717        for (j = 0; j < l; j++) {
718          x = j % wrapAt - originX;
719          y = originY - (j / wrapAt | 0);
720          distances[j] = d = !axis ? _sqrt(x * x + y * y) : Math.abs(axis === "y" ? y : x);
721          d > max && (max = d);
722          d < min && (min = d);
723        }
724
725        from === "random" && shuffle(distances);
726        distances.max = max - min;
727        distances.min = min;
728        distances.v = l = (parseFloat(vars.amount) || parseFloat(vars.each) * (wrapAt > l ? l - 1 : !axis ? Math.max(wrapAt, l / wrapAt) : axis === "y" ? l / wrapAt : wrapAt) || 0) * (from === "edges" ? -1 : 1);
729        distances.b = l < 0 ? base - l : base;
730        distances.u = getUnit(vars.amount || vars.each) || 0;
731        ease = ease && l < 0 ? _invertEase(ease) : ease;
732      }
733
734      l = (distances[i] - distances.min) / distances.max || 0;
735      return _roundPrecise(distances.b + (ease ? ease(l) : l) * distances.v) + distances.u;
736    };
737  },
738      _roundModifier = function _roundModifier(v) {
739    var p = Math.pow(10, ((v + "").split(".")[1] || "").length);
740    return function (raw) {
741      var n = _roundPrecise(Math.round(parseFloat(raw) / v) * v * p);
742
743      return (n - n % 1) / p + (_isNumber(raw) ? 0 : getUnit(raw));
744    };
745  },
746      snap = function snap(snapTo, value) {
747    var isArray = _isArray(snapTo),
748        radius,
749        is2D;
750
751    if (!isArray && _isObject(snapTo)) {
752      radius = isArray = snapTo.radius || _bigNum;
753
754      if (snapTo.values) {
755        snapTo = toArray(snapTo.values);
756
757        if (is2D = !_isNumber(snapTo[0])) {
758          radius *= radius;
759        }
760      } else {
761        snapTo = _roundModifier(snapTo.increment);
762      }
763    }
764
765    return _conditionalReturn(value, !isArray ? _roundModifier(snapTo) : _isFunction(snapTo) ? function (raw) {
766      is2D = snapTo(raw);
767      return Math.abs(is2D - raw) <= radius ? is2D : raw;
768    } : function (raw) {
769      var x = parseFloat(is2D ? raw.x : raw),
770          y = parseFloat(is2D ? raw.y : 0),
771          min = _bigNum,
772          closest = 0,
773          i = snapTo.length,
774          dx,
775          dy;
776
777      while (i--) {
778        if (is2D) {
779          dx = snapTo[i].x - x;
780          dy = snapTo[i].y - y;
781          dx = dx * dx + dy * dy;
782        } else {
783          dx = Math.abs(snapTo[i] - x);
784        }
785
786        if (dx < min) {
787          min = dx;
788          closest = i;
789        }
790      }
791
792      closest = !radius || min <= radius ? snapTo[closest] : raw;
793      return is2D || closest === raw || _isNumber(raw) ? closest : closest + getUnit(raw);
794    });
795  },
796      random = function random(min, max, roundingIncrement, returnFunction) {
797    return _conditionalReturn(_isArray(min) ? !max : roundingIncrement === true ? !!(roundingIncrement = 0) : !returnFunction, function () {
798      return _isArray(min) ? min[~~(Math.random() * min.length)] : (roundingIncrement = roundingIncrement || 1e-5) && (returnFunction = roundingIncrement < 1 ? Math.pow(10, (roundingIncrement + "").length - 2) : 1) && Math.floor(Math.round((min - roundingIncrement / 2 + Math.random() * (max - min + roundingIncrement * .99)) / roundingIncrement) * roundingIncrement * returnFunction) / returnFunction;
799    });
800  },
801      pipe = function pipe() {
802    for (var _len = arguments.length, functions = new Array(_len), _key = 0; _key < _len; _key++) {
803      functions[_key] = arguments[_key];
804    }
805
806    return function (value) {
807      return functions.reduce(function (v, f) {
808        return f(v);
809      }, value);
810    };
811  },
812      unitize = function unitize(func, unit) {
813    return function (value) {
814      return func(parseFloat(value)) + (unit || getUnit(value));
815    };
816  },
817      normalize = function normalize(min, max, value) {
818    return mapRange(min, max, 0, 1, value);
819  },
820      _wrapArray = function _wrapArray(a, wrapper, value) {
821    return _conditionalReturn(value, function (index) {
822      return a[~~wrapper(index)];
823    });
824  },
825      wrap = function wrap(min, max, value) {
826    var range = max - min;
827    return _isArray(min) ? _wrapArray(min, wrap(0, min.length), max) : _conditionalReturn(value, function (value) {
828      return (range + (value - min) % range) % range + min;
829    });
830  },
831      wrapYoyo = function wrapYoyo(min, max, value) {
832    var range = max - min,
833        total = range * 2;
834    return _isArray(min) ? _wrapArray(min, wrapYoyo(0, min.length - 1), max) : _conditionalReturn(value, function (value) {
835      value = (total + (value - min) % total) % total || 0;
836      return min + (value > range ? total - value : value);
837    });
838  },
839      _replaceRandom = function _replaceRandom(
vendor: 531 bytes, lines 839-855
839value) {
840    var prev = 0,
841        s = "",
842        i,
843        nums,
844        end,
845        isArray;
846
847    while (~(i = value.indexOf("random(", prev))) {
848      end = value.indexOf(")", i);
849      isArray = value.charAt(i + 7) === "[";
850      nums = value.substr(i + 7, end - i - 7).match(isArray ? _delimitedValueExp : _strictNumExp);
851      s += value.substr(prev, i - prev) + random(isArray ? nums : +nums[0], isArray ? 0 : +nums[1], +nums[2] || 1e-5);
852      prev = end + 1;
853    }
854
855    return s + value.substr(prev, value.length - prev
vendor: 14,290 bytes, lines 855-1371
855);
856  },
857      mapRange = function mapRange(inMin, inMax, outMin, outMax, value) {
858    var inRange = inMax - inMin,
859        outRange = outMax - outMin;
860    return _conditionalReturn(value, function (value) {
861      return outMin + ((value - inMin) / inRange * outRange || 0);
862    });
863  },
864      interpolate = function interpolate(start, end, progress, mutate) {
865    var func = isNaN(start + end) ? 0 : function (p) {
866      return (1 - p) * start + p * end;
867    };
868
869    if (!func) {
870      var isString = _isString(start),
871          master = {},
872          p,
873          i,
874          interpolators,
875          l,
876          il;
877
878      progress === true && (mutate = 1) && (progress = null);
879
880      if (isString) {
881        start = {
882          p: start
883        };
884        end = {
885          p: end
886        };
887      } else if (_isArray(start) && !_isArray(end)) {
888        interpolators = [];
889        l = start.length;
890        il = l - 2;
891
892        for (i = 1; i < l; i++) {
893          interpolators.push(interpolate(start[i - 1], start[i]));
894        }
895
896        l--;
897
898        func = function func(p) {
899          p *= l;
900          var i = Math.min(il, ~~p);
901          return interpolators[i](p - i);
902        };
903
904        progress = end;
905      } else if (!mutate) {
906        start = _merge(_isArray(start) ? [] : {}, start);
907      }
908
909      if (!interpolators) {
910        for (p in end) {
911          _addPropTween.call(master, start, p, "get", end[p]);
912        }
913
914        func = function func(p) {
915          return _renderPropTweens(p, master) || (isString ? start.p : start);
916        };
917      }
918    }
919
920    return _conditionalReturn(progress, func);
921  },
922      _getLabelInDirection = function _getLabelInDirection(timeline, fromTime, backward) {
923    var labels = timeline.labels,
924        min = _bigNum,
925        p,
926        distance,
927        label;
928
929    for (p in labels) {
930      distance = labels[p] - fromTime;
931
932      if (distance < 0 === !!backward && distance && min > (distance = Math.abs(distance))) {
933        label = p;
934        min = distance;
935      }
936    }
937
938    return label;
939  },
940      _callback = function _callback(animation, type, executeLazyFirst) {
941    var v = animation.vars,
942        callback = v[type],
943        prevContext = _context,
944        context = animation._ctx,
945        params,
946        scope,
947        result;
948
949    if (!callback) {
950      return;
951    }
952
953    params = v[type + "Params"];
954    scope = v.callbackScope || animation;
955    executeLazyFirst && _lazyTweens.length && _lazyRender();
956    context && (_context = context);
957    result = params ? callback.apply(scope, params) : callback.call(scope);
958    _context = prevContext;
959    return result;
960  },
961      _interrupt = function _interrupt(animation) {
962    _removeFromParent(animation);
963
964    animation.scrollTrigger && animation.scrollTrigger.kill(!!_reverting);
965    animation.progress() < 1 && _callback(animation, "onInterrupt");
966    return animation;
967  },
968      _quickTween,
969      _registerPluginQueue = [],
970      _createPlugin = function _createPlugin(config) {
971    if (!config) return;
972    config = !config.name && config["default"] || config;
973
974    if (_windowExists() || config.headless) {
975      var name = config.name,
976          isFunc = _isFunction(config),
977          Plugin = name && !isFunc && config.init ? function () {
978        this._props = [];
979      } : config,
980          instanceDefaults = {
981        init: _emptyFunc,
982        render: _renderPropTweens,
983        add: _addPropTween,
984        kill: _killPropTweensOf,
985        modifier: _addPluginModifier,
986        rawVars: 0
987      },
988          statics = {
989        targetTest: 0,
990        get: 0,
991        getSetter: _getSetter,
992        aliases: {},
993        register: 0
994      };
995
996      _wake();
997
998      if (config !== Plugin) {
999        if (_plugins[name]) {
1000          return;
1001        }
1002
1003        _setDefaults(Plugin, _setDefaults(_copyExcluding(config, instanceDefaults), statics));
1004
1005        _merge(Plugin.prototype, _merge(instanceDefaults, _copyExcluding(config, statics)));
1006
1007        _plugins[Plugin.prop = name] = Plugin;
1008
1009        if (config.targetTest) {
1010          _harnessPlugins.push(Plugin);
1011
1012          _reservedProps[name] = 1;
1013        }
1014
1015        name = (name === "css" ? "CSS" : name.charAt(0).toUpperCase() + name.substr(1)) + "Plugin";
1016      }
1017
1018      _addGlobal(name, Plugin);
1019
1020      config.register && config.register(gsap, Plugin, PropTween);
1021    } else {
1022      _registerPluginQueue.push(config);
1023    }
1024  },
1025      _255 = 255,
1026      _colorLookup = {
1027    aqua: [0, _255, _255],
1028    lime: [0, _255, 0],
1029    silver: [192, 192, 192],
1030    black: [0, 0, 0],
1031    maroon: [128, 0, 0],
1032    teal: [0, 128, 128],
1033    blue: [0, 0, _255],
1034    navy: [0, 0, 128],
1035    white: [_255, _255, _255],
1036    olive: [128, 128, 0],
1037    yellow: [_255, _255, 0],
1038    orange: [_255, 165, 0],
1039    gray: [128, 128, 128],
1040    purple: [128, 0, 128],
1041    green: [0, 128, 0],
1042    red: [_255, 0, 0],
1043    pink: [_255, 192, 203],
1044    cyan: [0, _255, _255],
1045    transparent: [_255, _255, _255, 0]
1046  },
1047      _hue = function _hue(h, m1, m2) {
1048    h += h < 0 ? 1 : h > 1 ? -1 : 0;
1049    return (h * 6 < 1 ? m1 + (m2 - m1) * h * 6 : h < .5 ? m2 : h * 3 < 2 ? m1 + (m2 - m1) * (2 / 3 - h) * 6 : m1) * _255 + .5 | 0;
1050  },
1051      splitColor = function splitColor(v, toHSL, forceAlpha) {
1052    var a = !v ? _colorLookup.black : _isNumber(v) ? [v >> 16, v >> 8 & _255, v & _255] : 0,
1053        r,
1054        g,
1055        b,
1056        h,
1057        s,
1058        l,
1059        max,
1060        min,
1061        d,
1062        wasHSL;
1063
1064    if (!a) {
1065      if (v.substr(-1) === ",") {
1066        v = v.substr(0, v.length - 1);
1067      }
1068
1069      if (_colorLookup[v]) {
1070        a = _colorLookup[v];
1071      } else if (v.charAt(0) === "#") {
1072        if (v.length < 6) {
1073          r = v.charAt(1);
1074          g = v.charAt(2);
1075          b = v.charAt(3);
1076          v = "#" + r + r + g + g + b + b + (v.length === 5 ? v.charAt(4) + v.charAt(4) : "");
1077        }
1078
1079        if (v.length === 9) {
1080          a = parseInt(v.substr(1, 6), 16);
1081          return [a >> 16, a >> 8 & _255, a & _255, parseInt(v.substr(7), 16) / 255];
1082        }
1083
1084        v = parseInt(v.substr(1), 16);
1085        a = [v >> 16, v >> 8 & _255, v & _255];
1086      } else if (v.substr(0, 3) === "hsl") {
1087        a = wasHSL = v.match(_strictNumExp);
1088
1089        if (!toHSL) {
1090          h = +a[0] % 360 / 360;
1091          s = +a[1] / 100;
1092          l = +a[2] / 100;
1093          g = l <= .5 ? l * (s + 1) : l + s - l * s;
1094          r = l * 2 - g;
1095          a.length > 3 && (a[3] *= 1);
1096          a[0] = _hue(h + 1 / 3, r, g);
1097          a[1] = _hue(h, r, g);
1098          a[2] = _hue(h - 1 / 3, r, g);
1099        } else if (~v.indexOf("=")) {
1100          a = v.match(_numExp);
1101          forceAlpha && a.length < 4 && (a[3] = 1);
1102          return a;
1103        }
1104      } else {
1105        a = v.match(_strictNumExp) || _colorLookup.transparent;
1106      }
1107
1108      a = a.map(Number);
1109    }
1110
1111    if (toHSL && !wasHSL) {
1112      r = a[0] / _255;
1113      g = a[1] / _255;
1114      b = a[2] / _255;
1115      max = Math.max(r, g, b);
1116      min = Math.min(r, g, b);
1117      l = (max + min) / 2;
1118
1119      if (max === min) {
1120        h = s = 0;
1121      } else {
1122        d = max - min;
1123        s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
1124        h = max === r ? (g - b) / d + (g < b ? 6 : 0) : max === g ? (b - r) / d + 2 : (r - g) / d + 4;
1125        h *= 60;
1126      }
1127
1128      a[0] = ~~(h + .5);
1129      a[1] = ~~(s * 100 + .5);
1130      a[2] = ~~(l * 100 + .5);
1131    }
1132
1133    forceAlpha && a.length < 4 && (a[3] = 1);
1134    return a;
1135  },
1136      _colorOrderData = function _colorOrderData(v) {
1137    var values = [],
1138        c = [],
1139        i = -1;
1140    v.split(_colorExp).forEach(function (v) {
1141      var a = v.match(_numWithUnitExp) || [];
1142      values.push.apply(values, a);
1143      c.push(i += a.length + 1);
1144    });
1145    values.c = c;
1146    return values;
1147  },
1148      _formatColors = function _formatColors(s, toHSL, orderMatchData) {
1149    var result = "",
1150        colors = (s + result).match(_colorExp),
1151        type = toHSL ? "hsla(" : "rgba(",
1152        i = 0,
1153        c,
1154        shell,
1155        d,
1156        l;
1157
1158    if (!colors) {
1159      return s;
1160    }
1161
1162    colors = colors.map(function (color) {
1163      return (color = splitColor(color, toHSL, 1)) && type + (toHSL ? color[0] + "," + color[1] + "%," + color[2] + "%," + color[3] : color.join(",")) + ")";
1164    });
1165
1166    if (orderMatchData) {
1167      d = _colorOrderData(s);
1168      c = orderMatchData.c;
1169
1170      if (c.join(result) !== d.c.join(result)) {
1171        shell = s.replace(_colorExp, "1").split(_numWithUnitExp);
1172        l = shell.length - 1;
1173
1174        for (; i < l; i++) {
1175          result += shell[i] + (~c.indexOf(i) ? colors.shift() || type + "0,0,0,0)" : (d.length ? d : colors.length ? colors : orderMatchData).shift());
1176        }
1177      }
1178    }
1179
1180    if (!shell) {
1181      shell = s.split(_colorExp);
1182      l = shell.length - 1;
1183
1184      for (; i < l; i++) {
1185        result += shell[i] + colors[i];
1186      }
1187    }
1188
1189    return result + shell[l];
1190  },
1191      _colorExp = function () {
1192    var s = "(?:\\b(?:(?:rgb|rgba|hsl|hsla)\\(.+?\\))|\\B#(?:[0-9a-f]{3,4}){1,2}\\b",
1193        p;
1194
1195    for (p in _colorLookup) {
1196      s += "|" + p + "\\b";
1197    }
1198
1199    return new RegExp(s + ")", "gi");
1200  }(),
1201      _hslExp = /hsl[a]?\(/,
1202      _colorStringFilter = function _colorStringFilter(a) {
1203    var combined = a.join(" "),
1204        toHSL;
1205    _colorExp.lastIndex = 0;
1206
1207    if (_colorExp.test(combined)) {
1208      toHSL = _hslExp.test(combined);
1209      a[1] = _formatColors(a[1], toHSL);
1210      a[0] = _formatColors(a[0], toHSL, _colorOrderData(a[1]));
1211      return true;
1212    }
1213  },
1214      _tickerActive,
1215      _ticker = function () {
1216    var _getTime = Date.now,
1217        _lagThreshold = 500,
1218        _adjustedLag = 33,
1219        _startTime = _getTime(),
1220        _lastUpdate = _startTime,
1221        _gap = 1000 / 240,
1222        _nextTime = _gap,
1223        _listeners = [],
1224        _id,
1225        _req,
1226        _raf,
1227        _self,
1228        _delta,
1229        _i,
1230        _tick = function _tick(v) {
1231      var elapsed = _getTime() - _lastUpdate,
1232          manual = v === true,
1233          overlap,
1234          dispatch,
1235          time,
1236          frame;
1237
1238      (elapsed > _lagThreshold || elapsed < 0) && (_startTime += elapsed - _adjustedLag);
1239      _lastUpdate += elapsed;
1240      time = _lastUpdate - _startTime;
1241      overlap = time - _nextTime;
1242
1243      if (overlap > 0 || manual) {
1244        frame = ++_self.frame;
1245        _delta = time - _self.time * 1000;
1246        _self.time = time = time / 1000;
1247        _nextTime += overlap + (overlap >= _gap ? 4 : _gap - overlap);
1248        dispatch = 1;
1249      }
1250
1251      manual || (_id = _req(_tick));
1252
1253      if (dispatch) {
1254        for (_i = 0; _i < _listeners.length; _i++) {
1255          _listeners[_i](time, _delta, frame, v);
1256        }
1257      }
1258    };
1259
1260    _self = {
1261      time: 0,
1262      frame: 0,
1263      tick: function tick() {
1264        _tick(true);
1265      },
1266      deltaRatio: function deltaRatio(fps) {
1267        return _delta / (1000 / (fps || 60));
1268      },
1269      wake: function wake() {
1270        if (_coreReady) {
1271          if (!_coreInitted && _windowExists()) {
1272            _win = _coreInitted = window;
1273            _doc = _win.document || {};
1274            _globals.gsap = gsap;
1275            (_win.gsapVersions || (_win.gsapVersions = [])).push(gsap.version);
1276
1277            _install(_installScope || _win.GreenSockGlobals || !_win.gsap && _win || {});
1278
1279            _registerPluginQueue.forEach(_createPlugin);
1280          }
1281
1282          _raf = typeof requestAnimationFrame !== "undefined" && requestAnimationFrame;
1283          _id && _self.sleep();
1284
1285          _req = _raf || function (f) {
1286            return setTimeout(f, _nextTime - _self.time * 1000 + 1 | 0);
1287          };
1288
1289          _tickerActive = 1;
1290
1291          _tick(2);
1292        }
1293      },
1294      sleep: function sleep() {
1295        (_raf ? cancelAnimationFrame : clearTimeout)(_id);
1296        _tickerActive = 0;
1297        _req = _emptyFunc;
1298      },
1299      lagSmoothing: function lagSmoothing(threshold, adjustedLag) {
1300        _lagThreshold = threshold || Infinity;
1301        _adjustedLag = Math.min(adjustedLag || 33, _lagThreshold);
1302      },
1303      fps: function fps(_fps) {
1304        _gap = 1000 / (_fps || 240);
1305        _nextTime = _self.time * 1000 + _gap;
1306      },
1307      add: function add(callback, once, prioritize) {
1308        var func = once ? function (t, d, f, v) {
1309          callback(t, d, f, v);
1310
1311          _self.remove(func);
1312        } : callback;
1313
1314        _self.remove(callback);
1315
1316        _listeners[prioritize ? "unshift" : "push"](func);
1317
1318        _wake();
1319
1320        return func;
1321      },
1322      remove: function remove(callback, i) {
1323        ~(i = _listeners.indexOf(callback)) && _listeners.splice(i, 1) && _i >= i && _i--;
1324      },
1325      _listeners: _listeners
1326    };
1327    return _self;
1328  }(),
1329      _wake = function _wake() {
1330    return !_tickerActive && _ticker.wake();
1331  },
1332      _easeMap = {},
1333      _customEaseExp = /^[\d.\-M][\d.\-,\s]/,
1334      _quotesExp = /["']/g,
1335      _parseObjectInString = function _parseObjectInString(value) {
1336    var obj = {},
1337        split = value.substr(1, value.length - 3).split(":"),
1338        key = split[0],
1339        i = 1,
1340        l = split.length,
1341        index,
1342        val,
1343        parsedVal;
1344
1345    for (; i < l; i++) {
1346      val = split[i];
1347      index = i !== l - 1 ? val.lastIndexOf(",") : val.length;
1348      parsedVal = val.substr(0, index);
1349      obj[key] = isNaN(parsedVal) ? parsedVal.replace(_quotesExp, "").trim() : +parsedVal;
1350      key = val.substr(index + 1).trim();
1351    }
1352
1353    return obj;
1354  },
1355      _valueInParentheses = function _valueInParentheses(value) {
1356    var open = value.indexOf("(") + 1,
1357        close = value.indexOf(")"),
1358        nested = value.indexOf("(", open);
1359    return value.substring(open, ~nested && nested < close ? value.indexOf(")", close + 1) : close);
1360  },
1361      _configEaseFromString = function _configEaseFromString(name) {
1362    var split = (name + "").split("("),
1363        ease = _easeMap[split[0]];
1364    return ease && split.length > 1 && ease.config ? ease.config.apply(null, ~name.indexOf("{") ? [_parseObjectInString(split[1])] : _valueInParentheses(name).split(",").map(_numericIfPossible)) : _easeMap._CE && _customEaseExp.test(name) ? _easeMap._CE("", name) : ease;
1365  },
1366      _invertEase = function _invertEase(ease) {
1367    return function (p) {
1368      return 1 - ease(1 - p);
1369    };
1370  },
1371      _p
1371ropagateYoyoEase = function _propagateYoyoEase(timeline, isYoyo) {
1372    var child = timeline._first,
1373        ease;
1374
1375    while (child) {
1376      if (child instanceof Timeline) {
1377        _propagateYoyoEase(child, isYoyo);
1378      } else if (child.vars.yoyoEase && (!child._yoyo || !child._repeat) && child._yoyo !== isYoyo) {
1379        if (child.timeline) {
1380          _propagateYoyoEase(child.timeline, isYoyo);
1381        } else {
1382          ease = child._ease;
1383          child._ease = child._yEase;
1384          child._yEase = ease;
1385          child._yoyo = isYoyo;
1386        }
1387      }
1388
1389      child = child._next;
1390    }
vendor: 3,445 bytes, lines 1390-1501
1390
1391  },
1392      _parseEase = function _parseEase(ease, defaultEase) {
1393    return !ease ? defaultEase : (_isFunction(ease) ? ease : _easeMap[ease] || _configEaseFromString(ease)) || defaultEase;
1394  },
1395      _insertEase = function _insertEase(names, easeIn, easeOut, easeInOut) {
1396    if (easeOut === void 0) {
1397      easeOut = function easeOut(p) {
1398        return 1 - easeIn(1 - p);
1399      };
1400    }
1401
1402    if (easeInOut === void 0) {
1403      easeInOut = function easeInOut(p) {
1404        return p < .5 ? easeIn(p * 2) / 2 : 1 - easeIn((1 - p) * 2) / 2;
1405      };
1406    }
1407
1408    var ease = {
1409      easeIn: easeIn,
1410      easeOut: easeOut,
1411      easeInOut: easeInOut
1412    },
1413        lowercaseName;
1414
1415    _forEachName(names, function (name) {
1416      _easeMap[name] = _globals[name] = ease;
1417      _easeMap[lowercaseName = name.toLowerCase()] = easeOut;
1418
1419      for (var p in ease) {
1420        _easeMap[lowercaseName + (p === "easeIn" ? ".in" : p === "easeOut" ? ".out" : ".inOut")] = _easeMap[name + "." + p] = ease[p];
1421      }
1422    });
1423
1424    return ease;
1425  },
1426      _easeInOutFromOut = function _easeInOutFromOut(easeOut) {
1427    return function (p) {
1428      return p < .5 ? (1 - easeOut(1 - p * 2)) / 2 : .5 + easeOut((p - .5) * 2) / 2;
1429    };
1430  },
1431      _configElastic = function _configElastic(type, amplitude, period) {
1432    var p1 = amplitude >= 1 ? amplitude : 1,
1433        p2 = (period || (type ? .3 : .45)) / (amplitude < 1 ? amplitude : 1),
1434        p3 = p2 / _2PI * (Math.asin(1 / p1) || 0),
1435        easeOut = function easeOut(p) {
1436      return p === 1 ? 1 : p1 * Math.pow(2, -10 * p) * _sin((p - p3) * p2) + 1;
1437    },
1438        ease = type === "out" ? easeOut : type === "in" ? function (p) {
1439      return 1 - easeOut(1 - p);
1440    } : _easeInOutFromOut(easeOut);
1441
1442    p2 = _2PI / p2;
1443
1444    ease.config = function (amplitude, period) {
1445      return _configElastic(type, amplitude, period);
1446    };
1447
1448    return ease;
1449  },
1450      _configBack = function _configBack(type, overshoot) {
1451    if (overshoot === void 0) {
1452      overshoot = 1.70158;
1453    }
1454
1455    var easeOut = function easeOut(p) {
1456      return p ? --p * p * ((overshoot + 1) * p + overshoot) + 1 : 0;
1457    },
1458        ease = type === "out" ? easeOut : type === "in" ? function (p) {
1459      return 1 - easeOut(1 - p);
1460    } : _easeInOutFromOut(easeOut);
1461
1462    ease.config = function (overshoot) {
1463      return _configBack(type, overshoot);
1464    };
1465
1466    return ease;
1467  };
1468
1469  _forEachName("Linear,Quad,Cubic,Quart,Quint,Strong", function (name, i) {
1470    var power = i < 5 ? i + 1 : i;
1471
1472    _insertEase(name + ",Power" + (power - 1), i ? function (p) {
1473      return Math.pow(p, power);
1474    } : function (p) {
1475      return p;
1476    }, function (p) {
1477      return 1 - Math.pow(1 - p, power);
1478    }, function (p) {
1479      return p < .5 ? Math.pow(p * 2, power) / 2 : 1 - Math.pow((1 - p) * 2, power) / 2;
1480    });
1481  });
1482
1483  _easeMap.Linear.easeNone = _easeMap.none = _easeMap.Linear.easeIn;
1484
1485  _insertEase("Elastic", _configElastic("in"), _configElastic("out"), _configElastic());
1486
1487  (function (n, c) {
1488    var n1 = 1 / c,
1489        n2 = 2 * n1,
1490        n3 = 2.5 * n1,
1491        easeOut = function easeOut(p) {
1492      return p < n1 ? n * p * p : p < n2 ? n * Math.pow(p - 1.5 / c, 2) + .75 : p < n3 ? n * (p -= 2.25 / c) * p + .9375 : n * Math.pow(p - 2.625 / c, 2) + .984375;
1493    };
1494
1495    _insertEase("Bounce", function (p) {
1496      return 1 - easeOut(1 - p);
1497    }, easeOut);
1498  })(7.5625, 2.75);
1499
1500  _insertEase("Expo", function (p) {
1501    return 
vendor: 18,509 bytes, lines 1501-2076
1501p ? Math.pow(2, 10 * (p - 1)) : 0;
1502  });
1503
1504  _insertEase("Circ", function (p) {
1505    return -(_sqrt(1 - p * p) - 1);
1506  });
1507
1508  _insertEase("Sine", function (p) {
1509    return p === 1 ? 1 : -_cos(p * _HALF_PI) + 1;
1510  });
1511
1512  _insertEase("Back", _configBack("in"), _configBack("out"), _configBack());
1513
1514  _easeMap.SteppedEase = _easeMap.steps = _globals.SteppedEase = {
1515    config: function config(steps, immediateStart) {
1516      if (steps === void 0) {
1517        steps = 1;
1518      }
1519
1520      var p1 = 1 / steps,
1521          p2 = steps + (immediateStart ? 0 : 1),
1522          p3 = immediateStart ? 1 : 0,
1523          max = 1 - _tinyNum;
1524      return function (p) {
1525        return ((p2 * _clamp(0, max, p) | 0) + p3) * p1;
1526      };
1527    }
1528  };
1529  _defaults.ease = _easeMap["quad.out"];
1530
1531  _forEachName("onComplete,onUpdate,onStart,onRepeat,onReverseComplete,onInterrupt", function (name) {
1532    return _callbackNames += name + "," + name + "Params,";
1533  });
1534
1535  var GSCache = function GSCache(target, harness) {
1536    this.id = _gsID++;
1537    target._gsap = this;
1538    this.target = target;
1539    this.harness = harness;
1540    this.get = harness ? harness.get : _getProperty;
1541    this.set = harness ? harness.getSetter : _getSetter;
1542  };
1543  var Animation = function () {
1544    function Animation(vars) {
1545      this.vars = vars;
1546      this._delay = +vars.delay || 0;
1547
1548      if (this._repeat = vars.repeat === Infinity ? -2 : vars.repeat || 0) {
1549        this._rDelay = vars.repeatDelay || 0;
1550        this._yoyo = !!vars.yoyo || !!vars.yoyoEase;
1551      }
1552
1553      this._ts = 1;
1554
1555      _setDuration(this, +vars.duration, 1, 1);
1556
1557      this.data = vars.data;
1558
1559      if (_context) {
1560        this._ctx = _context;
1561
1562        _context.data.push(this);
1563      }
1564
1565      _tickerActive || _ticker.wake();
1566    }
1567
1568    var _proto = Animation.prototype;
1569
1570    _proto.delay = function delay(value) {
1571      if (value || value === 0) {
1572        this.parent && this.parent.smoothChildTiming && this.startTime(this._start + value - this._delay);
1573        this._delay = value;
1574        return this;
1575      }
1576
1577      return this._delay;
1578    };
1579
1580    _proto.duration = function duration(value) {
1581      return arguments.length ? this.totalDuration(this._repeat > 0 ? value + (value + this._rDelay) * this._repeat : value) : this.totalDuration() && this._dur;
1582    };
1583
1584    _proto.totalDuration = function totalDuration(value) {
1585      if (!arguments.length) {
1586        return this._tDur;
1587      }
1588
1589      this._dirty = 0;
1590      return _setDuration(this, this._repeat < 0 ? value : (value - this._repeat * this._rDelay) / (this._repeat + 1));
1591    };
1592
1593    _proto.totalTime = function totalTime(_totalTime, suppressEvents) {
1594      _wake();
1595
1596      if (!arguments.length) {
1597        return this._tTime;
1598      }
1599
1600      var parent = this._dp;
1601
1602      if (parent && parent.smoothChildTiming && this._ts) {
1603        _alignPlayhead(this, _totalTime);
1604
1605        !parent._dp || parent.parent || _postAddChecks(parent, this);
1606
1607        while (parent && parent.parent) {
1608          if (parent.parent._time !== parent._start + (parent._ts >= 0 ? parent._tTime / parent._ts : (parent.totalDuration() - parent._tTime) / -parent._ts)) {
1609            parent.totalTime(parent._tTime, true);
1610          }
1611
1612          parent = parent.parent;
1613        }
1614
1615        if (!this.parent && this._dp.autoRemoveChildren && (this._ts > 0 && _totalTime < this._tDur || this._ts < 0 && _totalTime > 0 || !this._tDur && !_totalTime)) {
1616          _addToTimeline(this._dp, this, this._start - this._delay);
1617        }
1618      }
1619
1620      if (this._tTime !== _totalTime || !this._dur && !suppressEvents || this._initted && Math.abs(this._zTime) === _tinyNum || !_totalTime && !this._initted && (this.add || this._ptLookup)) {
1621        this._ts || (this._pTime = _totalTime);
1622
1623        _lazySafeRender(this, _totalTime, suppressEvents);
1624      }
1625
1626      return this;
1627    };
1628
1629    _proto.time = function time(value, suppressEvents) {
1630      return arguments.length ? this.totalTime(Math.min(this.totalDuration(), value + _elapsedCycleDuration(this)) % (this._dur + this._rDelay) || (value ? this._dur : 0), suppressEvents) : this._time;
1631    };
1632
1633    _proto.totalProgress = function totalProgress(value, suppressEvents) {
1634      return arguments.length ? this.totalTime(this.totalDuration() * value, suppressEvents) : this.totalDuration() ? Math.min(1, this._tTime / this._tDur) : this.rawTime() > 0 ? 1 : 0;
1635    };
1636
1637    _proto.progress = function progress(value, suppressEvents) {
1638      return arguments.length ? this.totalTime(this.duration() * (this._yoyo && !(this.iteration() & 1) ? 1 - value : value) + _elapsedCycleDuration(this), suppressEvents) : this.duration() ? Math.min(1, this._time / this._dur) : this.rawTime() > 0 ? 1 : 0;
1639    };
1640
1641    _proto.iteration = function iteration(value, suppressEvents) {
1642      var cycleDuration = this.duration() + this._rDelay;
1643
1644      return arguments.length ? this.totalTime(this._time + (value - 1) * cycleDuration, suppressEvents) : this._repeat ? _animationCycle(this._tTime, cycleDuration) + 1 : 1;
1645    };
1646
1647    _proto.timeScale = function timeScale(value, suppressEvents) {
1648      if (!arguments.length) {
1649        return this._rts === -_tinyNum ? 0 : this._rts;
1650      }
1651
1652      if (this._rts === value) {
1653        return this;
1654      }
1655
1656      var tTime = this.parent && this._ts ? _parentToChildTotalTime(this.parent._time, this) : this._tTime;
1657      this._rts = +value || 0;
1658      this._ts = this._ps || value === -_tinyNum ? 0 : this._rts;
1659      this.totalTime(_clamp(-Math.abs(this._delay), this._tDur, tTime), suppressEvents !== false);
1660
1661      _setEnd(this);
1662
1663      return _recacheAncestors(this);
1664    };
1665
1666    _proto.paused = function paused(value) {
1667      if (!arguments.length) {
1668        return this._ps;
1669      }
1670
1671      if (this._ps !== value) {
1672        this._ps = value;
1673
1674        if (value) {
1675          this._pTime = this._tTime || Math.max(-this._delay, this.rawTime());
1676          this._ts = this._act = 0;
1677        } else {
1678          _wake();
1679
1680          this._ts = this._rts;
1681          this.totalTime(this.parent && !this.parent.smoothChildTiming ? this.rawTime() : this._tTime || this._pTime, this.progress() === 1 && Math.abs(this._zTime) !== _tinyNum && (this._tTime -= _tinyNum));
1682        }
1683      }
1684
1685      return this;
1686    };
1687
1688    _proto.startTime = function startTime(value) {
1689      if (arguments.length) {
1690        this._start = value;
1691        var parent = this.parent || this._dp;
1692        parent && (parent._sort || !this.parent) && _addToTimeline(parent, this, value - this._delay);
1693        return this;
1694      }
1695
1696      return this._start;
1697    };
1698
1699    _proto.endTime = function endTime(includeRepeats) {
1700      return this._start + (_isNotFalse(includeRepeats) ? this.totalDuration() : this.duration()) / Math.abs(this._ts || 1);
1701    };
1702
1703    _proto.rawTime = function rawTime(wrapRepeats) {
1704      var parent = this.parent || this._dp;
1705      return !parent ? this._tTime : wrapRepeats && (!this._ts || this._repeat && this._time && this.totalProgress() < 1) ? this._tTime % (this._dur + this._rDelay) : !this._ts ? this._tTime : _parentToChildTotalTime(parent.rawTime(wrapRepeats), this);
1706    };
1707
1708    _proto.revert = function revert(config) {
1709      if (config === void 0) {
1710        config = _revertConfig;
1711      }
1712
1713      var prevIsReverting = _reverting;
1714      _reverting = config;
1715
1716      if (this._initted || this._startAt) {
1717        this.timeline && this.timeline.revert(config);
1718        this.totalTime(-0.01, config.suppressEvents);
1719      }
1720
1721      this.data !== "nested" && config.kill !== false && this.kill();
1722      _reverting = prevIsReverting;
1723      return this;
1724    };
1725
1726    _proto.globalTime = function globalTime(rawTime) {
1727      var animation = this,
1728          time = arguments.length ? rawTime : animation.rawTime();
1729
1730      while (animation) {
1731        time = animation._start + time / (Math.abs(animation._ts) || 1);
1732        animation = animation._dp;
1733      }
1734
1735      return !this.parent && this._sat ? this._sat.globalTime(rawTime) : time;
1736    };
1737
1738    _proto.repeat = function repeat(value) {
1739      if (arguments.length) {
1740        this._repeat = value === Infinity ? -2 : value;
1741        return _onUpdateTotalDuration(this);
1742      }
1743
1744      return this._repeat === -2 ? Infinity : this._repeat;
1745    };
1746
1747    _proto.repeatDelay = function repeatDelay(value) {
1748      if (arguments.length) {
1749        var time = this._time;
1750        this._rDelay = value;
1751
1752        _onUpdateTotalDuration(this);
1753
1754        return time ? this.time(time) : this;
1755      }
1756
1757      return this._rDelay;
1758    };
1759
1760    _proto.yoyo = function yoyo(value) {
1761      if (arguments.length) {
1762        this._yoyo = value;
1763        return this;
1764      }
1765
1766      return this._yoyo;
1767    };
1768
1769    _proto.seek = function seek(position, suppressEvents) {
1770      return this.totalTime(_parsePosition(this, position), _isNotFalse(suppressEvents));
1771    };
1772
1773    _proto.restart = function restart(includeDelay, suppressEvents) {
1774      return this.play().totalTime(includeDelay ? -this._delay : 0, _isNotFalse(suppressEvents));
1775    };
1776
1777    _proto.play = function play(from, suppressEvents) {
1778      from != null && this.seek(from, suppressEvents);
1779      return this.reversed(false).paused(false);
1780    };
1781
1782    _proto.reverse = function reverse(from, suppressEvents) {
1783      from != null && this.seek(from || this.totalDuration(), suppressEvents);
1784      return this.reversed(true).paused(false);
1785    };
1786
1787    _proto.pause = function pause(atTime, suppressEvents) {
1788      atTime != null && this.seek(atTime, suppressEvents);
1789      return this.paused(true);
1790    };
1791
1792    _proto.resume = function resume() {
1793      return this.paused(false);
1794    };
1795
1796    _proto.reversed = function reversed(value) {
1797      if (arguments.length) {
1798        !!value !== this.reversed() && this.timeScale(-this._rts || (value ? -_tinyNum : 0));
1799        return this;
1800      }
1801
1802      return this._rts < 0;
1803    };
1804
1805    _proto.invalidate = function invalidate() {
1806      this._initted = this._act = 0;
1807      this._zTime = -_tinyNum;
1808      return this;
1809    };
1810
1811    _proto.isActive = function isActive() {
1812      var parent = this.parent || this._dp,
1813          start = this._start,
1814          rawTime;
1815      return !!(!parent || this._ts && this._initted && parent.isActive() && (rawTime = parent.rawTime(true)) >= start && rawTime < this.endTime(true) - _tinyNum);
1816    };
1817
1818    _proto.eventCallback = function eventCallback(type, callback, params) {
1819      var vars = this.vars;
1820
1821      if (arguments.length > 1) {
1822        if (!callback) {
1823          delete vars[type];
1824        } else {
1825          vars[type] = callback;
1826          params && (vars[type + "Params"] = params);
1827          type === "onUpdate" && (this._onUpdate = callback);
1828        }
1829
1830        return this;
1831      }
1832
1833      return vars[type];
1834    };
1835
1836    _proto.then = function then(onFulfilled) {
1837      var self = this;
1838      return new Promise(function (resolve) {
1839        var f = _isFunction(onFulfilled) ? onFulfilled : _passThrough,
1840            _resolve = function _resolve() {
1841          var _then = self.then;
1842          self.then = null;
1843          _isFunction(f) && (f = f(self)) && (f.then || f === self) && (self.then = _then);
1844          resolve(f);
1845          self.then = _then;
1846        };
1847
1848        if (self._initted && self.totalProgress() === 1 && self._ts >= 0 || !self._tTime && self._ts < 0) {
1849          _resolve();
1850        } else {
1851          self._prom = _resolve;
1852        }
1853      });
1854    };
1855
1856    _proto.kill = function kill() {
1857      _interrupt(this);
1858    };
1859
1860    return Animation;
1861  }();
1862
1863  _setDefaults(Animation.prototype, {
1864    _time: 0,
1865    _start: 0,
1866    _end: 0,
1867    _tTime: 0,
1868    _tDur: 0,
1869    _dirty: 0,
1870    _repeat: 0,
1871    _yoyo: false,
1872    parent: null,
1873    _initted: false,
1874    _rDelay: 0,
1875    _ts: 1,
1876    _dp: 0,
1877    ratio: 0,
1878    _zTime: -_tinyNum,
1879    _prom: 0,
1880    _ps: false,
1881    _rts: 1
1882  });
1883
1884  var Timeline = function (_Animation) {
1885    _inheritsLoose(Timeline, _Animation);
1886
1887    function Timeline(vars, position) {
1888      var _this;
1889
1890      if (vars === void 0) {
1891        vars = {};
1892      }
1893
1894      _this = _Animation.call(this, vars) || this;
1895      _this.labels = {};
1896      _this.smoothChildTiming = !!vars.smoothChildTiming;
1897      _this.autoRemoveChildren = !!vars.autoRemoveChildren;
1898      _this._sort = _isNotFalse(vars.sortChildren);
1899      _globalTimeline && _addToTimeline(vars.parent || _globalTimeline, _assertThisInitialized(_this), position);
1900      vars.reversed && _this.reverse();
1901      vars.paused && _this.paused(true);
1902      vars.scrollTrigger && _scrollTrigger(_assertThisInitialized(_this), vars.scrollTrigger);
1903      return _this;
1904    }
1905
1906    var _proto2 = Timeline.prototype;
1907
1908    _proto2.to = function to(targets, vars, position) {
1909      _createTweenType(0, arguments, this);
1910
1911      return this;
1912    };
1913
1914    _proto2.from = function from(targets, vars, position) {
1915      _createTweenType(1, arguments, this);
1916
1917      return this;
1918    };
1919
1920    _proto2.fromTo = function fromTo(targets, fromVars, toVars, position) {
1921      _createTweenType(2, arguments, this);
1922
1923      return this;
1924    };
1925
1926    _proto2.set = function set(targets, vars, position) {
1927      vars.duration = 0;
1928      vars.parent = this;
1929      _inheritDefaults(vars).repeatDelay || (vars.repeat = 0);
1930      vars.immediateRender = !!vars.immediateRender;
1931      new Tween(targets, vars, _parsePosition(this, position), 1);
1932      return this;
1933    };
1934
1935    _proto2.call = function call(callback, params, position) {
1936      return _addToTimeline(this, Tween.delayedCall(0, callback, params), position);
1937    };
1938
1939    _proto2.staggerTo = function staggerTo(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams) {
1940      vars.duration = duration;
1941      vars.stagger = vars.stagger || stagger;
1942      vars.onComplete = onCompleteAll;
1943      vars.onCompleteParams = onCompleteAllParams;
1944      vars.parent = this;
1945      new Tween(targets, vars, _parsePosition(this, position));
1946      return this;
1947    };
1948
1949    _proto2.staggerFrom = function staggerFrom(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams) {
1950      vars.runBackwards = 1;
1951      _inheritDefaults(vars).immediateRender = _isNotFalse(vars.immediateRender);
1952      return this.staggerTo(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams);
1953    };
1954
1955    _proto2.staggerFromTo = function staggerFromTo(targets, duration, fromVars, toVars, stagger, position, onCompleteAll, onCompleteAllParams) {
1956      toVars.startAt = fromVars;
1957      _inheritDefaults(toVars).immediateRender = _isNotFalse(toVars.immediateRender);
1958      return this.staggerTo(targets, duration, toVars, stagger, position, onCompleteAll, onCompleteAllParams);
1959    };
1960
1961    _proto2.render = function render(totalTime, suppressEvents, force) {
1962      var prevTime = this._time,
1963          tDur = this._dirty ? this.totalDuration() : this._tDur,
1964          dur = this._dur,
1965          tTime = totalTime <= 0 ? 0 : _roundPrecise(totalTime),
1966          crossingStart = this._zTime < 0 !== totalTime < 0 && (this._initted || !dur),
1967          time,
1968          child,
1969          next,
1970          iteration,
1971          cycleDuration,
1972          prevPaused,
1973          pauseTween,
1974          timeScale,
1975          prevStart,
1976          prevIteration,
1977          yoyo,
1978          isYoyo;
1979      this !== _globalTimeline && tTime > tDur && totalTime >= 0 && (tTime = tDur);
1980
1981      if (tTime !== this._tTime || force || crossingStart) {
1982        if (prevTime !== this._time && dur) {
1983          tTime += this._time - prevTime;
1984          totalTime += this._time - prevTime;
1985        }
1986
1987        time = tTime;
1988        prevStart = this._start;
1989        timeScale = this._ts;
1990        prevPaused = !timeScale;
1991
1992        if (crossingStart) {
1993          dur || (prevTime = this._zTime);
1994          (totalTime || !suppressEvents) && (this._zTime = totalTime);
1995        }
1996
1997        if (this._repeat) {
1998          yoyo = this._yoyo;
1999          cycleDuration = dur + this._rDelay;
2000
2001          if (this._repeat < -1 && totalTime < 0) {
2002            return this.totalTime(cycleDuration * 100 + totalTime, suppressEvents, force);
2003          }
2004
2005          time = _roundPrecise(tTime % cycleDuration);
2006
2007          if (tTime === tDur) {
2008            iteration = this._repeat;
2009            time = dur;
2010          } else {
2011            iteration = ~~(tTime / cycleDuration);
2012
2013            if (iteration && iteration === tTime / cycleDuration) {
2014              time = dur;
2015              iteration--;
2016            }
2017
2018            time > dur && (time = dur);
2019          }
2020
2021          prevIteration = _animationCycle(this._tTime, cycleDuration);
2022          !prevTime && this._tTime && prevIteration !== iteration && this._tTime - prevIteration * cycleDuration - this._dur <= 0 && (prevIteration = iteration);
2023
2024          if (yoyo && iteration & 1) {
2025            time = dur - time;
2026            isYoyo = 1;
2027          }
2028
2029          if (iteration !== prevIteration && !this._lock) {
2030            var rewinding = yoyo && prevIteration & 1,
2031                doesWrap = rewinding === (yoyo && iteration & 1);
2032            iteration < prevIteration && (rewinding = !rewinding);
2033            prevTime = rewinding ? 0 : tTime % dur ? dur : tTime;
2034            this._lock = 1;
2035            this.render(prevTime || (isYoyo ? 0 : _roundPrecise(iteration * cycleDuration)), suppressEvents, !dur)._lock = 0;
2036            this._tTime = tTime;
2037            !suppressEvents && this.parent && _callback(this, "onRepeat");
2038            this.vars.repeatRefresh && !isYoyo && (this.invalidate()._lock = 1);
2039
2040            if (prevTime && prevTime !== this._time || prevPaused !== !this._ts || this.vars.onRepeat && !this.parent && !this._act) {
2041              return this;
2042            }
2043
2044            dur = this._dur;
2045            tDur = this._tDur;
2046
2047            if (doesWrap) {
2048              this._lock = 2;
2049              prevTime = rewinding ? dur : -0.0001;
2050              this.render(prevTime, true);
2051              this.vars.repeatRefresh && !isYoyo && this.invalidate();
2052            }
2053
2054            this._lock = 0;
2055
2056            if (!this._ts && !prevPaused) {
2057              return this;
2058            }
2059
2060            _propagateYoyoEase(this, isYoyo);
2061          }
2062        }
2063
2064        if (this._hasPause && !this._forcing && this._lock < 2) {
2065          pauseTween = _findNextPauseTween(this, _roundPrecise(prevTime), _roundPrecise(time));
2066
2067          if (pauseTween) {
2068            tTime -= time - (time = pauseTween._start);
2069          }
2070        }
2071
2072        this._tTime = tTime;
2073        this._time = time;
2074        this._act = !timeScale;
2075
2076        if (!this._initted) {
vendor: 15,202 bytes, lines 2077-2609
2077          this._onUpdate = this.vars.onUpdate;
2078          this._initted = 1;
2079          this._zTime = totalTime;
2080          prevTime = 0;
2081        }
2082
2083        if (!prevTime && time && !suppressEvents && !iteration) {
2084          _callback(this, "onStart");
2085
2086          if (this._tTime !== tTime) {
2087            return this;
2088          }
2089        }
2090
2091        if (time >= prevTime && totalTime >= 0) {
2092          child = this._first;
2093
2094          while (child) {
2095            next = child._next;
2096
2097            if ((child._act || time >= child._start) && child._ts && pauseTween !== child) {
2098              if (child.parent !== this) {
2099                return this.render(totalTime, suppressEvents, force);
2100              }
2101
2102              child.render(child._ts > 0 ? (time - child._start) * child._ts : (child._dirty ? child.totalDuration() : child._tDur) + (time - child._start) * child._ts, suppressEvents, force);
2103
2104              if (time !== this._time || !this._ts && !prevPaused) {
2105                pauseTween = 0;
2106                next && (tTime += this._zTime = -_tinyNum);
2107                break;
2108              }
2109            }
2110
2111            child = next;
2112          }
2113        } else {
2114          child = this._last;
2115          var adjustedTime = totalTime < 0 ? totalTime : time;
2116
2117          while (child) {
2118            next = child._prev;
2119
2120            if ((child._act || adjustedTime <= child._end) && child._ts && pauseTween !== child) {
2121              if (child.parent !== this) {
2122                return this.render(totalTime, suppressEvents, force);
2123              }
2124
2125              child.render(child._ts > 0 ? (adjustedTime - child._start) * child._ts : (child._dirty ? child.totalDuration() : child._tDur) + (adjustedTime - child._start) * child._ts, suppressEvents, force || _reverting && (child._initted || child._startAt));
2126
2127              if (time !== this._time || !this._ts && !prevPaused) {
2128                pauseTween = 0;
2129                next && (tTime += this._zTime = adjustedTime ? -_tinyNum : _tinyNum);
2130                break;
2131              }
2132            }
2133
2134            child = next;
2135          }
2136        }
2137
2138        if (pauseTween && !suppressEvents) {
2139          this.pause();
2140          pauseTween.render(time >= prevTime ? 0 : -_tinyNum)._zTime = time >= prevTime ? 1 : -1;
2141
2142          if (this._ts) {
2143            this._start = prevStart;
2144
2145            _setEnd(this);
2146
2147            return this.render(totalTime, suppressEvents, force);
2148          }
2149        }
2150
2151        this._onUpdate && !suppressEvents && _callback(this, "onUpdate", true);
2152        if (tTime === tDur && this._tTime >= this.totalDuration() || !tTime && prevTime) if (prevStart === this._start || Math.abs(timeScale) !== Math.abs(this._ts)) if (!this._lock) {
2153          (totalTime || !dur) && (tTime === tDur && this._ts > 0 || !tTime && this._ts < 0) && _removeFromParent(this, 1);
2154
2155          if (!suppressEvents && !(totalTime < 0 && !prevTime) && (tTime || prevTime || !tDur)) {
2156            _callback(this, tTime === tDur && totalTime >= 0 ? "onComplete" : "onReverseComplete", true);
2157
2158            this._prom && !(tTime < tDur && this.timeScale() > 0) && this._prom();
2159          }
2160        }
2161      }
2162
2163      return this;
2164    };
2165
2166    _proto2.add = function add(child, position) {
2167      var _this2 = this;
2168
2169      _isNumber(position) || (position = _parsePosition(this, position, child));
2170
2171      if (!(child instanceof Animation)) {
2172        if (_isArray(child)) {
2173          child.forEach(function (obj) {
2174            return _this2.add(obj, position);
2175          });
2176          return this;
2177        }
2178
2179        if (_isString(child)) {
2180          return this.addLabel(child, position);
2181        }
2182
2183        if (_isFunction(child)) {
2184          child = Tween.delayedCall(0, child);
2185        } else {
2186          return this;
2187        }
2188      }
2189
2190      return this !== child ? _addToTimeline(this, child, position) : this;
2191    };
2192
2193    _proto2.getChildren = function getChildren(nested, tweens, timelines, ignoreBeforeTime) {
2194      if (nested === void 0) {
2195        nested = true;
2196      }
2197
2198      if (tweens === void 0) {
2199        tweens = true;
2200      }
2201
2202      if (timelines === void 0) {
2203        timelines = true;
2204      }
2205
2206      if (ignoreBeforeTime === void 0) {
2207        ignoreBeforeTime = -_bigNum;
2208      }
2209
2210      var a = [],
2211          child = this._first;
2212
2213      while (child) {
2214        if (child._start >= ignoreBeforeTime) {
2215          if (child instanceof Tween) {
2216            tweens && a.push(child);
2217          } else {
2218            timelines && a.push(child);
2219            nested && a.push.apply(a, child.getChildren(true, tweens, timelines));
2220          }
2221        }
2222
2223        child = child._next;
2224      }
2225
2226      return a;
2227    };
2228
2229    _proto2.getById = function getById(id) {
2230      var animations = this.getChildren(1, 1, 1),
2231          i = animations.length;
2232
2233      while (i--) {
2234        if (animations[i].vars.id === id) {
2235          return animations[i];
2236        }
2237      }
2238    };
2239
2240    _proto2.remove = function remove(child) {
2241      if (_isString(child)) {
2242        return this.removeLabel(child);
2243      }
2244
2245      if (_isFunction(child)) {
2246        return this.killTweensOf(child);
2247      }
2248
2249      _removeLinkedListItem(this, child);
2250
2251      if (child === this._recent) {
2252        this._recent = this._last;
2253      }
2254
2255      return _uncache(this);
2256    };
2257
2258    _proto2.totalTime = function totalTime(_totalTime2, suppressEvents) {
2259      if (!arguments.length) {
2260        return this._tTime;
2261      }
2262
2263      this._forcing = 1;
2264
2265      if (!this._dp && this._ts) {
2266        this._start = _roundPrecise(_ticker.time - (this._ts > 0 ? _totalTime2 / this._ts : (this.totalDuration() - _totalTime2) / -this._ts));
2267      }
2268
2269      _Animation.prototype.totalTime.call(this, _totalTime2, suppressEvents);
2270
2271      this._forcing = 0;
2272      return this;
2273    };
2274
2275    _proto2.addLabel = function addLabel(label, position) {
2276      this.labels[label] = _parsePosition(this, position);
2277      return this;
2278    };
2279
2280    _proto2.removeLabel = function removeLabel(label) {
2281      delete this.labels[label];
2282      return this;
2283    };
2284
2285    _proto2.addPause = function addPause(position, callback, params) {
2286      var t = Tween.delayedCall(0, callback || _emptyFunc, params);
2287      t.data = "isPause";
2288      this._hasPause = 1;
2289      return _addToTimeline(this, t, _parsePosition(this, position));
2290    };
2291
2292    _proto2.removePause = function removePause(position) {
2293      var child = this._first;
2294      position = _parsePosition(this, position);
2295
2296      while (child) {
2297        if (child._start === position && child.data === "isPause") {
2298          _removeFromParent(child);
2299        }
2300
2301        child = child._next;
2302      }
2303    };
2304
2305    _proto2.killTweensOf = function killTweensOf(targets, props, onlyActive) {
2306      var tweens = this.getTweensOf(targets, onlyActive),
2307          i = tweens.length;
2308
2309      while (i--) {
2310        _overwritingTween !== tweens[i] && tweens[i].kill(targets, props);
2311      }
2312
2313      return this;
2314    };
2315
2316    _proto2.getTweensOf = function getTweensOf(targets, onlyActive) {
2317      var a = [],
2318          parsedTargets = toArray(targets),
2319          child = this._first,
2320          isGlobalTime = _isNumber(onlyActive),
2321          children;
2322
2323      while (child) {
2324        if (child instanceof Tween) {
2325          if (_arrayContainsAny(child._targets, parsedTargets) && (isGlobalTime ? (!_overwritingTween || child._initted && child._ts) && child.globalTime(0) <= onlyActive && child.globalTime(child.totalDuration()) > onlyActive : !onlyActive || child.isActive())) {
2326            a.push(child);
2327          }
2328        } else if ((children = child.getTweensOf(parsedTargets, onlyActive)).length) {
2329          a.push.apply(a, children);
2330        }
2331
2332        child = child._next;
2333      }
2334
2335      return a;
2336    };
2337
2338    _proto2.tweenTo = function tweenTo(position, vars) {
2339      vars = vars || {};
2340
2341      var tl = this,
2342          endTime = _parsePosition(tl, position),
2343          _vars = vars,
2344          startAt = _vars.startAt,
2345          _onStart = _vars.onStart,
2346          onStartParams = _vars.onStartParams,
2347          immediateRender = _vars.immediateRender,
2348          initted,
2349          tween = Tween.to(tl, _setDefaults({
2350        ease: vars.ease || "none",
2351        lazy: false,
2352        immediateRender: false,
2353        time: endTime,
2354        overwrite: "auto",
2355        duration: vars.duration || Math.abs((endTime - (startAt && "time" in startAt ? startAt.time : tl._time)) / tl.timeScale()) || _tinyNum,
2356        onStart: function onStart() {
2357          tl.pause();
2358
2359          if (!initted) {
2360            var duration = vars.duration || Math.abs((endTime - (startAt && "time" in startAt ? startAt.time : tl._time)) / tl.timeScale());
2361            tween._dur !== duration && _setDuration(tween, duration, 0, 1).render(tween._time, true, true);
2362            initted = 1;
2363          }
2364
2365          _onStart && _onStart.apply(tween, onStartParams || []);
2366        }
2367      }, vars));
2368
2369      return immediateRender ? tween.render(0) : tween;
2370    };
2371
2372    _proto2.tweenFromTo = function tweenFromTo(fromPosition, toPosition, vars) {
2373      return this.tweenTo(toPosition, _setDefaults({
2374        startAt: {
2375          time: _parsePosition(this, fromPosition)
2376        }
2377      }, vars));
2378    };
2379
2380    _proto2.recent = function recent() {
2381      return this._recent;
2382    };
2383
2384    _proto2.nextLabel = function nextLabel(afterTime) {
2385      if (afterTime === void 0) {
2386        afterTime = this._time;
2387      }
2388
2389      return _getLabelInDirection(this, _parsePosition(this, afterTime));
2390    };
2391
2392    _proto2.previousLabel = function previousLabel(beforeTime) {
2393      if (beforeTime === void 0) {
2394        beforeTime = this._time;
2395      }
2396
2397      return _getLabelInDirection(this, _parsePosition(this, beforeTime), 1);
2398    };
2399
2400    _proto2.currentLabel = function currentLabel(value) {
2401      return arguments.length ? this.seek(value, true) : this.previousLabel(this._time + _tinyNum);
2402    };
2403
2404    _proto2.shiftChildren = function shiftChildren(amount, adjustLabels, ignoreBeforeTime) {
2405      if (ignoreBeforeTime === void 0) {
2406        ignoreBeforeTime = 0;
2407      }
2408
2409      var child = this._first,
2410          labels = this.labels,
2411          p;
2412
2413      while (child) {
2414        if (child._start >= ignoreBeforeTime) {
2415          child._start += amount;
2416          child._end += amount;
2417        }
2418
2419        child = child._next;
2420      }
2421
2422      if (adjustLabels) {
2423        for (p in labels) {
2424          if (labels[p] >= ignoreBeforeTime) {
2425            labels[p] += amount;
2426          }
2427        }
2428      }
2429
2430      return _uncache(this);
2431    };
2432
2433    _proto2.invalidate = function invalidate(soft) {
2434      var child = this._first;
2435      this._lock = 0;
2436
2437      while (child) {
2438        child.invalidate(soft);
2439        child = child._next;
2440      }
2441
2442      return _Animation.prototype.invalidate.call(this, soft);
2443    };
2444
2445    _proto2.clear = function clear(includeLabels) {
2446      if (includeLabels === void 0) {
2447        includeLabels = true;
2448      }
2449
2450      var child = this._first,
2451          next;
2452
2453      while (child) {
2454        next = child._next;
2455        this.remove(child);
2456        child = next;
2457      }
2458
2459      this._dp && (this._time = this._tTime = this._pTime = 0);
2460      includeLabels && (this.labels = {});
2461      return _uncache(this);
2462    };
2463
2464    _proto2.totalDuration = function totalDuration(value) {
2465      var max = 0,
2466          self = this,
2467          child = self._last,
2468          prevStart = _bigNum,
2469          prev,
2470          start,
2471          parent;
2472
2473      if (arguments.length) {
2474        return self.timeScale((self._repeat < 0 ? self.duration() : self.totalDuration()) / (self.reversed() ? -value : value));
2475      }
2476
2477      if (self._dirty) {
2478        parent = self.parent;
2479
2480        while (child) {
2481          prev = child._prev;
2482          child._dirty && child.totalDuration();
2483          start = child._start;
2484
2485          if (start > prevStart && self._sort && child._ts && !self._lock) {
2486            self._lock = 1;
2487            _addToTimeline(self, child, start - child._delay, 1)._lock = 0;
2488          } else {
2489            prevStart = start;
2490          }
2491
2492          if (start < 0 && child._ts) {
2493            max -= start;
2494
2495            if (!parent && !self._dp || parent && parent.smoothChildTiming) {
2496              self._start += start / self._ts;
2497              self._time -= start;
2498              self._tTime -= start;
2499            }
2500
2501            self.shiftChildren(-start, false, -1e999);
2502            prevStart = 0;
2503          }
2504
2505          child._end > max && child._ts && (max = child._end);
2506          child = prev;
2507        }
2508
2509        _setDuration(self, self === _globalTimeline && self._time > max ? self._time : max, 1, 1);
2510
2511        self._dirty = 0;
2512      }
2513
2514      return self._tDur;
2515    };
2516
2517    Timeline.updateRoot = function updateRoot(time) {
2518      if (_globalTimeline._ts) {
2519        _lazySafeRender(_globalTimeline, _parentToChildTotalTime(time, _globalTimeline));
2520
2521        _lastRenderedFrame = _ticker.frame;
2522      }
2523
2524      if (_ticker.frame >= _nextGCFrame) {
2525        _nextGCFrame += _config.autoSleep || 120;
2526        var child = _globalTimeline._first;
2527        if (!child || !child._ts) if (_config.autoSleep && _ticker._listeners.length < 2) {
2528          while (child && !child._ts) {
2529            child = child._next;
2530          }
2531
2532          child || _ticker.sleep();
2533        }
2534      }
2535    };
2536
2537    return Timeline;
2538  }(Animation);
2539
2540  _setDefaults(Timeline.prototype, {
2541    _lock: 0,
2542    _hasPause: 0,
2543    _forcing: 0
2544  });
2545
2546  var _addComplexStringPropTween = function _addComplexStringPropTween(target, prop, start, end, setter, stringFilter, funcParam) {
2547    var pt = new PropTween(this._pt, target, prop, 0, 1, _renderComplexString, null, setter),
2548        index = 0,
2549        matchIndex = 0,
2550        result,
2551        startNums,
2552        color,
2553        endNum,
2554        chunk,
2555        startNum,
2556        hasRandom,
2557        a;
2558    pt.b = start;
2559    pt.e = end;
2560    start += "";
2561    end += "";
2562
2563    if (hasRandom = ~end.indexOf("random(")) {
2564      end = _replaceRandom(end);
2565    }
2566
2567    if (stringFilter) {
2568      a = [start, end];
2569      stringFilter(a, target, prop);
2570      start = a[0];
2571      end = a[1];
2572    }
2573
2574    startNums = start.match(_complexStringNumExp) || [];
2575
2576    while (result = _complexStringNumExp.exec(end)) {
2577      endNum = result[0];
2578      chunk = end.substring(index, result.index);
2579
2580      if (color) {
2581        color = (color + 1) % 5;
2582      } else if (chunk.substr(-5) === "rgba(") {
2583        color = 1;
2584      }
2585
2586      if (endNum !== startNums[matchIndex++]) {
2587        startNum = parseFloat(startNums[matchIndex - 1]) || 0;
2588        pt._pt = {
2589          _next: pt._pt,
2590          p: chunk || matchIndex === 1 ? chunk : ",",
2591          s: startNum,
2592          c: endNum.charAt(1) === "=" ? _parseRelative(startNum, endNum) - startNum : parseFloat(endNum) - startNum,
2593          m: color && color < 4 ? Math.round : 0
2594        };
2595        index = _complexStringNumExp.lastIndex;
2596      }
2597    }
2598
2599    pt.c = index < end.length ? end.substring(index, end.length) : "";
2600    pt.fp = funcParam;
2601
2602    if (_relExp.test(end) || hasRandom) {
2603      pt.e = 0;
2604    }
2605
2606    this._pt = pt;
2607    return pt;
2608  },
2609      _addPropTween = function _addPropTween(target, prop, start, end, index, targets, modifier, stringFilter, funcParam, optional) {
vendor: 9,840 bytes, lines 2610-2896
2610    _isFunction(end) && (end = end(index || 0, target, targets));
2611    var currentValue = target[prop],
2612        parsedStart = start !== "get" ? start : !_isFunction(currentValue) ? currentValue : funcParam ? target[prop.indexOf("set") || !_isFunction(target["get" + prop.substr(3)]) ? prop : "get" + prop.substr(3)](funcParam) : target[prop](),
2613        setter = !_isFunction(currentValue) ? _setterPlain : funcParam ? _setterFuncWithParam : _setterFunc,
2614        pt;
2615
2616    if (_isString(end)) {
2617      if (~end.indexOf("random(")) {
2618        end = _replaceRandom(end);
2619      }
2620
2621      if (end.charAt(1) === "=") {
2622        pt = _parseRelative(parsedStart, end) + (getUnit(parsedStart) || 0);
2623
2624        if (pt || pt === 0) {
2625          end = pt;
2626        }
2627      }
2628    }
2629
2630    if (!optional || parsedStart !== end || _forceAllPropTweens) {
2631      if (!isNaN(parsedStart * end) && end !== "") {
2632        pt = new PropTween(this._pt, target, prop, +parsedStart || 0, end - (parsedStart || 0), typeof currentValue === "boolean" ? _renderBoolean : _renderPlain, 0, setter);
2633        funcParam && (pt.fp = funcParam);
2634        modifier && pt.modifier(modifier, this, target);
2635        return this._pt = pt;
2636      }
2637
2638      !currentValue && !(prop in target) && _missingPlugin(prop, end);
2639      return _addComplexStringPropTween.call(this, target, prop, parsedStart, end, setter, stringFilter || _config.stringFilter, funcParam);
2640    }
2641  },
2642      _processVars = function _processVars(vars, index, target, targets, tween) {
2643    _isFunction(vars) && (vars = _parseFuncOrString(vars, tween, index, target, targets));
2644
2645    if (!_isObject(vars) || vars.style && vars.nodeType || _isArray(vars) || _isTypedArray(vars)) {
2646      return _isString(vars) ? _parseFuncOrString(vars, tween, index, target, targets) : vars;
2647    }
2648
2649    var copy = {},
2650        p;
2651
2652    for (p in vars) {
2653      copy[p] = _parseFuncOrString(vars[p], tween, index, target, targets);
2654    }
2655
2656    return copy;
2657  },
2658      _checkPlugin = function _checkPlugin(property, vars, tween, index, target, targets) {
2659    var plugin, pt, ptLookup, i;
2660
2661    if (_plugins[property] && (plugin = new _plugins[property]()).init(target, plugin.rawVars ? vars[property] : _processVars(vars[property], index, target, targets, tween), tween, index, targets) !== false) {
2662      tween._pt = pt = new PropTween(tween._pt, target, property, 0, 1, plugin.render, plugin, 0, plugin.priority);
2663
2664      if (tween !== _quickTween) {
2665        ptLookup = tween._ptLookup[tween._targets.indexOf(target)];
2666        i = plugin._props.length;
2667
2668        while (i--) {
2669          ptLookup[plugin._props[i]] = pt;
2670        }
2671      }
2672    }
2673
2674    return plugin;
2675  },
2676      _overwritingTween,
2677      _forceAllPropTweens,
2678      _initTween = function _initTween(tween, time, tTime) {
2679    var vars = tween.vars,
2680        ease = vars.ease,
2681        startAt = vars.startAt,
2682        immediateRender = vars.immediateRender,
2683        lazy = vars.lazy,
2684        onUpdate = vars.onUpdate,
2685        runBackwards = vars.runBackwards,
2686        yoyoEase = vars.yoyoEase,
2687        keyframes = vars.keyframes,
2688        autoRevert = vars.autoRevert,
2689        dur = tween._dur,
2690        prevStartAt = tween._startAt,
2691        targets = tween._targets,
2692        parent = tween.parent,
2693        fullTargets = parent && parent.data === "nested" ? parent.vars.targets : targets,
2694        autoOverwrite = tween._overwrite === "auto" && !_suppressOverwrites,
2695        tl = tween.timeline,
2696        cleanVars,
2697        i,
2698        p,
2699        pt,
2700        target,
2701        hasPriority,
2702        gsData,
2703        harness,
2704        plugin,
2705        ptLookup,
2706        index,
2707        harnessVars,
2708        overwritten;
2709    tl && (!keyframes || !ease) && (ease = "none");
2710    tween._ease = _parseEase(ease, _defaults.ease);
2711    tween._yEase = yoyoEase ? _invertEase(_parseEase(yoyoEase === true ? ease : yoyoEase, _defaults.ease)) : 0;
2712
2713    if (yoyoEase && tween._yoyo && !tween._repeat) {
2714      yoyoEase = tween._yEase;
2715      tween._yEase = tween._ease;
2716      tween._ease = yoyoEase;
2717    }
2718
2719    tween._from = !tl && !!vars.runBackwards;
2720
2721    if (!tl || keyframes && !vars.stagger) {
2722      harness = targets[0] ? _getCache(targets[0]).harness : 0;
2723      harnessVars = harness && vars[harness.prop];
2724      cleanVars = _copyExcluding(vars, _reservedProps);
2725
2726      if (prevStartAt) {
2727        prevStartAt._zTime < 0 && prevStartAt.progress(1);
2728        time < 0 && runBackwards && immediateRender && !autoRevert ? prevStartAt.render(-1, true) : prevStartAt.revert(runBackwards && dur ? _revertConfigNoKill : _startAtRevertConfig);
2729        prevStartAt._lazy = 0;
2730      }
2731
2732      if (startAt) {
2733        _removeFromParent(tween._startAt = Tween.set(targets, _setDefaults({
2734          data: "isStart",
2735          overwrite: false,
2736          parent: parent,
2737          immediateRender: true,
2738          lazy: !prevStartAt && _isNotFalse(lazy),
2739          startAt: null,
2740          delay: 0,
2741          onUpdate: onUpdate && function () {
2742            return _callback(tween, "onUpdate");
2743          },
2744          stagger: 0
2745        }, startAt)));
2746
2747        tween._startAt._dp = 0;
2748        tween._startAt._sat = tween;
2749        time < 0 && (_reverting || !immediateRender && !autoRevert) && tween._startAt.revert(_revertConfigNoKill);
2750
2751        if (immediateRender) {
2752          if (dur && time <= 0 && tTime <= 0) {
2753            time && (tween._zTime = time);
2754            return;
2755          }
2756        }
2757      } else if (runBackwards && dur) {
2758        if (!prevStartAt) {
2759          time && (immediateRender = false);
2760          p = _setDefaults({
2761            overwrite: false,
2762            data: "isFromStart",
2763            lazy: immediateRender && !prevStartAt && _isNotFalse(lazy),
2764            immediateRender: immediateRender,
2765            stagger: 0,
2766            parent: parent
2767          }, cleanVars);
2768          harnessVars && (p[harness.prop] = harnessVars);
2769
2770          _removeFromParent(tween._startAt = Tween.set(targets, p));
2771
2772          tween._startAt._dp = 0;
2773          tween._startAt._sat = tween;
2774          time < 0 && (_reverting ? tween._startAt.revert(_revertConfigNoKill) : tween._startAt.render(-1, true));
2775          tween._zTime = time;
2776
2777          if (!immediateRender) {
2778            _initTween(tween._startAt, _tinyNum, _tinyNum);
2779          } else if (!time) {
2780            return;
2781          }
2782        }
2783      }
2784
2785      tween._pt = tween._ptCache = 0;
2786      lazy = dur && _isNotFalse(lazy) || lazy && !dur;
2787
2788      for (i = 0; i < targets.length; i++) {
2789        target = targets[i];
2790        gsData = target._gsap || _harness(targets)[i]._gsap;
2791        tween._ptLookup[i] = ptLookup = {};
2792        _lazyLookup[gsData.id] && _lazyTweens.length && _lazyRender();
2793        index = fullTargets === targets ? i : fullTargets.indexOf(target);
2794
2795        if (harness && (plugin = new harness()).init(target, harnessVars || cleanVars, tween, index, fullTargets) !== false) {
2796          tween._pt = pt = new PropTween(tween._pt, target, plugin.name, 0, 1, plugin.render, plugin, 0, plugin.priority);
2797
2798          plugin._props.forEach(function (name) {
2799            ptLookup[name] = pt;
2800          });
2801
2802          plugin.priority && (hasPriority = 1);
2803        }
2804
2805        if (!harness || harnessVars) {
2806          for (p in cleanVars) {
2807            if (_plugins[p] && (plugin = _checkPlugin(p, cleanVars, tween, index, target, fullTargets))) {
2808              plugin.priority && (hasPriority = 1);
2809            } else {
2810              ptLookup[p] = pt = _addPropTween.call(tween, target, p, "get", cleanVars[p], index, fullTargets, 0, vars.stringFilter);
2811            }
2812          }
2813        }
2814
2815        tween._op && tween._op[i] && tween.kill(target, tween._op[i]);
2816
2817        if (autoOverwrite && tween._pt) {
2818          _overwritingTween = tween;
2819
2820          _globalTimeline.killTweensOf(target, ptLookup, tween.globalTime(time));
2821
2822          overwritten = !tween.parent;
2823          _overwritingTween = 0;
2824        }
2825
2826        tween._pt && lazy && (_lazyLookup[gsData.id] = 1);
2827      }
2828
2829      hasPriority && _sortPropTweensByPriority(tween);
2830      tween._onInit && tween._onInit(tween);
2831    }
2832
2833    tween._onUpdate = onUpdate;
2834    tween._initted = (!tween._op || tween._pt) && !overwritten;
2835    keyframes && time <= 0 && tl.render(_bigNum, true, true);
2836  },
2837      _updatePropTweens = function _updatePropTweens(tween, property, value, start, startIsRelative, ratio, time, skipRecursion) {
2838    var ptCache = (tween._pt && tween._ptCache || (tween._ptCache = {}))[property],
2839        pt,
2840        rootPT,
2841        lookup,
2842        i;
2843
2844    if (!ptCache) {
2845      ptCache = tween._ptCache[property] = [];
2846      lookup = tween._ptLookup;
2847      i = tween._targets.length;
2848
2849      while (i--) {
2850        pt = lookup[i][property];
2851
2852        if (pt && pt.d && pt.d._pt) {
2853          pt = pt.d._pt;
2854
2855          while (pt && pt.p !== property && pt.fp !== property) {
2856            pt = pt._next;
2857          }
2858        }
2859
2860        if (!pt) {
2861          _forceAllPropTweens = 1;
2862          tween.vars[property] = "+=0";
2863
2864          _initTween(tween, time);
2865
2866          _forceAllPropTweens = 0;
2867          return skipRecursion ? _warn(property + " not eligible for reset") : 1;
2868        }
2869
2870        ptCache.push(pt);
2871      }
2872    }
2873
2874    i = ptCache.length;
2875
2876    while (i--) {
2877      rootPT = ptCache[i];
2878      pt = rootPT._pt || rootPT;
2879      pt.s = (start || start === 0) && !startIsRelative ? start : pt.s + (start || 0) + ratio * pt.c;
2880      pt.c = value - pt.s;
2881      rootPT.e && (rootPT.e = _round(value) + getUnit(rootPT.e));
2882      rootPT.b && (rootPT.b = pt.s + getUnit(rootPT.b));
2883    }
2884  },
2885      _addAliasesToVars = function _addAliasesToVars(targets, vars) {
2886    var harness = targets[0] ? _getCache(targets[0]).harness : 0,
2887        propertyAliases = harness && harness.aliases,
2888        copy,
2889        p,
2890        i,
2891        aliases;
2892
2893    if (!propertyAliases) {
2894      return vars;
2895    }
2896
vendor: 4,984 bytes, lines 2897-3039
2897    copy = _merge({}, vars);
2898
2899    for (p in propertyAliases) {
2900      if (p in copy) {
2901        aliases = propertyAliases[p].split(",");
2902        i = aliases.length;
2903
2904        while (i--) {
2905          copy[aliases[i]] = copy[p];
2906        }
2907      }
2908    }
2909
2910    return copy;
2911  },
2912      _parseKeyframe = function _parseKeyframe(prop, obj, allProps, easeEach) {
2913    var ease = obj.ease || easeEach || "power1.inOut",
2914        p,
2915        a;
2916
2917    if (_isArray(obj)) {
2918      a = allProps[prop] || (allProps[prop] = []);
2919      obj.forEach(function (value, i) {
2920        return a.push({
2921          t: i / (obj.length - 1) * 100,
2922          v: value,
2923          e: ease
2924        });
2925      });
2926    } else {
2927      for (p in obj) {
2928        a = allProps[p] || (allProps[p] = []);
2929        p === "ease" || a.push({
2930          t: parseFloat(prop),
2931          v: obj[p],
2932          e: ease
2933        });
2934      }
2935    }
2936  },
2937      _parseFuncOrString = function _parseFuncOrString(value, tween, i, target, targets) {
2938    return _isFunction(value) ? value.call(tween, i, target, targets) : _isString(value) && ~value.indexOf("random(") ? _replaceRandom(value) : value;
2939  },
2940      _staggerTweenProps = _callbackNames + "repeat,repeatDelay,yoyo,repeatRefresh,yoyoEase,autoRevert",
2941      _staggerPropsToSkip = {};
2942
2943  _forEachName(_staggerTweenProps + ",id,stagger,delay,duration,paused,scrollTrigger", function (name) {
2944    return _staggerPropsToSkip[name] = 1;
2945  });
2946
2947  var Tween = function (_Animation2) {
2948    _inheritsLoose(Tween, _Animation2);
2949
2950    function Tween(targets, vars, position, skipInherit) {
2951      var _this3;
2952
2953      if (typeof vars === "number") {
2954        position.duration = vars;
2955        vars = position;
2956        position = null;
2957      }
2958
2959      _this3 = _Animation2.call(this, skipInherit ? vars : _inheritDefaults(vars)) || this;
2960      var _this3$vars = _this3.vars,
2961          duration = _this3$vars.duration,
2962          delay = _this3$vars.delay,
2963          immediateRender = _this3$vars.immediateRender,
2964          stagger = _this3$vars.stagger,
2965          overwrite = _this3$vars.overwrite,
2966          keyframes = _this3$vars.keyframes,
2967          defaults = _this3$vars.defaults,
2968          scrollTrigger = _this3$vars.scrollTrigger,
2969          yoyoEase = _this3$vars.yoyoEase,
2970          parent = vars.parent || _globalTimeline,
2971          parsedTargets = (_isArray(targets) || _isTypedArray(targets) ? _isNumber(targets[0]) : "length" in vars) ? [targets] : toArray(targets),
2972          tl,
2973          i,
2974          copy,
2975          l,
2976          p,
2977          curTarget,
2978          staggerFunc,
2979          staggerVarsToMerge;
2980      _this3._targets = parsedTargets.length ? _harness(parsedTargets) : _warn("GSAP target " + targets + " not found. https://gsap.com", !_config.nullTargetWarn) || [];
2981      _this3._ptLookup = [];
2982      _this3._overwrite = overwrite;
2983
2984      if (keyframes || stagger || _isFuncOrString(duration) || _isFuncOrString(delay)) {
2985        vars = _this3.vars;
2986        tl = _this3.timeline = new Timeline({
2987          data: "nested",
2988          defaults: defaults || {},
2989          targets: parent && parent.data === "nested" ? parent.vars.targets : parsedTargets
2990        });
2991        tl.kill();
2992        tl.parent = tl._dp = _assertThisInitialized(_this3);
2993        tl._start = 0;
2994
2995        if (stagger || _isFuncOrString(duration) || _isFuncOrString(delay)) {
2996          l = parsedTargets.length;
2997          staggerFunc = stagger && distribute(stagger);
2998
2999          if (_isObject(stagger)) {
3000            for (p in stagger) {
3001              if (~_staggerTweenProps.indexOf(p)) {
3002                staggerVarsToMerge || (staggerVarsToMerge = {});
3003                staggerVarsToMerge[p] = stagger[p];
3004              }
3005            }
3006          }
3007
3008          for (i = 0; i < l; i++) {
3009            copy = _copyExcluding(vars, _staggerPropsToSkip);
3010            copy.stagger = 0;
3011            yoyoEase && (copy.yoyoEase = yoyoEase);
3012            staggerVarsToMerge && _merge(copy, staggerVarsToMerge);
3013            curTarget = parsedTargets[i];
3014            copy.duration = +_parseFuncOrString(duration, _assertThisInitialized(_this3), i, curTarget, parsedTargets);
3015            copy.delay = (+_parseFuncOrString(delay, _assertThisInitialized(_this3), i, curTarget, parsedTargets) || 0) - _this3._delay;
3016
3017            if (!stagger && l === 1 && copy.delay) {
3018              _this3._delay = delay = copy.delay;
3019              _this3._start += delay;
3020              copy.delay = 0;
3021            }
3022
3023            tl.to(curTarget, copy, staggerFunc ? staggerFunc(i, curTarget, parsedTargets) : 0);
3024            tl._ease = _easeMap.none;
3025          }
3026
3027          tl.duration() ? duration = delay = 0 : _this3.timeline = 0;
3028        } else if (keyframes) {
3029          _inheritDefaults(_setDefaults(tl.vars.defaults, {
3030            ease: "none"
3031          }));
3032
3033          tl._ease = _parseEase(keyframes.ease || vars.ease || "none");
3034          var time = 0,
3035              a,
3036              kf,
3037              v;
3038
3039          if (_isArray(keyframes)) {
vendor: 6,477 bytes, lines 3040-3246
3040            keyframes.forEach(function (frame) {
3041              return tl.to(parsedTargets, frame, ">");
3042            });
3043            tl.duration();
3044          } else {
3045            copy = {};
3046
3047            for (p in keyframes) {
3048              p === "ease" || p === "easeEach" || _parseKeyframe(p, keyframes[p], copy, keyframes.easeEach);
3049            }
3050
3051            for (p in copy) {
3052              a = copy[p].sort(function (a, b) {
3053                return a.t - b.t;
3054              });
3055              time = 0;
3056
3057              for (i = 0; i < a.length; i++) {
3058                kf = a[i];
3059                v = {
3060                  ease: kf.e,
3061                  duration: (kf.t - (i ? a[i - 1].t : 0)) / 100 * duration
3062                };
3063                v[p] = kf.v;
3064                tl.to(parsedTargets, v, time);
3065                time += v.duration;
3066              }
3067            }
3068
3069            tl.duration() < duration && tl.to({}, {
3070              duration: duration - tl.duration()
3071            });
3072          }
3073        }
3074
3075        duration || _this3.duration(duration = tl.duration());
3076      } else {
3077        _this3.timeline = 0;
3078      }
3079
3080      if (overwrite === true && !_suppressOverwrites) {
3081        _overwritingTween = _assertThisInitialized(_this3);
3082
3083        _globalTimeline.killTweensOf(parsedTargets);
3084
3085        _overwritingTween = 0;
3086      }
3087
3088      _addToTimeline(parent, _assertThisInitialized(_this3), position);
3089
3090      vars.reversed && _this3.reverse();
3091      vars.paused && _this3.paused(true);
3092
3093      if (immediateRender || !duration && !keyframes && _this3._start === _roundPrecise(parent._time) && _isNotFalse(immediateRender) && _hasNoPausedAncestors(_assertThisInitialized(_this3)) && parent.data !== "nested") {
3094        _this3._tTime = -_tinyNum;
3095
3096        _this3.render(Math.max(0, -delay) || 0);
3097      }
3098
3099      scrollTrigger && _scrollTrigger(_assertThisInitialized(_this3), scrollTrigger);
3100      return _this3;
3101    }
3102
3103    var _proto3 = Tween.prototype;
3104
3105    _proto3.render = function render(totalTime, suppressEvents, force) {
3106      var prevTime = this._time,
3107          tDur = this._tDur,
3108          dur = this._dur,
3109          isNegative = totalTime < 0,
3110          tTime = totalTime > tDur - _tinyNum && !isNegative ? tDur : totalTime < _tinyNum ? 0 : totalTime,
3111          time,
3112          pt,
3113          iteration,
3114          cycleDuration,
3115          prevIteration,
3116          isYoyo,
3117          ratio,
3118          timeline,
3119          yoyoEase;
3120
3121      if (!dur) {
3122        _renderZeroDurationTween(this, totalTime, suppressEvents, force);
3123      } else if (tTime !== this._tTime || !totalTime || force || !this._initted && this._tTime || this._startAt && this._zTime < 0 !== isNegative) {
3124        time = tTime;
3125        timeline = this.timeline;
3126
3127        if (this._repeat) {
3128          cycleDuration = dur + this._rDelay;
3129
3130          if (this._repeat < -1 && isNegative) {
3131            return this.totalTime(cycleDuration * 100 + totalTime, suppressEvents, force);
3132          }
3133
3134          time = _roundPrecise(tTime % cycleDuration);
3135
3136          if (tTime === tDur) {
3137            iteration = this._repeat;
3138            time = dur;
3139          } else {
3140            iteration = ~~(tTime / cycleDuration);
3141
3142            if (iteration && iteration === _roundPrecise(tTime / cycleDuration)) {
3143              time = dur;
3144              iteration--;
3145            }
3146
3147            time > dur && (time = dur);
3148          }
3149
3150          isYoyo = this._yoyo && iteration & 1;
3151
3152          if (isYoyo) {
3153            yoyoEase = this._yEase;
3154            time = dur - time;
3155          }
3156
3157          prevIteration = _animationCycle(this._tTime, cycleDuration);
3158
3159          if (time === prevTime && !force && this._initted && iteration === prevIteration) {
3160            this._tTime = tTime;
3161            return this;
3162          }
3163
3164          if (iteration !== prevIteration) {
3165            timeline && this._yEase && _propagateYoyoEase(timeline, isYoyo);
3166
3167            if (this.vars.repeatRefresh && !isYoyo && !this._lock && this._time !== cycleDuration && this._initted) {
3168              this._lock = force = 1;
3169              this.render(_roundPrecise(cycleDuration * iteration), true).invalidate()._lock = 0;
3170            }
3171          }
3172        }
3173
3174        if (!this._initted) {
3175          if (_attemptInitTween(this, isNegative ? totalTime : time, force, suppressEvents, tTime)) {
3176            this._tTime = 0;
3177            return this;
3178          }
3179
3180          if (prevTime !== this._time && !(force && this.vars.repeatRefresh && iteration !== prevIteration)) {
3181            return this;
3182          }
3183
3184          if (dur !== this._dur) {
3185            return this.render(totalTime, suppressEvents, force);
3186          }
3187        }
3188
3189        this._tTime = tTime;
3190        this._time = time;
3191
3192        if (!this._act && this._ts) {
3193          this._act = 1;
3194          this._lazy = 0;
3195        }
3196
3197        this.ratio = ratio = (yoyoEase || this._ease)(time / dur);
3198
3199        if (this._from) {
3200          this.ratio = ratio = 1 - ratio;
3201        }
3202
3203        if (time && !prevTime && !suppressEvents && !iteration) {
3204          _callback(this, "onStart");
3205
3206          if (this._tTime !== tTime) {
3207            return this;
3208          }
3209        }
3210
3211        pt = this._pt;
3212
3213        while (pt) {
3214          pt.r(ratio, pt.d);
3215          pt = pt._next;
3216        }
3217
3218        timeline && timeline.render(totalTime < 0 ? totalTime : timeline._dur * timeline._ease(time / this._dur), suppressEvents, force) || this._startAt && (this._zTime = totalTime);
3219
3220        if (this._onUpdate && !suppressEvents) {
3221          isNegative && _rewindStartAt(this, totalTime, suppressEvents, force);
3222
3223          _callback(this, "onUpdate");
3224        }
3225
3226        this._repeat && iteration !== prevIteration && this.vars.onRepeat && !suppressEvents && this.parent && _callback(this, "onRepeat");
3227
3228        if ((tTime === this._tDur || !tTime) && this._tTime === tTime) {
3229          isNegative && !this._onUpdate && _rewindStartAt(this, totalTime, true, true);
3230          (totalTime || !dur) && (tTime === this._tDur && this._ts > 0 || !tTime && this._ts < 0) && _removeFromParent(this, 1);
3231
3232          if (!suppressEvents && !(isNegative && !prevTime) && (tTime || prevTime || isYoyo)) {
3233            _callback(this, tTime === tDur ? "onComplete" : "onReverseComplete", true);
3234
3235            this._prom && !(tTime < tDur && this.timeScale() > 0) && this._prom();
3236          }
3237        }
3238      }
3239
3240      return this;
3241    };
3242
3243    _proto3.targets = function targets() {
3244      return this._targets;
3245    };
3246
vendor: 1,310 bytes, lines 3247-3280
3247    _proto3.invalidate = function invalidate(soft) {
3248      (!soft || !this.vars.runBackwards) && (this._startAt = 0);
3249      this._pt = this._op = this._onUpdate = this._lazy = this.ratio = 0;
3250      this._ptLookup = [];
3251      this.timeline && this.timeline.invalidate(soft);
3252      return _Animation2.prototype.invalidate.call(this, soft);
3253    };
3254
3255    _proto3.resetTo = function resetTo(property, value, start, startIsRelative, skipRecursion) {
3256      _tickerActive || _ticker.wake();
3257      this._ts || this.play();
3258      var time = Math.min(this._dur, (this._dp._time - this._start) * this._ts),
3259          ratio;
3260      this._initted || _initTween(this, time);
3261      ratio = this._ease(time / this._dur);
3262
3263      if (_updatePropTweens(this, property, value, start, startIsRelative, ratio, time, skipRecursion)) {
3264        return this.resetTo(property, value, start, startIsRelative, 1);
3265      }
3266
3267      _alignPlayhead(this, 0);
3268
3269      this.parent || _addLinkedListItem(this._dp, this, "_first", "_last", this._dp._sort ? "_start" : 0);
3270      return this.render(0);
3271    };
3272
3273    _proto3.kill = function kill(targets, vars) {
3274      if (vars === void 0) {
3275        vars = "all";
3276      }
3277
3278      if (!targets && (!vars || vars === "all")) {
3279        this._lazy = this._pt = 0;
3280        return this.parent ? _interrupt(this) :
vendor: 16,527 bytes, lines 3280-3882
3280 this;
3281      }
3282
3283      if (this.timeline) {
3284        var tDur = this.timeline.totalDuration();
3285        this.timeline.killTweensOf(targets, vars, _overwritingTween && _overwritingTween.vars.overwrite !== true)._first || _interrupt(this);
3286        this.parent && tDur !== this.timeline.totalDuration() && _setDuration(this, this._dur * this.timeline._tDur / tDur, 0, 1);
3287        return this;
3288      }
3289
3290      var parsedTargets = this._targets,
3291          killingTargets = targets ? toArray(targets) : parsedTargets,
3292          propTweenLookup = this._ptLookup,
3293          firstPT = this._pt,
3294          overwrittenProps,
3295          curLookup,
3296          curOverwriteProps,
3297          props,
3298          p,
3299          pt,
3300          i;
3301
3302      if ((!vars || vars === "all") && _arraysMatch(parsedTargets, killingTargets)) {
3303        vars === "all" && (this._pt = 0);
3304        return _interrupt(this);
3305      }
3306
3307      overwrittenProps = this._op = this._op || [];
3308
3309      if (vars !== "all") {
3310        if (_isString(vars)) {
3311          p = {};
3312
3313          _forEachName(vars, function (name) {
3314            return p[name] = 1;
3315          });
3316
3317          vars = p;
3318        }
3319
3320        vars = _addAliasesToVars(parsedTargets, vars);
3321      }
3322
3323      i = parsedTargets.length;
3324
3325      while (i--) {
3326        if (~killingTargets.indexOf(parsedTargets[i])) {
3327          curLookup = propTweenLookup[i];
3328
3329          if (vars === "all") {
3330            overwrittenProps[i] = vars;
3331            props = curLookup;
3332            curOverwriteProps = {};
3333          } else {
3334            curOverwriteProps = overwrittenProps[i] = overwrittenProps[i] || {};
3335            props = vars;
3336          }
3337
3338          for (p in props) {
3339            pt = curLookup && curLookup[p];
3340
3341            if (pt) {
3342              if (!("kill" in pt.d) || pt.d.kill(p) === true) {
3343                _removeLinkedListItem(this, pt, "_pt");
3344              }
3345
3346              delete curLookup[p];
3347            }
3348
3349            if (curOverwriteProps !== "all") {
3350              curOverwriteProps[p] = 1;
3351            }
3352          }
3353        }
3354      }
3355
3356      this._initted && !this._pt && firstPT && _interrupt(this);
3357      return this;
3358    };
3359
3360    Tween.to = function to(targets, vars) {
3361      return new Tween(targets, vars, arguments[2]);
3362    };
3363
3364    Tween.from = function from(targets, vars) {
3365      return _createTweenType(1, arguments);
3366    };
3367
3368    Tween.delayedCall = function delayedCall(delay, callback, params, scope) {
3369      return new Tween(callback, 0, {
3370        immediateRender: false,
3371        lazy: false,
3372        overwrite: false,
3373        delay: delay,
3374        onComplete: callback,
3375        onReverseComplete: callback,
3376        onCompleteParams: params,
3377        onReverseCompleteParams: params,
3378        callbackScope: scope
3379      });
3380    };
3381
3382    Tween.fromTo = function fromTo(targets, fromVars, toVars) {
3383      return _createTweenType(2, arguments);
3384    };
3385
3386    Tween.set = function set(targets, vars) {
3387      vars.duration = 0;
3388      vars.repeatDelay || (vars.repeat = 0);
3389      return new Tween(targets, vars);
3390    };
3391
3392    Tween.killTweensOf = function killTweensOf(targets, props, onlyActive) {
3393      return _globalTimeline.killTweensOf(targets, props, onlyActive);
3394    };
3395
3396    return Tween;
3397  }(Animation);
3398
3399  _setDefaults(Tween.prototype, {
3400    _targets: [],
3401    _lazy: 0,
3402    _startAt: 0,
3403    _op: 0,
3404    _onInit: 0
3405  });
3406
3407  _forEachName("staggerTo,staggerFrom,staggerFromTo", function (name) {
3408    Tween[name] = function () {
3409      var tl = new Timeline(),
3410          params = _slice.call(arguments, 0);
3411
3412      params.splice(name === "staggerFromTo" ? 5 : 4, 0, 0);
3413      return tl[name].apply(tl, params);
3414    };
3415  });
3416
3417  var _setterPlain = function _setterPlain(target, property, value) {
3418    return target[property] = value;
3419  },
3420      _setterFunc = function _setterFunc(target, property, value) {
3421    return target[property](value);
3422  },
3423      _setterFuncWithParam = function _setterFuncWithParam(target, property, value, data) {
3424    return target[property](data.fp, value);
3425  },
3426      _setterAttribute = function _setterAttribute(target, property, value) {
3427    return target.setAttribute(property, value);
3428  },
3429      _getSetter = function _getSetter(target, property) {
3430    return _isFunction(target[property]) ? _setterFunc : _isUndefined(target[property]) && target.setAttribute ? _setterAttribute : _setterPlain;
3431  },
3432      _renderPlain = function _renderPlain(ratio, data) {
3433    return data.set(data.t, data.p, Math.round((data.s + data.c * ratio) * 1000000) / 1000000, data);
3434  },
3435      _renderBoolean = function _renderBoolean(ratio, data) {
3436    return data.set(data.t, data.p, !!(data.s + data.c * ratio), data);
3437  },
3438      _renderComplexString = function _renderComplexString(ratio, data) {
3439    var pt = data._pt,
3440        s = "";
3441
3442    if (!ratio && data.b) {
3443      s = data.b;
3444    } else if (ratio === 1 && data.e) {
3445      s = data.e;
3446    } else {
3447      while (pt) {
3448        s = pt.p + (pt.m ? pt.m(pt.s + pt.c * ratio) : Math.round((pt.s + pt.c * ratio) * 10000) / 10000) + s;
3449        pt = pt._next;
3450      }
3451
3452      s += data.c;
3453    }
3454
3455    data.set(data.t, data.p, s, data);
3456  },
3457      _renderPropTweens = function _renderPropTweens(ratio, data) {
3458    var pt = data._pt;
3459
3460    while (pt) {
3461      pt.r(ratio, pt.d);
3462      pt = pt._next;
3463    }
3464  },
3465      _addPluginModifier = function _addPluginModifier(modifier, tween, target, property) {
3466    var pt = this._pt,
3467        next;
3468
3469    while (pt) {
3470      next = pt._next;
3471      pt.p === property && pt.modifier(modifier, tween, target);
3472      pt = next;
3473    }
3474  },
3475      _killPropTweensOf = function _killPropTweensOf(property) {
3476    var pt = this._pt,
3477        hasNonDependentRemaining,
3478        next;
3479
3480    while (pt) {
3481      next = pt._next;
3482
3483      if (pt.p === property && !pt.op || pt.op === property) {
3484        _removeLinkedListItem(this, pt, "_pt");
3485      } else if (!pt.dep) {
3486        hasNonDependentRemaining = 1;
3487      }
3488
3489      pt = next;
3490    }
3491
3492    return !hasNonDependentRemaining;
3493  },
3494      _setterWithModifier = function _setterWithModifier(target, property, value, data) {
3495    data.mSet(target, property, data.m.call(data.tween, value, data.mt), data);
3496  },
3497      _sortPropTweensByPriority = function _sortPropTweensByPriority(parent) {
3498    var pt = parent._pt,
3499        next,
3500        pt2,
3501        first,
3502        last;
3503
3504    while (pt) {
3505      next = pt._next;
3506      pt2 = first;
3507
3508      while (pt2 && pt2.pr > pt.pr) {
3509        pt2 = pt2._next;
3510      }
3511
3512      if (pt._prev = pt2 ? pt2._prev : last) {
3513        pt._prev._next = pt;
3514      } else {
3515        first = pt;
3516      }
3517
3518      if (pt._next = pt2) {
3519        pt2._prev = pt;
3520      } else {
3521        last = pt;
3522      }
3523
3524      pt = next;
3525    }
3526
3527    parent._pt = first;
3528  };
3529
3530  var PropTween = function () {
3531    function PropTween(next, target, prop, start, change, renderer, data, setter, priority) {
3532      this.t = target;
3533      this.s = start;
3534      this.c = change;
3535      this.p = prop;
3536      this.r = renderer || _renderPlain;
3537      this.d = data || this;
3538      this.set = setter || _setterPlain;
3539      this.pr = priority || 0;
3540      this._next = next;
3541
3542      if (next) {
3543        next._prev = this;
3544      }
3545    }
3546
3547    var _proto4 = PropTween.prototype;
3548
3549    _proto4.modifier = function modifier(func, tween, target) {
3550      this.mSet = this.mSet || this.set;
3551      this.set = _setterWithModifier;
3552      this.m = func;
3553      this.mt = target;
3554      this.tween = tween;
3555    };
3556
3557    return PropTween;
3558  }();
3559
3560  _forEachName(_callbackNames + "parent,duration,ease,delay,overwrite,runBackwards,startAt,yoyo,immediateRender,repeat,repeatDelay,data,paused,reversed,lazy,callbackScope,stringFilter,id,yoyoEase,stagger,inherit,repeatRefresh,keyframes,autoRevert,scrollTrigger", function (name) {
3561    return _reservedProps[name] = 1;
3562  });
3563
3564  _globals.TweenMax = _globals.TweenLite = Tween;
3565  _globals.TimelineLite = _globals.TimelineMax = Timeline;
3566  _globalTimeline = new Timeline({
3567    sortChildren: false,
3568    defaults: _defaults,
3569    autoRemoveChildren: true,
3570    id: "root",
3571    smoothChildTiming: true
3572  });
3573  _config.stringFilter = _colorStringFilter;
3574
3575  var _media = [],
3576      _listeners = {},
3577      _emptyArray = [],
3578      _lastMediaTime = 0,
3579      _contextID = 0,
3580      _dispatch = function _dispatch(type) {
3581    return (_listeners[type] || _emptyArray).map(function (f) {
3582      return f();
3583    });
3584  },
3585      _onMediaChange = function _onMediaChange() {
3586    var time = Date.now(),
3587        matches = [];
3588
3589    if (time - _lastMediaTime > 2) {
3590      _dispatch("matchMediaInit");
3591
3592      _media.forEach(function (c) {
3593        var queries = c.queries,
3594            conditions = c.conditions,
3595            match,
3596            p,
3597            anyMatch,
3598            toggled;
3599
3600        for (p in queries) {
3601          match = _win.matchMedia(queries[p]).matches;
3602          match && (anyMatch = 1);
3603
3604          if (match !== conditions[p]) {
3605            conditions[p] = match;
3606            toggled = 1;
3607          }
3608        }
3609
3610        if (toggled) {
3611          c.revert();
3612          anyMatch && matches.push(c);
3613        }
3614      });
3615
3616      _dispatch("matchMediaRevert");
3617
3618      matches.forEach(function (c) {
3619        return c.onMatch(c, function (func) {
3620          return c.add(null, func);
3621        });
3622      });
3623      _lastMediaTime = time;
3624
3625      _dispatch("matchMedia");
3626    }
3627  };
3628
3629  var Context = function () {
3630    function Context(func, scope) {
3631      this.selector = scope && selector(scope);
3632      this.data = [];
3633      this._r = [];
3634      this.isReverted = false;
3635      this.id = _contextID++;
3636      func && this.add(func);
3637    }
3638
3639    var _proto5 = Context.prototype;
3640
3641    _proto5.add = function add(name, func, scope) {
3642      if (_isFunction(name)) {
3643        scope = func;
3644        func = name;
3645        name = _isFunction;
3646      }
3647
3648      var self = this,
3649          f = function f() {
3650        var prev = _context,
3651            prevSelector = self.selector,
3652            result;
3653        prev && prev !== self && prev.data.push(self);
3654        scope && (self.selector = selector(scope));
3655        _context = self;
3656        result = func.apply(self, arguments);
3657        _isFunction(result) && self._r.push(result);
3658        _context = prev;
3659        self.selector = prevSelector;
3660        self.isReverted = false;
3661        return result;
3662      };
3663
3664      self.last = f;
3665      return name === _isFunction ? f(self, function (func) {
3666        return self.add(null, func);
3667      }) : name ? self[name] = f : f;
3668    };
3669
3670    _proto5.ignore = function ignore(func) {
3671      var prev = _context;
3672      _context = null;
3673      func(this);
3674      _context = prev;
3675    };
3676
3677    _proto5.getTweens = function getTweens() {
3678      var a = [];
3679      this.data.forEach(function (e) {
3680        return e instanceof Context ? a.push.apply(a, e.getTweens()) : e instanceof Tween && !(e.parent && e.parent.data === "nested") && a.push(e);
3681      });
3682      return a;
3683    };
3684
3685    _proto5.clear = function clear() {
3686      this._r.length = this.data.length = 0;
3687    };
3688
3689    _proto5.kill = function kill(revert, matchMedia) {
3690      var _this4 = this;
3691
3692      if (revert) {
3693        (function () {
3694          var tweens = _this4.getTweens(),
3695              i = _this4.data.length,
3696              t;
3697
3698          while (i--) {
3699            t = _this4.data[i];
3700
3701            if (t.data === "isFlip") {
3702              t.revert();
3703              t.getChildren(true, true, false).forEach(function (tween) {
3704                return tweens.splice(tweens.indexOf(tween), 1);
3705              });
3706            }
3707          }
3708
3709          tweens.map(function (t) {
3710            return {
3711              g: t._dur || t._delay || t._sat && !t._sat.vars.immediateRender ? t.globalTime(0) : -Infinity,
3712              t: t
3713            };
3714          }).sort(function (a, b) {
3715            return b.g - a.g || -Infinity;
3716          }).forEach(function (o) {
3717            return o.t.revert(revert);
3718          });
3719          i = _this4.data.length;
3720
3721          while (i--) {
3722            t = _this4.data[i];
3723
3724            if (t instanceof Timeline) {
3725              if (t.data !== "nested") {
3726                t.scrollTrigger && t.scrollTrigger.revert();
3727                t.kill();
3728              }
3729            } else {
3730              !(t instanceof Tween) && t.revert && t.revert(revert);
3731            }
3732          }
3733
3734          _this4._r.forEach(function (f) {
3735            return f(revert, _this4);
3736          });
3737
3738          _this4.isReverted = true;
3739        })();
3740      } else {
3741        this.data.forEach(function (e) {
3742          return e.kill && e.kill();
3743        });
3744      }
3745
3746      this.clear();
3747
3748      if (matchMedia) {
3749        var i = _media.length;
3750
3751        while (i--) {
3752          _media[i].id === this.id && _media.splice(i, 1);
3753        }
3754      }
3755    };
3756
3757    _proto5.revert = function revert(config) {
3758      this.kill(config || {});
3759    };
3760
3761    return Context;
3762  }();
3763
3764  var MatchMedia = function () {
3765    function MatchMedia(scope) {
3766      this.contexts = [];
3767      this.scope = scope;
3768      _context && _context.data.push(this);
3769    }
3770
3771    var _proto6 = MatchMedia.prototype;
3772
3773    _proto6.add = function add(conditions, func, scope) {
3774      _isObject(conditions) || (conditions = {
3775        matches: conditions
3776      });
3777      var context = new Context(0, scope || this.scope),
3778          cond = context.conditions = {},
3779          mq,
3780          p,
3781          active;
3782      _context && !context.selector && (context.selector = _context.selector);
3783      this.contexts.push(context);
3784      func = context.add("onMatch", func);
3785      context.queries = conditions;
3786
3787      for (p in conditions) {
3788        if (p === "all") {
3789          active = 1;
3790        } else {
3791          mq = _win.matchMedia(conditions[p]);
3792
3793          if (mq) {
3794            _media.indexOf(context) < 0 && _media.push(context);
3795            (cond[p] = mq.matches) && (active = 1);
3796            mq.addListener ? mq.addListener(_onMediaChange) : mq.addEventListener("change", _onMediaChange);
3797          }
3798        }
3799      }
3800
3801      active && func(context, function (f) {
3802        return context.add(null, f);
3803      });
3804      return this;
3805    };
3806
3807    _proto6.revert = function revert(config) {
3808      this.kill(config || {});
3809    };
3810
3811    _proto6.kill = function kill(revert) {
3812      this.contexts.forEach(function (c) {
3813        return c.kill(revert, true);
3814      });
3815    };
3816
3817    return MatchMedia;
3818  }();
3819
3820  var _gsap = {
3821    registerPlugin: function registerPlugin() {
3822      for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
3823        args[_key2] = arguments[_key2];
3824      }
3825
3826      args.forEach(function (config) {
3827        return _createPlugin(config);
3828      });
3829    },
3830    timeline: function timeline(vars) {
3831      return new Timeline(vars);
3832    },
3833    getTweensOf: function getTweensOf(targets, onlyActive) {
3834      return _globalTimeline.getTweensOf(targets, onlyActive);
3835    },
3836    getProperty: function getProperty(target, property, unit, uncache) {
3837      _isString(target) && (target = toArray(target)[0]);
3838
3839      var getter = _getCache(target || {}).get,
3840          format = unit ? _passThrough : _numericIfPossible;
3841
3842      unit === "native" && (unit = "");
3843      return !target ? target : !property ? function (property, unit, uncache) {
3844        return format((_plugins[property] && _plugins[property].get || getter)(target, property, unit, uncache));
3845      } : format((_plugins[property] && _plugins[property].get || getter)(target, property, unit, uncache));
3846    },
3847    quickSetter: function quickSetter(target, property, unit) {
3848      target = toArray(target);
3849
3850      if (target.length > 1) {
3851        var setters = target.map(function (t) {
3852          return gsap.quickSetter(t, property, unit);
3853        }),
3854            l = setters.length;
3855        return function (value) {
3856          var i = l;
3857
3858          while (i--) {
3859            setters[i](value);
3860          }
3861        };
3862      }
3863
3864      target = target[0] || {};
3865
3866      var Plugin = _plugins[property],
3867          cache = _getCache(target),
3868          p = cache.harness && (cache.harness.aliases || {})[property] || property,
3869          setter = Plugin ? function (value) {
3870        var p = new Plugin();
3871        _quickTween._pt = 0;
3872        p.init(target, unit ? value + unit : value, _quickTween, 0, [target]);
3873        p.render(1, p);
3874        _quickTween._pt && _renderPropTweens(1, _quickTween);
3875      } : cache.set(target, p);
3876
3877      return Plugin ? setter : function (value) {
3878        return setter(target, p, unit ? value + unit : value, cache, 1);
3879      };
3880    },
3881    quickTo: function quickTo(target, property, vars) {
3882      var _
3882merge2;
3883
3884      var tween = gsap.to(target, _merge((_merge2 = {}, _merge2[property] = "+=0.1", _merge2.paused = true, _merge
vendor: 5,649 bytes, lines 3884-4086
38842), vars || {})),
3885          func = function func(value, start, startIsRelative) {
3886        return tween.resetTo(property, value, start, startIsRelative);
3887      };
3888
3889      func.tween = tween;
3890      return func;
3891    },
3892    isTweening: function isTweening(targets) {
3893      return _globalTimeline.getTweensOf(targets, true).length > 0;
3894    },
3895    defaults: function defaults(value) {
3896      value && value.ease && (value.ease = _parseEase(value.ease, _defaults.ease));
3897      return _mergeDeep(_defaults, value || {});
3898    },
3899    config: function config(value) {
3900      return _mergeDeep(_config, value || {});
3901    },
3902    registerEffect: function registerEffect(_ref3) {
3903      var name = _ref3.name,
3904          effect = _ref3.effect,
3905          plugins = _ref3.plugins,
3906          defaults = _ref3.defaults,
3907          extendTimeline = _ref3.extendTimeline;
3908      (plugins || "").split(",").forEach(function (pluginName) {
3909        return pluginName && !_plugins[pluginName] && !_globals[pluginName] && _warn(name + " effect requires " + pluginName + " plugin.");
3910      });
3911
3912      _effects[name] = function (targets, vars, tl) {
3913        return effect(toArray(targets), _setDefaults(vars || {}, defaults), tl);
3914      };
3915
3916      if (extendTimeline) {
3917        Timeline.prototype[name] = function (targets, vars, position) {
3918          return this.add(_effects[name](targets, _isObject(vars) ? vars : (position = vars) && {}, this), position);
3919        };
3920      }
3921    },
3922    registerEase: function registerEase(name, ease) {
3923      _easeMap[name] = _parseEase(ease);
3924    },
3925    parseEase: function parseEase(ease, defaultEase) {
3926      return arguments.length ? _parseEase(ease, defaultEase) : _easeMap;
3927    },
3928    getById: function getById(id) {
3929      return _globalTimeline.getById(id);
3930    },
3931    exportRoot: function exportRoot(vars, includeDelayedCalls) {
3932      if (vars === void 0) {
3933        vars = {};
3934      }
3935
3936      var tl = new Timeline(vars),
3937          child,
3938          next;
3939      tl.smoothChildTiming = _isNotFalse(vars.smoothChildTiming);
3940
3941      _globalTimeline.remove(tl);
3942
3943      tl._dp = 0;
3944      tl._time = tl._tTime = _globalTimeline._time;
3945      child = _globalTimeline._first;
3946
3947      while (child) {
3948        next = child._next;
3949
3950        if (includeDelayedCalls || !(!child._dur && child instanceof Tween && child.vars.onComplete === child._targets[0])) {
3951          _addToTimeline(tl, child, child._start - child._delay);
3952        }
3953
3954        child = next;
3955      }
3956
3957      _addToTimeline(_globalTimeline, tl, 0);
3958
3959      return tl;
3960    },
3961    context: function context(func, scope) {
3962      return func ? new Context(func, scope) : _context;
3963    },
3964    matchMedia: function matchMedia(scope) {
3965      return new MatchMedia(scope);
3966    },
3967    matchMediaRefresh: function matchMediaRefresh() {
3968      return _media.forEach(function (c) {
3969        var cond = c.conditions,
3970            found,
3971            p;
3972
3973        for (p in cond) {
3974          if (cond[p]) {
3975            cond[p] = false;
3976            found = 1;
3977          }
3978        }
3979
3980        found && c.revert();
3981      }) || _onMediaChange();
3982    },
3983    addEventListener: function addEventListener(type, callback) {
3984      var a = _listeners[type] || (_listeners[type] = []);
3985      ~a.indexOf(callback) || a.push(callback);
3986    },
3987    removeEventListener: function removeEventListener(type, callback) {
3988      var a = _listeners[type],
3989          i = a && a.indexOf(callback);
3990      i >= 0 && a.splice(i, 1);
3991    },
3992    utils: {
3993      wrap: wrap,
3994      wrapYoyo: wrapYoyo,
3995      distribute: distribute,
3996      random: random,
3997      snap: snap,
3998      normalize: normalize,
3999      getUnit: getUnit,
4000      clamp: clamp,
4001      splitColor: splitColor,
4002      toArray: toArray,
4003      selector: selector,
4004      mapRange: mapRange,
4005      pipe: pipe,
4006      unitize: unitize,
4007      interpolate: interpolate,
4008      shuffle: shuffle
4009    },
4010    install: _install,
4011    effects: _effects,
4012    ticker: _ticker,
4013    updateRoot: Timeline.updateRoot,
4014    plugins: _plugins,
4015    globalTimeline: _globalTimeline,
4016    core: {
4017      PropTween: PropTween,
4018      globals: _addGlobal,
4019      Tween: Tween,
4020      Timeline: Timeline,
4021      Animation: Animation,
4022      getCache: _getCache,
4023      _removeLinkedListItem: _removeLinkedListItem,
4024      reverting: function reverting() {
4025        return _reverting;
4026      },
4027      context: function context(toAdd) {
4028        if (toAdd && _context) {
4029          _context.data.push(toAdd);
4030
4031          toAdd._ctx = _context;
4032        }
4033
4034        return _context;
4035      },
4036      suppressOverwrites: function suppressOverwrites(value) {
4037        return _suppressOverwrites = value;
4038      }
4039    }
4040  };
4041
4042  _forEachName("to,from,fromTo,delayedCall,set,killTweensOf", function (name) {
4043    return _gsap[name] = Tween[name];
4044  });
4045
4046  _ticker.add(Timeline.updateRoot);
4047
4048  _quickTween = _gsap.to({}, {
4049    duration: 0
4050  });
4051
4052  var _getPluginPropTween = function _getPluginPropTween(plugin, prop) {
4053    var pt = plugin._pt;
4054
4055    while (pt && pt.p !== prop && pt.op !== prop && pt.fp !== prop) {
4056      pt = pt._next;
4057    }
4058
4059    return pt;
4060  },
4061      _addModifiers = function _addModifiers(tween, modifiers) {
4062    var targets = tween._targets,
4063        p,
4064        i,
4065        pt;
4066
4067    for (p in modifiers) {
4068      i = targets.length;
4069
4070      while (i--) {
4071        pt = tween._ptLookup[i][p];
4072
4073        if (pt && (pt = pt.d)) {
4074          if (pt._pt) {
4075            pt = _getPluginPropTween(pt, p);
4076          }
4077
4078          pt && pt.modifier && pt.modifier(modifiers[p], tween, targets[i], p);
4079        }
4080      }
4081    }
4082  },
4083      _buildModifierPlugin = function _buildModifierPlugin(name, modifier) {
4084    return {
4085      name: name,
4086      
vendor: 21,125 bytes, lines 4086-4737
4086rawVars: 1,
4087      init: function init(target, vars, tween) {
4088        tween._onInit = function (tween) {
4089          var temp, p;
4090
4091          if (_isString(vars)) {
4092            temp = {};
4093
4094            _forEachName(vars, function (name) {
4095              return temp[name] = 1;
4096            });
4097
4098            vars = temp;
4099          }
4100
4101          if (modifier) {
4102            temp = {};
4103
4104            for (p in vars) {
4105              temp[p] = modifier(vars[p]);
4106            }
4107
4108            vars = temp;
4109          }
4110
4111          _addModifiers(tween, vars);
4112        };
4113      }
4114    };
4115  };
4116
4117  var gsap = _gsap.registerPlugin({
4118    name: "attr",
4119    init: function init(target, vars, tween, index, targets) {
4120      var p, pt, v;
4121      this.tween = tween;
4122
4123      for (p in vars) {
4124        v = target.getAttribute(p) || "";
4125        pt = this.add(target, "setAttribute", (v || 0) + "", vars[p], index, targets, 0, 0, p);
4126        pt.op = p;
4127        pt.b = v;
4128
4129        this._props.push(p);
4130      }
4131    },
4132    render: function render(ratio, data) {
4133      var pt = data._pt;
4134
4135      while (pt) {
4136        _reverting ? pt.set(pt.t, pt.p, pt.b, pt) : pt.r(ratio, pt.d);
4137        pt = pt._next;
4138      }
4139    }
4140  }, {
4141    name: "endArray",
4142    init: function init(target, value) {
4143      var i = value.length;
4144
4145      while (i--) {
4146        this.add(target, i, target[i] || 0, value[i], 0, 0, 0, 0, 0, 1);
4147      }
4148    }
4149  }, _buildModifierPlugin("roundProps", _roundModifier), _buildModifierPlugin("modifiers"), _buildModifierPlugin("snap", snap)) || _gsap;
4150  Tween.version = Timeline.version = gsap.version = "3.12.5";
4151  _coreReady = 1;
4152  _windowExists() && _wake();
4153  var Power0 = _easeMap.Power0,
4154      Power1 = _easeMap.Power1,
4155      Power2 = _easeMap.Power2,
4156      Power3 = _easeMap.Power3,
4157      Power4 = _easeMap.Power4,
4158      Linear = _easeMap.Linear,
4159      Quad = _easeMap.Quad,
4160      Cubic = _easeMap.Cubic,
4161      Quart = _easeMap.Quart,
4162      Quint = _easeMap.Quint,
4163      Strong = _easeMap.Strong,
4164      Elastic = _easeMap.Elastic,
4165      Back = _easeMap.Back,
4166      SteppedEase = _easeMap.SteppedEase,
4167      Bounce = _easeMap.Bounce,
4168      Sine = _easeMap.Sine,
4169      Expo = _easeMap.Expo,
4170      Circ = _easeMap.Circ;
4171
4172  var _win$1,
4173      _doc$1,
4174      _docElement,
4175      _pluginInitted,
4176      _tempDiv,
4177      _tempDivStyler,
4178      _recentSetterPlugin,
4179      _reverting$1,
4180      _windowExists$1 = function _windowExists() {
4181    return typeof window !== "undefined";
4182  },
4183      _transformProps = {},
4184      _RAD2DEG = 180 / Math.PI,
4185      _DEG2RAD = Math.PI / 180,
4186      _atan2 = Math.atan2,
4187      _bigNum$1 = 1e8,
4188      _capsExp = /([A-Z])/g,
4189      _horizontalExp = /(left|right|width|margin|padding|x)/i,
4190      _complexExp = /[\s,\(]\S/,
4191      _propertyAliases = {
4192    autoAlpha: "opacity,visibility",
4193    scale: "scaleX,scaleY",
4194    alpha: "opacity"
4195  },
4196      _renderCSSProp = function _renderCSSProp(ratio, data) {
4197    return data.set(data.t, data.p, Math.round((data.s + data.c * ratio) * 10000) / 10000 + data.u, data);
4198  },
4199      _renderPropWithEnd = function _renderPropWithEnd(ratio, data) {
4200    return data.set(data.t, data.p, ratio === 1 ? data.e : Math.round((data.s + data.c * ratio) * 10000) / 10000 + data.u, data);
4201  },
4202      _renderCSSPropWithBeginning = function _renderCSSPropWithBeginning(ratio, data) {
4203    return data.set(data.t, data.p, ratio ? Math.round((data.s + data.c * ratio) * 10000) / 10000 + data.u : data.b, data);
4204  },
4205      _renderRoundedCSSProp = function _renderRoundedCSSProp(ratio, data) {
4206    var value = data.s + data.c * ratio;
4207    data.set(data.t, data.p, ~~(value + (value < 0 ? -.5 : .5)) + data.u, data);
4208  },
4209      _renderNonTweeningValue = function _renderNonTweeningValue(ratio, data) {
4210    return data.set(data.t, data.p, ratio ? data.e : data.b, data);
4211  },
4212      _renderNonTweeningValueOnlyAtEnd = function _renderNonTweeningValueOnlyAtEnd(ratio, data) {
4213    return data.set(data.t, data.p, ratio !== 1 ? data.b : data.e, data);
4214  },
4215      _setterCSSStyle = function _setterCSSStyle(target, property, value) {
4216    return target.style[property] = value;
4217  },
4218      _setterCSSProp = function _setterCSSProp(target, property, value) {
4219    return target.style.setProperty(property, value);
4220  },
4221      _setterTransform = function _setterTransform(target, property, value) {
4222    return target._gsap[property] = value;
4223  },
4224      _setterScale = function _setterScale(target, property, value) {
4225    return target._gsap.scaleX = target._gsap.scaleY = value;
4226  },
4227      _setterScaleWithRender = function _setterScaleWithRender(target, property, value, data, ratio) {
4228    var cache = target._gsap;
4229    cache.scaleX = cache.scaleY = value;
4230    cache.renderTransform(ratio, cache);
4231  },
4232      _setterTransformWithRender = function _setterTransformWithRender(target, property, value, data, ratio) {
4233    var cache = target._gsap;
4234    cache[property] = value;
4235    cache.renderTransform(ratio, cache);
4236  },
4237      _transformProp = "transform",
4238      _transformOriginProp = _transformProp + "Origin",
4239      _saveStyle = function _saveStyle(property, isNotCSS) {
4240    var _this = this;
4241
4242    var target = this.target,
4243        style = target.style,
4244        cache = target._gsap;
4245
4246    if (property in _transformProps && style) {
4247      this.tfm = this.tfm || {};
4248
4249      if (property !== "transform") {
4250        property = _propertyAliases[property] || property;
4251        ~property.indexOf(",") ? property.split(",").forEach(function (a) {
4252          return _this.tfm[a] = _get(target, a);
4253        }) : this.tfm[property] = cache.x ? cache[property] : _get(target, property);
4254        property === _transformOriginProp && (this.tfm.zOrigin = cache.zOrigin);
4255      } else {
4256        return _propertyAliases.transform.split(",").forEach(function (p) {
4257          return _saveStyle.call(_this, p, isNotCSS);
4258        });
4259      }
4260
4261      if (this.props.indexOf(_transformProp) >= 0) {
4262        return;
4263      }
4264
4265      if (cache.svg) {
4266        this.svgo = target.getAttribute("data-svg-origin");
4267        this.props.push(_transformOriginProp, isNotCSS, "");
4268      }
4269
4270      property = _transformProp;
4271    }
4272
4273    (style || isNotCSS) && this.props.push(property, isNotCSS, style[property]);
4274  },
4275      _removeIndependentTransforms = function _removeIndependentTransforms(style) {
4276    if (style.translate) {
4277      style.removeProperty("translate");
4278      style.removeProperty("scale");
4279      style.removeProperty("rotate");
4280    }
4281  },
4282      _revertStyle = function _revertStyle() {
4283    var props = this.props,
4284        target = this.target,
4285        style = target.style,
4286        cache = target._gsap,
4287        i,
4288        p;
4289
4290    for (i = 0; i < props.length; i += 3) {
4291      props[i + 1] ? target[props[i]] = props[i + 2] : props[i + 2] ? style[props[i]] = props[i + 2] : style.removeProperty(props[i].substr(0, 2) === "--" ? props[i] : props[i].replace(_capsExp, "-$1").toLowerCase());
4292    }
4293
4294    if (this.tfm) {
4295      for (p in this.tfm) {
4296        cache[p] = this.tfm[p];
4297      }
4298
4299      if (cache.svg) {
4300        cache.renderTransform();
4301        target.setAttribute("data-svg-origin", this.svgo || "");
4302      }
4303
4304      i = _reverting$1();
4305
4306      if ((!i || !i.isStart) && !style[_transformProp]) {
4307        _removeIndependentTransforms(style);
4308
4309        if (cache.zOrigin && style[_transformOriginProp]) {
4310          style[_transformOriginProp] += " " + cache.zOrigin + "px";
4311          cache.zOrigin = 0;
4312          cache.renderTransform();
4313        }
4314
4315        cache.uncache = 1;
4316      }
4317    }
4318  },
4319      _getStyleSaver = function _getStyleSaver(target, properties) {
4320    var saver = {
4321      target: target,
4322      props: [],
4323      revert: _revertStyle,
4324      save: _saveStyle
4325    };
4326    target._gsap || gsap.core.getCache(target);
4327    properties && properties.split(",").forEach(function (p) {
4328      return saver.save(p);
4329    });
4330    return saver;
4331  },
4332      _supports3D,
4333      _createElement = function _createElement(type, ns) {
4334    var e = _doc$1.createElementNS ? _doc$1.createElementNS((ns || "http://www.w3.org/1999/xhtml").replace(/^https/, "http"), type) : _doc$1.createElement(type);
4335    return e && e.style ? e : _doc$1.createElement(type);
4336  },
4337      _getComputedProperty = function _getComputedProperty(target, property, skipPrefixFallback) {
4338    var cs = getComputedStyle(target);
4339    return cs[property] || cs.getPropertyValue(property.replace(_capsExp, "-$1").toLowerCase()) || cs.getPropertyValue(property) || !skipPrefixFallback && _getComputedProperty(target, _checkPropPrefix(property) || property, 1) || "";
4340  },
4341      _prefixes = "O,Moz,ms,Ms,Webkit".split(","),
4342      _checkPropPrefix = function _checkPropPrefix(property, element, preferPrefix) {
4343    var e = element || _tempDiv,
4344        s = e.style,
4345        i = 5;
4346
4347    if (property in s && !preferPrefix) {
4348      return property;
4349    }
4350
4351    property = property.charAt(0).toUpperCase() + property.substr(1);
4352
4353    while (i-- && !(_prefixes[i] + property in s)) {}
4354
4355    return i < 0 ? null : (i === 3 ? "ms" : i >= 0 ? _prefixes[i] : "") + property;
4356  },
4357      _initCore = function _initCore() {
4358    if (_windowExists$1() && window.document) {
4359      _win$1 = window;
4360      _doc$1 = _win$1.document;
4361      _docElement = _doc$1.documentElement;
4362      _tempDiv = _createElement("div") || {
4363        style: {}
4364      };
4365      _tempDivStyler = _createElement("div");
4366      _transformProp = _checkPropPrefix(_transformProp);
4367      _transformOriginProp = _transformProp + "Origin";
4368      _tempDiv.style.cssText = "border-width:0;line-height:0;position:absolute;padding:0";
4369      _supports3D = !!_checkPropPrefix("perspective");
4370      _reverting$1 = gsap.core.reverting;
4371      _pluginInitted = 1;
4372    }
4373  },
4374      _getBBoxHack = function _getBBoxHack(swapIfPossible) {
4375    var svg = _createElement("svg", this.ownerSVGElement && this.ownerSVGElement.getAttribute("xmlns") || "http://www.w3.org/2000/svg"),
4376        oldParent = this.parentNode,
4377        oldSibling = this.nextSibling,
4378        oldCSS = this.style.cssText,
4379        bbox;
4380
4381    _docElement.appendChild(svg);
4382
4383    svg.appendChild(this);
4384    this.style.display = "block";
4385
4386    if (swapIfPossible) {
4387      try {
4388        bbox = this.getBBox();
4389        this._gsapBBox = this.getBBox;
4390        this.getBBox = _getBBoxHack;
4391      } catch (e) {}
4392    } else if (this._gsapBBox) {
4393      bbox = this._gsapBBox();
4394    }
4395
4396    if (oldParent) {
4397      if (oldSibling) {
4398        oldParent.insertBefore(this, oldSibling);
4399      } else {
4400        oldParent.appendChild(this);
4401      }
4402    }
4403
4404    _docElement.removeChild(svg);
4405
4406    this.style.cssText = oldCSS;
4407    return bbox;
4408  },
4409      _getAttributeFallbacks = function _getAttributeFallbacks(target, attributesArray) {
4410    var i = attributesArray.length;
4411
4412    while (i--) {
4413      if (target.hasAttribute(attributesArray[i])) {
4414        return target.getAttribute(attributesArray[i]);
4415      }
4416    }
4417  },
4418      _getBBox = function _getBBox(target) {
4419    var bounds;
4420
4421    try {
4422      bounds = target.getBBox();
4423    } catch (error) {
4424      bounds = _getBBoxHack.call(target, true);
4425    }
4426
4427    bounds && (bounds.width || bounds.height) || target.getBBox === _getBBoxHack || (bounds = _getBBoxHack.call(target, true));
4428    return bounds && !bounds.width && !bounds.x && !bounds.y ? {
4429      x: +_getAttributeFallbacks(target, ["x", "cx", "x1"]) || 0,
4430      y: +_getAttributeFallbacks(target, ["y", "cy", "y1"]) || 0,
4431      width: 0,
4432      height: 0
4433    } : bounds;
4434  },
4435      _isSVG = function _isSVG(e) {
4436    return !!(e.getCTM && (!e.parentNode || e.ownerSVGElement) && _getBBox(e));
4437  },
4438      _removeProperty = function _removeProperty(target, property) {
4439    if (property) {
4440      var style = target.style,
4441          first2Chars;
4442
4443      if (property in _transformProps && property !== _transformOriginProp) {
4444        property = _transformProp;
4445      }
4446
4447      if (style.removeProperty) {
4448        first2Chars = property.substr(0, 2);
4449
4450        if (first2Chars === "ms" || property.substr(0, 6) === "webkit") {
4451          property = "-" + property;
4452        }
4453
4454        style.removeProperty(first2Chars === "--" ? property : property.replace(_capsExp, "-$1").toLowerCase());
4455      } else {
4456        style.removeAttribute(property);
4457      }
4458    }
4459  },
4460      _addNonTweeningPT = function _addNonTweeningPT(plugin, target, property, beginning, end, onlySetAtEnd) {
4461    var pt = new PropTween(plugin._pt, target, property, 0, 1, onlySetAtEnd ? _renderNonTweeningValueOnlyAtEnd : _renderNonTweeningValue);
4462    plugin._pt = pt;
4463    pt.b = beginning;
4464    pt.e = end;
4465
4466    plugin._props.push(property);
4467
4468    return pt;
4469  },
4470      _nonConvertibleUnits = {
4471    deg: 1,
4472    rad: 1,
4473    turn: 1
4474  },
4475      _nonStandardLayouts = {
4476    grid: 1,
4477    flex: 1
4478  },
4479      _convertToUnit = function _convertToUnit(target, property, value, unit) {
4480    var curValue = parseFloat(value) || 0,
4481        curUnit = (value + "").trim().substr((curValue + "").length) || "px",
4482        style = _tempDiv.style,
4483        horizontal = _horizontalExp.test(property),
4484        isRootSVG = target.tagName.toLowerCase() === "svg",
4485        measureProperty = (isRootSVG ? "client" : "offset") + (horizontal ? "Width" : "Height"),
4486        amount = 100,
4487        toPixels = unit === "px",
4488        toPercent = unit === "%",
4489        px,
4490        parent,
4491        cache,
4492        isSVG;
4493
4494    if (unit === curUnit || !curValue || _nonConvertibleUnits[unit] || _nonConvertibleUnits[curUnit]) {
4495      return curValue;
4496    }
4497
4498    curUnit !== "px" && !toPixels && (curValue = _convertToUnit(target, property, value, "px"));
4499    isSVG = target.getCTM && _isSVG(target);
4500
4501    if ((toPercent || curUnit === "%") && (_transformProps[property] || ~property.indexOf("adius"))) {
4502      px = isSVG ? target.getBBox()[horizontal ? "width" : "height"] : target[measureProperty];
4503      return _round(toPercent ? curValue / px * amount : curValue / 100 * px);
4504    }
4505
4506    style[horizontal ? "width" : "height"] = amount + (toPixels ? curUnit : unit);
4507    parent = ~property.indexOf("adius") || unit === "em" && target.appendChild && !isRootSVG ? target : target.parentNode;
4508
4509    if (isSVG) {
4510      parent = (target.ownerSVGElement || {}).parentNode;
4511    }
4512
4513    if (!parent || parent === _doc$1 || !parent.appendChild) {
4514      parent = _doc$1.body;
4515    }
4516
4517    cache = parent._gsap;
4518
4519    if (cache && toPercent && cache.width && horizontal && cache.time === _ticker.time && !cache.uncache) {
4520      return _round(curValue / cache.width * amount);
4521    } else {
4522      if (toPercent && (property === "height" || property === "width")) {
4523        var v = target.style[property];
4524        target.style[property] = amount + unit;
4525        px = target[measureProperty];
4526        v ? target.style[property] = v : _removeProperty(target, property);
4527      } else {
4528        (toPercent || curUnit === "%") && !_nonStandardLayouts[_getComputedProperty(parent, "display")] && (style.position = _getComputedProperty(target, "position"));
4529        parent === target && (style.position = "static");
4530        parent.appendChild(_tempDiv);
4531        px = _tempDiv[measureProperty];
4532        parent.removeChild(_tempDiv);
4533        style.position = "absolute";
4534      }
4535
4536      if (horizontal && toPercent) {
4537        cache = _getCache(parent);
4538        cache.time = _ticker.time;
4539        cache.width = parent[measureProperty];
4540      }
4541    }
4542
4543    return _round(toPixels ? px * curValue / amount : px && curValue ? amount / px * curValue : 0);
4544  },
4545      _get = function _get(target, property, unit, uncache) {
4546    var value;
4547    _pluginInitted || _initCore();
4548
4549    if (property in _propertyAliases && property !== "transform") {
4550      property = _propertyAliases[property];
4551
4552      if (~property.indexOf(",")) {
4553        property = property.split(",")[0];
4554      }
4555    }
4556
4557    if (_transformProps[property] && property !== "transform") {
4558      value = _parseTransform(target, uncache);
4559      value = property !== "transformOrigin" ? value[property] : value.svg ? value.origin : _firstTwoOnly(_getComputedProperty(target, _transformOriginProp)) + " " + value.zOrigin + "px";
4560    } else {
4561      value = target.style[property];
4562
4563      if (!value || value === "auto" || uncache || ~(value + "").indexOf("calc(")) {
4564        value = _specialProps[property] && _specialProps[property](target, property, unit) || _getComputedProperty(target, property) || _getProperty(target, property) || (property === "opacity" ? 1 : 0);
4565      }
4566    }
4567
4568    return unit && !~(value + "").trim().indexOf(" ") ? _convertToUnit(target, property, value, unit) + unit : value;
4569  },
4570      _tweenComplexCSSString = function _tweenComplexCSSString(target, prop, start, end) {
4571    if (!start || start === "none") {
4572      var p = _checkPropPrefix(prop, target, 1),
4573          s = p && _getComputedProperty(target, p, 1);
4574
4575      if (s && s !== start) {
4576        prop = p;
4577        start = s;
4578      } else if (prop === "borderColor") {
4579        start = _getComputedProperty(target, "borderTopColor");
4580      }
4581    }
4582
4583    var pt = new PropTween(this._pt, target.style, prop, 0, 1, _renderComplexString),
4584        index = 0,
4585        matchIndex = 0,
4586        a,
4587        result,
4588        startValues,
4589        startNum,
4590        color,
4591        startValue,
4592        endValue,
4593        endNum,
4594        chunk,
4595        endUnit,
4596        startUnit,
4597        endValues;
4598    pt.b = start;
4599    pt.e = end;
4600    start += "";
4601    end += "";
4602
4603    if (end === "auto") {
4604      startValue = target.style[prop];
4605      target.style[prop] = end;
4606      end = _getComputedProperty(target, prop) || end;
4607      startValue ? target.style[prop] = startValue : _removeProperty(target, prop);
4608    }
4609
4610    a = [start, end];
4611
4612    _colorStringFilter(a);
4613
4614    start = a[0];
4615    end = a[1];
4616    startValues = start.match(_numWithUnitExp) || [];
4617    endValues = end.match(_numWithUnitExp) || [];
4618
4619    if (endValues.length) {
4620      while (result = _numWithUnitExp.exec(end)) {
4621        endValue = result[0];
4622        chunk = end.substring(index, result.index);
4623
4624        if (color) {
4625          color = (color + 1) % 5;
4626        } else if (chunk.substr(-5) === "rgba(" || chunk.substr(-5) === "hsla(") {
4627          color = 1;
4628        }
4629
4630        if (endValue !== (startValue = startValues[matchIndex++] || "")) {
4631          startNum = parseFloat(startValue) || 0;
4632          startUnit = startValue.substr((startNum + "").length);
4633          endValue.charAt(1) === "=" && (endValue = _parseRelative(startNum, endValue) + startUnit);
4634          endNum = parseFloat(endValue);
4635          endUnit = endValue.substr((endNum + "").length);
4636          index = _numWithUnitExp.lastIndex - endUnit.length;
4637
4638          if (!endUnit) {
4639            endUnit = endUnit || _config.units[prop] || startUnit;
4640
4641            if (index === end.length) {
4642              end += endUnit;
4643              pt.e += endUnit;
4644            }
4645          }
4646
4647          if (startUnit !== endUnit) {
4648            startNum = _convertToUnit(target, prop, startValue, endUnit) || 0;
4649          }
4650
4651          pt._pt = {
4652            _next: pt._pt,
4653            p: chunk || matchIndex === 1 ? chunk : ",",
4654            s: startNum,
4655            c: endNum - startNum,
4656            m: color && color < 4 || prop === "zIndex" ? Math.round : 0
4657          };
4658        }
4659      }
4660
4661      pt.c = index < end.length ? end.substring(index, end.length) : "";
4662    } else {
4663      pt.r = prop === "display" && end === "none" ? _renderNonTweeningValueOnlyAtEnd : _renderNonTweeningValue;
4664    }
4665
4666    _relExp.test(end) && (pt.e = 0);
4667    this._pt = pt;
4668    return pt;
4669  },
4670      _keywordToPercent = {
4671    top: "0%",
4672    bottom: "100%",
4673    left: "0%",
4674    right: "100%",
4675    center: "50%"
4676  },
4677      _convertKeywordsToPercentages = function _convertKeywordsToPercentages(value) {
4678    var split = value.split(" "),
4679        x = split[0],
4680        y = split[1] || "50%";
4681
4682    if (x === "top" || x === "bottom" || y === "left" || y === "right") {
4683      value = x;
4684      x = y;
4685      y = value;
4686    }
4687
4688    split[0] = _keywordToPercent[x] || x;
4689    split[1] = _keywordToPercent[y] || y;
4690    return split.join(" ");
4691  },
4692      _renderClearProps = function _renderClearProps(ratio, data) {
4693    if (data.tween && data.tween._time === data.tween._dur) {
4694      var target = data.t,
4695          style = target.style,
4696          props = data.u,
4697          cache = target._gsap,
4698          prop,
4699          clearTransforms,
4700          i;
4701
4702      if (props === "all" || props === true) {
4703        style.cssText = "";
4704        clearTransforms = 1;
4705      } else {
4706        props = props.split(",");
4707        i = props.length;
4708
4709        while (--i > -1) {
4710          prop = props[i];
4711
4712          if (_transformProps[prop]) {
4713            clearTransforms = 1;
4714            prop = prop === "transformOrigin" ? _transformOriginProp : _transformProp;
4715          }
4716
4717          _removeProperty(target, prop);
4718        }
4719      }
4720
4721      if (clearTransforms) {
4722        _removeProperty(target, _transformProp);
4723
4724        if (cache) {
4725          cache.svg && target.removeAttribute("transform");
4726
4727          _parseTransform(target, 1);
4728
4729          cache.uncache = 1;
4730
4731          _removeIndependentTransforms(style);
4732        }
4733      }
4734    }
4735  },
4736      _specialProps = {
4737    clearProps: function clearProps(plugin, target, property, endValue, tween) {
vendor: 1,580 bytes, lines 4738-4778
4738      if (tween.data !== "isFromStart") {
4739        var pt = plugin._pt = new PropTween(plugin._pt, target, property, 0, 0, _renderClearProps);
4740        pt.u = endValue;
4741        pt.pr = -10;
4742        pt.tween = tween;
4743
4744        plugin._props.push(property);
4745
4746        return 1;
4747      }
4748    }
4749  },
4750      _identity2DMatrix = [1, 0, 0, 1, 0, 0],
4751      _rotationalProperties = {},
4752      _isNullTransform = function _isNullTransform(value) {
4753    return value === "matrix(1, 0, 0, 1, 0, 0)" || value === "none" || !value;
4754  },
4755      _getComputedTransformMatrixAsArray = function _getComputedTransformMatrixAsArray(target) {
4756    var matrixString = _getComputedProperty(target, _transformProp);
4757
4758    return _isNullTransform(matrixString) ? _identity2DMatrix : matrixString.substr(7).match(_numExp).map(_round);
4759  },
4760      _getMatrix = function _getMatrix(target, force2D) {
4761    var cache = target._gsap || _getCache(target),
4762        style = target.style,
4763        matrix = _getComputedTransformMatrixAsArray(target),
4764        parent,
4765        nextSibling,
4766        temp,
4767        addedToDOM;
4768
4769    if (cache.svg && target.getAttribute("transform")) {
4770      temp = target.transform.baseVal.consolidate().matrix;
4771      matrix = [temp.a, temp.b, temp.c, temp.d, temp.e, temp.f];
4772      return matrix.join(",") === "1,0,0,1,0,0" ? _identity2DMatrix : matrix;
4773    } else if (matrix === _identity2DMatrix && !target.offsetParent && target !== _docElement && !cache.svg) {
4774      temp = style.display;
4775      style.display = "block";
4776      parent = target.parentNode;
4777
4778      if (!parent || !target.offsetParent
vendor: 18,926 bytes, lines 4778-5375
4778) {
4779        addedToDOM = 1;
4780        nextSibling = target.nextElementSibling;
4781
4782        _docElement.appendChild(target);
4783      }
4784
4785      matrix = _getComputedTransformMatrixAsArray(target);
4786      temp ? style.display = temp : _removeProperty(target, "display");
4787
4788      if (addedToDOM) {
4789        nextSibling ? parent.insertBefore(target, nextSibling) : parent ? parent.appendChild(target) : _docElement.removeChild(target);
4790      }
4791    }
4792
4793    return force2D && matrix.length > 6 ? [matrix[0], matrix[1], matrix[4], matrix[5], matrix[12], matrix[13]] : matrix;
4794  },
4795      _applySVGOrigin = function _applySVGOrigin(target, origin, originIsAbsolute, smooth, matrixArray, pluginToAddPropTweensTo) {
4796    var cache = target._gsap,
4797        matrix = matrixArray || _getMatrix(target, true),
4798        xOriginOld = cache.xOrigin || 0,
4799        yOriginOld = cache.yOrigin || 0,
4800        xOffsetOld = cache.xOffset || 0,
4801        yOffsetOld = cache.yOffset || 0,
4802        a = matrix[0],
4803        b = matrix[1],
4804        c = matrix[2],
4805        d = matrix[3],
4806        tx = matrix[4],
4807        ty = matrix[5],
4808        originSplit = origin.split(" "),
4809        xOrigin = parseFloat(originSplit[0]) || 0,
4810        yOrigin = parseFloat(originSplit[1]) || 0,
4811        bounds,
4812        determinant,
4813        x,
4814        y;
4815
4816    if (!originIsAbsolute) {
4817      bounds = _getBBox(target);
4818      xOrigin = bounds.x + (~originSplit[0].indexOf("%") ? xOrigin / 100 * bounds.width : xOrigin);
4819      yOrigin = bounds.y + (~(originSplit[1] || originSplit[0]).indexOf("%") ? yOrigin / 100 * bounds.height : yOrigin);
4820    } else if (matrix !== _identity2DMatrix && (determinant = a * d - b * c)) {
4821      x = xOrigin * (d / determinant) + yOrigin * (-c / determinant) + (c * ty - d * tx) / determinant;
4822      y = xOrigin * (-b / determinant) + yOrigin * (a / determinant) - (a * ty - b * tx) / determinant;
4823      xOrigin = x;
4824      yOrigin = y;
4825    }
4826
4827    if (smooth || smooth !== false && cache.smooth) {
4828      tx = xOrigin - xOriginOld;
4829      ty = yOrigin - yOriginOld;
4830      cache.xOffset = xOffsetOld + (tx * a + ty * c) - tx;
4831      cache.yOffset = yOffsetOld + (tx * b + ty * d) - ty;
4832    } else {
4833      cache.xOffset = cache.yOffset = 0;
4834    }
4835
4836    cache.xOrigin = xOrigin;
4837    cache.yOrigin = yOrigin;
4838    cache.smooth = !!smooth;
4839    cache.origin = origin;
4840    cache.originIsAbsolute = !!originIsAbsolute;
4841    target.style[_transformOriginProp] = "0px 0px";
4842
4843    if (pluginToAddPropTweensTo) {
4844      _addNonTweeningPT(pluginToAddPropTweensTo, cache, "xOrigin", xOriginOld, xOrigin);
4845
4846      _addNonTweeningPT(pluginToAddPropTweensTo, cache, "yOrigin", yOriginOld, yOrigin);
4847
4848      _addNonTweeningPT(pluginToAddPropTweensTo, cache, "xOffset", xOffsetOld, cache.xOffset);
4849
4850      _addNonTweeningPT(pluginToAddPropTweensTo, cache, "yOffset", yOffsetOld, cache.yOffset);
4851    }
4852
4853    target.setAttribute("data-svg-origin", xOrigin + " " + yOrigin);
4854  },
4855      _parseTransform = function _parseTransform(target, uncache) {
4856    var cache = target._gsap || new GSCache(target);
4857
4858    if ("x" in cache && !uncache && !cache.uncache) {
4859      return cache;
4860    }
4861
4862    var style = target.style,
4863        invertedScaleX = cache.scaleX < 0,
4864        px = "px",
4865        deg = "deg",
4866        cs = getComputedStyle(target),
4867        origin = _getComputedProperty(target, _transformOriginProp) || "0",
4868        x,
4869        y,
4870        z,
4871        scaleX,
4872        scaleY,
4873        rotation,
4874        rotationX,
4875        rotationY,
4876        skewX,
4877        skewY,
4878        perspective,
4879        xOrigin,
4880        yOrigin,
4881        matrix,
4882        angle,
4883        cos,
4884        sin,
4885        a,
4886        b,
4887        c,
4888        d,
4889        a12,
4890        a22,
4891        t1,
4892        t2,
4893        t3,
4894        a13,
4895        a23,
4896        a33,
4897        a42,
4898        a43,
4899        a32;
4900    x = y = z = rotation = rotationX = rotationY = skewX = skewY = perspective = 0;
4901    scaleX = scaleY = 1;
4902    cache.svg = !!(target.getCTM && _isSVG(target));
4903
4904    if (cs.translate) {
4905      if (cs.translate !== "none" || cs.scale !== "none" || cs.rotate !== "none") {
4906        style[_transformProp] = (cs.translate !== "none" ? "translate3d(" + (cs.translate + " 0 0").split(" ").slice(0, 3).join(", ") + ") " : "") + (cs.rotate !== "none" ? "rotate(" + cs.rotate + ") " : "") + (cs.scale !== "none" ? "scale(" + cs.scale.split(" ").join(",") + ") " : "") + (cs[_transformProp] !== "none" ? cs[_transformProp] : "");
4907      }
4908
4909      style.scale = style.rotate = style.translate = "none";
4910    }
4911
4912    matrix = _getMatrix(target, cache.svg);
4913
4914    if (cache.svg) {
4915      if (cache.uncache) {
4916        t2 = target.getBBox();
4917        origin = cache.xOrigin - t2.x + "px " + (cache.yOrigin - t2.y) + "px";
4918        t1 = "";
4919      } else {
4920        t1 = !uncache && target.getAttribute("data-svg-origin");
4921      }
4922
4923      _applySVGOrigin(target, t1 || origin, !!t1 || cache.originIsAbsolute, cache.smooth !== false, matrix);
4924    }
4925
4926    xOrigin = cache.xOrigin || 0;
4927    yOrigin = cache.yOrigin || 0;
4928
4929    if (matrix !== _identity2DMatrix) {
4930      a = matrix[0];
4931      b = matrix[1];
4932      c = matrix[2];
4933      d = matrix[3];
4934      x = a12 = matrix[4];
4935      y = a22 = matrix[5];
4936
4937      if (matrix.length === 6) {
4938        scaleX = Math.sqrt(a * a + b * b);
4939        scaleY = Math.sqrt(d * d + c * c);
4940        rotation = a || b ? _atan2(b, a) * _RAD2DEG : 0;
4941        skewX = c || d ? _atan2(c, d) * _RAD2DEG + rotation : 0;
4942        skewX && (scaleY *= Math.abs(Math.cos(skewX * _DEG2RAD)));
4943
4944        if (cache.svg) {
4945          x -= xOrigin - (xOrigin * a + yOrigin * c);
4946          y -= yOrigin - (xOrigin * b + yOrigin * d);
4947        }
4948      } else {
4949        a32 = matrix[6];
4950        a42 = matrix[7];
4951        a13 = matrix[8];
4952        a23 = matrix[9];
4953        a33 = matrix[10];
4954        a43 = matrix[11];
4955        x = matrix[12];
4956        y = matrix[13];
4957        z = matrix[14];
4958        angle = _atan2(a32, a33);
4959        rotationX = angle * _RAD2DEG;
4960
4961        if (angle) {
4962          cos = Math.cos(-angle);
4963          sin = Math.sin(-angle);
4964          t1 = a12 * cos + a13 * sin;
4965          t2 = a22 * cos + a23 * sin;
4966          t3 = a32 * cos + a33 * sin;
4967          a13 = a12 * -sin + a13 * cos;
4968          a23 = a22 * -sin + a23 * cos;
4969          a33 = a32 * -sin + a33 * cos;
4970          a43 = a42 * -sin + a43 * cos;
4971          a12 = t1;
4972          a22 = t2;
4973          a32 = t3;
4974        }
4975
4976        angle = _atan2(-c, a33);
4977        rotationY = angle * _RAD2DEG;
4978
4979        if (angle) {
4980          cos = Math.cos(-angle);
4981          sin = Math.sin(-angle);
4982          t1 = a * cos - a13 * sin;
4983          t2 = b * cos - a23 * sin;
4984          t3 = c * cos - a33 * sin;
4985          a43 = d * sin + a43 * cos;
4986          a = t1;
4987          b = t2;
4988          c = t3;
4989        }
4990
4991        angle = _atan2(b, a);
4992        rotation = angle * _RAD2DEG;
4993
4994        if (angle) {
4995          cos = Math.cos(angle);
4996          sin = Math.sin(angle);
4997          t1 = a * cos + b * sin;
4998          t2 = a12 * cos + a22 * sin;
4999          b = b * cos - a * sin;
5000          a22 = a22 * cos - a12 * sin;
5001          a = t1;
5002          a12 = t2;
5003        }
5004
5005        if (rotationX && Math.abs(rotationX) + Math.abs(rotation) > 359.9) {
5006          rotationX = rotation = 0;
5007          rotationY = 180 - rotationY;
5008        }
5009
5010        scaleX = _round(Math.sqrt(a * a + b * b + c * c));
5011        scaleY = _round(Math.sqrt(a22 * a22 + a32 * a32));
5012        angle = _atan2(a12, a22);
5013        skewX = Math.abs(angle) > 0.0002 ? angle * _RAD2DEG : 0;
5014        perspective = a43 ? 1 / (a43 < 0 ? -a43 : a43) : 0;
5015      }
5016
5017      if (cache.svg) {
5018        t1 = target.getAttribute("transform");
5019        cache.forceCSS = target.setAttribute("transform", "") || !_isNullTransform(_getComputedProperty(target, _transformProp));
5020        t1 && target.setAttribute("transform", t1);
5021      }
5022    }
5023
5024    if (Math.abs(skewX) > 90 && Math.abs(skewX) < 270) {
5025      if (invertedScaleX) {
5026        scaleX *= -1;
5027        skewX += rotation <= 0 ? 180 : -180;
5028        rotation += rotation <= 0 ? 180 : -180;
5029      } else {
5030        scaleY *= -1;
5031        skewX += skewX <= 0 ? 180 : -180;
5032      }
5033    }
5034
5035    uncache = uncache || cache.uncache;
5036    cache.x = x - ((cache.xPercent = x && (!uncache && cache.xPercent || (Math.round(target.offsetWidth / 2) === Math.round(-x) ? -50 : 0))) ? target.offsetWidth * cache.xPercent / 100 : 0) + px;
5037    cache.y = y - ((cache.yPercent = y && (!uncache && cache.yPercent || (Math.round(target.offsetHeight / 2) === Math.round(-y) ? -50 : 0))) ? target.offsetHeight * cache.yPercent / 100 : 0) + px;
5038    cache.z = z + px;
5039    cache.scaleX = _round(scaleX);
5040    cache.scaleY = _round(scaleY);
5041    cache.rotation = _round(rotation) + deg;
5042    cache.rotationX = _round(rotationX) + deg;
5043    cache.rotationY = _round(rotationY) + deg;
5044    cache.skewX = skewX + deg;
5045    cache.skewY = skewY + deg;
5046    cache.transformPerspective = perspective + px;
5047
5048    if (cache.zOrigin = parseFloat(origin.split(" ")[2]) || !uncache && cache.zOrigin || 0) {
5049      style[_transformOriginProp] = _firstTwoOnly(origin);
5050    }
5051
5052    cache.xOffset = cache.yOffset = 0;
5053    cache.force3D = _config.force3D;
5054    cache.renderTransform = cache.svg ? _renderSVGTransforms : _supports3D ? _renderCSSTransforms : _renderNon3DTransforms;
5055    cache.uncache = 0;
5056    return cache;
5057  },
5058      _firstTwoOnly = function _firstTwoOnly(value) {
5059    return (value = value.split(" "))[0] + " " + value[1];
5060  },
5061      _addPxTranslate = function _addPxTranslate(target, start, value) {
5062    var unit = getUnit(start);
5063    return _round(parseFloat(start) + parseFloat(_convertToUnit(target, "x", value + "px", unit))) + unit;
5064  },
5065      _renderNon3DTransforms = function _renderNon3DTransforms(ratio, cache) {
5066    cache.z = "0px";
5067    cache.rotationY = cache.rotationX = "0deg";
5068    cache.force3D = 0;
5069
5070    _renderCSSTransforms(ratio, cache);
5071  },
5072      _zeroDeg = "0deg",
5073      _zeroPx = "0px",
5074      _endParenthesis = ") ",
5075      _renderCSSTransforms = function _renderCSSTransforms(ratio, cache) {
5076    var _ref = cache || this,
5077        xPercent = _ref.xPercent,
5078        yPercent = _ref.yPercent,
5079        x = _ref.x,
5080        y = _ref.y,
5081        z = _ref.z,
5082        rotation = _ref.rotation,
5083        rotationY = _ref.rotationY,
5084        rotationX = _ref.rotationX,
5085        skewX = _ref.skewX,
5086        skewY = _ref.skewY,
5087        scaleX = _ref.scaleX,
5088        scaleY = _ref.scaleY,
5089        transformPerspective = _ref.transformPerspective,
5090        force3D = _ref.force3D,
5091        target = _ref.target,
5092        zOrigin = _ref.zOrigin,
5093        transforms = "",
5094        use3D = force3D === "auto" && ratio && ratio !== 1 || force3D === true;
5095
5096    if (zOrigin && (rotationX !== _zeroDeg || rotationY !== _zeroDeg)) {
5097      var angle = parseFloat(rotationY) * _DEG2RAD,
5098          a13 = Math.sin(angle),
5099          a33 = Math.cos(angle),
5100          cos;
5101
5102      angle = parseFloat(rotationX) * _DEG2RAD;
5103      cos = Math.cos(angle);
5104      x = _addPxTranslate(target, x, a13 * cos * -zOrigin);
5105      y = _addPxTranslate(target, y, -Math.sin(angle) * -zOrigin);
5106      z = _addPxTranslate(target, z, a33 * cos * -zOrigin + zOrigin);
5107    }
5108
5109    if (transformPerspective !== _zeroPx) {
5110      transforms += "perspective(" + transformPerspective + _endParenthesis;
5111    }
5112
5113    if (xPercent || yPercent) {
5114      transforms += "translate(" + xPercent + "%, " + yPercent + "%) ";
5115    }
5116
5117    if (use3D || x !== _zeroPx || y !== _zeroPx || z !== _zeroPx) {
5118      transforms += z !== _zeroPx || use3D ? "translate3d(" + x + ", " + y + ", " + z + ") " : "translate(" + x + ", " + y + _endParenthesis;
5119    }
5120
5121    if (rotation !== _zeroDeg) {
5122      transforms += "rotate(" + rotation + _endParenthesis;
5123    }
5124
5125    if (rotationY !== _zeroDeg) {
5126      transforms += "rotateY(" + rotationY + _endParenthesis;
5127    }
5128
5129    if (rotationX !== _zeroDeg) {
5130      transforms += "rotateX(" + rotationX + _endParenthesis;
5131    }
5132
5133    if (skewX !== _zeroDeg || skewY !== _zeroDeg) {
5134      transforms += "skew(" + skewX + ", " + skewY + _endParenthesis;
5135    }
5136
5137    if (scaleX !== 1 || scaleY !== 1) {
5138      transforms += "scale(" + scaleX + ", " + scaleY + _endParenthesis;
5139    }
5140
5141    target.style[_transformProp] = transforms || "translate(0, 0)";
5142  },
5143      _renderSVGTransforms = function _renderSVGTransforms(ratio, cache) {
5144    var _ref2 = cache || this,
5145        xPercent = _ref2.xPercent,
5146        yPercent = _ref2.yPercent,
5147        x = _ref2.x,
5148        y = _ref2.y,
5149        rotation = _ref2.rotation,
5150        skewX = _ref2.skewX,
5151        skewY = _ref2.skewY,
5152        scaleX = _ref2.scaleX,
5153        scaleY = _ref2.scaleY,
5154        target = _ref2.target,
5155        xOrigin = _ref2.xOrigin,
5156        yOrigin = _ref2.yOrigin,
5157        xOffset = _ref2.xOffset,
5158        yOffset = _ref2.yOffset,
5159        forceCSS = _ref2.forceCSS,
5160        tx = parseFloat(x),
5161        ty = parseFloat(y),
5162        a11,
5163        a21,
5164        a12,
5165        a22,
5166        temp;
5167
5168    rotation = parseFloat(rotation);
5169    skewX = parseFloat(skewX);
5170    skewY = parseFloat(skewY);
5171
5172    if (skewY) {
5173      skewY = parseFloat(skewY);
5174      skewX += skewY;
5175      rotation += skewY;
5176    }
5177
5178    if (rotation || skewX) {
5179      rotation *= _DEG2RAD;
5180      skewX *= _DEG2RAD;
5181      a11 = Math.cos(rotation) * scaleX;
5182      a21 = Math.sin(rotation) * scaleX;
5183      a12 = Math.sin(rotation - skewX) * -scaleY;
5184      a22 = Math.cos(rotation - skewX) * scaleY;
5185
5186      if (skewX) {
5187        skewY *= _DEG2RAD;
5188        temp = Math.tan(skewX - skewY);
5189        temp = Math.sqrt(1 + temp * temp);
5190        a12 *= temp;
5191        a22 *= temp;
5192
5193        if (skewY) {
5194          temp = Math.tan(skewY);
5195          temp = Math.sqrt(1 + temp * temp);
5196          a11 *= temp;
5197          a21 *= temp;
5198        }
5199      }
5200
5201      a11 = _round(a11);
5202      a21 = _round(a21);
5203      a12 = _round(a12);
5204      a22 = _round(a22);
5205    } else {
5206      a11 = scaleX;
5207      a22 = scaleY;
5208      a21 = a12 = 0;
5209    }
5210
5211    if (tx && !~(x + "").indexOf("px") || ty && !~(y + "").indexOf("px")) {
5212      tx = _convertToUnit(target, "x", x, "px");
5213      ty = _convertToUnit(target, "y", y, "px");
5214    }
5215
5216    if (xOrigin || yOrigin || xOffset || yOffset) {
5217      tx = _round(tx + xOrigin - (xOrigin * a11 + yOrigin * a12) + xOffset);
5218      ty = _round(ty + yOrigin - (xOrigin * a21 + yOrigin * a22) + yOffset);
5219    }
5220
5221    if (xPercent || yPercent) {
5222      temp = target.getBBox();
5223      tx = _round(tx + xPercent / 100 * temp.width);
5224      ty = _round(ty + yPercent / 100 * temp.height);
5225    }
5226
5227    temp = "matrix(" + a11 + "," + a21 + "," + a12 + "," + a22 + "," + tx + "," + ty + ")";
5228    target.setAttribute("transform", temp);
5229    forceCSS && (target.style[_transformProp] = temp);
5230  },
5231      _addRotationalPropTween = function _addRotationalPropTween(plugin, target, property, startNum, endValue) {
5232    var cap = 360,
5233        isString = _isString(endValue),
5234        endNum = parseFloat(endValue) * (isString && ~endValue.indexOf("rad") ? _RAD2DEG : 1),
5235        change = endNum - startNum,
5236        finalValue = startNum + change + "deg",
5237        direction,
5238        pt;
5239
5240    if (isString) {
5241      direction = endValue.split("_")[1];
5242
5243      if (direction === "short") {
5244        change %= cap;
5245
5246        if (change !== change % (cap / 2)) {
5247          change += change < 0 ? cap : -cap;
5248        }
5249      }
5250
5251      if (direction === "cw" && change < 0) {
5252        change = (change + cap * _bigNum$1) % cap - ~~(change / cap) * cap;
5253      } else if (direction === "ccw" && change > 0) {
5254        change = (change - cap * _bigNum$1) % cap - ~~(change / cap) * cap;
5255      }
5256    }
5257
5258    plugin._pt = pt = new PropTween(plugin._pt, target, property, startNum, change, _renderPropWithEnd);
5259    pt.e = finalValue;
5260    pt.u = "deg";
5261
5262    plugin._props.push(property);
5263
5264    return pt;
5265  },
5266      _assign = function _assign(target, source) {
5267    for (var p in source) {
5268      target[p] = source[p];
5269    }
5270
5271    return target;
5272  },
5273      _addRawTransformPTs = function _addRawTransformPTs(plugin, transforms, target) {
5274    var startCache = _assign({}, target._gsap),
5275        exclude = "perspective,force3D,transformOrigin,svgOrigin",
5276        style = target.style,
5277        endCache,
5278        p,
5279        startValue,
5280        endValue,
5281        startNum,
5282        endNum,
5283        startUnit,
5284        endUnit;
5285
5286    if (startCache.svg) {
5287      startValue = target.getAttribute("transform");
5288      target.setAttribute("transform", "");
5289      style[_transformProp] = transforms;
5290      endCache = _parseTransform(target, 1);
5291
5292      _removeProperty(target, _transformProp);
5293
5294      target.setAttribute("transform", startValue);
5295    } else {
5296      startValue = getComputedStyle(target)[_transformProp];
5297      style[_transformProp] = transforms;
5298      endCache = _parseTransform(target, 1);
5299      style[_transformProp] = startValue;
5300    }
5301
5302    for (p in _transformProps) {
5303      startValue = startCache[p];
5304      endValue = endCache[p];
5305
5306      if (startValue !== endValue && exclude.indexOf(p) < 0) {
5307        startUnit = getUnit(startValue);
5308        endUnit = getUnit(endValue);
5309        startNum = startUnit !== endUnit ? _convertToUnit(target, p, startValue, endUnit) : parseFloat(startValue);
5310        endNum = parseFloat(endValue);
5311        plugin._pt = new PropTween(plugin._pt, endCache, p, startNum, endNum - startNum, _renderCSSProp);
5312        plugin._pt.u = endUnit || 0;
5313
5314        plugin._props.push(p);
5315      }
5316    }
5317
5318    _assign(endCache, startCache);
5319  };
5320
5321  _forEachName("padding,margin,Width,Radius", function (name, index) {
5322    var t = "Top",
5323        r = "Right",
5324        b = "Bottom",
5325        l = "Left",
5326        props = (index < 3 ? [t, r, b, l] : [t + l, t + r, b + r, b + l]).map(function (side) {
5327      return index < 2 ? name + side : "border" + side + name;
5328    });
5329
5330    _specialProps[index > 1 ? "border" + name : name] = function (plugin, target, property, endValue, tween) {
5331      var a, vars;
5332
5333      if (arguments.length < 4) {
5334        a = props.map(function (prop) {
5335          return _get(plugin, prop, property);
5336        });
5337        vars = a.join(" ");
5338        return vars.split(a[0]).length === 5 ? a[0] : vars;
5339      }
5340
5341      a = (endValue + "").split(" ");
5342      vars = {};
5343      props.forEach(function (prop, i) {
5344        return vars[prop] = a[i] = a[i] || a[(i - 1) / 2 | 0];
5345      });
5346      plugin.init(target, vars, tween);
5347    };
5348  });
5349
5350  var CSSPlugin = {
5351    name: "css",
5352    register: _initCore,
5353    targetTest: function targetTest(target) {
5354      return target.style && target.nodeType;
5355    },
5356    init: function init(target, vars, tween, index, targets) {
5357      var props = this._props,
5358          style = target.style,
5359          startAt = tween.vars.startAt,
5360          startValue,
5361          endValue,
5362          endNum,
5363          startNum,
5364          type,
5365          specialProp,
5366          p,
5367          startUnit,
5368          endUnit,
5369          relative,
5370          isTransformRelated,
5371          transformPropTween,
5372          cache,
5373          smooth,
5374          hasPriority,
5375          inlineProps
vendor: 8,025 bytes, lines 5375-5562
5375;
5376      _pluginInitted || _initCore();
5377      this.styles = this.styles || _getStyleSaver(target);
5378      inlineProps = this.styles.props;
5379      this.tween = tween;
5380
5381      for (p in vars) {
5382        if (p === "autoRound") {
5383          continue;
5384        }
5385
5386        endValue = vars[p];
5387
5388        if (_plugins[p] && _checkPlugin(p, vars, tween, index, target, targets)) {
5389          continue;
5390        }
5391
5392        type = typeof endValue;
5393        specialProp = _specialProps[p];
5394
5395        if (type === "function") {
5396          endValue = endValue.call(tween, index, target, targets);
5397          type = typeof endValue;
5398        }
5399
5400        if (type === "string" && ~endValue.indexOf("random(")) {
5401          endValue = _replaceRandom(endValue);
5402        }
5403
5404        if (specialProp) {
5405          specialProp(this, target, p, endValue, tween) && (hasPriority = 1);
5406        } else if (p.substr(0, 2) === "--") {
5407          startValue = (getComputedStyle(target).getPropertyValue(p) + "").trim();
5408          endValue += "";
5409          _colorExp.lastIndex = 0;
5410
5411          if (!_colorExp.test(startValue)) {
5412            startUnit = getUnit(startValue);
5413            endUnit = getUnit(endValue);
5414          }
5415
5416          endUnit ? startUnit !== endUnit && (startValue = _convertToUnit(target, p, startValue, endUnit) + endUnit) : startUnit && (endValue += startUnit);
5417          this.add(style, "setProperty", startValue, endValue, index, targets, 0, 0, p);
5418          props.push(p);
5419          inlineProps.push(p, 0, style[p]);
5420        } else if (type !== "undefined") {
5421          if (startAt && p in startAt) {
5422            startValue = typeof startAt[p] === "function" ? startAt[p].call(tween, index, target, targets) : startAt[p];
5423            _isString(startValue) && ~startValue.indexOf("random(") && (startValue = _replaceRandom(startValue));
5424            getUnit(startValue + "") || startValue === "auto" || (startValue += _config.units[p] || getUnit(_get(target, p)) || "");
5425            (startValue + "").charAt(1) === "=" && (startValue = _get(target, p));
5426          } else {
5427            startValue = _get(target, p);
5428          }
5429
5430          startNum = parseFloat(startValue);
5431          relative = type === "string" && endValue.charAt(1) === "=" && endValue.substr(0, 2);
5432          relative && (endValue = endValue.substr(2));
5433          endNum = parseFloat(endValue);
5434
5435          if (p in _propertyAliases) {
5436            if (p === "autoAlpha") {
5437              if (startNum === 1 && _get(target, "visibility") === "hidden" && endNum) {
5438                startNum = 0;
5439              }
5440
5441              inlineProps.push("visibility", 0, style.visibility);
5442
5443              _addNonTweeningPT(this, style, "visibility", startNum ? "inherit" : "hidden", endNum ? "inherit" : "hidden", !endNum);
5444            }
5445
5446            if (p !== "scale" && p !== "transform") {
5447              p = _propertyAliases[p];
5448              ~p.indexOf(",") && (p = p.split(",")[0]);
5449            }
5450          }
5451
5452          isTransformRelated = p in _transformProps;
5453
5454          if (isTransformRelated) {
5455            this.styles.save(p);
5456
5457            if (!transformPropTween) {
5458              cache = target._gsap;
5459              cache.renderTransform && !vars.parseTransform || _parseTransform(target, vars.parseTransform);
5460              smooth = vars.smoothOrigin !== false && cache.smooth;
5461              transformPropTween = this._pt = new PropTween(this._pt, style, _transformProp, 0, 1, cache.renderTransform, cache, 0, -1);
5462              transformPropTween.dep = 1;
5463            }
5464
5465            if (p === "scale") {
5466              this._pt = new PropTween(this._pt, cache, "scaleY", cache.scaleY, (relative ? _parseRelative(cache.scaleY, relative + endNum) : endNum) - cache.scaleY || 0, _renderCSSProp);
5467              this._pt.u = 0;
5468              props.push("scaleY", p);
5469              p += "X";
5470            } else if (p === "transformOrigin") {
5471              inlineProps.push(_transformOriginProp, 0, style[_transformOriginProp]);
5472              endValue = _convertKeywordsToPercentages(endValue);
5473
5474              if (cache.svg) {
5475                _applySVGOrigin(target, endValue, 0, smooth, 0, this);
5476              } else {
5477                endUnit = parseFloat(endValue.split(" ")[2]) || 0;
5478                endUnit !== cache.zOrigin && _addNonTweeningPT(this, cache, "zOrigin", cache.zOrigin, endUnit);
5479
5480                _addNonTweeningPT(this, style, p, _firstTwoOnly(startValue), _firstTwoOnly(endValue));
5481              }
5482
5483              continue;
5484            } else if (p === "svgOrigin") {
5485              _applySVGOrigin(target, endValue, 1, smooth, 0, this);
5486
5487              continue;
5488            } else if (p in _rotationalProperties) {
5489              _addRotationalPropTween(this, cache, p, startNum, relative ? _parseRelative(startNum, relative + endValue) : endValue);
5490
5491              continue;
5492            } else if (p === "smoothOrigin") {
5493              _addNonTweeningPT(this, cache, "smooth", cache.smooth, endValue);
5494
5495              continue;
5496            } else if (p === "force3D") {
5497              cache[p] = endValue;
5498              continue;
5499            } else if (p === "transform") {
5500              _addRawTransformPTs(this, endValue, target);
5501
5502              continue;
5503            }
5504          } else if (!(p in style)) {
5505            p = _checkPropPrefix(p) || p;
5506          }
5507
5508          if (isTransformRelated || (endNum || endNum === 0) && (startNum || startNum === 0) && !_complexExp.test(endValue) && p in style) {
5509            startUnit = (startValue + "").substr((startNum + "").length);
5510            endNum || (endNum = 0);
5511            endUnit = getUnit(endValue) || (p in _config.units ? _config.units[p] : startUnit);
5512            startUnit !== endUnit && (startNum = _convertToUnit(target, p, startValue, endUnit));
5513            this._pt = new PropTween(this._pt, isTransformRelated ? cache : style, p, startNum, (relative ? _parseRelative(startNum, relative + endNum) : endNum) - startNum, !isTransformRelated && (endUnit === "px" || p === "zIndex") && vars.autoRound !== false ? _renderRoundedCSSProp : _renderCSSProp);
5514            this._pt.u = endUnit || 0;
5515
5516            if (startUnit !== endUnit && endUnit !== "%") {
5517              this._pt.b = startValue;
5518              this._pt.r = _renderCSSPropWithBeginning;
5519            }
5520          } else if (!(p in style)) {
5521            if (p in target) {
5522              this.add(target, p, startValue || target[p], relative ? relative + endValue : endValue, index, targets);
5523            } else if (p !== "parseTransform") {
5524              _missingPlugin(p, endValue);
5525
5526              continue;
5527            }
5528          } else {
5529            _tweenComplexCSSString.call(this, target, p, startValue, relative ? relative + endValue : endValue);
5530          }
5531
5532          isTransformRelated || (p in style ? inlineProps.push(p, 0, style[p]) : inlineProps.push(p, 1, startValue || target[p]));
5533          props.push(p);
5534        }
5535      }
5536
5537      hasPriority && _sortPropTweensByPriority(this);
5538    },
5539    render: function render(ratio, data) {
5540      if (data.tween._time || !_reverting$1()) {
5541        var pt = data._pt;
5542
5543        while (pt) {
5544          pt.r(ratio, pt.d);
5545          pt = pt._next;
5546        }
5547      } else {
5548        data.styles.revert();
5549      }
5550    },
5551    get: _get,
5552    aliases: _propertyAliases,
5553    getSetter: function getSetter(target, property, plugin) {
5554      var p = _propertyAliases[property];
5555      p && p.indexOf(",") < 0 && (property = p);
5556      return property in _transformProps && property !== _transformOriginProp && (target._gsap.x || _get(target, "x")) ? plugin && _recentSetterPlugin === plugin ? property === "scale" ? _setterScale : _setterTransform : (_recentSetterPlugin = plugin || {}) && (property === "scale" ? _setterScaleWithRender : _setterTransformWithRender) : target.style && !_isUndefined(target.style[property]) ? _setterCSSStyle : ~property.indexOf("-") ? _setterCSSProp : _getSetter(target, property);
5557    },
5558    core: {
5559      _removeProperty: _removeProperty,
5560      _getMatrix: _getMatrix
5561    }
5562  };
vendor: 2,056 bytes, lines 5563-5621
5563  gsap.utils.checkPrefix = _checkPropPrefix;
5564  gsap.core.getStyleSaver = _getStyleSaver;
5565
5566  (function (positionAndScale, rotation, others, aliases) {
5567    var all = _forEachName(positionAndScale + "," + rotation + "," + others, function (name) {
5568      _transformProps[name] = 1;
5569    });
5570
5571    _forEachName(rotation, function (name) {
5572      _config.units[name] = "deg";
5573      _rotationalProperties[name] = 1;
5574    });
5575
5576    _propertyAliases[all[13]] = positionAndScale + "," + rotation;
5577
5578    _forEachName(aliases, function (name) {
5579      var split = name.split(":");
5580      _propertyAliases[split[1]] = all[split[0]];
5581    });
5582  })("x,y,z,scale,scaleX,scaleY,xPercent,yPercent", "rotation,rotationX,rotationY,skewX,skewY", "transform,transformOrigin,svgOrigin,force3D,smoothOrigin,transformPerspective", "0:translateX,1:translateY,2:translateZ,8:rotate,8:rotationZ,8:rotateZ,9:rotateX,10:rotateY");
5583
5584  _forEachName("x,y,z,top,right,bottom,left,width,height,fontSize,padding,margin,perspective", function (name) {
5585    _config.units[name] = "px";
5586  });
5587
5588  gsap.registerPlugin(CSSPlugin);
5589
5590  var gsapWithCSS = gsap.registerPlugin(CSSPlugin) || gsap,
5591      TweenMaxWithCSS = gsapWithCSS.core.Tween;
5592
5593  exports.Back = Back;
5594  exports.Bounce = Bounce;
5595  exports.CSSPlugin = CSSPlugin;
5596  exports.Circ = Circ;
5597  exports.Cubic = Cubic;
5598  exports.Elastic = Elastic;
5599  exports.Expo = Expo;
5600  exports.Linear = Linear;
5601  exports.Power0 = Power0;
5602  exports.Power1 = Power1;
5603  exports.Power2 = Power2;
5604  exports.Power3 = Power3;
5605  exports.Power4 = Power4;
5606  exports.Quad = Quad;
5607  exports.Quart = Quart;
5608  exports.Quint = Quint;
5609  exports.Sine = Sine;
5610  exports.SteppedEase = SteppedEase;
5611  exports.Strong = Strong;
5612  exports.TimelineLite = Timeline;
5613  exports.TimelineMax = Timeline;
5614  exports.TweenLite = Tween;
5615  exports.TweenMax = TweenMaxWithCSS;
5616  exports.default = gsapWithCSS;
5617  exports.gsap = gsapWithCSS;
5618
5619  if (typeof(window) === 'undefined' || window !== exports) {Object.defineProperty(exports, '__esModule', { value: true });} else {delete window.default;}
5620
5621})));
vendor: 247,641 bytes, lines 5622-13099
5622/*!
5623 * matter-js 0.20.0 by @liabru
5624 * http://brm.io/matter-js/
5625 * License MIT
5626 * 
5627 * The MIT License (MIT)
5628 * 
5629 * Copyright (c) Liam Brummitt and contributors.
5630 * 
5631 * Permission is hereby granted, free of charge, to any person obtaining a copy
5632 * of this software and associated documentation files (the "Software"), to deal
5633 * in the Software without restriction, including without limitation the rights
5634 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
5635 * copies of the Software, and to permit persons to whom the Software is
5636 * furnished to do so, subject to the following conditions:
5637 * 
5638 * The above copyright notice and this permission notice shall be included in
5639 * all copies or substantial portions of the Software.
5640 * 
5641 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
5642 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
5643 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
5644 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
5645 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
5646 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
5647 * THE SOFTWARE.
5648 */
5649(function webpackUniversalModuleDefinition(root, factory) {
5650	if(typeof exports === 'object' && typeof module === 'object')
5651		module.exports = factory();
5652	else if(typeof define === 'function' && define.amd)
5653		define("Matter", [], factory);
5654	else if(typeof exports === 'object')
5655		exports["Matter"] = factory();
5656	else
5657		root["Matter"] = factory();
5658})(this, function() {
5659return /******/ (function(modules) { // webpackBootstrap
5660/******/ 	// The module cache
5661/******/ 	var installedModules = {};
5662/******/
5663/******/ 	// The require function
5664/******/ 	function __webpack_require__(moduleId) {
5665/******/
5666/******/ 		// Check if module is in cache
5667/******/ 		if(installedModules[moduleId]) {
5668/******/ 			return installedModules[moduleId].exports;
5669/******/ 		}
5670/******/ 		// Create a new module (and put it into the cache)
5671/******/ 		var module = installedModules[moduleId] = {
5672/******/ 			i: moduleId,
5673/******/ 			l: false,
5674/******/ 			exports: {}
5675/******/ 		};
5676/******/
5677/******/ 		// Execute the module function
5678/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
5679/******/
5680/******/ 		// Flag the module as loaded
5681/******/ 		module.l = true;
5682/******/
5683/******/ 		// Return the exports of the module
5684/******/ 		return module.exports;
5685/******/ 	}
5686/******/
5687/******/
5688/******/ 	// expose the modules object (__webpack_modules__)
5689/******/ 	__webpack_require__.m = modules;
5690/******/
5691/******/ 	// expose the module cache
5692/******/ 	__webpack_require__.c = installedModules;
5693/******/
5694/******/ 	// define getter function for harmony exports
5695/******/ 	__webpack_require__.d = function(exports, name, getter) {
5696/******/ 		if(!__webpack_require__.o(exports, name)) {
5697/******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
5698/******/ 		}
5699/******/ 	};
5700/******/
5701/******/ 	// define __esModule on exports
5702/******/ 	__webpack_require__.r = function(exports) {
5703/******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
5704/******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
5705/******/ 		}
5706/******/ 		Object.defineProperty(exports, '__esModule', { value: true });
5707/******/ 	};
5708/******/
5709/******/ 	// create a fake namespace object
5710/******/ 	// mode & 1: value is a module id, require it
5711/******/ 	// mode & 2: merge all properties of value into the ns
5712/******/ 	// mode & 4: return value when already ns object
5713/******/ 	// mode & 8|1: behave like require
5714/******/ 	__webpack_require__.t = function(value, mode) {
5715/******/ 		if(mode & 1) value = __webpack_require__(value);
5716/******/ 		if(mode & 8) return value;
5717/******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
5718/******/ 		var ns = Object.create(null);
5719/******/ 		__webpack_require__.r(ns);
5720/******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
5721/******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
5722/******/ 		return ns;
5723/******/ 	};
5724/******/
5725/******/ 	// getDefaultExport function for compatibility with non-harmony modules
5726/******/ 	__webpack_require__.n = function(module) {
5727/******/ 		var getter = module && module.__esModule ?
5728/******/ 			function getDefault() { return module['default']; } :
5729/******/ 			function getModuleExports() { return module; };
5730/******/ 		__webpack_require__.d(getter, 'a', getter);
5731/******/ 		return getter;
5732/******/ 	};
5733/******/
5734/******/ 	// Object.prototype.hasOwnProperty.call
5735/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
5736/******/
5737/******/ 	// __webpack_public_path__
5738/******/ 	__webpack_require__.p = "";
5739/******/
5740/******/
5741/******/ 	// Load entry module and return exports
5742/******/ 	return __webpack_require__(__webpack_require__.s = 20);
5743/******/ })
5744/************************************************************************/
5745/******/ ([
5746/* 0 */
5747/***/ (function(module, exports) {
5748
5749/**
5750* The `Matter.Common` module contains utility functions that are common to all modules.
5751*
5752* @class Common
5753*/
5754
5755var Common = {};
5756
5757module.exports = Common;
5758
5759(function() {
5760
5761    Common._baseDelta = 1000 / 60;
5762    Common._nextId = 0;
5763    Common._seed = 0;
5764    Common._nowStartTime = +(new Date());
5765    Common._warnedOnce = {};
5766    Common._decomp = null;
5767    
5768    /**
5769     * Extends the object in the first argument using the object in the second argument.
5770     * @method extend
5771     * @param {} obj
5772     * @param {boolean} deep
5773     * @return {} obj extended
5774     */
5775    Common.extend = function(obj, deep) {
5776        var argsStart,
5777            args,
5778            deepClone;
5779
5780        if (typeof deep === 'boolean') {
5781            argsStart = 2;
5782            deepClone = deep;
5783        } else {
5784            argsStart = 1;
5785            deepClone = true;
5786        }
5787
5788        for (var i = argsStart; i < arguments.length; i++) {
5789            var source = arguments[i];
5790
5791            if (source) {
5792                for (var prop in source) {
5793                    if (deepClone && source[prop] && source[prop].constructor === Object) {
5794                        if (!obj[prop] || obj[prop].constructor === Object) {
5795                            obj[prop] = obj[prop] || {};
5796                            Common.extend(obj[prop], deepClone, source[prop]);
5797                        } else {
5798                            obj[prop] = source[prop];
5799                        }
5800                    } else {
5801                        obj[prop] = source[prop];
5802                    }
5803                }
5804            }
5805        }
5806        
5807        return obj;
5808    };
5809
5810    /**
5811     * Creates a new clone of the object, if deep is true references will also be cloned.
5812     * @method clone
5813     * @param {} obj
5814     * @param {bool} deep
5815     * @return {} obj cloned
5816     */
5817    Common.clone = function(obj, deep) {
5818        return Common.extend({}, deep, obj);
5819    };
5820
5821    /**
5822     * Returns the list of keys for the given object.
5823     * @method keys
5824     * @param {} obj
5825     * @return {string[]} keys
5826     */
5827    Common.keys = function(obj) {
5828        if (Object.keys)
5829            return Object.keys(obj);
5830
5831        // avoid hasOwnProperty for performance
5832        var keys = [];
5833        for (var key in obj)
5834            keys.push(key);
5835        return keys;
5836    };
5837
5838    /**
5839     * Returns the list of values for the given object.
5840     * @method values
5841     * @param {} obj
5842     * @return {array} Array of the objects property values
5843     */
5844    Common.values = function(obj) {
5845        var values = [];
5846        
5847        if (Object.keys) {
5848            var keys = Object.keys(obj);
5849            for (var i = 0; i < keys.length; i++) {
5850                values.push(obj[keys[i]]);
5851            }
5852            return values;
5853        }
5854        
5855        // avoid hasOwnProperty for performance
5856        for (var key in obj)
5857            values.push(obj[key]);
5858        return values;
5859    };
5860
5861    /**
5862     * Gets a value from `base` relative to the `path` string.
5863     * @method get
5864     * @param {} obj The base object
5865     * @param {string} path The path relative to `base`, e.g. 'Foo.Bar.baz'
5866     * @param {number} [begin] Path slice begin
5867     * @param {number} [end] Path slice end
5868     * @return {} The object at the given path
5869     */
5870    Common.get = function(obj, path, begin, end) {
5871        path = path.split('.').slice(begin, end);
5872
5873        for (var i = 0; i < path.length; i += 1) {
5874            obj = obj[path[i]];
5875        }
5876
5877        return obj;
5878    };
5879
5880    /**
5881     * Sets a value on `base` relative to the given `path` string.
5882     * @method set
5883     * @param {} obj The base object
5884     * @param {string} path The path relative to `base`, e.g. 'Foo.Bar.baz'
5885     * @param {} val The value to set
5886     * @param {number} [begin] Path slice begin
5887     * @param {number} [end] Path slice end
5888     * @return {} Pass through `val` for chaining
5889     */
5890    Common.set = function(obj, path, val, begin, end) {
5891        var parts = path.split('.').slice(begin, end);
5892        Common.get(obj, path, 0, -1)[parts[parts.length - 1]] = val;
5893        return val;
5894    };
5895
5896    /**
5897     * Shuffles the given array in-place.
5898     * The function uses a seeded random generator.
5899     * @method shuffle
5900     * @param {array} array
5901     * @return {array} array shuffled randomly
5902     */
5903    Common.shuffle = function(array) {
5904        for (var i = array.length - 1; i > 0; i--) {
5905            var j = Math.floor(Common.random() * (i + 1));
5906            var temp = array[i];
5907            array[i] = array[j];
5908            array[j] = temp;
5909        }
5910        return array;
5911    };
5912
5913    /**
5914     * Randomly chooses a value from a list with equal probability.
5915     * The function uses a seeded random generator.
5916     * @method choose
5917     * @param {array} choices
5918     * @return {object} A random choice object from the array
5919     */
5920    Common.choose = function(choices) {
5921        return choices[Math.floor(Common.random() * choices.length)];
5922    };
5923
5924    /**
5925     * Returns true if the object is a HTMLElement, otherwise false.
5926     * @method isElement
5927     * @param {object} obj
5928     * @return {boolean} True if the object is a HTMLElement, otherwise false
5929     */
5930    Common.isElement = function(obj) {
5931        if (typeof HTMLElement !== 'undefined') {
5932            return obj instanceof HTMLElement;
5933        }
5934
5935        return !!(obj && obj.nodeType && obj.nodeName);
5936    };
5937
5938    /**
5939     * Returns true if the object is an array.
5940     * @method isArray
5941     * @param {object} obj
5942     * @return {boolean} True if the object is an array, otherwise false
5943     */
5944    Common.isArray = function(obj) {
5945        return Object.prototype.toString.call(obj) === '[object Array]';
5946    };
5947
5948    /**
5949     * Returns true if the object is a function.
5950     * @method isFunction
5951     * @param {object} obj
5952     * @return {boolean} True if the object is a function, otherwise false
5953     */
5954    Common.isFunction = function(obj) {
5955        return typeof obj === "function";
5956    };
5957
5958    /**
5959     * Returns true if the object is a plain object.
5960     * @method isPlainObject
5961     * @param {object} obj
5962     * @return {boolean} True if the object is a plain object, otherwise false
5963     */
5964    Common.isPlainObject = function(obj) {
5965        return typeof obj === 'object' && obj.constructor === Object;
5966    };
5967
5968    /**
5969     * Returns true if the object is a string.
5970     * @method isString
5971     * @param {object} obj
5972     * @return {boolean} True if the object is a string, otherwise false
5973     */
5974    Common.isString = function(obj) {
5975        return toString.call(obj) === '[object String]';
5976    };
5977    
5978    /**
5979     * Returns the given value clamped between a minimum and maximum value.
5980     * @method clamp
5981     * @param {number} value
5982     * @param {number} min
5983     * @param {number} max
5984     * @return {number} The value clamped between min and max inclusive
5985     */
5986    Common.clamp = function(value, min, max) {
5987        if (value < min)
5988            return min;
5989        if (value > max)
5990            return max;
5991        return value;
5992    };
5993    
5994    /**
5995     * Returns the sign of the given value.
5996     * @method sign
5997     * @param {number} value
5998     * @return {number} -1 if negative, +1 if 0 or positive
5999     */
6000    Common.sign = function(value) {
6001        return value < 0 ? -1 : 1;
6002    };
6003    
6004    /**
6005     * Returns the current timestamp since the time origin (e.g. from page load).
6006     * The result is in milliseconds and will use high-resolution timing if available.
6007     * @method now
6008     * @return {number} the current timestamp in milliseconds
6009     */
6010    Common.now = function() {
6011        if (typeof window !== 'undefined' && window.performance) {
6012            if (window.performance.now) {
6013                return window.performance.now();
6014            } else if (window.performance.webkitNow) {
6015                return window.performance.webkitNow();
6016            }
6017        }
6018
6019        if (Date.now) {
6020            return Date.now();
6021        }
6022
6023        return (new Date()) - Common._nowStartTime;
6024    };
6025    
6026    /**
6027     * Returns a random value between a minimum and a maximum value inclusive.
6028     * The function uses a seeded random generator.
6029     * @method random
6030     * @param {number} min
6031     * @param {number} max
6032     * @return {number} A random number between min and max inclusive
6033     */
6034    Common.random = function(min, max) {
6035        min = (typeof min !== "undefined") ? min : 0;
6036        max = (typeof max !== "undefined") ? max : 1;
6037        return min + _seededRandom() * (max - min);
6038    };
6039
6040    var _seededRandom = function() {
6041        // https://en.wikipedia.org/wiki/Linear_congruential_generator
6042        Common._seed = (Common._seed * 9301 + 49297) % 233280;
6043        return Common._seed / 233280;
6044    };
6045
6046    /**
6047     * Converts a CSS hex colour string into an integer.
6048     * @method colorToNumber
6049     * @param {string} colorString
6050     * @return {number} An integer representing the CSS hex string
6051     */
6052    Common.colorToNumber = function(colorString) {
6053        colorString = colorString.replace('#','');
6054
6055        if (colorString.length == 3) {
6056            colorString = colorString.charAt(0) + colorString.charAt(0)
6057                        + colorString.charAt(1) + colorString.charAt(1)
6058                        + colorString.charAt(2) + colorString.charAt(2);
6059        }
6060
6061        return parseInt(colorString, 16);
6062    };
6063
6064    /**
6065     * The console logging level to use, where each level includes all levels above and excludes the levels below.
6066     * The default level is 'debug' which shows all console messages.  
6067     *
6068     * Possible level values are:
6069     * - 0 = None
6070     * - 1 = Debug
6071     * - 2 = Info
6072     * - 3 = Warn
6073     * - 4 = Error
6074     * @static
6075     * @property logLevel
6076     * @type {Number}
6077     * @default 1
6078     */
6079    Common.logLevel = 1;
6080
6081    /**
6082     * Shows a `console.log` message only if the current `Common.logLevel` allows it.
6083     * The message will be prefixed with 'matter-js' to make it easily identifiable.
6084     * @method log
6085     * @param ...objs {} The objects to log.
6086     */
6087    Common.log = function() {
6088        if (console && Common.logLevel > 0 && Common.logLevel <= 3) {
6089            console.log.apply(console, ['matter-js:'].concat(Array.prototype.slice.call(arguments)));
6090        }
6091    };
6092
6093    /**
6094     * Shows a `console.info` message only if the current `Common.logLevel` allows it.
6095     * The message will be prefixed with 'matter-js' to make it easily identifiable.
6096     * @method info
6097     * @param ...objs {} The objects to log.
6098     */
6099    Common.info = function() {
6100        if (console && Common.logLevel > 0 && Common.logLevel <= 2) {
6101            console.info.apply(console, ['matter-js:'].concat(Array.prototype.slice.call(arguments)));
6102        }
6103    };
6104
6105    /**
6106     * Shows a `console.warn` message only if the current `Common.logLevel` allows it.
6107     * The message will be prefixed with 'matter-js' to make it easily identifiable.
6108     * @method warn
6109     * @param ...objs {} The objects to log.
6110     */
6111    Common.warn = function() {
6112        if (console && Common.logLevel > 0 && Common.logLevel <= 3) {
6113            console.warn.apply(console, ['matter-js:'].concat(Array.prototype.slice.call(arguments)));
6114        }
6115    };
6116
6117    /**
6118     * Uses `Common.warn` to log the given message one time only.
6119     * @method warnOnce
6120     * @param ...objs {} The objects to log.
6121     */
6122    Common.warnOnce = function() {
6123        var message = Array.prototype.slice.call(arguments).join(' ');
6124
6125        if (!Common._warnedOnce[message]) {
6126            Common.warn(message);
6127            Common._warnedOnce[message] = true;
6128        }
6129    };
6130
6131    /**
6132     * Shows a deprecated console warning when the function on the given object is called.
6133     * The target function will be replaced with a new function that first shows the warning
6134     * and then calls the original function.
6135     * @method deprecated
6136     * @param {object} obj The object or module
6137     * @param {string} name The property name of the function on obj
6138     * @param {string} warning The one-time message to show if the function is called
6139     */
6140    Common.deprecated = function(obj, prop, warning) {
6141        obj[prop] = Common.chain(function() {
6142            Common.warnOnce('🔅 deprecated 🔅', warning);
6143        }, obj[prop]);
6144    };
6145
6146    /**
6147     * Returns the next unique sequential ID.
6148     * @method nextId
6149     * @return {Number} Unique sequential ID
6150     */
6151    Common.nextId = function() {
6152        return Common._nextId++;
6153    };
6154
6155    /**
6156     * A cross browser compatible indexOf implementation.
6157     * @method indexOf
6158     * @param {array} haystack
6159     * @param {object} needle
6160     * @return {number} The position of needle in haystack, otherwise -1.
6161     */
6162    Common.indexOf = function(haystack, needle) {
6163        if (haystack.indexOf)
6164            return haystack.indexOf(needle);
6165
6166        for (var i = 0; i < haystack.length; i++) {
6167            if (haystack[i] === needle)
6168                return i;
6169        }
6170
6171        return -1;
6172    };
6173
6174    /**
6175     * A cross browser compatible array map implementation.
6176     * @method map
6177     * @param {array} list
6178     * @param {function} func
6179     * @return {array} Values from list transformed by func.
6180     */
6181    Common.map = function(list, func) {
6182        if (list.map) {
6183            return list.map(func);
6184        }
6185
6186        var mapped = [];
6187
6188        for (var i = 0; i < list.length; i += 1) {
6189            mapped.push(func(list[i]));
6190        }
6191
6192        return mapped;
6193    };
6194
6195    /**
6196     * Takes a directed graph and returns the partially ordered set of vertices in topological order.
6197     * Circular dependencies are allowed.
6198     * @method topologicalSort
6199     * @param {object} graph
6200     * @return {array} Partially ordered set of vertices in topological order.
6201     */
6202    Common.topologicalSort = function(graph) {
6203        // https://github.com/mgechev/javascript-algorithms
6204        // Copyright (c) Minko Gechev (MIT license)
6205        // Modifications: tidy formatting and naming
6206        var result = [],
6207            visited = [],
6208            temp = [];
6209
6210        for (var node in graph) {
6211            if (!visited[node] && !temp[node]) {
6212                Common._topologicalSort(node, visited, temp, graph, result);
6213            }
6214        }
6215
6216        return result;
6217    };
6218
6219    Common._topologicalSort = function(node, visited, temp, graph, result) {
6220        var neighbors = graph[node] || [];
6221        temp[node] = true;
6222
6223        for (var i = 0; i < neighbors.length; i += 1) {
6224            var neighbor = neighbors[i];
6225
6226            if (temp[neighbor]) {
6227                // skip circular dependencies
6228                continue;
6229            }
6230
6231            if (!visited[neighbor]) {
6232                Common._topologicalSort(neighbor, visited, temp, graph, result);
6233            }
6234        }
6235
6236        temp[node] = false;
6237        visited[node] = true;
6238
6239        result.push(node);
6240    };
6241
6242    /**
6243     * Takes _n_ functions as arguments and returns a new function that calls them in order.
6244     * The arguments applied when calling the new function will also be applied to every function passed.
6245     * The value of `this` refers to the last value returned in the chain that was not `undefined`.
6246     * Therefore if a passed function does not return a value, the previously returned value is maintained.
6247     * After all passed functions have been called the new function returns the last returned value (if any).
6248     * If any of the passed functions are a chain, then the chain will be flattened.
6249     * @method chain
6250     * @param ...funcs {function} The functions to chain.
6251     * @return {function} A new function that calls the passed functions in order.
6252     */
6253    Common.chain = function() {
6254        var funcs = [];
6255
6256        for (var i = 0; i < arguments.length; i += 1) {
6257            var func = arguments[i];
6258
6259            if (func._chained) {
6260                // flatten already chained functions
6261                funcs.push.apply(funcs, func._chained);
6262            } else {
6263                funcs.push(func);
6264            }
6265        }
6266
6267        var chain = function() {
6268            // https://github.com/GoogleChrome/devtools-docs/issues/53#issuecomment-51941358
6269            var lastResult,
6270                args = new Array(arguments.length);
6271
6272            for (var i = 0, l = arguments.length; i < l; i++) {
6273                args[i] = arguments[i];
6274            }
6275
6276            for (i = 0; i < funcs.length; i += 1) {
6277                var result = funcs[i].apply(lastResult, args);
6278
6279                if (typeof result !== 'undefined') {
6280                    lastResult = result;
6281                }
6282            }
6283
6284            return lastResult;
6285        };
6286
6287        chain._chained = funcs;
6288
6289        return chain;
6290    };
6291
6292    /**
6293     * Chains a function to excute before the original function on the given `path` relative to `base`.
6294     * See also docs for `Common.chain`.
6295     * @method chainPathBefore
6296     * @param {} base The base object
6297     * @param {string} path The path relative to `base`
6298     * @param {function} func The function to chain before the original
6299     * @return {function} The chained function that replaced the original
6300     */
6301    Common.chainPathBefore = function(base, path, func) {
6302        return Common.set(base, path, Common.chain(
6303            func,
6304            Common.get(base, path)
6305        ));
6306    };
6307
6308    /**
6309     * Chains a function to excute after the original function on the given `path` relative to `base`.
6310     * See also docs for `Common.chain`.
6311     * @method chainPathAfter
6312     * @param {} base The base object
6313     * @param {string} path The path relative to `base`
6314     * @param {function} func The function to chain after the original
6315     * @return {function} The chained function that replaced the original
6316     */
6317    Common.chainPathAfter = function(base, path, func) {
6318        return Common.set(base, path, Common.chain(
6319            Common.get(base, path),
6320            func
6321        ));
6322    };
6323
6324    /**
6325     * Provide the [poly-decomp](https://github.com/schteppe/poly-decomp.js) library module to enable
6326     * concave vertex decomposition support when using `Bodies.fromVertices` e.g. `Common.setDecomp(require('poly-decomp'))`.
6327     * @method setDecomp
6328     * @param {} decomp The [poly-decomp](https://github.com/schteppe/poly-decomp.js) library module.
6329     */
6330    Common.setDecomp = function(decomp) {
6331        Common._decomp = decomp;
6332    };
6333
6334    /**
6335     * Returns the [poly-decomp](https://github.com/schteppe/poly-decomp.js) library module provided through `Common.setDecomp`,
6336     * otherwise returns the global `decomp` if set.
6337     * @method getDecomp
6338     * @return {} The [poly-decomp](https://github.com/schteppe/poly-decomp.js) library module if provided.
6339     */
6340    Common.getDecomp = function() {
6341        // get user provided decomp if set
6342        var decomp = Common._decomp;
6343
6344        try {
6345            // otherwise from window global
6346            if (!decomp && typeof window !== 'undefined') {
6347                decomp = window.decomp;
6348            }
6349    
6350            // otherwise from node global
6351            if (!decomp && typeof global !== 'undefined') {
6352                decomp = global.decomp;
6353            }
6354        } catch (e) {
6355            // decomp not available
6356            decomp = null;
6357        }
6358
6359        return decomp;
6360    };
6361})();
6362
6363
6364/***/ }),
6365/* 1 */
6366/***/ (function(module, exports) {
6367
6368/**
6369* The `Matter.Bounds` module contains methods for creating and manipulating axis-aligned bounding boxes (AABB).
6370*
6371* @class Bounds
6372*/
6373
6374var Bounds = {};
6375
6376module.exports = Bounds;
6377
6378(function() {
6379
6380    /**
6381     * Creates a new axis-aligned bounding box (AABB) for the given vertices.
6382     * @method create
6383     * @param {vertices} vertices
6384     * @return {bounds} A new bounds object
6385     */
6386    Bounds.create = function(vertices) {
6387        var bounds = { 
6388            min: { x: 0, y: 0 }, 
6389            max: { x: 0, y: 0 }
6390        };
6391
6392        if (vertices)
6393            Bounds.update(bounds, vertices);
6394        
6395        return bounds;
6396    };
6397
6398    /**
6399     * Updates bounds using the given vertices and extends the bounds given a velocity.
6400     * @method update
6401     * @param {bounds} bounds
6402     * @param {vertices} vertices
6403     * @param {vector} velocity
6404     */
6405    Bounds.update = function(bounds, vertices, velocity) {
6406        bounds.min.x = Infinity;
6407        bounds.max.x = -Infinity;
6408        bounds.min.y = Infinity;
6409        bounds.max.y = -Infinity;
6410
6411        for (var i = 0; i < vertices.length; i++) {
6412            var vertex = vertices[i];
6413            if (vertex.x > bounds.max.x) bounds.max.x = vertex.x;
6414            if (vertex.x < bounds.min.x) bounds.min.x = vertex.x;
6415            if (vertex.y > bounds.max.y) bounds.max.y = vertex.y;
6416            if (vertex.y < bounds.min.y) bounds.min.y = vertex.y;
6417        }
6418        
6419        if (velocity) {
6420            if (velocity.x > 0) {
6421                bounds.max.x += velocity.x;
6422            } else {
6423                bounds.min.x += velocity.x;
6424            }
6425            
6426            if (velocity.y > 0) {
6427                bounds.max.y += velocity.y;
6428            } else {
6429                bounds.min.y += velocity.y;
6430            }
6431        }
6432    };
6433
6434    /**
6435     * Returns true if the bounds contains the given point.
6436     * @method contains
6437     * @param {bounds} bounds
6438     * @param {vector} point
6439     * @return {boolean} True if the bounds contain the point, otherwise false
6440     */
6441    Bounds.contains = function(bounds, point) {
6442        return point.x >= bounds.min.x && point.x <= bounds.max.x 
6443               && point.y >= bounds.min.y && point.y <= bounds.max.y;
6444    };
6445
6446    /**
6447     * Returns true if the two bounds intersect.
6448     * @method overlaps
6449     * @param {bounds} boundsA
6450     * @param {bounds} boundsB
6451     * @return {boolean} True if the bounds overlap, otherwise false
6452     */
6453    Bounds.overlaps = function(boundsA, boundsB) {
6454        return (boundsA.min.x <= boundsB.max.x && boundsA.max.x >= boundsB.min.x
6455                && boundsA.max.y >= boundsB.min.y && boundsA.min.y <= boundsB.max.y);
6456    };
6457
6458    /**
6459     * Translates the bounds by the given vector.
6460     * @method translate
6461     * @param {bounds} bounds
6462     * @param {vector} vector
6463     */
6464    Bounds.translate = function(bounds, vector) {
6465        bounds.min.x += vector.x;
6466        bounds.max.x += vector.x;
6467        bounds.min.y += vector.y;
6468        bounds.max.y += vector.y;
6469    };
6470
6471    /**
6472     * Shifts the bounds to the given position.
6473     * @method shift
6474     * @param {bounds} bounds
6475     * @param {vector} position
6476     */
6477    Bounds.shift = function(bounds, position) {
6478        var deltaX = bounds.max.x - bounds.min.x,
6479            deltaY = bounds.max.y - bounds.min.y;
6480            
6481        bounds.min.x = position.x;
6482        bounds.max.x = position.x + deltaX;
6483        bounds.min.y = position.y;
6484        bounds.max.y = position.y + deltaY;
6485    };
6486    
6487})();
6488
6489
6490/***/ }),
6491/* 2 */
6492/***/ (function(module, exports) {
6493
6494/**
6495* The `Matter.Vector` module contains methods for creating and manipulating vectors.
6496* Vectors are the basis of all the geometry related operations in the engine.
6497* A `Matter.Vector` object is of the form `{ x: 0, y: 0 }`.
6498*
6499* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples).
6500*
6501* @class Vector
6502*/
6503
6504// TODO: consider params for reusing vector objects
6505
6506var Vector = {};
6507
6508module.exports = Vector;
6509
6510(function() {
6511
6512    /**
6513     * Creates a new vector.
6514     * @method create
6515     * @param {number} x
6516     * @param {number} y
6517     * @return {vector} A new vector
6518     */
6519    Vector.create = function(x, y) {
6520        return { x: x || 0, y: y || 0 };
6521    };
6522
6523    /**
6524     * Returns a new vector with `x` and `y` copied from the given `vector`.
6525     * @method clone
6526     * @param {vector} vector
6527     * @return {vector} A new cloned vector
6528     */
6529    Vector.clone = function(vector) {
6530        return { x: vector.x, y: vector.y };
6531    };
6532
6533    /**
6534     * Returns the magnitude (length) of a vector.
6535     * @method magnitude
6536     * @param {vector} vector
6537     * @return {number} The magnitude of the vector
6538     */
6539    Vector.magnitude = function(vector) {
6540        return Math.sqrt((vector.x * vector.x) + (vector.y * vector.y));
6541    };
6542
6543    /**
6544     * Returns the magnitude (length) of a vector (therefore saving a `sqrt` operation).
6545     * @method magnitudeSquared
6546     * @param {vector} vector
6547     * @return {number} The squared magnitude of the vector
6548     */
6549    Vector.magnitudeSquared = function(vector) {
6550        return (vector.x * vector.x) + (vector.y * vector.y);
6551    };
6552
6553    /**
6554     * Rotates the vector about (0, 0) by specified angle.
6555     * @method rotate
6556     * @param {vector} vector
6557     * @param {number} angle
6558     * @param {vector} [output]
6559     * @return {vector} The vector rotated about (0, 0)
6560     */
6561    Vector.rotate = function(vector, angle, output) {
6562        var cos = Math.cos(angle), sin = Math.sin(angle);
6563        if (!output) output = {};
6564        var x = vector.x * cos - vector.y * sin;
6565        output.y = vector.x * sin + vector.y * cos;
6566        output.x = x;
6567        return output;
6568    };
6569
6570    /**
6571     * Rotates the vector about a specified point by specified angle.
6572     * @method rotateAbout
6573     * @param {vector} vector
6574     * @param {number} angle
6575     * @param {vector} point
6576     * @param {vector} [output]
6577     * @return {vector} A new vector rotated about the point
6578     */
6579    Vector.rotateAbout = function(vector, angle, point, output) {
6580        var cos = Math.cos(angle), sin = Math.sin(angle);
6581        if (!output) output = {};
6582        var x = point.x + ((vector.x - point.x) * cos - (vector.y - point.y) * sin);
6583        output.y = point.y + ((vector.x - point.x) * sin + (vector.y - point.y) * cos);
6584        output.x = x;
6585        return output;
6586    };
6587
6588    /**
6589     * Normalises a vector (such that its magnitude is `1`).
6590     * @method normalise
6591     * @param {vector} vector
6592     * @return {vector} A new vector normalised
6593     */
6594    Vector.normalise = function(vector) {
6595        var magnitude = Vector.magnitude(vector);
6596        if (magnitude === 0)
6597            return { x: 0, y: 0 };
6598        return { x: vector.x / magnitude, y: vector.y / magnitude };
6599    };
6600
6601    /**
6602     * Returns the dot-product of two vectors.
6603     * @method dot
6604     * @param {vector} vectorA
6605     * @param {vector} vectorB
6606     * @return {number} The dot product of the two vectors
6607     */
6608    Vector.dot = function(vectorA, vectorB) {
6609        return (vectorA.x * vectorB.x) + (vectorA.y * vectorB.y);
6610    };
6611
6612    /**
6613     * Returns the cross-product of two vectors.
6614     * @method cross
6615     * @param {vector} vectorA
6616     * @param {vector} vectorB
6617     * @return {number} The cross product of the two vectors
6618     */
6619    Vector.cross = function(vectorA, vectorB) {
6620        return (vectorA.x * vectorB.y) - (vectorA.y * vectorB.x);
6621    };
6622
6623    /**
6624     * Returns the cross-product of three vectors.
6625     * @method cross3
6626     * @param {vector} vectorA
6627     * @param {vector} vectorB
6628     * @param {vector} vectorC
6629     * @return {number} The cross product of the three vectors
6630     */
6631    Vector.cross3 = function(vectorA, vectorB, vectorC) {
6632        return (vectorB.x - vectorA.x) * (vectorC.y - vectorA.y) - (vectorB.y - vectorA.y) * (vectorC.x - vectorA.x);
6633    };
6634
6635    /**
6636     * Adds the two vectors.
6637     * @method add
6638     * @param {vector} vectorA
6639     * @param {vector} vectorB
6640     * @param {vector} [output]
6641     * @return {vector} A new vector of vectorA and vectorB added
6642     */
6643    Vector.add = function(vectorA, vectorB, output) {
6644        if (!output) output = {};
6645        output.x = vectorA.x + vectorB.x;
6646        output.y = vectorA.y + vectorB.y;
6647        return output;
6648    };
6649
6650    /**
6651     * Subtracts the two vectors.
6652     * @method sub
6653     * @param {vector} vectorA
6654     * @param {vector} vectorB
6655     * @param {vector} [output]
6656     * @return {vector} A new vector of vectorA and vectorB subtracted
6657     */
6658    Vector.sub = function(vectorA, vectorB, output) {
6659        if (!output) output = {};
6660        output.x = vectorA.x - vectorB.x;
6661        output.y = vectorA.y - vectorB.y;
6662        return output;
6663    };
6664
6665    /**
6666     * Multiplies a vector and a scalar.
6667     * @method mult
6668     * @param {vector} vector
6669     * @param {number} scalar
6670     * @return {vector} A new vector multiplied by scalar
6671     */
6672    Vector.mult = function(vector, scalar) {
6673        return { x: vector.x * scalar, y: vector.y * scalar };
6674    };
6675
6676    /**
6677     * Divides a vector and a scalar.
6678     * @method div
6679     * @param {vector} vector
6680     * @param {number} scalar
6681     * @return {vector} A new vector divided by scalar
6682     */
6683    Vector.div = function(vector, scalar) {
6684        return { x: vector.x / scalar, y: vector.y / scalar };
6685    };
6686
6687    /**
6688     * Returns the perpendicular vector. Set `negate` to true for the perpendicular in the opposite direction.
6689     * @method perp
6690     * @param {vector} vector
6691     * @param {bool} [negate=false]
6692     * @return {vector} The perpendicular vector
6693     */
6694    Vector.perp = function(vector, negate) {
6695        negate = negate === true ? -1 : 1;
6696        return { x: negate * -vector.y, y: negate * vector.x };
6697    };
6698
6699    /**
6700     * Negates both components of a vector such that it points in the opposite direction.
6701     * @method neg
6702     * @param {vector} vector
6703     * @return {vector} The negated vector
6704     */
6705    Vector.neg = function(vector) {
6706        return { x: -vector.x, y: -vector.y };
6707    };
6708
6709    /**
6710     * Returns the angle between the vector `vectorB - vectorA` and the x-axis in radians.
6711     * @method angle
6712     * @param {vector} vectorA
6713     * @param {vector} vectorB
6714     * @return {number} The angle in radians
6715     */
6716    Vector.angle = function(vectorA, vectorB) {
6717        return Math.atan2(vectorB.y - vectorA.y, vectorB.x - vectorA.x);
6718    };
6719
6720    /**
6721     * Temporary vector pool (not thread-safe).
6722     * @property _temp
6723     * @type {vector[]}
6724     * @private
6725     */
6726    Vector._temp = [
6727        Vector.create(), Vector.create(), 
6728        Vector.create(), Vector.create(), 
6729        Vector.create(), Vector.create()
6730    ];
6731
6732})();
6733
6734/***/ }),
6735/* 3 */
6736/***/ (function(module, exports, __webpack_require__) {
6737
6738/**
6739* The `Matter.Vertices` module contains methods for creating and manipulating sets of vertices.
6740* A set of vertices is an array of `Matter.Vector` with additional indexing properties inserted by `Vertices.create`.
6741* A `Matter.Body` maintains a set of vertices to represent the shape of the object (its convex hull).
6742*
6743* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples).
6744*
6745* @class Vertices
6746*/
6747
6748var Vertices = {};
6749
6750module.exports = Vertices;
6751
6752var Vector = __webpack_require__(2);
6753var Common = __webpack_require__(0);
6754
6755(function() {
6756
6757    /**
6758     * Creates a new set of `Matter.Body` compatible vertices.
6759     * The `points` argument accepts an array of `Matter.Vector` points orientated around the origin `(0, 0)`, for example:
6760     *
6761     *     [{ x: 0, y: 0 }, { x: 25, y: 50 }, { x: 50, y: 0 }]
6762     *
6763     * The `Vertices.create` method returns a new array of vertices, which are similar to Matter.Vector objects,
6764     * but with some additional references required for efficient collision detection routines.
6765     *
6766     * Vertices must be specified in clockwise order.
6767     *
6768     * Note that the `body` argument is not optional, a `Matter.Body` reference must be provided.
6769     *
6770     * @method create
6771     * @param {vector[]} points
6772     * @param {body} body
6773     */
6774    Vertices.create = function(points, body) {
6775        var vertices = [];
6776
6777        for (var i = 0; i < points.length; i++) {
6778            var point = points[i],
6779                vertex = {
6780                    x: point.x,
6781                    y: point.y,
6782                    index: i,
6783                    body: body,
6784                    isInternal: false
6785                };
6786
6787            vertices.push(vertex);
6788        }
6789
6790        return vertices;
6791    };
6792
6793    /**
6794     * Parses a string containing ordered x y pairs separated by spaces (and optionally commas), 
6795     * into a `Matter.Vertices` object for the given `Matter.Body`.
6796     * For parsing SVG paths, see `Svg.pathToVertices`.
6797     * @method fromPath
6798     * @param {string} path
6799     * @param {body} body
6800     * @return {vertices} vertices
6801     */
6802    Vertices.fromPath = function(path, body) {
6803        var pathPattern = /L?\s*([-\d.e]+)[\s,]*([-\d.e]+)*/ig,
6804            points = [];
6805
6806        path.replace(pathPattern, function(match, x, y) {
6807            points.push({ x: parseFloat(x), y: parseFloat(y) });
6808        });
6809
6810        return Vertices.create(points, body);
6811    };
6812
6813    /**
6814     * Returns the centre (centroid) of the set of vertices.
6815     * @method centre
6816     * @param {vertices} vertices
6817     * @return {vector} The centre point
6818     */
6819    Vertices.centre = function(vertices) {
6820        var area = Vertices.area(vertices, true),
6821            centre = { x: 0, y: 0 },
6822            cross,
6823            temp,
6824            j;
6825
6826        for (var i = 0; i < vertices.length; i++) {
6827            j = (i + 1) % vertices.length;
6828            cross = Vector.cross(vertices[i], vertices[j]);
6829            temp = Vector.mult(Vector.add(vertices[i], vertices[j]), cross);
6830            centre = Vector.add(centre, temp);
6831        }
6832
6833        return Vector.div(centre, 6 * area);
6834    };
6835
6836    /**
6837     * Returns the average (mean) of the set of vertices.
6838     * @method mean
6839     * @param {vertices} vertices
6840     * @return {vector} The average point
6841     */
6842    Vertices.mean = function(vertices) {
6843        var average = { x: 0, y: 0 };
6844
6845        for (var i = 0; i < vertices.length; i++) {
6846            average.x += vertices[i].x;
6847            average.y += vertices[i].y;
6848        }
6849
6850        return Vector.div(average, vertices.length);
6851    };
6852
6853    /**
6854     * Returns the area of the set of vertices.
6855     * @method area
6856     * @param {vertices} vertices
6857     * @param {bool} signed
6858     * @return {number} The area
6859     */
6860    Vertices.area = function(vertices, signed) {
6861        var area = 0,
6862            j = vertices.length - 1;
6863
6864        for (var i = 0; i < vertices.length; i++) {
6865            area += (vertices[j].x - vertices[i].x) * (vertices[j].y + vertices[i].y);
6866            j = i;
6867        }
6868
6869        if (signed)
6870            return area / 2;
6871
6872        return Math.abs(area) / 2;
6873    };
6874
6875    /**
6876     * Returns the moment of inertia (second moment of area) of the set of vertices given the total mass.
6877     * @method inertia
6878     * @param {vertices} vertices
6879     * @param {number} mass
6880     * @return {number} The polygon's moment of inertia
6881     */
6882    Vertices.inertia = function(vertices, mass) {
6883        var numerator = 0,
6884            denominator = 0,
6885            v = vertices,
6886            cross,
6887            j;
6888
6889        // find the polygon's moment of inertia, using second moment of area
6890        // from equations at http://www.physicsforums.com/showthread.php?t=25293
6891        for (var n = 0; n < v.length; n++) {
6892            j = (n + 1) % v.length;
6893            cross = Math.abs(Vector.cross(v[j], v[n]));
6894            numerator += cross * (Vector.dot(v[j], v[j]) + Vector.dot(v[j], v[n]) + Vector.dot(v[n], v[n]));
6895            denominator += cross;
6896        }
6897
6898        return (mass / 6) * (numerator / denominator);
6899    };
6900
6901    /**
6902     * Translates the set of vertices in-place.
6903     * @method translate
6904     * @param {vertices} vertices
6905     * @param {vector} vector
6906     * @param {number} scalar
6907     */
6908    Vertices.translate = function(vertices, vector, scalar) {
6909        scalar = typeof scalar !== 'undefined' ? scalar : 1;
6910
6911        var verticesLength = vertices.length,
6912            translateX = vector.x * scalar,
6913            translateY = vector.y * scalar,
6914            i;
6915        
6916        for (i = 0; i < verticesLength; i++) {
6917            vertices[i].x += translateX;
6918            vertices[i].y += translateY;
6919        }
6920
6921        return vertices;
6922    };
6923
6924    /**
6925     * Rotates the set of vertices in-place.
6926     * @method rotate
6927     * @param {vertices} vertices
6928     * @param {number} angle
6929     * @param {vector} point
6930     */
6931    Vertices.rotate = function(vertices, angle, point) {
6932        if (angle === 0)
6933            return;
6934
6935        var cos = Math.cos(angle),
6936            sin = Math.sin(angle),
6937            pointX = point.x,
6938            pointY = point.y,
6939            verticesLength = vertices.length,
6940            vertex,
6941            dx,
6942            dy,
6943            i;
6944
6945        for (i = 0; i < verticesLength; i++) {
6946            vertex = vertices[i];
6947            dx = vertex.x - pointX;
6948            dy = vertex.y - pointY;
6949            vertex.x = pointX + (dx * cos - dy * sin);
6950            vertex.y = pointY + (dx * sin + dy * cos);
6951        }
6952
6953        return vertices;
6954    };
6955
6956    /**
6957     * Returns `true` if the `point` is inside the set of `vertices`.
6958     * @method contains
6959     * @param {vertices} vertices
6960     * @param {vector} point
6961     * @return {boolean} True if the vertices contains point, otherwise false
6962     */
6963    Vertices.contains = function(vertices, point) {
6964        var pointX = point.x,
6965            pointY = point.y,
6966            verticesLength = vertices.length,
6967            vertex = vertices[verticesLength - 1],
6968            nextVertex;
6969
6970        for (var i = 0; i < verticesLength; i++) {
6971            nextVertex = vertices[i];
6972
6973            if ((pointX - vertex.x) * (nextVertex.y - vertex.y) 
6974                + (pointY - vertex.y) * (vertex.x - nextVertex.x) > 0) {
6975                return false;
6976            }
6977
6978            vertex = nextVertex;
6979        }
6980
6981        return true;
6982    };
6983
6984    /**
6985     * Scales the vertices from a point (default is centre) in-place.
6986     * @method scale
6987     * @param {vertices} vertices
6988     * @param {number} scaleX
6989     * @param {number} scaleY
6990     * @param {vector} point
6991     */
6992    Vertices.scale = function(vertices, scaleX, scaleY, point) {
6993        if (scaleX === 1 && scaleY === 1)
6994            return vertices;
6995
6996        point = point || Vertices.centre(vertices);
6997
6998        var vertex,
6999            delta;
7000
7001        for (var i = 0; i < vertices.length; i++) {
7002            vertex = vertices[i];
7003            delta = Vector.sub(vertex, point);
7004            vertices[i].x = point.x + delta.x * scaleX;
7005            vertices[i].y = point.y + delta.y * scaleY;
7006        }
7007
7008        return vertices;
7009    };
7010
7011    /**
7012     * Chamfers a set of vertices by giving them rounded corners, returns a new set of vertices.
7013     * The radius parameter is a single number or an array to specify the radius for each vertex.
7014     * @method chamfer
7015     * @param {vertices} vertices
7016     * @param {number[]} radius
7017     * @param {number} quality
7018     * @param {number} qualityMin
7019     * @param {number} qualityMax
7020     */
7021    Vertices.chamfer = function(vertices, radius, quality, qualityMin, qualityMax) {
7022        if (typeof radius === 'number') {
7023            radius = [radius];
7024        } else {
7025            radius = radius || [8];
7026        }
7027
7028        // quality defaults to -1, which is auto
7029        quality = (typeof quality !== 'undefined') ? quality : -1;
7030        qualityMin = qualityMin || 2;
7031        qualityMax = qualityMax || 14;
7032
7033        var newVertices = [];
7034
7035        for (var i = 0; i < vertices.length; i++) {
7036            var prevVertex = vertices[i - 1 >= 0 ? i - 1 : vertices.length - 1],
7037                vertex = vertices[i],
7038                nextVertex = vertices[(i + 1) % vertices.length],
7039                currentRadius = radius[i < radius.length ? i : radius.length - 1];
7040
7041            if (currentRadius === 0) {
7042                newVertices.push(vertex);
7043                continue;
7044            }
7045
7046            var prevNormal = Vector.normalise({ 
7047                x: vertex.y - prevVertex.y, 
7048                y: prevVertex.x - vertex.x
7049            });
7050
7051            var nextNormal = Vector.normalise({ 
7052                x: nextVertex.y - vertex.y, 
7053                y: vertex.x - nextVertex.x
7054            });
7055
7056            var diagonalRadius = Math.sqrt(2 * Math.pow(currentRadius, 2)),
7057                radiusVector = Vector.mult(Common.clone(prevNormal), currentRadius),
7058                midNormal = Vector.normalise(Vector.mult(Vector.add(prevNormal, nextNormal), 0.5)),
7059                scaledVertex = Vector.sub(vertex, Vector.mult(midNormal, diagonalRadius));
7060
7061            var precision = quality;
7062
7063            if (quality === -1) {
7064                // automatically decide precision
7065                precision = Math.pow(currentRadius, 0.32) * 1.75;
7066            }
7067
7068            precision = Common.clamp(precision, qualityMin, qualityMax);
7069
7070            // use an even value for precision, more likely to reduce axes by using symmetry
7071            if (precision % 2 === 1)
7072                precision += 1;
7073
7074            var alpha = Math.acos(Vector.dot(prevNormal, nextNormal)),
7075                theta = alpha / precision;
7076
7077            for (var j = 0; j < precision; j++) {
7078                newVertices.push(Vector.add(Vector.rotate(radiusVector, theta * j), scaledVertex));
7079            }
7080        }
7081
7082        return newVertices;
7083    };
7084
7085    /**
7086     * Sorts the input vertices into clockwise order in place.
7087     * @method clockwiseSort
7088     * @param {vertices} vertices
7089     * @return {vertices} vertices
7090     */
7091    Vertices.clockwiseSort = function(vertices) {
7092        var centre = Vertices.mean(vertices);
7093
7094        vertices.sort(function(vertexA, vertexB) {
7095            return Vector.angle(centre, vertexA) - Vector.angle(centre, vertexB);
7096        });
7097
7098        return vertices;
7099    };
7100
7101    /**
7102     * Returns true if the vertices form a convex shape (vertices must be in clockwise order).
7103     * @method isConvex
7104     * @param {vertices} vertices
7105     * @return {bool} `true` if the `vertices` are convex, `false` if not (or `null` if not computable).
7106     */
7107    Vertices.isConvex = function(vertices) {
7108        // http://paulbourke.net/geometry/polygonmesh/
7109        // Copyright (c) Paul Bourke (use permitted)
7110
7111        var flag = 0,
7112            n = vertices.length,
7113            i,
7114            j,
7115            k,
7116            z;
7117
7118        if (n < 3)
7119            return null;
7120
7121        for (i = 0; i < n; i++) {
7122            j = (i + 1) % n;
7123            k = (i + 2) % n;
7124            z = (vertices[j].x - vertices[i].x) * (vertices[k].y - vertices[j].y);
7125            z -= (vertices[j].y - vertices[i].y) * (vertices[k].x - vertices[j].x);
7126
7127            if (z < 0) {
7128                flag |= 1;
7129            } else if (z > 0) {
7130                flag |= 2;
7131            }
7132
7133            if (flag === 3) {
7134                return false;
7135            }
7136        }
7137
7138        if (flag !== 0){
7139            return true;
7140        } else {
7141            return null;
7142        }
7143    };
7144
7145    /**
7146     * Returns the convex hull of the input vertices as a new array of points.
7147     * @method hull
7148     * @param {vertices} vertices
7149     * @return [vertex] vertices
7150     */
7151    Vertices.hull = function(vertices) {
7152        // http://geomalgorithms.com/a10-_hull-1.html
7153
7154        var upper = [],
7155            lower = [], 
7156            vertex,
7157            i;
7158
7159        // sort vertices on x-axis (y-axis for ties)
7160        vertices = vertices.slice(0);
7161        vertices.sort(function(vertexA, vertexB) {
7162            var dx = vertexA.x - vertexB.x;
7163            return dx !== 0 ? dx : vertexA.y - vertexB.y;
7164        });
7165
7166        // build lower hull
7167        for (i = 0; i < vertices.length; i += 1) {
7168            vertex = vertices[i];
7169
7170            while (lower.length >= 2 
7171                   && Vector.cross3(lower[lower.length - 2], lower[lower.length - 1], vertex) <= 0) {
7172                lower.pop();
7173            }
7174
7175            lower.push(vertex);
7176        }
7177
7178        // build upper hull
7179        for (i = vertices.length - 1; i >= 0; i -= 1) {
7180            vertex = vertices[i];
7181
7182            while (upper.length >= 2 
7183                   && Vector.cross3(upper[upper.length - 2], upper[upper.length - 1], vertex) <= 0) {
7184                upper.pop();
7185            }
7186
7187            upper.push(vertex);
7188        }
7189
7190        // concatenation of the lower and upper hulls gives the convex hull
7191        // omit last points because they are repeated at the beginning of the other list
7192        upper.pop();
7193        lower.pop();
7194
7195        return upper.concat(lower);
7196    };
7197
7198})();
7199
7200
7201/***/ }),
7202/* 4 */
7203/***/ (function(module, exports, __webpack_require__) {
7204
7205/**
7206* The `Matter.Body` module contains methods for creating and manipulating rigid bodies.
7207* For creating bodies with common configurations such as rectangles, circles and other polygons see the module `Matter.Bodies`.
7208*
7209* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples).
7210
7211* @class Body
7212*/
7213
7214var Body = {};
7215
7216module.exports = Body;
7217
7218var Vertices = __webpack_require__(3);
7219var Vector = __webpack_require__(2);
7220var Sleeping = __webpack_require__(7);
7221var Common = __webpack_require__(0);
7222var Bounds = __webpack_require__(1);
7223var Axes = __webpack_require__(11);
7224
7225(function() {
7226
7227    Body._timeCorrection = true;
7228    Body._inertiaScale = 4;
7229    Body._nextCollidingGroupId = 1;
7230    Body._nextNonCollidingGroupId = -1;
7231    Body._nextCategory = 0x0001;
7232    Body._baseDelta = 1000 / 60;
7233
7234    /**
7235     * Creates a new rigid body model. The options parameter is an object that specifies any properties you wish to override the defaults.
7236     * All properties have default values, and many are pre-calculated automatically based on other properties.
7237     * Vertices must be specified in clockwise order.
7238     * See the properties section below for detailed information on what you can pass via the `options` object.
7239     * @method create
7240     * @param {} options
7241     * @return {body} body
7242     */
7243    Body.create = function(options) {
7244        var defaults = {
7245            id: Common.nextId(),
7246            type: 'body',
7247            label: 'Body',
7248            parts: [],
7249            plugin: {},
7250            angle: 0,
7251            vertices: Vertices.fromPath('L 0 0 L 40 0 L 40 40 L 0 40'),
7252            position: { x: 0, y: 0 },
7253            force: { x: 0, y: 0 },
7254            torque: 0,
7255            positionImpulse: { x: 0, y: 0 },
7256            constraintImpulse: { x: 0, y: 0, angle: 0 },
7257            totalContacts: 0,
7258            speed: 0,
7259            angularSpeed: 0,
7260            velocity: { x: 0, y: 0 },
7261            angularVelocity: 0,
7262            isSensor: false,
7263            isStatic: false,
7264            isSleeping: false,
7265            motion: 0,
7266            sleepThreshold: 60,
7267            density: 0.001,
7268            restitution: 0,
7269            friction: 0.1,
7270            frictionStatic: 0.5,
7271            frictionAir: 0.01,
7272            collisionFilter: {
7273                category: 0x0001,
7274                mask: 0xFFFFFFFF,
7275                group: 0
7276            },
7277            slop: 0.05,
7278            timeScale: 1,
7279            render: {
7280                visible: true,
7281                opacity: 1,
7282                strokeStyle: null,
7283                fillStyle: null,
7284                lineWidth: null,
7285                sprite: {
7286                    xScale: 1,
7287                    yScale: 1,
7288                    xOffset: 0,
7289                    yOffset: 0
7290                }
7291            },
7292            events: null,
7293            bounds: null,
7294            chamfer: null,
7295            circleRadius: 0,
7296            positionPrev: null,
7297            anglePrev: 0,
7298            parent: null,
7299            axes: null,
7300            area: 0,
7301            mass: 0,
7302            inertia: 0,
7303            deltaTime: 1000 / 60,
7304            _original: null
7305        };
7306
7307        var body = Common.extend(defaults, options);
7308
7309        _initProperties(body, options);
7310
7311        return body;
7312    };
7313
7314    /**
7315     * Returns the next unique group index for which bodies will collide.
7316     * If `isNonColliding` is `true`, returns the next unique group index for which bodies will _not_ collide.
7317     * See `body.collisionFilter` for more information.
7318     * @method nextGroup
7319     * @param {bool} [isNonColliding=false]
7320     * @return {Number} Unique group index
7321     */
7322    Body.nextGroup = function(isNonColliding) {
7323        if (isNonColliding)
7324            return Body._nextNonCollidingGroupId--;
7325
7326        return Body._nextCollidingGroupId++;
7327    };
7328
7329    /**
7330     * Returns the next unique category bitfield (starting after the initial default category `0x0001`).
7331     * There are 32 available. See `body.collisionFilter` for more information.
7332     * @method nextCategory
7333     * @return {Number} Unique category bitfield
7334     */
7335    Body.nextCategory = function() {
7336        Body._nextCategory = Body._nextCategory << 1;
7337        return Body._nextCategory;
7338    };
7339
7340    /**
7341     * Initialises body properties.
7342     * @method _initProperties
7343     * @private
7344     * @param {body} body
7345     * @param {} [options]
7346     */
7347    var _initProperties = function(body, options) {
7348        options = options || {};
7349
7350        // init required properties (order is important)
7351        Body.set(body, {
7352            bounds: body.bounds || Bounds.create(body.vertices),
7353            positionPrev: body.positionPrev || Vector.clone(body.position),
7354            anglePrev: body.anglePrev || body.angle,
7355            vertices: body.vertices,
7356            parts: body.parts || [body],
7357            isStatic: body.isStatic,
7358            isSleeping: body.isSleeping,
7359            parent: body.parent || body
7360        });
7361
7362        Vertices.rotate(body.vertices, body.angle, body.position);
7363        Axes.rotate(body.axes, body.angle);
7364        Bounds.update(body.bounds, body.vertices, body.velocity);
7365
7366        // allow options to override the automatically calculated properties
7367        Body.set(body, {
7368            axes: options.axes || body.axes,
7369            area: options.area || body.area,
7370            mass: options.mass || body.mass,
7371            inertia: options.inertia || body.inertia
7372        });
7373
7374        // render properties
7375        var defaultFillStyle = (body.isStatic ? '#14151f' : Common.choose(['#f19648', '#f5d259', '#f55a3c', '#063e7b', '#ececd1'])),
7376            defaultStrokeStyle = body.isStatic ? '#555' : '#ccc',
7377            defaultLineWidth = body.isStatic && body.render.fillStyle === null ? 1 : 0;
7378        body.render.fillStyle = body.render.fillStyle || defaultFillStyle;
7379        body.render.strokeStyle = body.render.strokeStyle || defaultStrokeStyle;
7380        body.render.lineWidth = body.render.lineWidth || defaultLineWidth;
7381        body.render.sprite.xOffset += -(body.bounds.min.x - body.position.x) / (body.bounds.max.x - body.bounds.min.x);
7382        body.render.sprite.yOffset += -(body.bounds.min.y - body.position.y) / (body.bounds.max.y - body.bounds.min.y);
7383    };
7384
7385    /**
7386     * Given a property and a value (or map of), sets the property(s) on the body, using the appropriate setter functions if they exist.
7387     * Prefer to use the actual setter functions in performance critical situations.
7388     * @method set
7389     * @param {body} body
7390     * @param {} settings A property name (or map of properties and values) to set on the body.
7391     * @param {} value The value to set if `settings` is a single property name.
7392     */
7393    Body.set = function(body, settings, value) {
7394        var property;
7395
7396        if (typeof settings === 'string') {
7397            property = settings;
7398            settings = {};
7399            settings[property] = value;
7400        }
7401
7402        for (property in settings) {
7403            if (!Object.prototype.hasOwnProperty.call(settings, property))
7404                continue;
7405
7406            value = settings[property];
7407            switch (property) {
7408
7409            case 'isStatic':
7410                Body.setStatic(body, value);
7411                break;
7412            case 'isSleeping':
7413                Sleeping.set(body, value);
7414                break;
7415            case 'mass':
7416                Body.setMass(body, value);
7417                break;
7418            case 'density':
7419                Body.setDensity(body, value);
7420                break;
7421            case 'inertia':
7422                Body.setInertia(body, value);
7423                break;
7424            case 'vertices':
7425                Body.setVertices(body, value);
7426                break;
7427            case 'position':
7428                Body.setPosition(body, value);
7429                break;
7430            case 'angle':
7431                Body.setAngle(body, value);
7432                break;
7433            case 'velocity':
7434                Body.setVelocity(body, value);
7435                break;
7436            case 'angularVelocity':
7437                Body.setAngularVelocity(body, value);
7438                break;
7439            case 'speed':
7440                Body.setSpeed(body, value);
7441                break;
7442            case 'angularSpeed':
7443                Body.setAngularSpeed(body, value);
7444                break;
7445            case 'parts':
7446                Body.setParts(body, value);
7447                break;
7448            case 'centre':
7449                Body.setCentre(body, value);
7450                break;
7451            default:
7452                body[property] = value;
7453
7454            }
7455        }
7456    };
7457
7458    /**
7459     * Sets the body as static, including isStatic flag and setting mass and inertia to Infinity.
7460     * @method setStatic
7461     * @param {body} body
7462     * @param {bool} isStatic
7463     */
7464    Body.setStatic = function(body, isStatic) {
7465        for (var i = 0; i < body.parts.length; i++) {
7466            var part = body.parts[i];
7467
7468            if (isStatic) {
7469                if (!part.isStatic) {
7470                    part._original = {
7471                        restitution: part.restitution,
7472                        friction: part.friction,
7473                        mass: part.mass,
7474                        inertia: part.inertia,
7475                        density: part.density,
7476                        inverseMass: part.inverseMass,
7477                        inverseInertia: part.inverseInertia
7478                    };
7479                }
7480
7481                part.restitution = 0;
7482                part.friction = 1;
7483                part.mass = part.inertia = part.density = Infinity;
7484                part.inverseMass = part.inverseInertia = 0;
7485
7486                part.positionPrev.x = part.position.x;
7487                part.positionPrev.y = part.position.y;
7488                part.anglePrev = part.angle;
7489                part.angularVelocity = 0;
7490                part.speed = 0;
7491                part.angularSpeed = 0;
7492                part.motion = 0;
7493            } else if (part._original) {
7494                part.restitution = part._original.restitution;
7495                part.friction = part._original.friction;
7496                part.mass = part._original.mass;
7497                part.inertia = part._original.inertia;
7498                part.density = part._original.density;
7499                part.inverseMass = part._original.inverseMass;
7500                part.inverseInertia = part._original.inverseInertia;
7501
7502                part._original = null;
7503            }
7504
7505            part.isStatic = isStatic;
7506        }
7507    };
7508
7509    /**
7510     * Sets the mass of the body. Inverse mass, density and inertia are automatically updated to reflect the change.
7511     * @method setMass
7512     * @param {body} body
7513     * @param {number} mass
7514     */
7515    Body.setMass = function(body, mass) {
7516        var moment = body.inertia / (body.mass / 6);
7517        body.inertia = moment * (mass / 6);
7518        body.inverseInertia = 1 / body.inertia;
7519
7520        body.mass = mass;
7521        body.inverseMass = 1 / body.mass;
7522        body.density = body.mass / body.area;
7523    };
7524
7525    /**
7526     * Sets the density of the body. Mass and inertia are automatically updated to reflect the change.
7527     * @method setDensity
7528     * @param {body} body
7529     * @param {number} density
7530     */
7531    Body.setDensity = function(body, density) {
7532        Body.setMass(body, density * body.area);
7533        body.density = density;
7534    };
7535
7536    /**
7537     * Sets the moment of inertia of the body. This is the second moment of area in two dimensions.
7538     * Inverse inertia is automatically updated to reflect the change. Mass is not changed.
7539     * @method setInertia
7540     * @param {body} body
7541     * @param {number} inertia
7542     */
7543    Body.setInertia = function(body, inertia) {
7544        body.inertia = inertia;
7545        body.inverseInertia = 1 / body.inertia;
7546    };
7547
7548    /**
7549     * Sets the body's vertices and updates body properties accordingly, including inertia, area and mass (with respect to `body.density`).
7550     * Vertices will be automatically transformed to be orientated around their centre of mass as the origin.
7551     * They are then automatically translated to world space based on `body.position`.
7552     *
7553     * The `vertices` argument should be passed as an array of `Matter.Vector` points (or a `Matter.Vertices` array).
7554     * Vertices must form a convex hull. Concave vertices must be decomposed into convex parts.
7555     * 
7556     * @method setVertices
7557     * @param {body} body
7558     * @param {vector[]} vertices
7559     */
7560    Body.setVertices = function(body, vertices) {
7561        // change vertices
7562        if (vertices[0].body === body) {
7563            body.vertices = vertices;
7564        } else {
7565            body.vertices = Vertices.create(vertices, body);
7566        }
7567
7568        // update properties
7569        body.axes = Axes.fromVertices(body.vertices);
7570        body.area = Vertices.area(body.vertices);
7571        Body.setMass(body, body.density * body.area);
7572
7573        // orient vertices around the centre of mass at origin (0, 0)
7574        var centre = Vertices.centre(body.vertices);
7575        Vertices.translate(body.vertices, centre, -1);
7576
7577        // update inertia while vertices are at origin (0, 0)
7578        Body.setInertia(body, Body._inertiaScale * Vertices.inertia(body.vertices, body.mass));
7579
7580        // update geometry
7581        Vertices.translate(body.vertices, body.position);
7582        Bounds.update(body.bounds, body.vertices, body.velocity);
7583    };
7584
7585    /**
7586     * Sets the parts of the `body`. 
7587     * 
7588     * See `body.parts` for details and requirements on how parts are used.
7589     * 
7590     * See Bodies.fromVertices for a related utility.
7591     * 
7592     * This function updates `body` mass, inertia and centroid based on the parts geometry.  
7593     * Sets each `part.parent` to be this `body`.  
7594     * 
7595     * The convex hull is computed and set on this `body` (unless `autoHull` is `false`).  
7596     * Automatically ensures that the first part in `body.parts` is the `body`.
7597     * @method setParts
7598     * @param {body} body
7599     * @param {body[]} parts
7600     * @param {bool} [autoHull=true]
7601     */
7602    Body.setParts = function(body, parts, autoHull) {
7603        var i;
7604
7605        // add all the parts, ensuring that the first part is always the parent body
7606        parts = parts.slice(0);
7607        body.parts.length = 0;
7608        body.parts.push(body);
7609        body.parent = body;
7610
7611        for (i = 0; i < parts.length; i++) {
7612            var part = parts[i];
7613            if (part !== body) {
7614                part.parent = body;
7615                body.parts.push(part);
7616            }
7617        }
7618
7619        if (body.parts.length === 1)
7620            return;
7621
7622        autoHull = typeof autoHull !== 'undefined' ? autoHull : true;
7623
7624        // find the convex hull of all parts to set on the parent body
7625        if (autoHull) {
7626            var vertices = [];
7627            for (i = 0; i < parts.length; i++) {
7628                vertices = vertices.concat(parts[i].vertices);
7629            }
7630
7631            Vertices.clockwiseSort(vertices);
7632
7633            var hull = Vertices.hull(vertices),
7634                hullCentre = Vertices.centre(hull);
7635
7636            Body.setVertices(body, hull);
7637            Vertices.translate(body.vertices, hullCentre);
7638        }
7639
7640        // sum the properties of all compound parts of the parent body
7641        var total = Body._totalProperties(body);
7642
7643        body.area = total.area;
7644        body.parent = body;
7645        body.position.x = total.centre.x;
7646        body.position.y = total.centre.y;
7647        body.positionPrev.x = total.centre.x;
7648        body.positionPrev.y = total.centre.y;
7649
7650        Body.setMass(body, total.mass);
7651        Body.setInertia(body, total.inertia);
7652        Body.setPosition(body, total.centre);
7653    };
7654
7655    /**
7656     * Set the centre of mass of the body. 
7657     * The `centre` is a vector in world-space unless `relative` is set, in which case it is a translation.
7658     * The centre of mass is the point the body rotates about and can be used to simulate non-uniform density.
7659     * This is equal to moving `body.position` but not the `body.vertices`.
7660     * Invalid if the `centre` falls outside the body's convex hull.
7661     * @method setCentre
7662     * @param {body} body
7663     * @param {vector} centre
7664     * @param {bool} relative
7665     */
7666    Body.setCentre = function(body, centre, relative) {
7667        if (!relative) {
7668            body.positionPrev.x = centre.x - (body.position.x - body.positionPrev.x);
7669            body.positionPrev.y = centre.y - (body.position.y - body.positionPrev.y);
7670            body.position.x = centre.x;
7671            body.position.y = centre.y;
7672        } else {
7673            body.positionPrev.x += centre.x;
7674            body.positionPrev.y += centre.y;
7675            body.position.x += centre.x;
7676            body.position.y += centre.y;
7677        }
7678    };
7679
7680    /**
7681     * Sets the position of the body. By default velocity is unchanged.
7682     * If `updateVelocity` is `true` then velocity is inferred from the change in position.
7683     * @method setPosition
7684     * @param {body} body
7685     * @param {vector} position
7686     * @param {boolean} [updateVelocity=false]
7687     */
7688    Body.setPosition = function(body, position, updateVelocity) {
7689        var delta = Vector.sub(position, body.position);
7690
7691        if (updateVelocity) {
7692            body.positionPrev.x = body.position.x;
7693            body.positionPrev.y = body.position.y;
7694            body.velocity.x = delta.x;
7695            body.velocity.y = delta.y;
7696            body.speed = Vector.magnitude(delta);
7697        } else {
7698            body.positionPrev.x += delta.x;
7699            body.positionPrev.y += delta.y;
7700        }
7701
7702        for (var i = 0; i < body.parts.length; i++) {
7703            var part = body.parts[i];
7704            part.position.x += delta.x;
7705            part.position.y += delta.y;
7706            Vertices.translate(part.vertices, delta);
7707            Bounds.update(part.bounds, part.vertices, body.velocity);
7708        }
7709    };
7710
7711    /**
7712     * Sets the angle of the body. By default angular velocity is unchanged.
7713     * If `updateVelocity` is `true` then angular velocity is inferred from the change in angle.
7714     * @method setAngle
7715     * @param {body} body
7716     * @param {number} angle
7717     * @param {boolean} [updateVelocity=false]
7718     */
7719    Body.setAngle = function(body, angle, updateVelocity) {
7720        var delta = angle - body.angle;
7721        
7722        if (updateVelocity) {
7723            body.anglePrev = body.angle;
7724            body.angularVelocity = delta;
7725            body.angularSpeed = Math.abs(delta);
7726        } else {
7727            body.anglePrev += delta;
7728        }
7729
7730        for (var i = 0; i < body.parts.length; i++) {
7731            var part = body.parts[i];
7732            part.angle += delta;
7733            Vertices.rotate(part.vertices, delta, body.position);
7734            Axes.rotate(part.axes, delta);
7735            Bounds.update(part.bounds, part.vertices, body.velocity);
7736            if (i > 0) {
7737                Vector.rotateAbout(part.position, delta, body.position, part.position);
7738            }
7739        }
7740    };
7741
7742    /**
7743     * Sets the current linear velocity of the body.  
7744     * Affects body speed.
7745     * @method setVelocity
7746     * @param {body} body
7747     * @param {vector} velocity
7748     */
7749    Body.setVelocity = function(body, velocity) {
7750        var timeScale = body.deltaTime / Body._baseDelta;
7751        body.positionPrev.x = body.position.x - velocity.x * timeScale;
7752        body.positionPrev.y = body.position.y - velocity.y * timeScale;
7753        body.velocity.x = (body.position.x - body.positionPrev.x) / timeScale;
7754        body.velocity.y = (body.position.y - body.positionPrev.y) / timeScale;
7755        body.speed = Vector.magnitude(body.velocity);
7756    };
7757
7758    /**
7759     * Gets the current linear velocity of the body.
7760     * @method getVelocity
7761     * @param {body} body
7762     * @return {vector} velocity
7763     */
7764    Body.getVelocity = function(body) {
7765        var timeScale = Body._baseDelta / body.deltaTime;
7766
7767        return {
7768            x: (body.position.x - body.positionPrev.x) * timeScale,
7769            y: (body.position.y - body.positionPrev.y) * timeScale
7770        };
7771    };
7772
7773    /**
7774     * Gets the current linear speed of the body.  
7775     * Equivalent to the magnitude of its velocity.
7776     * @method getSpeed
7777     * @param {body} body
7778     * @return {number} speed
7779     */
7780    Body.getSpeed = function(body) {
7781        return Vector.magnitude(Body.getVelocity(body));
7782    };
7783
7784    /**
7785     * Sets the current linear speed of the body.  
7786     * Direction is maintained. Affects body velocity.
7787     * @method setSpeed
7788     * @param {body} body
7789     * @param {number} speed
7790     */
7791    Body.setSpeed = function(body, speed) {
7792        Body.setVelocity(body, Vector.mult(Vector.normalise(Body.getVelocity(body)), speed));
7793    };
7794
7795    /**
7796     * Sets the current rotational velocity of the body.  
7797     * Affects body angular speed.
7798     * @method setAngularVelocity
7799     * @param {body} body
7800     * @param {number} velocity
7801     */
7802    Body.setAngularVelocity = function(body, velocity) {
7803        var timeScale = body.deltaTime / Body._baseDelta;
7804        body.anglePrev = body.angle - velocity * timeScale;
7805        body.angularVelocity = (body.angle - body.anglePrev) / timeScale;
7806        body.angularSpeed = Math.abs(body.angularVelocity);
7807    };
7808
7809    /**
7810     * Gets the current rotational velocity of the body.
7811     * @method getAngularVelocity
7812     * @param {body} body
7813     * @return {number} angular velocity
7814     */
7815    Body.getAngularVelocity = function(body) {
7816        return (body.angle - body.anglePrev) * Body._baseDelta / body.deltaTime;
7817    };
7818
7819    /**
7820     * Gets the current rotational speed of the body.  
7821     * Equivalent to the magnitude of its angular velocity.
7822     * @method getAngularSpeed
7823     * @param {body} body
7824     * @return {number} angular speed
7825     */
7826    Body.getAngularSpeed = function(body) {
7827        return Math.abs(Body.getAngularVelocity(body));
7828    };
7829
7830    /**
7831     * Sets the current rotational speed of the body.  
7832     * Direction is maintained. Affects body angular velocity.
7833     * @method setAngularSpeed
7834     * @param {body} body
7835     * @param {number} speed
7836     */
7837    Body.setAngularSpeed = function(body, speed) {
7838        Body.setAngularVelocity(body, Common.sign(Body.getAngularVelocity(body)) * speed);
7839    };
7840
7841    /**
7842     * Moves a body by a given vector relative to its current position. By default velocity is unchanged.
7843     * If `updateVelocity` is `true` then velocity is inferred from the change in position.
7844     * @method translate
7845     * @param {body} body
7846     * @param {vector} translation
7847     * @param {boolean} [updateVelocity=false]
7848     */
7849    Body.translate = function(body, translation, updateVelocity) {
7850        Body.setPosition(body, Vector.add(body.position, translation), updateVelocity);
7851    };
7852
7853    /**
7854     * Rotates a body by a given angle relative to its current angle. By default angular velocity is unchanged.
7855     * If `updateVelocity` is `true` then angular velocity is inferred from the change in angle.
7856     * @method rotate
7857     * @param {body} body
7858     * @param {number} rotation
7859     * @param {vector} [point]
7860     * @param {boolean} [updateVelocity=false]
7861     */
7862    Body.rotate = function(body, rotation, point, updateVelocity) {
7863        if (!point) {
7864            Body.setAngle(body, body.angle + rotation, updateVelocity);
7865        } else {
7866            var cos = Math.cos(rotation),
7867                sin = Math.sin(rotation),
7868                dx = body.position.x - point.x,
7869                dy = body.position.y - point.y;
7870                
7871            Body.setPosition(body, {
7872                x: point.x + (dx * cos - dy * sin),
7873                y: point.y + (dx * sin + dy * cos)
7874            }, updateVelocity);
7875
7876            Body.setAngle(body, body.angle + rotation, updateVelocity);
7877        }
7878    };
7879
7880    /**
7881     * Scales the body, including updating physical properties (mass, area, axes, inertia), from a world-space point (default is body centre).
7882     * @method scale
7883     * @param {body} body
7884     * @param {number} scaleX
7885     * @param {number} scaleY
7886     * @param {vector} [point]
7887     */
7888    Body.scale = function(body, scaleX, scaleY, point) {
7889        var totalArea = 0,
7890            totalInertia = 0;
7891
7892        point = point || body.position;
7893
7894        for (var i = 0; i < body.parts.length; i++) {
7895            var part = body.parts[i];
7896
7897            // scale vertices
7898            Vertices.scale(part.vertices, scaleX, scaleY, point);
7899
7900            // update properties
7901            part.axes = Axes.fromVertices(part.vertices);
7902            part.area = Vertices.area(part.vertices);
7903            Body.setMass(part, body.density * part.area);
7904
7905            // update inertia (requires vertices to be at origin)
7906            Vertices.translate(part.vertices, { x: -part.position.x, y: -part.position.y });
7907            Body.setInertia(part, Body._inertiaScale * Vertices.inertia(part.vertices, part.mass));
7908            Vertices.translate(part.vertices, { x: part.position.x, y: part.position.y });
7909
7910            if (i > 0) {
7911                totalArea += part.area;
7912                totalInertia += part.inertia;
7913            }
7914
7915            // scale position
7916            part.position.x = point.x + (part.position.x - point.x) * scaleX;
7917            part.position.y = point.y + (part.position.y - point.y) * scaleY;
7918
7919            // update bounds
7920            Bounds.update(part.bounds, part.vertices, body.velocity);
7921        }
7922
7923        // handle parent body
7924        if (body.parts.length > 1) {
7925            body.area = totalArea;
7926
7927            if (!body.isStatic) {
7928                Body.setMass(body, body.density * totalArea);
7929                Body.setInertia(body, totalInertia);
7930            }
7931        }
7932
7933        // handle circles
7934        if (body.circleRadius) { 
7935            if (scaleX === scaleY) {
7936                body.circleRadius *= scaleX;
7937            } else {
7938                // body is no longer a circle
7939                body.circleRadius = null;
7940            }
7941        }
7942    };
7943
7944    /**
7945     * Performs an update by integrating the equations of motion on the `body`.
7946     * This is applied every update by `Matter.Engine` automatically.
7947     * @method update
7948     * @param {body} body
7949     * @param {number} [deltaTime=16.666]
7950     */
7951    Body.update = function(body, deltaTime) {
7952        deltaTime = (typeof deltaTime !== 'undefined' ? deltaTime : (1000 / 60)) * body.timeScale;
7953
7954        var deltaTimeSquared = deltaTime * deltaTime,
7955            correction = Body._timeCorrection ? deltaTime / (body.deltaTime || deltaTime) : 1;
7956
7957        // from the previous step
7958        var frictionAir = 1 - body.frictionAir * (deltaTime / Common._baseDelta),
7959            velocityPrevX = (body.position.x - body.positionPrev.x) * correction,
7960            velocityPrevY = (body.position.y - body.positionPrev.y) * correction;
7961
7962        // update velocity with Verlet integration
7963        body.velocity.x = (velocityPrevX * frictionAir) + (body.force.x / body.mass) * deltaTimeSquared;
7964        body.velocity.y = (velocityPrevY * frictionAir) + (body.force.y / body.mass) * deltaTimeSquared;
7965
7966        body.positionPrev.x = body.position.x;
7967        body.positionPrev.y = body.position.y;
7968        body.position.x += body.velocity.x;
7969        body.position.y += body.velocity.y;
7970        body.deltaTime = deltaTime;
7971
7972        // update angular velocity with Verlet integration
7973        body.angularVelocity = ((body.angle - body.anglePrev) * frictionAir * correction) + (body.torque / body.inertia) * deltaTimeSquared;
7974        body.anglePrev = body.angle;
7975        body.angle += body.angularVelocity;
7976
7977        // transform the body geometry
7978        for (var i = 0; i < body.parts.length; i++) {
7979            var part = body.parts[i];
7980
7981            Vertices.translate(part.vertices, body.velocity);
7982            
7983            if (i > 0) {
7984                part.position.x += body.velocity.x;
7985                part.position.y += body.velocity.y;
7986            }
7987
7988            if (body.angularVelocity !== 0) {
7989                Vertices.rotate(part.vertices, body.angularVelocity, body.position);
7990                Axes.rotate(part.axes, body.angularVelocity);
7991                if (i > 0) {
7992                    Vector.rotateAbout(part.position, body.angularVelocity, body.position, part.position);
7993                }
7994            }
7995
7996            Bounds.update(part.bounds, part.vertices, body.velocity);
7997        }
7998    };
7999
8000    /**
8001     * Updates properties `body.velocity`, `body.speed`, `body.angularVelocity` and `body.angularSpeed` which are normalised in relation to `Body._baseDelta`.
8002     * @method updateVelocities
8003     * @param {body} body
8004     */
8005    Body.updateVelocities = function(body) {
8006        var timeScale = Body._baseDelta / body.deltaTime,
8007            bodyVelocity = body.velocity;
8008
8009        bodyVelocity.x = (body.position.x - body.positionPrev.x) * timeScale;
8010        bodyVelocity.y = (body.position.y - body.positionPrev.y) * timeScale;
8011        body.speed = Math.sqrt((bodyVelocity.x * bodyVelocity.x) + (bodyVelocity.y * bodyVelocity.y));
8012
8013        body.angularVelocity = (body.angle - body.anglePrev) * timeScale;
8014        body.angularSpeed = Math.abs(body.angularVelocity);
8015    };
8016
8017    /**
8018     * Applies the `force` to the `body` from the force origin `position` in world-space, over a single timestep, including applying any resulting angular torque.
8019     * 
8020     * Forces are useful for effects like gravity, wind or rocket thrust, but can be difficult in practice when precise control is needed. In these cases see `Body.setVelocity` and `Body.setPosition` as an alternative.
8021     * 
8022     * The force from this function is only applied once for the duration of a single timestep, in other words the duration depends directly on the current engine update `delta` and the rate of calls to this function.
8023     * 
8024     * Therefore to account for time, you should apply the force constantly over as many engine updates as equivalent to the intended duration.
8025     * 
8026     * If all or part of the force duration is some fraction of a timestep, first multiply the force by `duration / timestep`.
8027     * 
8028     * The force origin `position` in world-space must also be specified. Passing `body.position` will result in zero angular effect as the force origin would be at the centre of mass.
8029     * 
8030     * The `body` will take time to accelerate under a force, the resulting effect depends on duration of the force, the body mass and other forces on the body including friction combined.
8031     * @method applyForce
8032     * @param {body} body
8033     * @param {vector} position The force origin in world-space. Pass `body.position` to avoid angular torque.
8034     * @param {vector} force
8035     */
8036    Body.applyForce = function(body, position, force) {
8037        var offset = { x: position.x - body.position.x, y: position.y - body.position.y };
8038        body.force.x += force.x;
8039        body.force.y += force.y;
8040        body.torque += offset.x * force.y - offset.y * force.x;
8041    };
8042
8043    /**
8044     * Returns the sums of the properties of all compound parts of the parent body.
8045     * @method _totalProperties
8046     * @private
8047     * @param {body} body
8048     * @return {}
8049     */
8050    Body._totalProperties = function(body) {
8051        // from equations at:
8052        // https://ecourses.ou.edu/cgi-bin/ebook.cgi?doc=&topic=st&chap_sec=07.2&page=theory
8053        // http://output.to/sideway/default.asp?qno=121100087
8054
8055        var properties = {
8056            mass: 0,
8057            area: 0,
8058            inertia: 0,
8059            centre: { x: 0, y: 0 }
8060        };
8061
8062        // sum the properties of all compound parts of the parent body
8063        for (var i = body.parts.length === 1 ? 0 : 1; i < body.parts.length; i++) {
8064            var part = body.parts[i],
8065                mass = part.mass !== Infinity ? part.mass : 1;
8066
8067            properties.mass += mass;
8068            properties.area += part.area;
8069            properties.inertia += part.inertia;
8070            properties.centre = Vector.add(properties.centre, Vector.mult(part.position, mass));
8071        }
8072
8073        properties.centre = Vector.div(properties.centre, properties.mass);
8074
8075        return properties;
8076    };
8077
8078    /*
8079    *
8080    *  Events Documentation
8081    *
8082    */
8083
8084    /**
8085    * Fired when a body starts sleeping (where `this` is the body).
8086    *
8087    * @event sleepStart
8088    * @this {body} The body that has started sleeping
8089    * @param {} event An event object
8090    * @param {} event.source The source object of the event
8091    * @param {} event.name The name of the event
8092    */
8093
8094    /**
8095    * Fired when a body ends sleeping (where `this` is the body).
8096    *
8097    * @event sleepEnd
8098    * @this {body} The body that has ended sleeping
8099    * @param {} event An event object
8100    * @param {} event.source The source object of the event
8101    * @param {} event.name The name of the event
8102    */
8103
8104    /*
8105    *
8106    *  Properties Documentation
8107    *
8108    */
8109
8110    /**
8111     * An integer `Number` uniquely identifying number generated in `Body.create` by `Common.nextId`.
8112     *
8113     * @property id
8114     * @type number
8115     */
8116
8117    /**
8118     * _Read only_. Set by `Body.create`.
8119     * 
8120     * A `String` denoting the type of object.
8121     *
8122     * @readOnly
8123     * @property type
8124     * @type string
8125     * @default "body"
8126     */
8127
8128    /**
8129     * An arbitrary `String` name to help the user identify and manage bodies.
8130     *
8131     * @property label
8132     * @type string
8133     * @default "Body"
8134     */
8135
8136    /**
8137     * _Read only_. Use `Body.setParts` to set. 
8138     * 
8139     * See `Bodies.fromVertices` for a related utility.
8140     * 
8141     * An array of bodies (the 'parts') that make up this body (the 'parent'). The first body in this array must always be a self-reference to this `body`.  
8142     * 
8143     * The parts are fixed together and therefore perform as a single unified rigid body.
8144     * 
8145     * Parts in relation to each other are allowed to overlap, as well as form gaps or holes, so can be used to create complex concave bodies unlike when using a single part. 
8146     * 
8147     * Use properties and functions on the parent `body` rather than on parts.
8148     *   
8149     * Outside of their geometry, most properties on parts are not considered or updated.  
8150     * As such 'per-part' material properties among others are not currently considered.
8151     * 
8152     * Parts should be created specifically for their parent body.  
8153     * Parts should not be shared or reused between bodies, only one parent is supported.  
8154     * Parts should not have their own parts, they are not handled recursively.  
8155     * Parts should not be added to the world directly or any other composite.  
8156     * Parts own vertices must be convex and in clockwise order.   
8157     * 
8158     * A body with more than one part is sometimes referred to as a 'compound' body. 
8159     * 
8160     * Use `Body.setParts` when setting parts to ensure correct updates of all properties.  
8161     *
8162     * @readOnly
8163     * @property parts
8164     * @type body[]
8165     */
8166
8167    /**
8168     * An object reserved for storing plugin-specific properties.
8169     *
8170     * @property plugin
8171     * @type {}
8172     */
8173
8174    /**
8175     * _Read only_. Updated by `Body.setParts`.
8176     * 
8177     * A reference to the body that this is a part of. See `body.parts`.
8178     * This is a self reference if the body is not a part of another body.
8179     *
8180     * @readOnly
8181     * @property parent
8182     * @type body
8183     */
8184
8185    /**
8186     * A `Number` specifying the angle of the body, in radians.
8187     *
8188     * @property angle
8189     * @type number
8190     * @default 0
8191     */
8192
8193    /**
8194     * _Read only_. Use `Body.setVertices` or `Body.setParts` to set. See also `Bodies.fromVertices`.
8195     * 
8196     * An array of `Vector` objects that specify the convex hull of the rigid body.
8197     * These should be provided about the origin `(0, 0)`. E.g.
8198     *
8199     * `[{ x: 0, y: 0 }, { x: 25, y: 50 }, { x: 50, y: 0 }]`
8200     * 
8201     * Vertices must always be convex, in clockwise order and must not contain any duplicate points.
8202     * 
8203     * Concave vertices should be decomposed into convex `parts`, see `Bodies.fromVertices` and `Body.setParts`.
8204     *
8205     * When set the vertices are translated such that `body.position` is at the centre of mass.
8206     * Many other body properties are automatically calculated from these vertices when set including `density`, `area` and `inertia`.
8207     * 
8208     * The module `Matter.Vertices` contains useful methods for working with vertices.
8209     *
8210     * @readOnly
8211     * @property vertices
8212     * @type vector[]
8213     */
8214
8215    /**
8216     * _Read only_. Use `Body.setPosition` to set. 
8217     * 
8218     * A `Vector` that specifies the current world-space position of the body.
8219     * 
8220     * @readOnly
8221     * @property position
8222     * @type vector
8223     * @default { x: 0, y: 0 }
8224     */
8225
8226    /**
8227     * A `Vector` that accumulates the total force applied to the body for a single update.
8228     * Force is zeroed after every `Engine.update`, so constant forces should be applied for every update they are needed. See also `Body.applyForce`.
8229     * 
8230     * @property force
8231     * @type vector
8232     * @default { x: 0, y: 0 }
8233     */
8234
8235    /**
8236     * A `Number` that accumulates the total torque (turning force) applied to the body for a single update. See also `Body.applyForce`.
8237     * Torque is zeroed after every `Engine.update`, so constant torques should be applied for every update they are needed.
8238     *
8239     * Torques result in angular acceleration on every update, which depends on body inertia and the engine update delta.
8240     * 
8241     * @property torque
8242     * @type number
8243     * @default 0
8244     */
8245
8246    /**
8247     * _Read only_. Use `Body.setSpeed` to set. 
8248     * 
8249     * See `Body.getSpeed` for details.
8250     * 
8251     * Equivalent to the magnitude of `body.velocity` (always positive).
8252     * 
8253     * @readOnly
8254     * @property speed
8255     * @type number
8256     * @default 0
8257     */
8258
8259    /**
8260     * _Read only_. Use `Body.setVelocity` to set. 
8261     * 
8262     * See `Body.getVelocity` for details.
8263     * 
8264     * Equivalent to the magnitude of `body.angularVelocity` (always positive).
8265     * 
8266     * @readOnly
8267     * @property velocity
8268     * @type vector
8269     * @default { x: 0, y: 0 }
8270     */
8271
8272    /**
8273     * _Read only_. Use `Body.setAngularSpeed` to set. 
8274     * 
8275     * See `Body.getAngularSpeed` for details.
8276     * 
8277     * 
8278     * @readOnly
8279     * @property angularSpeed
8280     * @type number
8281     * @default 0
8282     */
8283
8284    /**
8285     * _Read only_. Use `Body.setAngularVelocity` to set. 
8286     * 
8287     * See `Body.getAngularVelocity` for details.
8288     * 
8289     *
8290     * @readOnly
8291     * @property angularVelocity
8292     * @type number
8293     * @default 0
8294     */
8295
8296    /**
8297     * _Read only_. Use `Body.setStatic` to set. 
8298     * 
8299     * A flag that indicates whether a body is considered static. A static body can never change position or angle and is completely fixed.
8300     *
8301     * @readOnly
8302     * @property isStatic
8303     * @type boolean
8304     * @default false
8305     */
8306
8307    /**
8308     * A flag that indicates whether a body is a sensor. Sensor triggers collision events, but doesn't react with colliding body physically.
8309     *
8310     * @property isSensor
8311     * @type boolean
8312     * @default false
8313     */
8314
8315    /**
8316     * _Read only_. Use `Sleeping.set` to set. 
8317     * 
8318     * A flag that indicates whether the body is considered sleeping. A sleeping body acts similar to a static body, except it is only temporary and can be awoken.
8319     *
8320     * @readOnly
8321     * @property isSleeping
8322     * @type boolean
8323     * @default false
8324     */
8325
8326    /**
8327     * _Read only_. Calculated during engine update only when sleeping is enabled.
8328     * 
8329     * A `Number` that loosely measures the amount of movement a body currently has.
8330     *
8331     * Derived from `body.speed^2 + body.angularSpeed^2`. See `Sleeping.update`.
8332     * 
8333     * @readOnly
8334     * @property motion
8335     * @type number
8336     * @default 0
8337     */
8338
8339    /**
8340     * A `Number` that defines the length of time during which this body must have near-zero velocity before it is set as sleeping by the `Matter.Sleeping` module (if sleeping is enabled by the engine).
8341     * 
8342     * @property sleepThreshold
8343     * @type number
8344     * @default 60
8345     */
8346
8347    /**
8348     * _Read only_. Use `Body.setDensity` to set. 
8349     * 
8350     * A `Number` that defines the density of the body (mass per unit area).
8351     * 
8352     * Mass will also be updated when set.
8353     *
8354     * @readOnly
8355     * @property density
8356     * @type number
8357     * @default 0.001
8358     */
8359
8360    /**
8361     * _Read only_. Use `Body.setMass` to set. 
8362     * 
8363     * A `Number` that defines the mass of the body.
8364     * 
8365     * Density will also be updated when set.
8366     * 
8367     * @readOnly
8368     * @property mass
8369     * @type number
8370     */
8371
8372    /**
8373     * _Read only_. Use `Body.setMass` to set. 
8374     * 
8375     * A `Number` that defines the inverse mass of the body (`1 / mass`).
8376     *
8377     * @readOnly
8378     * @property inverseMass
8379     * @type number
8380     */
8381
8382    /**
8383     * _Read only_. Automatically calculated when vertices, mass or density are set or set through `Body.setInertia`.
8384     * 
8385     * A `Number` that defines the moment of inertia of the body. This is the second moment of area in two dimensions.
8386     * 
8387     * Can be manually set to `Infinity` to prevent rotation of the body. See `Body.setInertia`.
8388     * 
8389     * @readOnly
8390     * @property inertia
8391     * @type number
8392     */
8393
8394    /**
8395     * _Read only_. Automatically calculated when vertices, mass or density are set or calculated by `Body.setInertia`.
8396     * 
8397     * A `Number` that defines the inverse moment of inertia of the body (`1 / inertia`).
8398     * 
8399     * @readOnly
8400     * @property inverseInertia
8401     * @type number
8402     */
8403
8404    /**
8405     * A `Number` that defines the restitution (elasticity) of the body. The value is always positive and is in the range `(0, 1)`.
8406     * A value of `0` means collisions may be perfectly inelastic and no bouncing may occur. 
8407     * A value of `0.8` means the body may bounce back with approximately 80% of its kinetic energy.
8408     * Note that collision response is based on _pairs_ of bodies, and that `restitution` values are _combined_ with the following formula:
8409     *
8410     * `Math.max(bodyA.restitution, bodyB.restitution)`
8411     *
8412     * @property restitution
8413     * @type number
8414     * @default 0
8415     */
8416
8417    /**
8418     * A `Number` that defines the friction of the body. The value is always positive and is in the range `(0, 1)`.
8419     * A value of `0` means that the body may slide indefinitely.
8420     * A value of `1` means the body may come to a stop almost instantly after a force is applied.
8421     *
8422     * The effects of the value may be non-linear. 
8423     * High values may be unstable depending on the body.
8424     * The engine uses a Coulomb friction model including static and kinetic friction.
8425     * Note that collision response is based on _pairs_ of bodies, and that `friction` values are _combined_ with the following formula:
8426     *
8427     * `Math.min(bodyA.friction, bodyB.friction)`
8428     *
8429     * @property friction
8430     * @type number
8431     * @default 0.1
8432     */
8433
8434    /**
8435     * A `Number` that defines the static friction of the body (in the Coulomb friction model). 
8436     * A value of `0` means the body will never 'stick' when it is nearly stationary and only dynamic `friction` is used.
8437     * The higher the value (e.g. `10`), the more force it will take to initially get the body moving when nearly stationary.
8438     * This value is multiplied with the `friction` property to make it easier to change `friction` and maintain an appropriate amount of static friction.
8439     *
8440     * @property frictionStatic
8441     * @type number
8442     * @default 0.5
8443     */
8444
8445    /**
8446     * A `Number` that defines the air friction of the body (air resistance). 
8447     * A value of `0` means the body will never slow as it moves through space.
8448     * The higher the value, the faster a body slows when moving through space.
8449     * The effects of the value are non-linear. 
8450     *
8451     * @property frictionAir
8452     * @type number
8453     * @default 0.01
8454     */
8455
8456    /**
8457     * An `Object` that specifies the collision filtering properties of this body.
8458     *
8459     * Collisions between two bodies will obey the following rules:
8460     * - If the two bodies have the same non-zero value of `collisionFilter.group`,
8461     *   they will always collide if the value is positive, and they will never collide
8462     *   if the value is negative.
8463     * - If the two bodies have different values of `collisionFilter.group` or if one
8464     *   (or both) of the bodies has a value of 0, then the category/mask rules apply as follows:
8465     *
8466     * Each body belongs to a collision category, given by `collisionFilter.category`. This
8467     * value is used as a bit field and the category should have only one bit set, meaning that
8468     * the value of this property is a power of two in the range [1, 2^31]. Thus, there are 32
8469     * different collision categories available.
8470     *
8471     * Each body also defines a collision bitmask, given by `collisionFilter.mask` which specifies
8472     * the categories it collides with (the value is the bitwise AND value of all these categories).
8473     *
8474     * Using the category/mask rules, two bodies `A` and `B` collide if each includes the other's
8475     * category in its mask, i.e. `(categoryA & maskB) !== 0` and `(categoryB & maskA) !== 0`
8476     * are both true.
8477     *
8478     * @property collisionFilter
8479     * @type object
8480     */
8481
8482    /**
8483     * An Integer `Number`, that specifies the collision group this body belongs to.
8484     * See `body.collisionFilter` for more information.
8485     *
8486     * @property collisionFilter.group
8487     * @type object
8488     * @default 0
8489     */
8490
8491    /**
8492     * A bit field that specifies the collision category this body belongs to.
8493     * The category value should have only one bit set, for example `0x0001`.
8494     * This means there are up to 32 unique collision categories available.
8495     * See `body.collisionFilter` for more information.
8496     *
8497     * @property collisionFilter.category
8498     * @type object
8499     * @default 1
8500     */
8501
8502    /**
8503     * A bit mask that specifies the collision categories this body may collide with.
8504     * See `body.collisionFilter` for more information.
8505     *
8506     * @property collisionFilter.mask
8507     * @type object
8508     * @default -1
8509     */
8510
8511    /**
8512     * A `Number` that specifies a thin boundary around the body where it is allowed to slightly sink into other bodies.
8513     * 
8514     * This is required for proper collision response, including friction and restitution effects.
8515     * 
8516     * The default should generally suffice in most cases. You may need to decrease this value for very small bodies that are nearing the default value in scale.
8517     *
8518     * @property slop
8519     * @type number
8520     * @default 0.05
8521     */
8522
8523    /**
8524     * A `Number` that specifies per-body time scaling.
8525     *
8526     * @property timeScale
8527     * @type number
8528     * @default 1
8529     */
8530
8531    /**
8532     * _Read only_. Updated during engine update.
8533     * 
8534     * A `Number` that records the last delta time value used to update this body.
8535     * Used to calculate speed and velocity.
8536     *
8537     * @readOnly
8538     * @property deltaTime
8539     * @type number
8540     * @default 1000 / 60
8541     */
8542
8543    /**
8544     * An `Object` that defines the rendering properties to be consumed by the module `Matter.Render`.
8545     *
8546     * @property render
8547     * @type object
8548     */
8549
8550    /**
8551     * A flag that indicates if the body should be rendered.
8552     *
8553     * @property render.visible
8554     * @type boolean
8555     * @default true
8556     */
8557
8558    /**
8559     * Sets the opacity to use when rendering.
8560     *
8561     * @property render.opacity
8562     * @type number
8563     * @default 1
8564    */
8565
8566    /**
8567     * An `Object` that defines the sprite properties to use when rendering, if any.
8568     *
8569     * @property render.sprite
8570     * @type object
8571     */
8572
8573    /**
8574     * An `String` that defines the path to the image to use as the sprite texture, if any.
8575     *
8576     * @property render.sprite.texture
8577     * @type string
8578     */
8579     
8580    /**
8581     * A `Number` that defines the scaling in the x-axis for the sprite, if any.
8582     *
8583     * @property render.sprite.xScale
8584     * @type number
8585     * @default 1
8586     */
8587
8588    /**
8589     * A `Number` that defines the scaling in the y-axis for the sprite, if any.
8590     *
8591     * @property render.sprite.yScale
8592     * @type number
8593     * @default 1
8594     */
8595
8596    /**
8597      * A `Number` that defines the offset in the x-axis for the sprite (normalised by texture width).
8598      *
8599      * @property render.sprite.xOffset
8600      * @type number
8601      * @default 0
8602      */
8603
8604    /**
8605      * A `Number` that defines the offset in the y-axis for the sprite (normalised by texture height).
8606      *
8607      * @property render.sprite.yOffset
8608      * @type number
8609      * @default 0
8610      */
8611
8612    /**
8613     * A `Number` that defines the line width to use when rendering the body outline (if a sprite is not defined).
8614     * A value of `0` means no outline will be rendered.
8615     *
8616     * @property render.lineWidth
8617     * @type number
8618     * @default 0
8619     */
8620
8621    /**
8622     * A `String` that defines the fill style to use when rendering the body (if a sprite is not defined).
8623     * It is the same as when using a canvas, so it accepts CSS style property values.
8624     *
8625     * @property render.fillStyle
8626     * @type string
8627     * @default a random colour
8628     */
8629
8630    /**
8631     * A `String` that defines the stroke style to use when rendering the body outline (if a sprite is not defined).
8632     * It is the same as when using a canvas, so it accepts CSS style property values.
8633     *
8634     * @property render.strokeStyle
8635     * @type string
8636     * @default a random colour
8637     */
8638
8639    /**
8640     * _Read only_. Calculated automatically when vertices are set.
8641     * 
8642     * An array of unique axis vectors (edge normals) used for collision detection.
8643     * These are automatically calculated when vertices are set.
8644     * They are constantly updated by `Body.update` during the simulation.
8645     *
8646     * @readOnly
8647     * @property axes
8648     * @type vector[]
8649     */
8650     
8651    /**
8652     * _Read only_. Calculated automatically when vertices are set.
8653     * 
8654     * A `Number` that measures the area of the body's convex hull.
8655     * 
8656     * @readOnly
8657     * @property area
8658     * @type string
8659     * @default 
8660     */
8661
8662    /**
8663     * A `Bounds` object that defines the AABB region for the body.
8664     * It is automatically calculated when vertices are set and constantly updated by `Body.update` during simulation.
8665     * 
8666     * @property bounds
8667     * @type bounds
8668     */
8669
8670    /**
8671     * Temporarily may hold parameters to be passed to `Vertices.chamfer` where supported by external functions.
8672     * 
8673     * See `Vertices.chamfer` for possible parameters this object may hold.
8674     * 
8675     * Currently only functions inside `Matter.Bodies` provide a utility using this property as a vertices pre-processing option.
8676     * 
8677     * Alternatively consider using `Vertices.chamfer` directly on vertices before passing them to a body creation function.
8678     * 
8679     * @property chamfer
8680     * @type object|null|undefined
8681     */
8682
8683})();
8684
8685
8686/***/ }),
8687/* 5 */
8688/***/ (function(module, exports, __webpack_require__) {
8689
8690/**
8691* The `Matter.Events` module contains methods to fire and listen to events on other objects.
8692*
8693* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples).
8694*
8695* @class Events
8696*/
8697
8698var Events = {};
8699
8700module.exports = Events;
8701
8702var Common = __webpack_require__(0);
8703
8704(function() {
8705
8706    /**
8707     * Subscribes a callback function to the given object's `eventName`.
8708     * @method on
8709     * @param {} object
8710     * @param {string} eventNames
8711     * @param {function} callback
8712     */
8713    Events.on = function(object, eventNames, callback) {
8714        var names = eventNames.split(' '),
8715            name;
8716
8717        for (var i = 0; i < names.length; i++) {
8718            name = names[i];
8719            object.events = object.events || {};
8720            object.events[name] = object.events[name] || [];
8721            object.events[name].push(callback);
8722        }
8723
8724        return callback;
8725    };
8726
8727    /**
8728     * Removes the given event callback. If no callback, clears all callbacks in `eventNames`. If no `eventNames`, clears all events.
8729     * @method off
8730     * @param {} object
8731     * @param {string} eventNames
8732     * @param {function} callback
8733     */
8734    Events.off = function(object, eventNames, callback) {
8735        if (!eventNames) {
8736            object.events = {};
8737            return;
8738        }
8739
8740        // handle Events.off(object, callback)
8741        if (typeof eventNames === 'function') {
8742            callback = eventNames;
8743            eventNames = Common.keys(object.events).join(' ');
8744        }
8745
8746        var names = eventNames.split(' ');
8747
8748        for (var i = 0; i < names.length; i++) {
8749            var callbacks = object.events[names[i]],
8750                newCallbacks = [];
8751
8752            if (callback && callbacks) {
8753                for (var j = 0; j < callbacks.length; j++) {
8754                    if (callbacks[j] !== callback)
8755                        newCallbacks.push(callbacks[j]);
8756                }
8757            }
8758
8759            object.events[names[i]] = newCallbacks;
8760        }
8761    };
8762
8763    /**
8764     * Fires all the callbacks subscribed to the given object's `eventName`, in the order they subscribed, if any.
8765     * @method trigger
8766     * @param {} object
8767     * @param {string} eventNames
8768     * @param {} event
8769     */
8770    Events.trigger = function(object, eventNames, event) {
8771        var names,
8772            name,
8773            callbacks,
8774            eventClone;
8775
8776        var events = object.events;
8777        
8778        if (events && Common.keys(events).length > 0) {
8779            if (!event)
8780                event = {};
8781
8782            names = eventNames.split(' ');
8783
8784            for (var i = 0; i < names.length; i++) {
8785                name = names[i];
8786                callbacks = events[name];
8787
8788                if (callbacks) {
8789                    eventClone = Common.clone(event, false);
8790                    eventClone.name = name;
8791                    eventClone.source = object;
8792
8793                    for (var j = 0; j < callbacks.length; j++) {
8794                        callbacks[j].apply(object, [eventClone]);
8795                    }
8796                }
8797            }
8798        }
8799    };
8800
8801})();
8802
8803
8804/***/ }),
8805/* 6 */
8806/***/ (function(module, exports, __webpack_require__) {
8807
8808/**
8809* A composite is a collection of `Matter.Body`, `Matter.Constraint` and other `Matter.Composite` objects.
8810*
8811* They are a container that can represent complex objects made of multiple parts, even if they are not physically connected.
8812* A composite could contain anything from a single body all the way up to a whole world.
8813* 
8814* When making any changes to composites, use the included functions rather than changing their properties directly.
8815*
8816* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples).
8817*
8818* @class Composite
8819*/
8820
8821var Composite = {};
8822
8823module.exports = Composite;
8824
8825var Events = __webpack_require__(5);
8826var Common = __webpack_require__(0);
8827var Bounds = __webpack_require__(1);
8828var Body = __webpack_require__(4);
8829
8830(function() {
8831
8832    /**
8833     * Creates a new composite. The options parameter is an object that specifies any properties you wish to override the defaults.
8834     * See the properites section below for detailed information on what you can pass via the `options` object.
8835     * @method create
8836     * @param {} [options]
8837     * @return {composite} A new composite
8838     */
8839    Composite.create = function(options) {
8840        return Common.extend({ 
8841            id: Common.nextId(),
8842            type: 'composite',
8843            parent: null,
8844            isModified: false,
8845            bodies: [], 
8846            constraints: [], 
8847            composites: [],
8848            label: 'Composite',
8849            plugin: {},
8850            cache: {
8851                allBodies: null,
8852                allConstraints: null,
8853                allComposites: null
8854            }
8855        }, options);
8856    };
8857
8858    /**
8859     * Sets the composite's `isModified` flag. 
8860     * If `updateParents` is true, all parents will be set (default: false).
8861     * If `updateChildren` is true, all children will be set (default: false).
8862     * @private
8863     * @method setModified
8864     * @param {composite} composite
8865     * @param {boolean} isModified
8866     * @param {boolean} [updateParents=false]
8867     * @param {boolean} [updateChildren=false]
8868     */
8869    Composite.setModified = function(composite, isModified, updateParents, updateChildren) {
8870        composite.isModified = isModified;
8871
8872        if (isModified && composite.cache) {
8873            composite.cache.allBodies = null;
8874            composite.cache.allConstraints = null;
8875            composite.cache.allComposites = null;
8876        }
8877
8878        if (updateParents && composite.parent) {
8879            Composite.setModified(composite.parent, isModified, updateParents, updateChildren);
8880        }
8881
8882        if (updateChildren) {
8883            for (var i = 0; i < composite.composites.length; i++) {
8884                var childComposite = composite.composites[i];
8885                Composite.setModified(childComposite, isModified, updateParents, updateChildren);
8886            }
8887        }
8888    };
8889
8890    /**
8891     * Generic single or multi-add function. Adds a single or an array of body(s), constraint(s) or composite(s) to the given composite.
8892     * Triggers `beforeAdd` and `afterAdd` events on the `composite`.
8893     * @method add
8894     * @param {composite} composite
8895     * @param {object|array} object A single or an array of body(s), constraint(s) or composite(s)
8896     * @return {composite} The original composite with the objects added
8897     */
8898    Composite.add = function(composite, object) {
8899        var objects = [].concat(object);
8900
8901        Events.trigger(composite, 'beforeAdd', { object: object });
8902
8903        for (var i = 0; i < objects.length; i++) {
8904            var obj = objects[i];
8905
8906            switch (obj.type) {
8907
8908            case 'body':
8909                // skip adding compound parts
8910                if (obj.parent !== obj) {
8911                    Common.warn('Composite.add: skipped adding a compound body part (you must add its parent instead)');
8912                    break;
8913                }
8914
8915                Composite.addBody(composite, obj);
8916                break;
8917            case 'constraint':
8918                Composite.addConstraint(composite, obj);
8919                break;
8920            case 'composite':
8921                Composite.addComposite(composite, obj);
8922                break;
8923            case 'mouseConstraint':
8924                Composite.addConstraint(composite, obj.constraint);
8925                break;
8926
8927            }
8928        }
8929
8930        Events.trigger(composite, 'afterAdd', { object: object });
8931
8932        return composite;
8933    };
8934
8935    /**
8936     * Generic remove function. Removes one or many body(s), constraint(s) or a composite(s) to the given composite.
8937     * Optionally searching its children recursively.
8938     * Triggers `beforeRemove` and `afterRemove` events on the `composite`.
8939     * @method remove
8940     * @param {composite} composite
8941     * @param {object|array} object
8942     * @param {boolean} [deep=false]
8943     * @return {composite} The original composite with the objects removed
8944     */
8945    Composite.remove = function(composite, object, deep) {
8946        var objects = [].concat(object);
8947
8948        Events.trigger(composite, 'beforeRemove', { object: object });
8949
8950        for (var i = 0; i < objects.length; i++) {
8951            var obj = objects[i];
8952
8953            switch (obj.type) {
8954
8955            case 'body':
8956                Composite.removeBody(composite, obj, deep);
8957                break;
8958            case 'constraint':
8959                Composite.removeConstraint(composite, obj, deep);
8960                break;
8961            case 'composite':
8962                Composite.removeComposite(composite, obj, deep);
8963                break;
8964            case 'mouseConstraint':
8965                Composite.removeConstraint(composite, obj.constraint);
8966                break;
8967
8968            }
8969        }
8970
8971        Events.trigger(composite, 'afterRemove', { object: object });
8972
8973        return composite;
8974    };
8975
8976    /**
8977     * Adds a composite to the given composite.
8978     * @private
8979     * @method addComposite
8980     * @param {composite} compositeA
8981     * @param {composite} compositeB
8982     * @return {composite} The original compositeA with the objects from compositeB added
8983     */
8984    Composite.addComposite = function(compositeA, compositeB) {
8985        compositeA.composites.push(compositeB);
8986        compositeB.parent = compositeA;
8987        Composite.setModified(compositeA, true, true, false);
8988        return compositeA;
8989    };
8990
8991    /**
8992     * Removes a composite from the given composite, and optionally searching its children recursively.
8993     * @private
8994     * @method removeComposite
8995     * @param {composite} compositeA
8996     * @param {composite} compositeB
8997     * @param {boolean} [deep=false]
8998     * @return {composite} The original compositeA with the composite removed
8999     */
9000    Composite.removeComposite = function(compositeA, compositeB, deep) {
9001        var position = Common.indexOf(compositeA.composites, compositeB);
9002
9003        if (position !== -1) {
9004            var bodies = Composite.allBodies(compositeB);
9005
9006            Composite.removeCompositeAt(compositeA, position);
9007
9008            for (var i = 0; i < bodies.length; i++) {
9009                bodies[i].sleepCounter = 0;
9010            }
9011        }
9012
9013        if (deep) {
9014            for (var i = 0; i < compositeA.composites.length; i++){
9015                Composite.removeComposite(compositeA.composites[i], compositeB, true);
9016            }
9017        }
9018
9019        return compositeA;
9020    };
9021
9022    /**
9023     * Removes a composite from the given composite.
9024     * @private
9025     * @method removeCompositeAt
9026     * @param {composite} composite
9027     * @param {number} position
9028     * @return {composite} The original composite with the composite removed
9029     */
9030    Composite.removeCompositeAt = function(composite, position) {
9031        composite.composites.splice(position, 1);
9032        Composite.setModified(composite, true, true, false);
9033        return composite;
9034    };
9035
9036    /**
9037     * Adds a body to the given composite.
9038     * @private
9039     * @method addBody
9040     * @param {composite} composite
9041     * @param {body} body
9042     * @return {composite} The original composite with the body added
9043     */
9044    Composite.addBody = function(composite, body) {
9045        composite.bodies.push(body);
9046        Composite.setModified(composite, true, true, false);
9047        return composite;
9048    };
9049
9050    /**
9051     * Removes a body from the given composite, and optionally searching its children recursively.
9052     * @private
9053     * @method removeBody
9054     * @param {composite} composite
9055     * @param {body} body
9056     * @param {boolean} [deep=false]
9057     * @return {composite} The original composite with the body removed
9058     */
9059    Composite.removeBody = function(composite, body, deep) {
9060        var position = Common.indexOf(composite.bodies, body);
9061
9062        if (position !== -1) {
9063            Composite.removeBodyAt(composite, position);
9064            body.sleepCounter = 0;
9065        }
9066
9067        if (deep) {
9068            for (var i = 0; i < composite.composites.length; i++){
9069                Composite.removeBody(composite.composites[i], body, true);
9070            }
9071        }
9072
9073        return composite;
9074    };
9075
9076    /**
9077     * Removes a body from the given composite.
9078     * @private
9079     * @method removeBodyAt
9080     * @param {composite} composite
9081     * @param {number} position
9082     * @return {composite} The original composite with the body removed
9083     */
9084    Composite.removeBodyAt = function(composite, position) {
9085        composite.bodies.splice(position, 1);
9086        Composite.setModified(composite, true, true, false);
9087        return composite;
9088    };
9089
9090    /**
9091     * Adds a constraint to the given composite.
9092     * @private
9093     * @method addConstraint
9094     * @param {composite} composite
9095     * @param {constraint} constraint
9096     * @return {composite} The original composite with the constraint added
9097     */
9098    Composite.addConstraint = function(composite, constraint) {
9099        composite.constraints.push(constraint);
9100        Composite.setModified(composite, true, true, false);
9101        return composite;
9102    };
9103
9104    /**
9105     * Removes a constraint from the given composite, and optionally searching its children recursively.
9106     * @private
9107     * @method removeConstraint
9108     * @param {composite} composite
9109     * @param {constraint} constraint
9110     * @param {boolean} [deep=false]
9111     * @return {composite} The original composite with the constraint removed
9112     */
9113    Composite.removeConstraint = function(composite, constraint, deep) {
9114        var position = Common.indexOf(composite.constraints, constraint);
9115        
9116        if (position !== -1) {
9117            Composite.removeConstraintAt(composite, position);
9118        }
9119
9120        if (deep) {
9121            for (var i = 0; i < composite.composites.length; i++){
9122                Composite.removeConstraint(composite.composites[i], constraint, true);
9123            }
9124        }
9125
9126        return composite;
9127    };
9128
9129    /**
9130     * Removes a body from the given composite.
9131     * @private
9132     * @method removeConstraintAt
9133     * @param {composite} composite
9134     * @param {number} position
9135     * @return {composite} The original composite with the constraint removed
9136     */
9137    Composite.removeConstraintAt = function(composite, position) {
9138        composite.constraints.splice(position, 1);
9139        Composite.setModified(composite, true, true, false);
9140        return composite;
9141    };
9142
9143    /**
9144     * Removes all bodies, constraints and composites from the given composite.
9145     * Optionally clearing its children recursively.
9146     * @method clear
9147     * @param {composite} composite
9148     * @param {boolean} keepStatic
9149     * @param {boolean} [deep=false]
9150     */
9151    Composite.clear = function(composite, keepStatic, deep) {
9152        if (deep) {
9153            for (var i = 0; i < composite.composites.length; i++){
9154                Composite.clear(composite.composites[i], keepStatic, true);
9155            }
9156        }
9157        
9158        if (keepStatic) {
9159            composite.bodies = composite.bodies.filter(function(body) { return body.isStatic; });
9160        } else {
9161            composite.bodies.length = 0;
9162        }
9163
9164        composite.constraints.length = 0;
9165        composite.composites.length = 0;
9166
9167        Composite.setModified(composite, true, true, false);
9168
9169        return composite;
9170    };
9171
9172    /**
9173     * Returns all bodies in the given composite, including all bodies in its children, recursively.
9174     * @method allBodies
9175     * @param {composite} composite
9176     * @return {body[]} All the bodies
9177     */
9178    Composite.allBodies = function(composite) {
9179        if (composite.cache && composite.cache.allBodies) {
9180            return composite.cache.allBodies;
9181        }
9182
9183        var bodies = [].concat(composite.bodies);
9184
9185        for (var i = 0; i < composite.composites.length; i++)
9186            bodies = bodies.concat(Composite.allBodies(composite.composites[i]));
9187
9188        if (composite.cache) {
9189            composite.cache.allBodies = bodies;
9190        }
9191
9192        return bodies;
9193    };
9194
9195    /**
9196     * Returns all constraints in the given composite, including all constraints in its children, recursively.
9197     * @method allConstraints
9198     * @param {composite} composite
9199     * @return {constraint[]} All the constraints
9200     */
9201    Composite.allConstraints = function(composite) {
9202        if (composite.cache && composite.cache.allConstraints) {
9203            return composite.cache.allConstraints;
9204        }
9205
9206        var constraints = [].concat(composite.constraints);
9207
9208        for (var i = 0; i < composite.composites.length; i++)
9209            constraints = constraints.concat(Composite.allConstraints(composite.composites[i]));
9210
9211        if (composite.cache) {
9212            composite.cache.allConstraints = constraints;
9213        }
9214
9215        return constraints;
9216    };
9217
9218    /**
9219     * Returns all composites in the given composite, including all composites in its children, recursively.
9220     * @method allComposites
9221     * @param {composite} composite
9222     * @return {composite[]} All the composites
9223     */
9224    Composite.allComposites = function(composite) {
9225        if (composite.cache && composite.cache.allComposites) {
9226            return composite.cache.allComposites;
9227        }
9228
9229        var composites = [].concat(composite.composites);
9230
9231        for (var i = 0; i < composite.composites.length; i++)
9232            composites = composites.concat(Composite.allComposites(composite.composites[i]));
9233
9234        if (composite.cache) {
9235            composite.cache.allComposites = composites;
9236        }
9237
9238        return composites;
9239    };
9240
9241    /**
9242     * Searches the composite recursively for an object matching the type and id supplied, null if not found.
9243     * @method get
9244     * @param {composite} composite
9245     * @param {number} id
9246     * @param {string} type
9247     * @return {object} The requested object, if found
9248     */
9249    Composite.get = function(composite, id, type) {
9250        var objects,
9251            object;
9252
9253        switch (type) {
9254        case 'body':
9255            objects = Composite.allBodies(composite);
9256            break;
9257        case 'constraint':
9258            objects = Composite.allConstraints(composite);
9259            break;
9260        case 'composite':
9261            objects = Composite.allComposites(composite).concat(composite);
9262            break;
9263        }
9264
9265        if (!objects)
9266            return null;
9267
9268        object = objects.filter(function(object) { 
9269            return object.id.toString() === id.toString(); 
9270        });
9271
9272        return object.length === 0 ? null : object[0];
9273    };
9274
9275    /**
9276     * Moves the given object(s) from compositeA to compositeB (equal to a remove followed by an add).
9277     * @method move
9278     * @param {compositeA} compositeA
9279     * @param {object[]} objects
9280     * @param {compositeB} compositeB
9281     * @return {composite} Returns compositeA
9282     */
9283    Composite.move = function(compositeA, objects, compositeB) {
9284        Composite.remove(compositeA, objects);
9285        Composite.add(compositeB, objects);
9286        return compositeA;
9287    };
9288
9289    /**
9290     * Assigns new ids for all objects in the composite, recursively.
9291     * @method rebase
9292     * @param {composite} composite
9293     * @return {composite} Returns composite
9294     */
9295    Composite.rebase = function(composite) {
9296        var objects = Composite.allBodies(composite)
9297            .concat(Composite.allConstraints(composite))
9298            .concat(Composite.allComposites(composite));
9299
9300        for (var i = 0; i < objects.length; i++) {
9301            objects[i].id = Common.nextId();
9302        }
9303
9304        return composite;
9305    };
9306
9307    /**
9308     * Translates all children in the composite by a given vector relative to their current positions, 
9309     * without imparting any velocity.
9310     * @method translate
9311     * @param {composite} composite
9312     * @param {vector} translation
9313     * @param {bool} [recursive=true]
9314     */
9315    Composite.translate = function(composite, translation, recursive) {
9316        var bodies = recursive ? Composite.allBodies(composite) : composite.bodies;
9317
9318        for (var i = 0; i < bodies.length; i++) {
9319            Body.translate(bodies[i], translation);
9320        }
9321
9322        return composite;
9323    };
9324
9325    /**
9326     * Rotates all children in the composite by a given angle about the given point, without imparting any angular velocity.
9327     * @method rotate
9328     * @param {composite} composite
9329     * @param {number} rotation
9330     * @param {vector} point
9331     * @param {bool} [recursive=true]
9332     */
9333    Composite.rotate = function(composite, rotation, point, recursive) {
9334        var cos = Math.cos(rotation),
9335            sin = Math.sin(rotation),
9336            bodies = recursive ? Composite.allBodies(composite) : composite.bodies;
9337
9338        for (var i = 0; i < bodies.length; i++) {
9339            var body = bodies[i],
9340                dx = body.position.x - point.x,
9341                dy = body.position.y - point.y;
9342                
9343            Body.setPosition(body, {
9344                x: point.x + (dx * cos - dy * sin),
9345                y: point.y + (dx * sin + dy * cos)
9346            });
9347
9348            Body.rotate(body, rotation);
9349        }
9350
9351        return composite;
9352    };
9353
9354    /**
9355     * Scales all children in the composite, including updating physical properties (mass, area, axes, inertia), from a world-space point.
9356     * @method scale
9357     * @param {composite} composite
9358     * @param {number} scaleX
9359     * @param {number} scaleY
9360     * @param {vector} point
9361     * @param {bool} [recursive=true]
9362     */
9363    Composite.scale = function(composite, scaleX, scaleY, point, recursive) {
9364        var bodies = recursive ? Composite.allBodies(composite) : composite.bodies;
9365
9366        for (var i = 0; i < bodies.length; i++) {
9367            var body = bodies[i],
9368                dx = body.position.x - point.x,
9369                dy = body.position.y - point.y;
9370                
9371            Body.setPosition(body, {
9372                x: point.x + dx * scaleX,
9373                y: point.y + dy * scaleY
9374            });
9375
9376            Body.scale(body, scaleX, scaleY);
9377        }
9378
9379        return composite;
9380    };
9381
9382    /**
9383     * Returns the union of the bounds of all of the composite's bodies.
9384     * @method bounds
9385     * @param {composite} composite The composite.
9386     * @returns {bounds} The composite bounds.
9387     */
9388    Composite.bounds = function(composite) {
9389        var bodies = Composite.allBodies(composite),
9390            vertices = [];
9391
9392        for (var i = 0; i < bodies.length; i += 1) {
9393            var body = bodies[i];
9394            vertices.push(body.bounds.min, body.bounds.max);
9395        }
9396
9397        return Bounds.create(vertices);
9398    };
9399
9400    /*
9401    *
9402    *  Events Documentation
9403    *
9404    */
9405
9406    /**
9407    * Fired when a call to `Composite.add` is made, before objects have been added.
9408    *
9409    * @event beforeAdd
9410    * @param {} event An event object
9411    * @param {} event.object The object(s) to be added (may be a single body, constraint, composite or a mixed array of these)
9412    * @param {} event.source The source object of the event
9413    * @param {} event.name The name of the event
9414    */
9415
9416    /**
9417    * Fired when a call to `Composite.add` is made, after objects have been added.
9418    *
9419    * @event afterAdd
9420    * @param {} event An event object
9421    * @param {} event.object The object(s) that have been added (may be a single body, constraint, composite or a mixed array of these)
9422    * @param {} event.source The source object of the event
9423    * @param {} event.name The name of the event
9424    */
9425
9426    /**
9427    * Fired when a call to `Composite.remove` is made, before objects have been removed.
9428    *
9429    * @event beforeRemove
9430    * @param {} event An event object
9431    * @param {} event.object The object(s) to be removed (may be a single body, constraint, composite or a mixed array of these)
9432    * @param {} event.source The source object of the event
9433    * @param {} event.name The name of the event
9434    */
9435
9436    /**
9437    * Fired when a call to `Composite.remove` is made, after objects have been removed.
9438    *
9439    * @event afterRemove
9440    * @param {} event An event object
9441    * @param {} event.object The object(s) that have been removed (may be a single body, constraint, composite or a mixed array of these)
9442    * @param {} event.source The source object of the event
9443    * @param {} event.name The name of the event
9444    */
9445
9446    /*
9447    *
9448    *  Properties Documentation
9449    *
9450    */
9451
9452    /**
9453     * An integer `Number` uniquely identifying number generated in `Composite.create` by `Common.nextId`.
9454     *
9455     * @property id
9456     * @type number
9457     */
9458
9459    /**
9460     * A `String` denoting the type of object.
9461     *
9462     * @property type
9463     * @type string
9464     * @default "composite"
9465     * @readOnly
9466     */
9467
9468    /**
9469     * An arbitrary `String` name to help the user identify and manage composites.
9470     *
9471     * @property label
9472     * @type string
9473     * @default "Composite"
9474     */
9475
9476    /**
9477     * A flag that specifies whether the composite has been modified during the current step.
9478     * This is automatically managed when bodies, constraints or composites are added or removed.
9479     *
9480     * @property isModified
9481     * @type boolean
9482     * @default false
9483     */
9484
9485    /**
9486     * The `Composite` that is the parent of this composite. It is automatically managed by the `Matter.Composite` methods.
9487     *
9488     * @property parent
9489     * @type composite
9490     * @default null
9491     */
9492
9493    /**
9494     * An array of `Body` that are _direct_ children of this composite.
9495     * To add or remove bodies you should use `Composite.add` and `Composite.remove` methods rather than directly modifying this property.
9496     * If you wish to recursively find all descendants, you should use the `Composite.allBodies` method.
9497     *
9498     * @property bodies
9499     * @type body[]
9500     * @default []
9501     */
9502
9503    /**
9504     * An array of `Constraint` that are _direct_ children of this composite.
9505     * To add or remove constraints you should use `Composite.add` and `Composite.remove` methods rather than directly modifying this property.
9506     * If you wish to recursively find all descendants, you should use the `Composite.allConstraints` method.
9507     *
9508     * @property constraints
9509     * @type constraint[]
9510     * @default []
9511     */
9512
9513    /**
9514     * An array of `Composite` that are _direct_ children of this composite.
9515     * To add or remove composites you should use `Composite.add` and `Composite.remove` methods rather than directly modifying this property.
9516     * If you wish to recursively find all descendants, you should use the `Composite.allComposites` method.
9517     *
9518     * @property composites
9519     * @type composite[]
9520     * @default []
9521     */
9522
9523    /**
9524     * An object reserved for storing plugin-specific properties.
9525     *
9526     * @property plugin
9527     * @type {}
9528     */
9529
9530    /**
9531     * An object used for storing cached results for performance reasons.
9532     * This is used internally only and is automatically managed.
9533     *
9534     * @private
9535     * @property cache
9536     * @type {}
9537     */
9538
9539})();
9540
9541
9542/***/ }),
9543/* 7 */
9544/***/ (function(module, exports, __webpack_require__) {
9545
9546/**
9547* The `Matter.Sleeping` module contains methods to manage the sleeping state of bodies.
9548*
9549* @class Sleeping
9550*/
9551
9552var Sleeping = {};
9553
9554module.exports = Sleeping;
9555
9556var Body = __webpack_require__(4);
9557var Events = __webpack_require__(5);
9558var Common = __webpack_require__(0);
9559
9560(function() {
9561
9562    Sleeping._motionWakeThreshold = 0.18;
9563    Sleeping._motionSleepThreshold = 0.08;
9564    Sleeping._minBias = 0.9;
9565
9566    /**
9567     * Puts bodies to sleep or wakes them up depending on their motion.
9568     * @method update
9569     * @param {body[]} bodies
9570     * @param {number} delta
9571     */
9572    Sleeping.update = function(bodies, delta) {
9573        var timeScale = delta / Common._baseDelta,
9574            motionSleepThreshold = Sleeping._motionSleepThreshold;
9575        
9576        // update bodies sleeping status
9577        for (var i = 0; i < bodies.length; i++) {
9578            var body = bodies[i],
9579                speed = Body.getSpeed(body),
9580                angularSpeed = Body.getAngularSpeed(body),
9581                motion = speed * speed + angularSpeed * angularSpeed;
9582
9583            // wake up bodies if they have a force applied
9584            if (body.force.x !== 0 || body.force.y !== 0) {
9585                Sleeping.set(body, false);
9586                continue;
9587            }
9588
9589            var minMotion = Math.min(body.motion, motion),
9590                maxMotion = Math.max(body.motion, motion);
9591        
9592            // biased average motion estimation between frames
9593            body.motion = Sleeping._minBias * minMotion + (1 - Sleeping._minBias) * maxMotion;
9594
9595            if (body.sleepThreshold > 0 && body.motion < motionSleepThreshold) {
9596                body.sleepCounter += 1;
9597                
9598                if (body.sleepCounter >= body.sleepThreshold / timeScale) {
9599                    Sleeping.set(body, true);
9600                }
9601            } else if (body.sleepCounter > 0) {
9602                body.sleepCounter -= 1;
9603            }
9604        }
9605    };
9606
9607    /**
9608     * Given a set of colliding pairs, wakes the sleeping bodies involved.
9609     * @method afterCollisions
9610     * @param {pair[]} pairs
9611     */
9612    Sleeping.afterCollisions = function(pairs) {
9613        var motionSleepThreshold = Sleeping._motionSleepThreshold;
9614
9615        // wake up bodies involved in collisions
9616        for (var i = 0; i < pairs.length; i++) {
9617            var pair = pairs[i];
9618            
9619            // don't wake inactive pairs
9620            if (!pair.isActive)
9621                continue;
9622
9623            var collision = pair.collision,
9624                bodyA = collision.bodyA.parent, 
9625                bodyB = collision.bodyB.parent;
9626        
9627            // don't wake if at least one body is static
9628            if ((bodyA.isSleeping && bodyB.isSleeping) || bodyA.isStatic || bodyB.isStatic)
9629                continue;
9630        
9631            if (bodyA.isSleeping || bodyB.isSleeping) {
9632                var sleepingBody = (bodyA.isSleeping && !bodyA.isStatic) ? bodyA : bodyB,
9633                    movingBody = sleepingBody === bodyA ? bodyB : bodyA;
9634
9635                if (!sleepingBody.isStatic && movingBody.motion > motionSleepThreshold) {
9636                    Sleeping.set(sleepingBody, false);
9637                }
9638            }
9639        }
9640    };
9641  
9642    /**
9643     * Set a body as sleeping or awake.
9644     * @method set
9645     * @param {body} body
9646     * @param {boolean} isSleeping
9647     */
9648    Sleeping.set = function(body, isSleeping) {
9649        var wasSleeping = body.isSleeping;
9650
9651        if (isSleeping) {
9652            body.isSleeping = true;
9653            body.sleepCounter = body.sleepThreshold;
9654
9655            body.positionImpulse.x = 0;
9656            body.positionImpulse.y = 0;
9657
9658            body.positionPrev.x = body.position.x;
9659            body.positionPrev.y = body.position.y;
9660
9661            body.anglePrev = body.angle;
9662            body.speed = 0;
9663            body.angularSpeed = 0;
9664            body.motion = 0;
9665
9666            if (!wasSleeping) {
9667                Events.trigger(body, 'sleepStart');
9668            }
9669        } else {
9670            body.isSleeping = false;
9671            body.sleepCounter = 0;
9672
9673            if (wasSleeping) {
9674                Events.trigger(body, 'sleepEnd');
9675            }
9676        }
9677    };
9678
9679})();
9680
9681
9682/***/ }),
9683/* 8 */
9684/***/ (function(module, exports, __webpack_require__) {
9685
9686/**
9687* The `Matter.Collision` module contains methods for detecting collisions between a given pair of bodies.
9688*
9689* For efficient detection between a list of bodies, see `Matter.Detector` and `Matter.Query`.
9690*
9691* See `Matter.Engine` for collision events.
9692*
9693* @class Collision
9694*/
9695
9696var Collision = {};
9697
9698module.exports = Collision;
9699
9700var Vertices = __webpack_require__(3);
9701var Pair = __webpack_require__(9);
9702
9703(function() {
9704    var _supports = [];
9705
9706    var _overlapAB = {
9707        overlap: 0,
9708        axis: null
9709    };
9710
9711    var _overlapBA = {
9712        overlap: 0,
9713        axis: null
9714    };
9715
9716    /**
9717     * Creates a new collision record.
9718     * @method create
9719     * @param {body} bodyA The first body part represented by the collision record
9720     * @param {body} bodyB The second body part represented by the collision record
9721     * @return {collision} A new collision record
9722     */
9723    Collision.create = function(bodyA, bodyB) {
9724        return { 
9725            pair: null,
9726            collided: false,
9727            bodyA: bodyA,
9728            bodyB: bodyB,
9729            parentA: bodyA.parent,
9730            parentB: bodyB.parent,
9731            depth: 0,
9732            normal: { x: 0, y: 0 },
9733            tangent: { x: 0, y: 0 },
9734            penetration: { x: 0, y: 0 },
9735            supports: [null, null],
9736            supportCount: 0
9737        };
9738    };
9739
9740    /**
9741     * Detect collision between two bodies.
9742     * @method collides
9743     * @param {body} bodyA
9744     * @param {body} bodyB
9745     * @param {pairs} [pairs] Optionally reuse collision records from existing pairs.
9746     * @return {collision|null} A collision record if detected, otherwise null
9747     */
9748    Collision.collides = function(bodyA, bodyB, pairs) {
9749        Collision._overlapAxes(_overlapAB, bodyA.vertices, bodyB.vertices, bodyA.axes);
9750
9751        if (_overlapAB.overlap <= 0) {
9752            return null;
9753        }
9754
9755        Collision._overlapAxes(_overlapBA, bodyB.vertices, bodyA.vertices, bodyB.axes);
9756
9757        if (_overlapBA.overlap <= 0) {
9758            return null;
9759        }
9760
9761        // reuse collision records for gc efficiency
9762        var pair = pairs && pairs.table[Pair.id(bodyA, bodyB)],
9763            collision;
9764
9765        if (!pair) {
9766            collision = Collision.create(bodyA, bodyB);
9767            collision.collided = true;
9768            collision.bodyA = bodyA.id < bodyB.id ? bodyA : bodyB;
9769            collision.bodyB = bodyA.id < bodyB.id ? bodyB : bodyA;
9770            collision.parentA = collision.bodyA.parent;
9771            collision.parentB = collision.bodyB.parent;
9772        } else {
9773            collision = pair.collision;
9774        }
9775
9776        bodyA = collision.bodyA;
9777        bodyB = collision.bodyB;
9778
9779        var minOverlap;
9780
9781        if (_overlapAB.overlap < _overlapBA.overlap) {
9782            minOverlap = _overlapAB;
9783        } else {
9784            minOverlap = _overlapBA;
9785        }
9786
9787        var normal = collision.normal,
9788            tangent = collision.tangent,
9789            penetration = collision.penetration,
9790            supports = collision.supports,
9791            depth = minOverlap.overlap,
9792            minAxis = minOverlap.axis,
9793            normalX = minAxis.x,
9794            normalY = minAxis.y,
9795            deltaX = bodyB.position.x - bodyA.position.x,
9796            deltaY = bodyB.position.y - bodyA.position.y;
9797
9798        // ensure normal is facing away from bodyA
9799        if (normalX * deltaX + normalY * deltaY >= 0) {
9800            normalX = -normalX;
9801            normalY = -normalY;
9802        }
9803
9804        normal.x = normalX;
9805        normal.y = normalY;
9806        
9807        tangent.x = -normalY;
9808        tangent.y = normalX;
9809
9810        penetration.x = normalX * depth;
9811        penetration.y = normalY * depth;
9812
9813        collision.depth = depth;
9814
9815        // find support points, there is always either exactly one or two
9816        var supportsB = Collision._findSupports(bodyA, bodyB, normal, 1),
9817            supportCount = 0;
9818
9819        // find the supports from bodyB that are inside bodyA
9820        if (Vertices.contains(bodyA.vertices, supportsB[0])) {
9821            supports[supportCount++] = supportsB[0];
9822        }
9823
9824        if (Vertices.contains(bodyA.vertices, supportsB[1])) {
9825            supports[supportCount++] = supportsB[1];
9826        }
9827
9828        // find the supports from bodyA that are inside bodyB
9829        if (supportCount < 2) {
9830            var supportsA = Collision._findSupports(bodyB, bodyA, normal, -1);
9831
9832            if (Vertices.contains(bodyB.vertices, supportsA[0])) {
9833                supports[supportCount++] = supportsA[0];
9834            }
9835
9836            if (supportCount < 2 && Vertices.contains(bodyB.vertices, supportsA[1])) {
9837                supports[supportCount++] = supportsA[1];
9838            }
9839        }
9840
9841        // account for the edge case of overlapping but no vertex containment
9842        if (supportCount === 0) {
9843            supports[supportCount++] = supportsB[0];
9844        }
9845
9846        // update support count
9847        collision.supportCount = supportCount;
9848
9849        return collision;
9850    };
9851
9852    /**
9853     * Find the overlap between two sets of vertices.
9854     * @method _overlapAxes
9855     * @private
9856     * @param {object} result
9857     * @param {vertices} verticesA
9858     * @param {vertices} verticesB
9859     * @param {axes} axes
9860     */
9861    Collision._overlapAxes = function(result, verticesA, verticesB, axes) {
9862        var verticesALength = verticesA.length,
9863            verticesBLength = verticesB.length,
9864            verticesAX = verticesA[0].x,
9865            verticesAY = verticesA[0].y,
9866            verticesBX = verticesB[0].x,
9867            verticesBY = verticesB[0].y,
9868            axesLength = axes.length,
9869            overlapMin = Number.MAX_VALUE,
9870            overlapAxisNumber = 0,
9871            overlap,
9872            overlapAB,
9873            overlapBA,
9874            dot,
9875            i,
9876            j;
9877
9878        for (i = 0; i < axesLength; i++) {
9879            var axis = axes[i],
9880                axisX = axis.x,
9881                axisY = axis.y,
9882                minA = verticesAX * axisX + verticesAY * axisY,
9883                minB = verticesBX * axisX + verticesBY * axisY,
9884                maxA = minA,
9885                maxB = minB;
9886            
9887            for (j = 1; j < verticesALength; j += 1) {
9888                dot = verticesA[j].x * axisX + verticesA[j].y * axisY;
9889
9890                if (dot > maxA) { 
9891                    maxA = dot;
9892                } else if (dot < minA) { 
9893                    minA = dot;
9894                }
9895            }
9896
9897            for (j = 1; j < verticesBLength; j += 1) {
9898                dot = verticesB[j].x * axisX + verticesB[j].y * axisY;
9899
9900                if (dot > maxB) { 
9901                    maxB = dot;
9902                } else if (dot < minB) { 
9903                    minB = dot;
9904                }
9905            }
9906
9907            overlapAB = maxA - minB;
9908            overlapBA = maxB - minA;
9909            overlap = overlapAB < overlapBA ? overlapAB : overlapBA;
9910
9911            if (overlap < overlapMin) {
9912                overlapMin = overlap;
9913                overlapAxisNumber = i;
9914
9915                if (overlap <= 0) {
9916                    // can not be intersecting
9917                    break;
9918                }
9919            } 
9920        }
9921
9922        result.axis = axes[overlapAxisNumber];
9923        result.overlap = overlapMin;
9924    };
9925
9926    /**
9927     * Finds supporting vertices given two bodies along a given direction using hill-climbing.
9928     * @method _findSupports
9929     * @private
9930     * @param {body} bodyA
9931     * @param {body} bodyB
9932     * @param {vector} normal
9933     * @param {number} direction
9934     * @return [vector]
9935     */
9936    Collision._findSupports = function(bodyA, bodyB, normal, direction) {
9937        var vertices = bodyB.vertices,
9938            verticesLength = vertices.length,
9939            bodyAPositionX = bodyA.position.x,
9940            bodyAPositionY = bodyA.position.y,
9941            normalX = normal.x * direction,
9942            normalY = normal.y * direction,
9943            vertexA = vertices[0],
9944            vertexB = vertexA,
9945            nearestDistance = normalX * (bodyAPositionX - vertexB.x) + normalY * (bodyAPositionY - vertexB.y),
9946            vertexC,
9947            distance,
9948            j;
9949
9950        // find deepest vertex relative to the axis
9951        for (j = 1; j < verticesLength; j += 1) {
9952            vertexB = vertices[j];
9953            distance = normalX * (bodyAPositionX - vertexB.x) + normalY * (bodyAPositionY - vertexB.y);
9954
9955            // convex hill-climbing
9956            if (distance < nearestDistance) {
9957                nearestDistance = distance;
9958                vertexA = vertexB;
9959            }
9960        }
9961
9962        // measure next vertex
9963        vertexC = vertices[(verticesLength + vertexA.index - 1) % verticesLength];
9964        nearestDistance = normalX * (bodyAPositionX - vertexC.x) + normalY * (bodyAPositionY - vertexC.y);
9965
9966        // compare with previous vertex
9967        vertexB = vertices[(vertexA.index + 1) % verticesLength];
9968        if (normalX * (bodyAPositionX - vertexB.x) + normalY * (bodyAPositionY - vertexB.y) < nearestDistance) {
9969            _supports[0] = vertexA;
9970            _supports[1] = vertexB;
9971
9972            return _supports;
9973        }
9974
9975        _supports[0] = vertexA;
9976        _supports[1] = vertexC;
9977
9978        return _supports;
9979    };
9980
9981    /*
9982    *
9983    *  Properties Documentation
9984    *
9985    */
9986
9987    /**
9988     * A reference to the pair using this collision record, if there is one.
9989     *
9990     * @property pair
9991     * @type {pair|null}
9992     * @default null
9993     */
9994
9995    /**
9996     * A flag that indicates if the bodies were colliding when the collision was last updated.
9997     * 
9998     * @property collided
9999     * @type boolean
10000     * @default false
10001     */
10002
10003    /**
10004     * The first body part represented by the collision (see also `collision.parentA`).
10005     * 
10006     * @property bodyA
10007     * @type body
10008     */
10009
10010    /**
10011     * The second body part represented by the collision (see also `collision.parentB`).
10012     * 
10013     * @property bodyB
10014     * @type body
10015     */
10016
10017    /**
10018     * The first body represented by the collision (i.e. `collision.bodyA.parent`).
10019     * 
10020     * @property parentA
10021     * @type body
10022     */
10023
10024    /**
10025     * The second body represented by the collision (i.e. `collision.bodyB.parent`).
10026     * 
10027     * @property parentB
10028     * @type body
10029     */
10030
10031    /**
10032     * A `Number` that represents the minimum separating distance between the bodies along the collision normal.
10033     *
10034     * @readOnly
10035     * @property depth
10036     * @type number
10037     * @default 0
10038     */
10039
10040    /**
10041     * A normalised `Vector` that represents the direction between the bodies that provides the minimum separating distance.
10042     *
10043     * @property normal
10044     * @type vector
10045     * @default { x: 0, y: 0 }
10046     */
10047
10048    /**
10049     * A normalised `Vector` that is the tangent direction to the collision normal.
10050     *
10051     * @property tangent
10052     * @type vector
10053     * @default { x: 0, y: 0 }
10054     */
10055
10056    /**
10057     * A `Vector` that represents the direction and depth of the collision.
10058     *
10059     * @property penetration
10060     * @type vector
10061     * @default { x: 0, y: 0 }
10062     */
10063
10064    /**
10065     * An array of body vertices that represent the support points in the collision.
10066     * 
10067     * _Note:_ Only the first `collision.supportCount` items of `collision.supports` are active.
10068     * Therefore use `collision.supportCount` instead of `collision.supports.length` when iterating the active supports.
10069     * 
10070     * These are the deepest vertices (along the collision normal) of each body that are contained by the other body's vertices.
10071     *
10072     * @property supports
10073     * @type vector[]
10074     * @default []
10075     */
10076
10077    /**
10078     * The number of active supports for this collision found in `collision.supports`.
10079     * 
10080     * _Note:_ Only the first `collision.supportCount` items of `collision.supports` are active.
10081     * Therefore use `collision.supportCount` instead of `collision.supports.length` when iterating the active supports.
10082     *
10083     * @property supportCount
10084     * @type number
10085     * @default 0
10086     */
10087
10088})();
10089
10090
10091/***/ }),
10092/* 9 */
10093/***/ (function(module, exports, __webpack_require__) {
10094
10095/**
10096* The `Matter.Pair` module contains methods for creating and manipulating collision pairs.
10097*
10098* @class Pair
10099*/
10100
10101var Pair = {};
10102
10103module.exports = Pair;
10104
10105var Contact = __webpack_require__(16);
10106
10107(function() {
10108    
10109    /**
10110     * Creates a pair.
10111     * @method create
10112     * @param {collision} collision
10113     * @param {number} timestamp
10114     * @return {pair} A new pair
10115     */
10116    Pair.create = function(collision, timestamp) {
10117        var bodyA = collision.bodyA,
10118            bodyB = collision.bodyB;
10119
10120        var pair = {
10121            id: Pair.id(bodyA, bodyB),
10122            bodyA: bodyA,
10123            bodyB: bodyB,
10124            collision: collision,
10125            contacts: [Contact.create(), Contact.create()],
10126            contactCount: 0,
10127            separation: 0,
10128            isActive: true,
10129            isSensor: bodyA.isSensor || bodyB.isSensor,
10130            timeCreated: timestamp,
10131            timeUpdated: timestamp,
10132            inverseMass: 0,
10133            friction: 0,
10134            frictionStatic: 0,
10135            restitution: 0,
10136            slop: 0
10137        };
10138
10139        Pair.update(pair, collision, timestamp);
10140
10141        return pair;
10142    };
10143
10144    /**
10145     * Updates a pair given a collision.
10146     * @method update
10147     * @param {pair} pair
10148     * @param {collision} collision
10149     * @param {number} timestamp
10150     */
10151    Pair.update = function(pair, collision, timestamp) {
10152        var supports = collision.supports,
10153            supportCount = collision.supportCount,
10154            contacts = pair.contacts,
10155            parentA = collision.parentA,
10156            parentB = collision.parentB;
10157        
10158        pair.isActive = true;
10159        pair.timeUpdated = timestamp;
10160        pair.collision = collision;
10161        pair.separation = collision.depth;
10162        pair.inverseMass = parentA.inverseMass + parentB.inverseMass;
10163        pair.friction = parentA.friction < parentB.friction ? parentA.friction : parentB.friction;
10164        pair.frictionStatic = parentA.frictionStatic > parentB.frictionStatic ? parentA.frictionStatic : parentB.frictionStatic;
10165        pair.restitution = parentA.restitution > parentB.restitution ? parentA.restitution : parentB.restitution;
10166        pair.slop = parentA.slop > parentB.slop ? parentA.slop : parentB.slop;
10167
10168        pair.contactCount = supportCount;
10169        collision.pair = pair;
10170
10171        var supportA = supports[0],
10172            contactA = contacts[0],
10173            supportB = supports[1],
10174            contactB = contacts[1];
10175
10176        // match contacts to supports
10177        if (contactB.vertex === supportA || contactA.vertex === supportB) {
10178            contacts[1] = contactA;
10179            contacts[0] = contactA = contactB;
10180            contactB = contacts[1];
10181        }
10182
10183        // update contacts
10184        contactA.vertex = supportA;
10185        contactB.vertex = supportB;
10186    };
10187    
10188    /**
10189     * Set a pair as active or inactive.
10190     * @method setActive
10191     * @param {pair} pair
10192     * @param {bool} isActive
10193     * @param {number} timestamp
10194     */
10195    Pair.setActive = function(pair, isActive, timestamp) {
10196        if (isActive) {
10197            pair.isActive = true;
10198            pair.timeUpdated = timestamp;
10199        } else {
10200            pair.isActive = false;
10201            pair.contactCount = 0;
10202        }
10203    };
10204
10205    /**
10206     * Get the id for the given pair.
10207     * @method id
10208     * @param {body} bodyA
10209     * @param {body} bodyB
10210     * @return {string} Unique pairId
10211     */
10212    Pair.id = function(bodyA, bodyB) {
10213        return bodyA.id < bodyB.id ? bodyA.id.toString(36) + ':' + bodyB.id.toString(36) 
10214            : bodyB.id.toString(36) + ':' + bodyA.id.toString(36);
10215    };
10216
10217})();
10218
10219
10220/***/ }),
10221/* 10 */
10222/***/ (function(module, exports, __webpack_require__) {
10223
10224/**
10225* The `Matter.Constraint` module contains methods for creating and manipulating constraints.
10226* Constraints are used for specifying that a fixed distance must be maintained between two bodies (or a body and a fixed world-space position).
10227* The stiffness of constraints can be modified to create springs or elastic.
10228*
10229* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples).
10230*
10231* @class Constraint
10232*/
10233
10234var Constraint = {};
10235
10236module.exports = Constraint;
10237
10238var Vertices = __webpack_require__(3);
10239var Vector = __webpack_require__(2);
10240var Sleeping = __webpack_require__(7);
10241var Bounds = __webpack_require__(1);
10242var Axes = __webpack_require__(11);
10243var Common = __webpack_require__(0);
10244
10245(function() {
10246
10247    Constraint._warming = 0.4;
10248    Constraint._torqueDampen = 1;
10249    Constraint._minLength = 0.000001;
10250
10251    /**
10252     * Creates a new constraint.
10253     * All properties have default values, and many are pre-calculated automatically based on other properties.
10254     * To simulate a revolute constraint (or pin joint) set `length: 0` and a high `stiffness` value (e.g. `0.7` or above).
10255     * If the constraint is unstable, try lowering the `stiffness` value and / or increasing `engine.constraintIterations`.
10256     * For compound bodies, constraints must be applied to the parent body (not one of its parts).
10257     * See the properties section below for detailed information on what you can pass via the `options` object.
10258     * @method create
10259     * @param {} options
10260     * @return {constraint} constraint
10261     */
10262    Constraint.create = function(options) {
10263        var constraint = options;
10264
10265        // if bodies defined but no points, use body centre
10266        if (constraint.bodyA && !constraint.pointA)
10267            constraint.pointA = { x: 0, y: 0 };
10268        if (constraint.bodyB && !constraint.pointB)
10269            constraint.pointB = { x: 0, y: 0 };
10270
10271        // calculate static length using initial world space points
10272        var initialPointA = constraint.bodyA ? Vector.add(constraint.bodyA.position, constraint.pointA) : constraint.pointA,
10273            initialPointB = constraint.bodyB ? Vector.add(constraint.bodyB.position, constraint.pointB) : constraint.pointB,
10274            length = Vector.magnitude(Vector.sub(initialPointA, initialPointB));
10275    
10276        constraint.length = typeof constraint.length !== 'undefined' ? constraint.length : length;
10277
10278        // option defaults
10279        constraint.id = constraint.id || Common.nextId();
10280        constraint.label = constraint.label || 'Constraint';
10281        constraint.type = 'constraint';
10282        constraint.stiffness = constraint.stiffness || (constraint.length > 0 ? 1 : 0.7);
10283        constraint.damping = constraint.damping || 0;
10284        constraint.angularStiffness = constraint.angularStiffness || 0;
10285        constraint.angleA = constraint.bodyA ? constraint.bodyA.angle : constraint.angleA;
10286        constraint.angleB = constraint.bodyB ? constraint.bodyB.angle : constraint.angleB;
10287        constraint.plugin = {};
10288
10289        // render
10290        var render = {
10291            visible: true,
10292            lineWidth: 2,
10293            strokeStyle: '#ffffff',
10294            type: 'line',
10295            anchors: true
10296        };
10297
10298        if (constraint.length === 0 && constraint.stiffness > 0.1) {
10299            render.type = 'pin';
10300            render.anchors = false;
10301        } else if (constraint.stiffness < 0.9) {
10302            render.type = 'spring';
10303        }
10304
10305        constraint.render = Common.extend(render, constraint.render);
10306
10307        return constraint;
10308    };
10309
10310    /**
10311     * Prepares for solving by constraint warming.
10312     * @private
10313     * @method preSolveAll
10314     * @param {body[]} bodies
10315     */
10316    Constraint.preSolveAll = function(bodies) {
10317        for (var i = 0; i < bodies.length; i += 1) {
10318            var body = bodies[i],
10319                impulse = body.constraintImpulse;
10320
10321            if (body.isStatic || (impulse.x === 0 && impulse.y === 0 && impulse.angle === 0)) {
10322                continue;
10323            }
10324
10325            body.position.x += impulse.x;
10326            body.position.y += impulse.y;
10327            body.angle += impulse.angle;
10328        }
10329    };
10330
10331    /**
10332     * Solves all constraints in a list of collisions.
10333     * @private
10334     * @method solveAll
10335     * @param {constraint[]} constraints
10336     * @param {number} delta
10337     */
10338    Constraint.solveAll = function(constraints, delta) {
10339        var timeScale = Common.clamp(delta / Common._baseDelta, 0, 1);
10340
10341        // Solve fixed constraints first.
10342        for (var i = 0; i < constraints.length; i += 1) {
10343            var constraint = constraints[i],
10344                fixedA = !constraint.bodyA || (constraint.bodyA && constraint.bodyA.isStatic),
10345                fixedB = !constraint.bodyB || (constraint.bodyB && constraint.bodyB.isStatic);
10346
10347            if (fixedA || fixedB) {
10348                Constraint.solve(constraints[i], timeScale);
10349            }
10350        }
10351
10352        // Solve free constraints last.
10353        for (i = 0; i < constraints.length; i += 1) {
10354            constraint = constraints[i];
10355            fixedA = !constraint.bodyA || (constraint.bodyA && constraint.bodyA.isStatic);
10356            fixedB = !constraint.bodyB || (constraint.bodyB && constraint.bodyB.isStatic);
10357
10358            if (!fixedA && !fixedB) {
10359                Constraint.solve(constraints[i], timeScale);
10360            }
10361        }
10362    };
10363
10364    /**
10365     * Solves a distance constraint with Gauss-Siedel method.
10366     * @private
10367     * @method solve
10368     * @param {constraint} constraint
10369     * @param {number} timeScale
10370     */
10371    Constraint.solve = function(constraint, timeScale) {
10372        var bodyA = constraint.bodyA,
10373            bodyB = constraint.bodyB,
10374            pointA = constraint.pointA,
10375            pointB = constraint.pointB;
10376
10377        if (!bodyA && !bodyB)
10378            return;
10379
10380        // update reference angle
10381        if (bodyA && !bodyA.isStatic) {
10382            Vector.rotate(pointA, bodyA.angle - constraint.angleA, pointA);
10383            constraint.angleA = bodyA.angle;
10384        }
10385        
10386        // update reference angle
10387        if (bodyB && !bodyB.isStatic) {
10388            Vector.rotate(pointB, bodyB.angle - constraint.angleB, pointB);
10389            constraint.angleB = bodyB.angle;
10390        }
10391
10392        var pointAWorld = pointA,
10393            pointBWorld = pointB;
10394
10395        if (bodyA) pointAWorld = Vector.add(bodyA.position, pointA);
10396        if (bodyB) pointBWorld = Vector.add(bodyB.position, pointB);
10397
10398        if (!pointAWorld || !pointBWorld)
10399            return;
10400
10401        var delta = Vector.sub(pointAWorld, pointBWorld),
10402            currentLength = Vector.magnitude(delta);
10403
10404        // prevent singularity
10405        if (currentLength < Constraint._minLength) {
10406            currentLength = Constraint._minLength;
10407        }
10408
10409        // solve distance constraint with Gauss-Siedel method
10410        var difference = (currentLength - constraint.length) / currentLength,
10411            isRigid = constraint.stiffness >= 1 || constraint.length === 0,
10412            stiffness = isRigid ? constraint.stiffness * timeScale 
10413                : constraint.stiffness * timeScale * timeScale,
10414            damping = constraint.damping * timeScale,
10415            force = Vector.mult(delta, difference * stiffness),
10416            massTotal = (bodyA ? bodyA.inverseMass : 0) + (bodyB ? bodyB.inverseMass : 0),
10417            inertiaTotal = (bodyA ? bodyA.inverseInertia : 0) + (bodyB ? bodyB.inverseInertia : 0),
10418            resistanceTotal = massTotal + inertiaTotal,
10419            torque,
10420            share,
10421            normal,
10422            normalVelocity,
10423            relativeVelocity;
10424    
10425        if (damping > 0) {
10426            var zero = Vector.create();
10427            normal = Vector.div(delta, currentLength);
10428
10429            relativeVelocity = Vector.sub(
10430                bodyB && Vector.sub(bodyB.position, bodyB.positionPrev) || zero,
10431                bodyA && Vector.sub(bodyA.position, bodyA.positionPrev) || zero
10432            );
10433
10434            normalVelocity = Vector.dot(normal, relativeVelocity);
10435        }
10436
10437        if (bodyA && !bodyA.isStatic) {
10438            share = bodyA.inverseMass / massTotal;
10439
10440            // keep track of applied impulses for post solving
10441            bodyA.constraintImpulse.x -= force.x * share;
10442            bodyA.constraintImpulse.y -= force.y * share;
10443
10444            // apply forces
10445            bodyA.position.x -= force.x * share;
10446            bodyA.position.y -= force.y * share;
10447
10448            // apply damping
10449            if (damping > 0) {
10450                bodyA.positionPrev.x -= damping * normal.x * normalVelocity * share;
10451                bodyA.positionPrev.y -= damping * normal.y * normalVelocity * share;
10452            }
10453
10454            // apply torque
10455            torque = (Vector.cross(pointA, force) / resistanceTotal) * Constraint._torqueDampen * bodyA.inverseInertia * (1 - constraint.angularStiffness);
10456            bodyA.constraintImpulse.angle -= torque;
10457            bodyA.angle -= torque;
10458        }
10459
10460        if (bodyB && !bodyB.isStatic) {
10461            share = bodyB.inverseMass / massTotal;
10462
10463            // keep track of applied impulses for post solving
10464            bodyB.constraintImpulse.x += force.x * share;
10465            bodyB.constraintImpulse.y += force.y * share;
10466            
10467            // apply forces
10468            bodyB.position.x += force.x * share;
10469            bodyB.position.y += force.y * share;
10470
10471            // apply damping
10472            if (damping > 0) {
10473                bodyB.positionPrev.x += damping * normal.x * normalVelocity * share;
10474                bodyB.positionPrev.y += damping * normal.y * normalVelocity * share;
10475            }
10476
10477            // apply torque
10478            torque = (Vector.cross(pointB, force) / resistanceTotal) * Constraint._torqueDampen * bodyB.inverseInertia * (1 - constraint.angularStiffness);
10479            bodyB.constraintImpulse.angle += torque;
10480            bodyB.angle += torque;
10481        }
10482
10483    };
10484
10485    /**
10486     * Performs body updates required after solving constraints.
10487     * @private
10488     * @method postSolveAll
10489     * @param {body[]} bodies
10490     */
10491    Constraint.postSolveAll = function(bodies) {
10492        for (var i = 0; i < bodies.length; i++) {
10493            var body = bodies[i],
10494                impulse = body.constraintImpulse;
10495
10496            if (body.isStatic || (impulse.x === 0 && impulse.y === 0 && impulse.angle === 0)) {
10497                continue;
10498            }
10499
10500            Sleeping.set(body, false);
10501
10502            // update geometry and reset
10503            for (var j = 0; j < body.parts.length; j++) {
10504                var part = body.parts[j];
10505                
10506                Vertices.translate(part.vertices, impulse);
10507
10508                if (j > 0) {
10509                    part.position.x += impulse.x;
10510                    part.position.y += impulse.y;
10511                }
10512
10513                if (impulse.angle !== 0) {
10514                    Vertices.rotate(part.vertices, impulse.angle, body.position);
10515                    Axes.rotate(part.axes, impulse.angle);
10516                    if (j > 0) {
10517                        Vector.rotateAbout(part.position, impulse.angle, body.position, part.position);
10518                    }
10519                }
10520
10521                Bounds.update(part.bounds, part.vertices, body.velocity);
10522            }
10523
10524            // dampen the cached impulse for warming next step
10525            impulse.angle *= Constraint._warming;
10526            impulse.x *= Constraint._warming;
10527            impulse.y *= Constraint._warming;
10528        }
10529    };
10530
10531    /**
10532     * Returns the world-space position of `constraint.pointA`, accounting for `constraint.bodyA`.
10533     * @method pointAWorld
10534     * @param {constraint} constraint
10535     * @returns {vector} the world-space position
10536     */
10537    Constraint.pointAWorld = function(constraint) {
10538        return {
10539            x: (constraint.bodyA ? constraint.bodyA.position.x : 0) 
10540                + (constraint.pointA ? constraint.pointA.x : 0),
10541            y: (constraint.bodyA ? constraint.bodyA.position.y : 0) 
10542                + (constraint.pointA ? constraint.pointA.y : 0)
10543        };
10544    };
10545
10546    /**
10547     * Returns the world-space position of `constraint.pointB`, accounting for `constraint.bodyB`.
10548     * @method pointBWorld
10549     * @param {constraint} constraint
10550     * @returns {vector} the world-space position
10551     */
10552    Constraint.pointBWorld = function(constraint) {
10553        return {
10554            x: (constraint.bodyB ? constraint.bodyB.position.x : 0) 
10555                + (constraint.pointB ? constraint.pointB.x : 0),
10556            y: (constraint.bodyB ? constraint.bodyB.position.y : 0) 
10557                + (constraint.pointB ? constraint.pointB.y : 0)
10558        };
10559    };
10560
10561    /**
10562     * Returns the current length of the constraint. 
10563     * This is the distance between both of the constraint's end points.
10564     * See `constraint.length` for the target rest length.
10565     * @method currentLength
10566     * @param {constraint} constraint
10567     * @returns {number} the current length
10568     */
10569    Constraint.currentLength = function(constraint) {
10570        var pointAX = (constraint.bodyA ? constraint.bodyA.position.x : 0) 
10571            + (constraint.pointA ? constraint.pointA.x : 0);
10572
10573        var pointAY = (constraint.bodyA ? constraint.bodyA.position.y : 0) 
10574            + (constraint.pointA ? constraint.pointA.y : 0);
10575
10576        var pointBX = (constraint.bodyB ? constraint.bodyB.position.x : 0) 
10577            + (constraint.pointB ? constraint.pointB.x : 0);
10578            
10579        var pointBY = (constraint.bodyB ? constraint.bodyB.position.y : 0) 
10580            + (constraint.pointB ? constraint.pointB.y : 0);
10581
10582        var deltaX = pointAX - pointBX;
10583        var deltaY = pointAY - pointBY;
10584
10585        return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
10586    };
10587
10588    /*
10589    *
10590    *  Properties Documentation
10591    *
10592    */
10593
10594    /**
10595     * An integer `Number` uniquely identifying number generated in `Composite.create` by `Common.nextId`.
10596     *
10597     * @property id
10598     * @type number
10599     */
10600
10601    /**
10602     * A `String` denoting the type of object.
10603     *
10604     * @property type
10605     * @type string
10606     * @default "constraint"
10607     * @readOnly
10608     */
10609
10610    /**
10611     * An arbitrary `String` name to help the user identify and manage bodies.
10612     *
10613     * @property label
10614     * @type string
10615     * @default "Constraint"
10616     */
10617
10618    /**
10619     * An `Object` that defines the rendering properties to be consumed by the module `Matter.Render`.
10620     *
10621     * @property render
10622     * @type object
10623     */
10624
10625    /**
10626     * A flag that indicates if the constraint should be rendered.
10627     *
10628     * @property render.visible
10629     * @type boolean
10630     * @default true
10631     */
10632
10633    /**
10634     * A `Number` that defines the line width to use when rendering the constraint outline.
10635     * A value of `0` means no outline will be rendered.
10636     *
10637     * @property render.lineWidth
10638     * @type number
10639     * @default 2
10640     */
10641
10642    /**
10643     * A `String` that defines the stroke style to use when rendering the constraint outline.
10644     * It is the same as when using a canvas, so it accepts CSS style property values.
10645     *
10646     * @property render.strokeStyle
10647     * @type string
10648     * @default a random colour
10649     */
10650
10651    /**
10652     * A `String` that defines the constraint rendering type. 
10653     * The possible values are 'line', 'pin', 'spring'.
10654     * An appropriate render type will be automatically chosen unless one is given in options.
10655     *
10656     * @property render.type
10657     * @type string
10658     * @default 'line'
10659     */
10660
10661    /**
10662     * A `Boolean` that defines if the constraint's anchor points should be rendered.
10663     *
10664     * @property render.anchors
10665     * @type boolean
10666     * @default true
10667     */
10668
10669    /**
10670     * The first possible `Body` that this constraint is attached to.
10671     *
10672     * @property bodyA
10673     * @type body
10674     * @default null
10675     */
10676
10677    /**
10678     * The second possible `Body` that this constraint is attached to.
10679     *
10680     * @property bodyB
10681     * @type body
10682     * @default null
10683     */
10684
10685    /**
10686     * A `Vector` that specifies the offset of the constraint from center of the `constraint.bodyA` if defined, otherwise a world-space position.
10687     *
10688     * @property pointA
10689     * @type vector
10690     * @default { x: 0, y: 0 }
10691     */
10692
10693    /**
10694     * A `Vector` that specifies the offset of the constraint from center of the `constraint.bodyB` if defined, otherwise a world-space position.
10695     *
10696     * @property pointB
10697     * @type vector
10698     * @default { x: 0, y: 0 }
10699     */
10700
10701    /**
10702     * A `Number` that specifies the stiffness of the constraint, i.e. the rate at which it returns to its resting `constraint.length`.
10703     * A value of `1` means the constraint should be very stiff.
10704     * A value of `0.2` means the constraint acts like a soft spring.
10705     *
10706     * @property stiffness
10707     * @type number
10708     * @default 1
10709     */
10710
10711    /**
10712     * A `Number` that specifies the damping of the constraint, 
10713     * i.e. the amount of resistance applied to each body based on their velocities to limit the amount of oscillation.
10714     * Damping will only be apparent when the constraint also has a very low `stiffness`.
10715     * A value of `0.1` means the constraint will apply heavy damping, resulting in little to no oscillation.
10716     * A value of `0` means the constraint will apply no damping.
10717     *
10718     * @property damping
10719     * @type number
10720     * @default 0
10721     */
10722
10723    /**
10724     * A `Number` that specifies the target resting length of the constraint. 
10725     * It is calculated automatically in `Constraint.create` from initial positions of the `constraint.bodyA` and `constraint.bodyB`.
10726     *
10727     * @property length
10728     * @type number
10729     */
10730
10731    /**
10732     * An object reserved for storing plugin-specific properties.
10733     *
10734     * @property plugin
10735     * @type {}
10736     */
10737
10738})();
10739
10740
10741/***/ }),
10742/* 11 */
10743/***/ (function(module, exports, __webpack_require__) {
10744
10745/**
10746* The `Matter.Axes` module contains methods for creating and manipulating sets of axes.
10747*
10748* @class Axes
10749*/
10750
10751var Axes = {};
10752
10753module.exports = Axes;
10754
10755var Vector = __webpack_require__(2);
10756var Common = __webpack_require__(0);
10757
10758(function() {
10759
10760    /**
10761     * Creates a new set of axes from the given vertices.
10762     * @method fromVertices
10763     * @param {vertices} vertices
10764     * @return {axes} A new axes from the given vertices
10765     */
10766    Axes.fromVertices = function(vertices) {
10767        var axes = {};
10768
10769        // find the unique axes, using edge normal gradients
10770        for (var i = 0; i < vertices.length; i++) {
10771            var j = (i + 1) % vertices.length, 
10772                normal = Vector.normalise({ 
10773                    x: vertices[j].y - vertices[i].y, 
10774                    y: vertices[i].x - vertices[j].x
10775                }),
10776                gradient = (normal.y === 0) ? Infinity : (normal.x / normal.y);
10777            
10778            // limit precision
10779            gradient = gradient.toFixed(3).toString();
10780            axes[gradient] = normal;
10781        }
10782
10783        return Common.values(axes);
10784    };
10785
10786    /**
10787     * Rotates a set of axes by the given angle.
10788     * @method rotate
10789     * @param {axes} axes
10790     * @param {number} angle
10791     */
10792    Axes.rotate = function(axes, angle) {
10793        if (angle === 0)
10794            return;
10795        
10796        var cos = Math.cos(angle),
10797            sin = Math.sin(angle);
10798
10799        for (var i = 0; i < axes.length; i++) {
10800            var axis = axes[i],
10801                xx;
10802            xx = axis.x * cos - axis.y * sin;
10803            axis.y = axis.x * sin + axis.y * cos;
10804            axis.x = xx;
10805        }
10806    };
10807
10808})();
10809
10810
10811/***/ }),
10812/* 12 */
10813/***/ (function(module, exports, __webpack_require__) {
10814
10815/**
10816* The `Matter.Bodies` module contains factory methods for creating rigid body models 
10817* with commonly used body configurations (such as rectangles, circles and other polygons).
10818*
10819* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples).
10820*
10821* @class Bodies
10822*/
10823
10824// TODO: true circle bodies
10825
10826var Bodies = {};
10827
10828module.exports = Bodies;
10829
10830var Vertices = __webpack_require__(3);
10831var Common = __webpack_require__(0);
10832var Body = __webpack_require__(4);
10833var Bounds = __webpack_require__(1);
10834var Vector = __webpack_require__(2);
10835
10836(function() {
10837
10838    /**
10839     * Creates a new rigid body model with a rectangle hull. 
10840     * The options parameter is an object that specifies any properties you wish to override the defaults.
10841     * See the properties section of the `Matter.Body` module for detailed information on what you can pass via the `options` object.
10842     * @method rectangle
10843     * @param {number} x
10844     * @param {number} y
10845     * @param {number} width
10846     * @param {number} height
10847     * @param {object} [options]
10848     * @return {body} A new rectangle body
10849     */
10850    Bodies.rectangle = function(x, y, width, height, options) {
10851        options = options || {};
10852
10853        var rectangle = { 
10854            label: 'Rectangle Body',
10855            position: { x: x, y: y },
10856            vertices: Vertices.fromPath('L 0 0 L ' + width + ' 0 L ' + width + ' ' + height + ' L 0 ' + height)
10857        };
10858
10859        if (options.chamfer) {
10860            var chamfer = options.chamfer;
10861            rectangle.vertices = Vertices.chamfer(rectangle.vertices, chamfer.radius, 
10862                chamfer.quality, chamfer.qualityMin, chamfer.qualityMax);
10863            delete options.chamfer;
10864        }
10865
10866        return Body.create(Common.extend({}, rectangle, options));
10867    };
10868    
10869    /**
10870     * Creates a new rigid body model with a trapezoid hull. 
10871     * The `slope` is parameterised as a fraction of `width` and must be < 1 to form a valid trapezoid. 
10872     * The options parameter is an object that specifies any properties you wish to override the defaults.
10873     * See the properties section of the `Matter.Body` module for detailed information on what you can pass via the `options` object.
10874     * @method trapezoid
10875     * @param {number} x
10876     * @param {number} y
10877     * @param {number} width
10878     * @param {number} height
10879     * @param {number} slope Must be a number < 1.
10880     * @param {object} [options]
10881     * @return {body} A new trapezoid body
10882     */
10883    Bodies.trapezoid = function(x, y, width, height, slope, options) {
10884        options = options || {};
10885
10886        if (slope >= 1) {
10887            Common.warn('Bodies.trapezoid: slope parameter must be < 1.');
10888        }
10889
10890        slope *= 0.5;
10891        var roof = (1 - (slope * 2)) * width;
10892        
10893        var x1 = width * slope,
10894            x2 = x1 + roof,
10895            x3 = x2 + x1,
10896            verticesPath;
10897
10898        if (slope < 0.5) {
10899            verticesPath = 'L 0 0 L ' + x1 + ' ' + (-height) + ' L ' + x2 + ' ' + (-height) + ' L ' + x3 + ' 0';
10900        } else {
10901            verticesPath = 'L 0 0 L ' + x2 + ' ' + (-height) + ' L ' + x3 + ' 0';
10902        }
10903
10904        var trapezoid = { 
10905            label: 'Trapezoid Body',
10906            position: { x: x, y: y },
10907            vertices: Vertices.fromPath(verticesPath)
10908        };
10909
10910        if (options.chamfer) {
10911            var chamfer = options.chamfer;
10912            trapezoid.vertices = Vertices.chamfer(trapezoid.vertices, chamfer.radius, 
10913                chamfer.quality, chamfer.qualityMin, chamfer.qualityMax);
10914            delete options.chamfer;
10915        }
10916
10917        return Body.create(Common.extend({}, trapezoid, options));
10918    };
10919
10920    /**
10921     * Creates a new rigid body model with a circle hull. 
10922     * The options parameter is an object that specifies any properties you wish to override the defaults.
10923     * See the properties section of the `Matter.Body` module for detailed information on what you can pass via the `options` object.
10924     * @method circle
10925     * @param {number} x
10926     * @param {number} y
10927     * @param {number} radius
10928     * @param {object} [options]
10929     * @param {number} [maxSides]
10930     * @return {body} A new circle body
10931     */
10932    Bodies.circle = function(x, y, radius, options, maxSides) {
10933        options = options || {};
10934
10935        var circle = {
10936            label: 'Circle Body',
10937            circleRadius: radius
10938        };
10939        
10940        // approximate circles with polygons until true circles implemented in SAT
10941        maxSides = maxSides || 25;
10942        var sides = Math.ceil(Math.max(10, Math.min(maxSides, radius)));
10943
10944        // optimisation: always use even number of sides (half the number of unique axes)
10945        if (sides % 2 === 1)
10946            sides += 1;
10947
10948        return Bodies.polygon(x, y, sides, radius, Common.extend({}, circle, options));
10949    };
10950
10951    /**
10952     * Creates a new rigid body model with a regular polygon hull with the given number of sides. 
10953     * The options parameter is an object that specifies any properties you wish to override the defaults.
10954     * See the properties section of the `Matter.Body` module for detailed information on what you can pass via the `options` object.
10955     * @method polygon
10956     * @param {number} x
10957     * @param {number} y
10958     * @param {number} sides
10959     * @param {number} radius
10960     * @param {object} [options]
10961     * @return {body} A new regular polygon body
10962     */
10963    Bodies.polygon = function(x, y, sides, radius, options) {
10964        options = options || {};
10965
10966        if (sides < 3)
10967            return Bodies.circle(x, y, radius, options);
10968
10969        var theta = 2 * Math.PI / sides,
10970            path = '',
10971            offset = theta * 0.5;
10972
10973        for (var i = 0; i < sides; i += 1) {
10974            var angle = offset + (i * theta),
10975                xx = Math.cos(angle) * radius,
10976                yy = Math.sin(angle) * radius;
10977
10978            path += 'L ' + xx.toFixed(3) + ' ' + yy.toFixed(3) + ' ';
10979        }
10980
10981        var polygon = { 
10982            label: 'Polygon Body',
10983            position: { x: x, y: y },
10984            vertices: Vertices.fromPath(path)
10985        };
10986
10987        if (options.chamfer) {
10988            var chamfer = options.chamfer;
10989            polygon.vertices = Vertices.chamfer(polygon.vertices, chamfer.radius, 
10990                chamfer.quality, chamfer.qualityMin, chamfer.qualityMax);
10991            delete options.chamfer;
10992        }
10993
10994        return Body.create(Common.extend({}, polygon, options));
10995    };
10996
10997    /**
10998     * Utility to create a compound body based on set(s) of vertices.
10999     * 
11000     * _Note:_ To optionally enable automatic concave vertices decomposition the [poly-decomp](https://github.com/schteppe/poly-decomp.js) 
11001     * package must be first installed and provided see `Common.setDecomp`, otherwise the convex hull of each vertex set will be used.
11002     * 
11003     * The resulting vertices are reorientated about their centre of mass,
11004     * and offset such that `body.position` corresponds to this point.
11005     * 
11006     * The resulting offset may be found if needed by subtracting `body.bounds` from the original input bounds.
11007     * To later move the centre of mass see `Body.setCentre`.
11008     * 
11009     * Note that automatic conconcave decomposition results are not always optimal. 
11010     * For best results, simplify the input vertices as much as possible first.
11011     * By default this function applies some addtional simplification to help.
11012     * 
11013     * Some outputs may also require further manual processing afterwards to be robust.
11014     * In particular some parts may need to be overlapped to avoid collision gaps.
11015     * Thin parts and sharp points should be avoided or removed where possible.
11016     *
11017     * The options parameter object specifies any `Matter.Body` properties you wish to override the defaults.
11018     * 
11019     * See the properties section of the `Matter.Body` module for detailed information on what you can pass via the `options` object.
11020     * @method fromVertices
11021     * @param {number} x
11022     * @param {number} y
11023     * @param {array} vertexSets One or more arrays of vertex points e.g. `[[{ x: 0, y: 0 }...], ...]`.
11024     * @param {object} [options] The body options.
11025     * @param {bool} [flagInternal=false] Optionally marks internal edges with `isInternal`.
11026     * @param {number} [removeCollinear=0.01] Threshold when simplifying vertices along the same edge.
11027     * @param {number} [minimumArea=10] Threshold when removing small parts.
11028     * @param {number} [removeDuplicatePoints=0.01] Threshold when simplifying nearby vertices.
11029     * @return {body}
11030     */
11031    Bodies.fromVertices = function(x, y, vertexSets, options, flagInternal, removeCollinear, minimumArea, removeDuplicatePoints) {
11032        var decomp = Common.getDecomp(),
11033            canDecomp,
11034            body,
11035            parts,
11036            isConvex,
11037            isConcave,
11038            vertices,
11039            i,
11040            j,
11041            k,
11042            v,
11043            z;
11044
11045        // check decomp is as expected
11046        canDecomp = Boolean(decomp && decomp.quickDecomp);
11047
11048        options = options || {};
11049        parts = [];
11050
11051        flagInternal = typeof flagInternal !== 'undefined' ? flagInternal : false;
11052        removeCollinear = typeof removeCollinear !== 'undefined' ? removeCollinear : 0.01;
11053        minimumArea = typeof minimumArea !== 'undefined' ? minimumArea : 10;
11054        removeDuplicatePoints = typeof removeDuplicatePoints !== 'undefined' ? removeDuplicatePoints : 0.01;
11055
11056        // ensure vertexSets is an array of arrays
11057        if (!Common.isArray(vertexSets[0])) {
11058            vertexSets = [vertexSets];
11059        }
11060
11061        for (v = 0; v < vertexSets.length; v += 1) {
11062            vertices = vertexSets[v];
11063            isConvex = Vertices.isConvex(vertices);
11064            isConcave = !isConvex;
11065
11066            if (isConcave && !canDecomp) {
11067                Common.warnOnce(
11068                    'Bodies.fromVertices: Install the \'poly-decomp\' library and use Common.setDecomp or provide \'decomp\' as a global to decompose concave vertices.'
11069                );
11070            }
11071
11072            if (isConvex || !canDecomp) {
11073                if (isConvex) {
11074                    vertices = Vertices.clockwiseSort(vertices);
11075                } else {
11076                    // fallback to convex hull when decomposition is not possible
11077                    vertices = Vertices.hull(vertices);
11078                }
11079
11080                parts.push({
11081                    position: { x: x, y: y },
11082                    vertices: vertices
11083                });
11084            } else {
11085                // initialise a decomposition
11086                var concave = vertices.map(function(vertex) {
11087                    return [vertex.x, vertex.y];
11088                });
11089
11090                // vertices are concave and simple, we can decompose into parts
11091                decomp.makeCCW(concave);
11092                if (removeCollinear !== false)
11093                    decomp.removeCollinearPoints(concave, removeCollinear);
11094                if (removeDuplicatePoints !== false && decomp.removeDuplicatePoints)
11095                    decomp.removeDuplicatePoints(concave, removeDuplicatePoints);
11096
11097                // use the quick decomposition algorithm (Bayazit)
11098                var decomposed = decomp.quickDecomp(concave);
11099
11100                // for each decomposed chunk
11101                for (i = 0; i < decomposed.length; i++) {
11102                    var chunk = decomposed[i];
11103
11104                    // convert vertices into the correct structure
11105                    var chunkVertices = chunk.map(function(vertices) {
11106                        return {
11107                            x: vertices[0],
11108                            y: vertices[1]
11109                        };
11110                    });
11111
11112                    // skip small chunks
11113                    if (minimumArea > 0 && Vertices.area(chunkVertices) < minimumArea)
11114                        continue;
11115
11116                    // create a compound part
11117                    parts.push({
11118                        position: Vertices.centre(chunkVertices),
11119                        vertices: chunkVertices
11120                    });
11121                }
11122            }
11123        }
11124
11125        // create body parts
11126        for (i = 0; i < parts.length; i++) {
11127            parts[i] = Body.create(Common.extend(parts[i], options));
11128        }
11129
11130        // flag internal edges (coincident part edges)
11131        if (flagInternal) {
11132            var coincident_max_dist = 5;
11133
11134            for (i = 0; i < parts.length; i++) {
11135                var partA = parts[i];
11136
11137                for (j = i + 1; j < parts.length; j++) {
11138                    var partB = parts[j];
11139
11140                    if (Bounds.overlaps(partA.bounds, partB.bounds)) {
11141                        var pav = partA.vertices,
11142                            pbv = partB.vertices;
11143
11144                        // iterate vertices of both parts
11145                        for (k = 0; k < partA.vertices.length; k++) {
11146                            for (z = 0; z < partB.vertices.length; z++) {
11147                                // find distances between the vertices
11148                                var da = Vector.magnitudeSquared(Vector.sub(pav[(k + 1) % pav.length], pbv[z])),
11149                                    db = Vector.magnitudeSquared(Vector.sub(pav[k], pbv[(z + 1) % pbv.length]));
11150
11151                                // if both vertices are very close, consider the edge concident (internal)
11152                                if (da < coincident_max_dist && db < coincident_max_dist) {
11153                                    pav[k].isInternal = true;
11154                                    pbv[z].isInternal = true;
11155                                }
11156                            }
11157                        }
11158
11159                    }
11160                }
11161            }
11162        }
11163
11164        if (parts.length > 1) {
11165            // create the parent body to be returned, that contains generated compound parts
11166            body = Body.create(Common.extend({ parts: parts.slice(0) }, options));
11167
11168            // offset such that body.position is at the centre off mass
11169            Body.setPosition(body, { x: x, y: y });
11170
11171            return body;
11172        } else {
11173            return parts[0];
11174        }
11175    };
11176
11177})();
11178
11179
11180/***/ }),
11181/* 13 */
11182/***/ (function(module, exports, __webpack_require__) {
11183
11184/**
11185* The `Matter.Detector` module contains methods for efficiently detecting collisions between a list of bodies using a broadphase algorithm.
11186*
11187* @class Detector
11188*/
11189
11190var Detector = {};
11191
11192module.exports = Detector;
11193
11194var Common = __webpack_require__(0);
11195var Collision = __webpack_require__(8);
11196
11197(function() {
11198
11199    /**
11200     * Creates a new collision detector.
11201     * @method create
11202     * @param {} options
11203     * @return {detector} A new collision detector
11204     */
11205    Detector.create = function(options) {
11206        var defaults = {
11207            bodies: [],
11208            collisions: [],
11209            pairs: null
11210        };
11211
11212        return Common.extend(defaults, options);
11213    };
11214
11215    /**
11216     * Sets the list of bodies in the detector.
11217     * @method setBodies
11218     * @param {detector} detector
11219     * @param {body[]} bodies
11220     */
11221    Detector.setBodies = function(detector, bodies) {
11222        detector.bodies = bodies.slice(0);
11223    };
11224
11225    /**
11226     * Clears the detector including its list of bodies.
11227     * @method clear
11228     * @param {detector} detector
11229     */
11230    Detector.clear = function(detector) {
11231        detector.bodies = [];
11232        detector.collisions = [];
11233    };
11234
11235    /**
11236     * Efficiently finds all collisions among all the bodies in `detector.bodies` using a broadphase algorithm.
11237     * 
11238     * _Note:_ The specific ordering of collisions returned is not guaranteed between releases and may change for performance reasons.
11239     * If a specific ordering is required then apply a sort to the resulting array.
11240     * @method collisions
11241     * @param {detector} detector
11242     * @return {collision[]} collisions
11243     */
11244    Detector.collisions = function(detector) {
11245        var pairs = detector.pairs,
11246            bodies = detector.bodies,
11247            bodiesLength = bodies.length,
11248            canCollide = Detector.canCollide,
11249            collides = Collision.collides,
11250            collisions = detector.collisions,
11251            collisionIndex = 0,
11252            i,
11253            j;
11254
11255        bodies.sort(Detector._compareBoundsX);
11256
11257        for (i = 0; i < bodiesLength; i++) {
11258            var bodyA = bodies[i],
11259                boundsA = bodyA.bounds,
11260                boundXMax = bodyA.bounds.max.x,
11261                boundYMax = bodyA.bounds.max.y,
11262                boundYMin = bodyA.bounds.min.y,
11263                bodyAStatic = bodyA.isStatic || bodyA.isSleeping,
11264                partsALength = bodyA.parts.length,
11265                partsASingle = partsALength === 1;
11266
11267            for (j = i + 1; j < bodiesLength; j++) {
11268                var bodyB = bodies[j],
11269                    boundsB = bodyB.bounds;
11270
11271                if (boundsB.min.x > boundXMax) {
11272                    break;
11273                }
11274
11275                if (boundYMax < boundsB.min.y || boundYMin > boundsB.max.y) {
11276                    continue;
11277                }
11278
11279                if (bodyAStatic && (bodyB.isStatic || bodyB.isSleeping)) {
11280                    continue;
11281                }
11282
11283                if (!canCollide(bodyA.collisionFilter, bodyB.collisionFilter)) {
11284                    continue;
11285                }
11286
11287                var partsBLength = bodyB.parts.length;
11288
11289                if (partsASingle && partsBLength === 1) {
11290                    var collision = collides(bodyA, bodyB, pairs);
11291
11292                    if (collision) {
11293                        collisions[collisionIndex++] = collision;
11294                    }
11295                } else {
11296                    var partsAStart = partsALength > 1 ? 1 : 0,
11297                        partsBStart = partsBLength > 1 ? 1 : 0;
11298                    
11299                    for (var k = partsAStart; k < partsALength; k++) {
11300                        var partA = bodyA.parts[k],
11301                            boundsA = partA.bounds;
11302
11303                        for (var z = partsBStart; z < partsBLength; z++) {
11304                            var partB = bodyB.parts[z],
11305                                boundsB = partB.bounds;
11306
11307                            if (boundsA.min.x > boundsB.max.x || boundsA.max.x < boundsB.min.x
11308                                || boundsA.max.y < boundsB.min.y || boundsA.min.y > boundsB.max.y) {
11309                                continue;
11310                            }
11311
11312                            var collision = collides(partA, partB, pairs);
11313
11314                            if (collision) {
11315                                collisions[collisionIndex++] = collision;
11316                            }
11317                        }
11318                    }
11319                }
11320            }
11321        }
11322
11323        if (collisions.length !== collisionIndex) {
11324            collisions.length = collisionIndex;
11325        }
11326
11327        return collisions;
11328    };
11329
11330    /**
11331     * Returns `true` if both supplied collision filters will allow a collision to occur.
11332     * See `body.collisionFilter` for more information.
11333     * @method canCollide
11334     * @param {} filterA
11335     * @param {} filterB
11336     * @return {bool} `true` if collision can occur
11337     */
11338    Detector.canCollide = function(filterA, filterB) {
11339        if (filterA.group === filterB.group && filterA.group !== 0)
11340            return filterA.group > 0;
11341
11342        return (filterA.mask & filterB.category) !== 0 && (filterB.mask & filterA.category) !== 0;
11343    };
11344
11345    /**
11346     * The comparison function used in the broadphase algorithm.
11347     * Returns the signed delta of the bodies bounds on the x-axis.
11348     * @private
11349     * @method _sortCompare
11350     * @param {body} bodyA
11351     * @param {body} bodyB
11352     * @return {number} The signed delta used for sorting
11353     */
11354    Detector._compareBoundsX = function(bodyA, bodyB) {
11355        return bodyA.bounds.min.x - bodyB.bounds.min.x;
11356    };
11357
11358    /*
11359    *
11360    *  Properties Documentation
11361    *
11362    */
11363
11364    /**
11365     * The array of `Matter.Body` between which the detector finds collisions.
11366     * 
11367     * _Note:_ The order of bodies in this array _is not fixed_ and will be continually managed by the detector.
11368     * @property bodies
11369     * @type body[]
11370     * @default []
11371     */
11372
11373    /**
11374     * The array of `Matter.Collision` found in the last call to `Detector.collisions` on this detector.
11375     * @property collisions
11376     * @type collision[]
11377     * @default []
11378     */
11379
11380    /**
11381     * Optional. A `Matter.Pairs` object from which previous collision objects may be reused. Intended for internal `Matter.Engine` usage.
11382     * @property pairs
11383     * @type {pairs|null}
11384     * @default null
11385     */
11386
11387})();
11388
11389
11390/***/ }),
11391/* 14 */
11392/***/ (function(module, exports, __webpack_require__) {
11393
11394/**
11395* The `Matter.Mouse` module contains methods for creating and manipulating mouse inputs.
11396*
11397* @class Mouse
11398*/
11399
11400var Mouse = {};
11401
11402module.exports = Mouse;
11403
11404var Common = __webpack_require__(0);
11405
11406(function() {
11407
11408    /**
11409     * Creates a mouse input.
11410     * @method create
11411     * @param {HTMLElement} element
11412     * @return {mouse} A new mouse
11413     */
11414    Mouse.create = function(element) {
11415        var mouse = {};
11416
11417        if (!element) {
11418            Common.log('Mouse.create: element was undefined, defaulting to document.body', 'warn');
11419        }
11420        
11421        mouse.element = element || document.body;
11422        mouse.absolute = { x: 0, y: 0 };
11423        mouse.position = { x: 0, y: 0 };
11424        mouse.mousedownPosition = { x: 0, y: 0 };
11425        mouse.mouseupPosition = { x: 0, y: 0 };
11426        mouse.offset = { x: 0, y: 0 };
11427        mouse.scale = { x: 1, y: 1 };
11428        mouse.wheelDelta = 0;
11429        mouse.button = -1;
11430        mouse.pixelRatio = parseInt(mouse.element.getAttribute('data-pixel-ratio'), 10) || 1;
11431
11432        mouse.sourceEvents = {
11433            mousemove: null,
11434            mousedown: null,
11435            mouseup: null,
11436            mousewheel: null
11437        };
11438        
11439        mouse.mousemove = function(event) { 
11440            var position = Mouse._getRelativeMousePosition(event, mouse.element, mouse.pixelRatio),
11441                touches = event.changedTouches;
11442
11443            if (touches) {
11444                mouse.button = 0;
11445                event.preventDefault();
11446            }
11447
11448            mouse.absolute.x = position.x;
11449            mouse.absolute.y = position.y;
11450            mouse.position.x = mouse.absolute.x * mouse.scale.x + mouse.offset.x;
11451            mouse.position.y = mouse.absolute.y * mouse.scale.y + mouse.offset.y;
11452            mouse.sourceEvents.mousemove = event;
11453        };
11454        
11455        mouse.mousedown = function(event) {
11456            var position = Mouse._getRelativeMousePosition(event, mouse.element, mouse.pixelRatio),
11457                touches = event.changedTouches;
11458
11459            if (touches) {
11460                mouse.button = 0;
11461                event.preventDefault();
11462            } else {
11463                mouse.button = event.button;
11464            }
11465
11466            mouse.absolute.x = position.x;
11467            mouse.absolute.y = position.y;
11468            mouse.position.x = mouse.absolute.x * mouse.scale.x + mouse.offset.x;
11469            mouse.position.y = mouse.absolute.y * mouse.scale.y + mouse.offset.y;
11470            mouse.mousedownPosition.x = mouse.position.x;
11471            mouse.mousedownPosition.y = mouse.position.y;
11472            mouse.sourceEvents.mousedown = event;
11473        };
11474        
11475        mouse.mouseup = function(event) {
11476            var position = Mouse._getRelativeMousePosition(event, mouse.element, mouse.pixelRatio),
11477                touches = event.changedTouches;
11478
11479            if (touches) {
11480                event.preventDefault();
11481            }
11482            
11483            mouse.button = -1;
11484            mouse.absolute.x = position.x;
11485            mouse.absolute.y = position.y;
11486            mouse.position.x = mouse.absolute.x * mouse.scale.x + mouse.offset.x;
11487            mouse.position.y = mouse.absolute.y * mouse.scale.y + mouse.offset.y;
11488            mouse.mouseupPosition.x = mouse.position.x;
11489            mouse.mouseupPosition.y = mouse.position.y;
11490            mouse.sourceEvents.mouseup = event;
11491        };
11492
11493        mouse.mousewheel = function(event) {
11494            mouse.wheelDelta = Math.max(-1, Math.min(1, event.wheelDelta || -event.detail));
11495            event.preventDefault();
11496            mouse.sourceEvents.mousewheel = event;
11497        };
11498
11499        Mouse.setElement(mouse, mouse.element);
11500
11501        return mouse;
11502    };
11503
11504    /**
11505     * Sets the element the mouse is bound to (and relative to).
11506     * @method setElement
11507     * @param {mouse} mouse
11508     * @param {HTMLElement} element
11509     */
11510    Mouse.setElement = function(mouse, element) {
11511        mouse.element = element;
11512
11513        element.addEventListener('mousemove', mouse.mousemove, { passive: true });
11514        element.addEventListener('mousedown', mouse.mousedown, { passive: true });
11515        element.addEventListener('mouseup', mouse.mouseup, { passive: true });
11516        
11517        element.addEventListener('wheel', mouse.mousewheel, { passive: false });
11518        
11519        element.addEventListener('touchmove', mouse.mousemove, { passive: false });
11520        element.addEventListener('touchstart', mouse.mousedown, { passive: false });
11521        element.addEventListener('touchend', mouse.mouseup, { passive: false });
11522    };
11523
11524    /**
11525     * Clears all captured source events.
11526     * @method clearSourceEvents
11527     * @param {mouse} mouse
11528     */
11529    Mouse.clearSourceEvents = function(mouse) {
11530        mouse.sourceEvents.mousemove = null;
11531        mouse.sourceEvents.mousedown = null;
11532        mouse.sourceEvents.mouseup = null;
11533        mouse.sourceEvents.mousewheel = null;
11534        mouse.wheelDelta = 0;
11535    };
11536
11537    /**
11538     * Sets the mouse position offset.
11539     * @method setOffset
11540     * @param {mouse} mouse
11541     * @param {vector} offset
11542     */
11543    Mouse.setOffset = function(mouse, offset) {
11544        mouse.offset.x = offset.x;
11545        mouse.offset.y = offset.y;
11546        mouse.position.x = mouse.absolute.x * mouse.scale.x + mouse.offset.x;
11547        mouse.position.y = mouse.absolute.y * mouse.scale.y + mouse.offset.y;
11548    };
11549
11550    /**
11551     * Sets the mouse position scale.
11552     * @method setScale
11553     * @param {mouse} mouse
11554     * @param {vector} scale
11555     */
11556    Mouse.setScale = function(mouse, scale) {
11557        mouse.scale.x = scale.x;
11558        mouse.scale.y = scale.y;
11559        mouse.position.x = mouse.absolute.x * mouse.scale.x + mouse.offset.x;
11560        mouse.position.y = mouse.absolute.y * mouse.scale.y + mouse.offset.y;
11561    };
11562    
11563    /**
11564     * Gets the mouse position relative to an element given a screen pixel ratio.
11565     * @method _getRelativeMousePosition
11566     * @private
11567     * @param {} event
11568     * @param {} element
11569     * @param {number} pixelRatio
11570     * @return {}
11571     */
11572    Mouse._getRelativeMousePosition = function(event, element, pixelRatio) {
11573        var elementBounds = element.getBoundingClientRect(),
11574            rootNode = (document.documentElement || document.body.parentNode || document.body),
11575            scrollX = (window.pageXOffset !== undefined) ? window.pageXOffset : rootNode.scrollLeft,
11576            scrollY = (window.pageYOffset !== undefined) ? window.pageYOffset : rootNode.scrollTop,
11577            touches = event.changedTouches,
11578            x, y;
11579        
11580        if (touches) {
11581            x = touches[0].pageX - elementBounds.left - scrollX;
11582            y = touches[0].pageY - elementBounds.top - scrollY;
11583        } else {
11584            x = event.pageX - elementBounds.left - scrollX;
11585            y = event.pageY - elementBounds.top - scrollY;
11586        }
11587
11588        return { 
11589            x: x / (element.clientWidth / (element.width || element.clientWidth) * pixelRatio),
11590            y: y / (element.clientHeight / (element.height || element.clientHeight) * pixelRatio)
11591        };
11592    };
11593
11594})();
11595
11596
11597/***/ }),
11598/* 15 */
11599/***/ (function(module, exports, __webpack_require__) {
11600
11601/**
11602* The `Matter.Plugin` module contains functions for registering and installing plugins on modules.
11603*
11604* @class Plugin
11605*/
11606
11607var Plugin = {};
11608
11609module.exports = Plugin;
11610
11611var Common = __webpack_require__(0);
11612
11613(function() {
11614
11615    Plugin._registry = {};
11616
11617    /**
11618     * Registers a plugin object so it can be resolved later by name.
11619     * @method register
11620     * @param plugin {} The plugin to register.
11621     * @return {object} The plugin.
11622     */
11623    Plugin.register = function(plugin) {
11624        if (!Plugin.isPlugin(plugin)) {
11625            Common.warn('Plugin.register:', Plugin.toString(plugin), 'does not implement all required fields.');
11626        }
11627
11628        if (plugin.name in Plugin._registry) {
11629            var registered = Plugin._registry[plugin.name],
11630                pluginVersion = Plugin.versionParse(plugin.version).number,
11631                registeredVersion = Plugin.versionParse(registered.version).number;
11632
11633            if (pluginVersion > registeredVersion) {
11634                Common.warn('Plugin.register:', Plugin.toString(registered), 'was upgraded to', Plugin.toString(plugin));
11635                Plugin._registry[plugin.name] = plugin;
11636            } else if (pluginVersion < registeredVersion) {
11637                Common.warn('Plugin.register:', Plugin.toString(registered), 'can not be downgraded to', Plugin.toString(plugin));
11638            } else if (plugin !== registered) {
11639                Common.warn('Plugin.register:', Plugin.toString(plugin), 'is already registered to different plugin object');
11640            }
11641        } else {
11642            Plugin._registry[plugin.name] = plugin;
11643        }
11644
11645        return plugin;
11646    };
11647
11648    /**
11649     * Resolves a dependency to a plugin object from the registry if it exists. 
11650     * The `dependency` may contain a version, but only the name matters when resolving.
11651     * @method resolve
11652     * @param dependency {string} The dependency.
11653     * @return {object} The plugin if resolved, otherwise `undefined`.
11654     */
11655    Plugin.resolve = function(dependency) {
11656        return Plugin._registry[Plugin.dependencyParse(dependency).name];
11657    };
11658
11659    /**
11660     * Returns a pretty printed plugin name and version.
11661     * @method toString
11662     * @param plugin {} The plugin.
11663     * @return {string} Pretty printed plugin name and version.
11664     */
11665    Plugin.toString = function(plugin) {
11666        return typeof plugin === 'string' ? plugin : (plugin.name || 'anonymous') + '@' + (plugin.version || plugin.range || '0.0.0');
11667    };
11668
11669    /**
11670     * Returns `true` if the object meets the minimum standard to be considered a plugin.
11671     * This means it must define the following properties:
11672     * - `name`
11673     * - `version`
11674     * - `install`
11675     * @method isPlugin
11676     * @param obj {} The obj to test.
11677     * @return {boolean} `true` if the object can be considered a plugin otherwise `false`.
11678     */
11679    Plugin.isPlugin = function(obj) {
11680        return obj && obj.name && obj.version && obj.install;
11681    };
11682
11683    /**
11684     * Returns `true` if a plugin with the given `name` been installed on `module`.
11685     * @method isUsed
11686     * @param module {} The module.
11687     * @param name {string} The plugin name.
11688     * @return {boolean} `true` if a plugin with the given `name` been installed on `module`, otherwise `false`.
11689     */
11690    Plugin.isUsed = function(module, name) {
11691        return module.used.indexOf(name) > -1;
11692    };
11693
11694    /**
11695     * Returns `true` if `plugin.for` is applicable to `module` by comparing against `module.name` and `module.version`.
11696     * If `plugin.for` is not specified then it is assumed to be applicable.
11697     * The value of `plugin.for` is a string of the format `'module-name'` or `'module-name@version'`.
11698     * @method isFor
11699     * @param plugin {} The plugin.
11700     * @param module {} The module.
11701     * @return {boolean} `true` if `plugin.for` is applicable to `module`, otherwise `false`.
11702     */
11703    Plugin.isFor = function(plugin, module) {
11704        var parsed = plugin.for && Plugin.dependencyParse(plugin.for);
11705        return !plugin.for || (module.name === parsed.name && Plugin.versionSatisfies(module.version, parsed.range));
11706    };
11707
11708    /**
11709     * Installs the plugins by calling `plugin.install` on each plugin specified in `plugins` if passed, otherwise `module.uses`.
11710     * For installing plugins on `Matter` see the convenience function `Matter.use`.
11711     * Plugins may be specified either by their name or a reference to the plugin object.
11712     * Plugins themselves may specify further dependencies, but each plugin is installed only once.
11713     * Order is important, a topological sort is performed to find the best resulting order of installation.
11714     * This sorting attempts to satisfy every dependency's requested ordering, but may not be exact in all cases.
11715     * This function logs the resulting status of each dependency in the console, along with any warnings.
11716     * - A green tick ✅ indicates a dependency was resolved and installed.
11717     * - An orange diamond 🔶 indicates a dependency was resolved but a warning was thrown for it or one if its dependencies.
11718     * - A red cross ❌ indicates a dependency could not be resolved.
11719     * Avoid calling this function multiple times on the same module unless you intend to manually control installation order.
11720     * @method use
11721     * @param module {} The module install plugins on.
11722     * @param [plugins=module.uses] {} The plugins to install on module (optional, defaults to `module.uses`).
11723     */
11724    Plugin.use = function(module, plugins) {
11725        module.uses = (module.uses || []).concat(plugins || []);
11726
11727        if (module.uses.length === 0) {
11728            Common.warn('Plugin.use:', Plugin.toString(module), 'does not specify any dependencies to install.');
11729            return;
11730        }
11731
11732        var dependencies = Plugin.dependencies(module),
11733            sortedDependencies = Common.topologicalSort(dependencies),
11734            status = [];
11735
11736        for (var i = 0; i < sortedDependencies.length; i += 1) {
11737            if (sortedDependencies[i] === module.name) {
11738                continue;
11739            }
11740
11741            var plugin = Plugin.resolve(sortedDependencies[i]);
11742
11743            if (!plugin) {
11744                status.push('❌ ' + sortedDependencies[i]);
11745                continue;
11746            }
11747
11748            if (Plugin.isUsed(module, plugin.name)) {
11749                continue;
11750            }
11751
11752            if (!Plugin.isFor(plugin, module)) {
11753                Common.warn('Plugin.use:', Plugin.toString(plugin), 'is for', plugin.for, 'but installed on', Plugin.toString(module) + '.');
11754                plugin._warned = true;
11755            }
11756
11757            if (plugin.install) {
11758                plugin.install(module);
11759            } else {
11760                Common.warn('Plugin.use:', Plugin.toString(plugin), 'does not specify an install function.');
11761                plugin._warned = true;
11762            }
11763
11764            if (plugin._warned) {
11765                status.push('🔶 ' + Plugin.toString(plugin));
11766                delete plugin._warned;
11767            } else {
11768                status.push('✅ ' + Plugin.toString(plugin));
11769            }
11770
11771            module.used.push(plugin.name);
11772        }
11773
11774        if (status.length > 0) {
11775            Common.info(status.join('  '));
11776        }
11777    };
11778
11779    /**
11780     * Recursively finds all of a module's dependencies and returns a flat dependency graph.
11781     * @method dependencies
11782     * @param module {} The module.
11783     * @return {object} A dependency graph.
11784     */
11785    Plugin.dependencies = function(module, tracked) {
11786        var parsedBase = Plugin.dependencyParse(module),
11787            name = parsedBase.name;
11788
11789        tracked = tracked || {};
11790
11791        if (name in tracked) {
11792            return;
11793        }
11794
11795        module = Plugin.resolve(module) || module;
11796
11797        tracked[name] = Common.map(module.uses || [], function(dependency) {
11798            if (Plugin.isPlugin(dependency)) {
11799                Plugin.register(dependency);
11800            }
11801
11802            var parsed = Plugin.dependencyParse(dependency),
11803                resolved = Plugin.resolve(dependency);
11804
11805            if (resolved && !Plugin.versionSatisfies(resolved.version, parsed.range)) {
11806                Common.warn(
11807                    'Plugin.dependencies:', Plugin.toString(resolved), 'does not satisfy',
11808                    Plugin.toString(parsed), 'used by', Plugin.toString(parsedBase) + '.'
11809                );
11810
11811                resolved._warned = true;
11812                module._warned = true;
11813            } else if (!resolved) {
11814                Common.warn(
11815                    'Plugin.dependencies:', Plugin.toString(dependency), 'used by',
11816                    Plugin.toString(parsedBase), 'could not be resolved.'
11817                );
11818
11819                module._warned = true;
11820            }
11821
11822            return parsed.name;
11823        });
11824
11825        for (var i = 0; i < tracked[name].length; i += 1) {
11826            Plugin.dependencies(tracked[name][i], tracked);
11827        }
11828
11829        return tracked;
11830    };
11831
11832    /**
11833     * Parses a dependency string into its components.
11834     * The `dependency` is a string of the format `'module-name'` or `'module-name@version'`.
11835     * See documentation for `Plugin.versionParse` for a description of the format.
11836     * This function can also handle dependencies that are already resolved (e.g. a module object).
11837     * @method dependencyParse
11838     * @param dependency {string} The dependency of the format `'module-name'` or `'module-name@version'`.
11839     * @return {object} The dependency parsed into its components.
11840     */
11841    Plugin.dependencyParse = function(dependency) {
11842        if (Common.isString(dependency)) {
11843            var pattern = /^[\w-]+(@(\*|[\^~]?\d+\.\d+\.\d+(-[0-9A-Za-z-+]+)?))?$/;
11844
11845            if (!pattern.test(dependency)) {
11846                Common.warn('Plugin.dependencyParse:', dependency, 'is not a valid dependency string.');
11847            }
11848
11849            return {
11850                name: dependency.split('@')[0],
11851                range: dependency.split('@')[1] || '*'
11852            };
11853        }
11854
11855        return {
11856            name: dependency.name,
11857            range: dependency.range || dependency.version
11858        };
11859    };
11860
11861    /**
11862     * Parses a version string into its components.  
11863     * Versions are strictly of the format `x.y.z` (as in [semver](http://semver.org/)).
11864     * Versions may optionally have a prerelease tag in the format `x.y.z-alpha`.
11865     * Ranges are a strict subset of [npm ranges](https://docs.npmjs.com/misc/semver#advanced-range-syntax).
11866     * Only the following range types are supported:
11867     * - Tilde ranges e.g. `~1.2.3`
11868     * - Caret ranges e.g. `^1.2.3`
11869     * - Greater than ranges e.g. `>1.2.3`
11870     * - Greater than or equal ranges e.g. `>=1.2.3`
11871     * - Exact version e.g. `1.2.3`
11872     * - Any version `*`
11873     * @method versionParse
11874     * @param range {string} The version string.
11875     * @return {object} The version range parsed into its components.
11876     */
11877    Plugin.versionParse = function(range) {
11878        var pattern = /^(\*)|(\^|~|>=|>)?\s*((\d+)\.(\d+)\.(\d+))(-[0-9A-Za-z-+]+)?$/;
11879
11880        if (!pattern.test(range)) {
11881            Common.warn('Plugin.versionParse:', range, 'is not a valid version or range.');
11882        }
11883
11884        var parts = pattern.exec(range);
11885        var major = Number(parts[4]);
11886        var minor = Number(parts[5]);
11887        var patch = Number(parts[6]);
11888
11889        return {
11890            isRange: Boolean(parts[1] || parts[2]),
11891            version: parts[3],
11892            range: range,
11893            operator: parts[1] || parts[2] || '',
11894            major: major,
11895            minor: minor,
11896            patch: patch,
11897            parts: [major, minor, patch],
11898            prerelease: parts[7],
11899            number: major * 1e8 + minor * 1e4 + patch
11900        };
11901    };
11902
11903    /**
11904     * Returns `true` if `version` satisfies the given `range`.
11905     * See documentation for `Plugin.versionParse` for a description of the format.
11906     * If a version or range is not specified, then any version (`*`) is assumed to satisfy.
11907     * @method versionSatisfies
11908     * @param version {string} The version string.
11909     * @param range {string} The range string.
11910     * @return {boolean} `true` if `version` satisfies `range`, otherwise `false`.
11911     */
11912    Plugin.versionSatisfies = function(version, range) {
11913        range = range || '*';
11914
11915        var r = Plugin.versionParse(range),
11916            v = Plugin.versionParse(version);
11917
11918        if (r.isRange) {
11919            if (r.operator === '*' || version === '*') {
11920                return true;
11921            }
11922
11923            if (r.operator === '>') {
11924                return v.number > r.number;
11925            }
11926
11927            if (r.operator === '>=') {
11928                return v.number >= r.number;
11929            }
11930
11931            if (r.operator === '~') {
11932                return v.major === r.major && v.minor === r.minor && v.patch >= r.patch;
11933            }
11934
11935            if (r.operator === '^') {
11936                if (r.major > 0) {
11937                    return v.major === r.major && v.number >= r.number;
11938                }
11939
11940                if (r.minor > 0) {
11941                    return v.minor === r.minor && v.patch >= r.patch;
11942                }
11943
11944                return v.patch === r.patch;
11945            }
11946        }
11947
11948        return version === range || version === '*';
11949    };
11950
11951})();
11952
11953
11954/***/ }),
11955/* 16 */
11956/***/ (function(module, exports) {
11957
11958/**
11959* The `Matter.Contact` module contains methods for creating and manipulating collision contacts.
11960*
11961* @class Contact
11962*/
11963
11964var Contact = {};
11965
11966module.exports = Contact;
11967
11968(function() {
11969
11970    /**
11971     * Creates a new contact.
11972     * @method create
11973     * @param {vertex} [vertex]
11974     * @return {contact} A new contact
11975     */
11976    Contact.create = function(vertex) {
11977        return {
11978            vertex: vertex,
11979            normalImpulse: 0,
11980            tangentImpulse: 0
11981        };
11982    };
11983
11984})();
11985
11986
11987/***/ }),
11988/* 17 */
11989/***/ (function(module, exports, __webpack_require__) {
11990
11991/**
11992* The `Matter.Engine` module contains methods for creating and manipulating engines.
11993* An engine is a controller that manages updating the simulation of the world.
11994* See `Matter.Runner` for an optional game loop utility.
11995*
11996* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples).
11997*
11998* @class Engine
11999*/
12000
12001var Engine = {};
12002
12003module.exports = Engine;
12004
12005var Sleeping = __webpack_require__(7);
12006var Resolver = __webpack_require__(18);
12007var Detector = __webpack_require__(13);
12008var Pairs = __webpack_require__(19);
12009var Events = __webpack_require__(5);
12010var Composite = __webpack_require__(6);
12011var Constraint = __webpack_require__(10);
12012var Common = __webpack_require__(0);
12013var Body = __webpack_require__(4);
12014
12015(function() {
12016
12017    Engine._deltaMax = 1000 / 60;
12018
12019    /**
12020     * Creates a new engine. The options parameter is an object that specifies any properties you wish to override the defaults.
12021     * All properties have default values, and many are pre-calculated automatically based on other properties.
12022     * See the properties section below for detailed information on what you can pass via the `options` object.
12023     * @method create
12024     * @param {object} [options]
12025     * @return {engine} engine
12026     */
12027    Engine.create = function(options) {
12028        options = options || {};
12029
12030        var defaults = {
12031            positionIterations: 6,
12032            velocityIterations: 4,
12033            constraintIterations: 2,
12034            enableSleeping: false,
12035            events: [],
12036            plugin: {},
12037            gravity: {
12038                x: 0,
12039                y: 1,
12040                scale: 0.001
12041            },
12042            timing: {
12043                timestamp: 0,
12044                timeScale: 1,
12045                lastDelta: 0,
12046                lastElapsed: 0,
12047                lastUpdatesPerFrame: 0
12048            }
12049        };
12050
12051        var engine = Common.extend(defaults, options);
12052
12053        engine.world = options.world || Composite.create({ label: 'World' });
12054        engine.pairs = options.pairs || Pairs.create();
12055        engine.detector = options.detector || Detector.create();
12056        engine.detector.pairs = engine.pairs;
12057
12058        // for temporary back compatibility only
12059        engine.grid = { buckets: [] };
12060        engine.world.gravity = engine.gravity;
12061        engine.broadphase = engine.grid;
12062        engine.metrics = {};
12063        
12064        return engine;
12065    };
12066
12067    /**
12068     * Moves the simulation forward in time by `delta` milliseconds.
12069     * Triggers `beforeUpdate`, `beforeSolve` and `afterUpdate` events.
12070     * Triggers `collisionStart`, `collisionActive` and `collisionEnd` events.
12071     * @method update
12072     * @param {engine} engine
12073     * @param {number} [delta=16.666]
12074     */
12075    Engine.update = function(engine, delta) {
12076        var startTime = Common.now();
12077
12078        var world = engine.world,
12079            detector = engine.detector,
12080            pairs = engine.pairs,
12081            timing = engine.timing,
12082            timestamp = timing.timestamp,
12083            i;
12084
12085        // warn if high delta
12086        if (delta > Engine._deltaMax) {
12087            Common.warnOnce(
12088                'Matter.Engine.update: delta argument is recommended to be less than or equal to', Engine._deltaMax.toFixed(3), 'ms.'
12089            );
12090        }
12091
12092        delta = typeof delta !== 'undefined' ? delta : Common._baseDelta;
12093        delta *= timing.timeScale;
12094
12095        // increment timestamp
12096        timing.timestamp += delta;
12097        timing.lastDelta = delta;
12098
12099        // create an event object
12100        var event = {
12101            timestamp: timing.timestamp,
12102            delta: delta
12103        };
12104
12105        Events.trigger(engine, 'beforeUpdate', event);
12106
12107        // get all bodies and all constraints in the world
12108        var allBodies = Composite.allBodies(world),
12109            allConstraints = Composite.allConstraints(world);
12110
12111        // if the world has changed
12112        if (world.isModified) {
12113            // update the detector bodies
12114            Detector.setBodies(detector, allBodies);
12115
12116            // reset all composite modified flags
12117            Composite.setModified(world, false, false, true);
12118        }
12119
12120        // update sleeping if enabled
12121        if (engine.enableSleeping)
12122            Sleeping.update(allBodies, delta);
12123
12124        // apply gravity to all bodies
12125        Engine._bodiesApplyGravity(allBodies, engine.gravity);
12126
12127        // update all body position and rotation by integration
12128        if (delta > 0) {
12129            Engine._bodiesUpdate(allBodies, delta);
12130        }
12131
12132        Events.trigger(engine, 'beforeSolve', event);
12133
12134        // update all constraints (first pass)
12135        Constraint.preSolveAll(allBodies);
12136        for (i = 0; i < engine.constraintIterations; i++) {
12137            Constraint.solveAll(allConstraints, delta);
12138        }
12139        Constraint.postSolveAll(allBodies);
12140
12141        // find all collisions
12142        var collisions = Detector.collisions(detector);
12143
12144        // update collision pairs
12145        Pairs.update(pairs, collisions, timestamp);
12146
12147        // wake up bodies involved in collisions
12148        if (engine.enableSleeping)
12149            Sleeping.afterCollisions(pairs.list);
12150
12151        // trigger collision events
12152        if (pairs.collisionStart.length > 0) {
12153            Events.trigger(engine, 'collisionStart', { 
12154                pairs: pairs.collisionStart,
12155                timestamp: timing.timestamp,
12156                delta: delta
12157            });
12158        }
12159
12160        // iteratively resolve position between collisions
12161        var positionDamping = Common.clamp(20 / engine.positionIterations, 0, 1);
12162        
12163        Resolver.preSolvePosition(pairs.list);
12164        for (i = 0; i < engine.positionIterations; i++) {
12165            Resolver.solvePosition(pairs.list, delta, positionDamping);
12166        }
12167        Resolver.postSolvePosition(allBodies);
12168
12169        // update all constraints (second pass)
12170        Constraint.preSolveAll(allBodies);
12171        for (i = 0; i < engine.constraintIterations; i++) {
12172            Constraint.solveAll(allConstraints, delta);
12173        }
12174        Constraint.postSolveAll(allBodies);
12175
12176        // iteratively resolve velocity between collisions
12177        Resolver.preSolveVelocity(pairs.list);
12178        for (i = 0; i < engine.velocityIterations; i++) {
12179            Resolver.solveVelocity(pairs.list, delta);
12180        }
12181
12182        // update body speed and velocity properties
12183        Engine._bodiesUpdateVelocities(allBodies);
12184
12185        // trigger collision events
12186        if (pairs.collisionActive.length > 0) {
12187            Events.trigger(engine, 'collisionActive', { 
12188                pairs: pairs.collisionActive, 
12189                timestamp: timing.timestamp,
12190                delta: delta
12191            });
12192        }
12193
12194        if (pairs.collisionEnd.length > 0) {
12195            Events.trigger(engine, 'collisionEnd', {
12196                pairs: pairs.collisionEnd,
12197                timestamp: timing.timestamp,
12198                delta: delta
12199            });
12200        }
12201
12202        // clear force buffers
12203        Engine._bodiesClearForces(allBodies);
12204
12205        Events.trigger(engine, 'afterUpdate', event);
12206
12207        // log the time elapsed computing this update
12208        engine.timing.lastElapsed = Common.now() - startTime;
12209
12210        return engine;
12211    };
12212    
12213    /**
12214     * Merges two engines by keeping the configuration of `engineA` but replacing the world with the one from `engineB`.
12215     * @method merge
12216     * @param {engine} engineA
12217     * @param {engine} engineB
12218     */
12219    Engine.merge = function(engineA, engineB) {
12220        Common.extend(engineA, engineB);
12221        
12222        if (engineB.world) {
12223            engineA.world = engineB.world;
12224
12225            Engine.clear(engineA);
12226
12227            var bodies = Composite.allBodies(engineA.world);
12228
12229            for (var i = 0; i < bodies.length; i++) {
12230                var body = bodies[i];
12231                Sleeping.set(body, false);
12232                body.id = Common.nextId();
12233            }
12234        }
12235    };
12236
12237    /**
12238     * Clears the engine pairs and detector.
12239     * @method clear
12240     * @param {engine} engine
12241     */
12242    Engine.clear = function(engine) {
12243        Pairs.clear(engine.pairs);
12244        Detector.clear(engine.detector);
12245    };
12246
12247    /**
12248     * Zeroes the `body.force` and `body.torque` force buffers.
12249     * @method _bodiesClearForces
12250     * @private
12251     * @param {body[]} bodies
12252     */
12253    Engine._bodiesClearForces = function(bodies) {
12254        var bodiesLength = bodies.length;
12255
12256        for (var i = 0; i < bodiesLength; i++) {
12257            var body = bodies[i];
12258
12259            // reset force buffers
12260            body.force.x = 0;
12261            body.force.y = 0;
12262            body.torque = 0;
12263        }
12264    };
12265
12266    /**
12267     * Applies gravitational acceleration to all `bodies`.
12268     * This models a [uniform gravitational field](https://en.wikipedia.org/wiki/Gravity_of_Earth), similar to near the surface of a planet.
12269     * 
12270     * @method _bodiesApplyGravity
12271     * @private
12272     * @param {body[]} bodies
12273     * @param {vector} gravity
12274     */
12275    Engine._bodiesApplyGravity = function(bodies, gravity) {
12276        var gravityScale = typeof gravity.scale !== 'undefined' ? gravity.scale : 0.001,
12277            bodiesLength = bodies.length;
12278
12279        if ((gravity.x === 0 && gravity.y === 0) || gravityScale === 0) {
12280            return;
12281        }
12282        
12283        for (var i = 0; i < bodiesLength; i++) {
12284            var body = bodies[i];
12285
12286            if (body.isStatic || body.isSleeping)
12287                continue;
12288
12289            // add the resultant force of gravity
12290            body.force.y += body.mass * gravity.y * gravityScale;
12291            body.force.x += body.mass * gravity.x * gravityScale;
12292        }
12293    };
12294
12295    /**
12296     * Applies `Body.update` to all given `bodies`.
12297     * @method _bodiesUpdate
12298     * @private
12299     * @param {body[]} bodies
12300     * @param {number} delta The amount of time elapsed between updates
12301     */
12302    Engine._bodiesUpdate = function(bodies, delta) {
12303        var bodiesLength = bodies.length;
12304
12305        for (var i = 0; i < bodiesLength; i++) {
12306            var body = bodies[i];
12307
12308            if (body.isStatic || body.isSleeping)
12309                continue;
12310
12311            Body.update(body, delta);
12312        }
12313    };
12314
12315    /**
12316     * Applies `Body.updateVelocities` to all given `bodies`.
12317     * @method _bodiesUpdateVelocities
12318     * @private
12319     * @param {body[]} bodies
12320     */
12321    Engine._bodiesUpdateVelocities = function(bodies) {
12322        var bodiesLength = bodies.length;
12323
12324        for (var i = 0; i < bodiesLength; i++) {
12325            Body.updateVelocities(bodies[i]);
12326        }
12327    };
12328
12329    /**
12330     * A deprecated alias for `Runner.run`, use `Matter.Runner.run(engine)` instead and see `Matter.Runner` for more information.
12331     * @deprecated use Matter.Runner.run(engine) instead
12332     * @method run
12333     * @param {engine} engine
12334     */
12335
12336    /**
12337    * Fired just before an update
12338    *
12339    * @event beforeUpdate
12340    * @param {object} event An event object
12341    * @param {number} event.timestamp The engine.timing.timestamp of the event
12342    * @param {number} event.delta The delta time in milliseconds value used in the update
12343    * @param {engine} event.source The source object of the event
12344    * @param {string} event.name The name of the event
12345    */
12346
12347    /**
12348    * Fired after bodies updated based on their velocity and forces, but before any collision detection, constraints and resolving etc.
12349    *
12350    * @event beforeSolve
12351    * @param {object} event An event object
12352    * @param {number} event.timestamp The engine.timing.timestamp of the event
12353    * @param {number} event.delta The delta time in milliseconds value used in the update
12354    * @param {engine} event.source The source object of the event
12355    * @param {string} event.name The name of the event
12356    */
12357
12358    /**
12359    * Fired after engine update and all collision events
12360    *
12361    * @event afterUpdate
12362    * @param {object} event An event object
12363    * @param {number} event.timestamp The engine.timing.timestamp of the event
12364    * @param {number} event.delta The delta time in milliseconds value used in the update
12365    * @param {engine} event.source The source object of the event
12366    * @param {string} event.name The name of the event
12367    */
12368
12369    /**
12370    * Fired after engine update, provides a list of all pairs that have started to collide in the current tick (if any)
12371    *
12372    * @event collisionStart
12373    * @param {object} event An event object
12374    * @param {pair[]} event.pairs List of affected pairs
12375    * @param {number} event.timestamp The engine.timing.timestamp of the event
12376    * @param {number} event.delta The delta time in milliseconds value used in the update
12377    * @param {engine} event.source The source object of the event
12378    * @param {string} event.name The name of the event
12379    */
12380
12381    /**
12382    * Fired after engine update, provides a list of all pairs that are colliding in the current tick (if any)
12383    *
12384    * @event collisionActive
12385    * @param {object} event An event object
12386    * @param {pair[]} event.pairs List of affected pairs
12387    * @param {number} event.timestamp The engine.timing.timestamp of the event
12388    * @param {number} event.delta The delta time in milliseconds value used in the update
12389    * @param {engine} event.source The source object of the event
12390    * @param {string} event.name The name of the event
12391    */
12392
12393    /**
12394    * Fired after engine update, provides a list of all pairs that have ended collision in the current tick (if any)
12395    *
12396    * @event collisionEnd
12397    * @param {object} event An event object
12398    * @param {pair[]} event.pairs List of affected pairs
12399    * @param {number} event.timestamp The engine.timing.timestamp of the event
12400    * @param {number} event.delta The delta time in milliseconds value used in the update
12401    * @param {engine} event.source The source object of the event
12402    * @param {string} event.name The name of the event
12403    */
12404
12405    /*
12406    *
12407    *  Properties Documentation
12408    *
12409    */
12410
12411    /**
12412     * An integer `Number` that specifies the number of position iterations to perform each update.
12413     * The higher the value, the higher quality the simulation will be at the expense of performance.
12414     *
12415     * @property positionIterations
12416     * @type number
12417     * @default 6
12418     */
12419
12420    /**
12421     * An integer `Number` that specifies the number of velocity iterations to perform each update.
12422     * The higher the value, the higher quality the simulation will be at the expense of performance.
12423     *
12424     * @property velocityIterations
12425     * @type number
12426     * @default 4
12427     */
12428
12429    /**
12430     * An integer `Number` that specifies the number of constraint iterations to perform each update.
12431     * The higher the value, the higher quality the simulation will be at the expense of performance.
12432     * The default value of `2` is usually very adequate.
12433     *
12434     * @property constraintIterations
12435     * @type number
12436     * @default 2
12437     */
12438
12439    /**
12440     * A flag that specifies whether the engine should allow sleeping via the `Matter.Sleeping` module.
12441     * Sleeping can improve stability and performance, but often at the expense of accuracy.
12442     *
12443     * @property enableSleeping
12444     * @type boolean
12445     * @default false
12446     */
12447
12448    /**
12449     * An `Object` containing properties regarding the timing systems of the engine. 
12450     *
12451     * @property timing
12452     * @type object
12453     */
12454
12455    /**
12456     * A `Number` that specifies the global scaling factor of time for all bodies.
12457     * A value of `0` freezes the simulation.
12458     * A value of `0.1` gives a slow-motion effect.
12459     * A value of `1.2` gives a speed-up effect.
12460     *
12461     * @property timing.timeScale
12462     * @type number
12463     * @default 1
12464     */
12465
12466    /**
12467     * A `Number` that specifies the current simulation-time in milliseconds starting from `0`. 
12468     * It is incremented on every `Engine.update` by the given `delta` argument. 
12469     * 
12470     * @property timing.timestamp
12471     * @type number
12472     * @default 0
12473     */
12474
12475    /**
12476     * A `Number` that represents the total execution time elapsed during the last `Engine.update` in milliseconds.
12477     * It is updated by timing from the start of the last `Engine.update` call until it ends.
12478     *
12479     * This value will also include the total execution time of all event handlers directly or indirectly triggered by the engine update.
12480     * 
12481     * @property timing.lastElapsed
12482     * @type number
12483     * @default 0
12484     */
12485
12486    /**
12487     * A `Number` that represents the `delta` value used in the last engine update.
12488     * 
12489     * @property timing.lastDelta
12490     * @type number
12491     * @default 0
12492     */
12493
12494    /**
12495     * A `Matter.Detector` instance.
12496     *
12497     * @property detector
12498     * @type detector
12499     * @default a Matter.Detector instance
12500     */
12501
12502    /**
12503     * A `Matter.Grid` instance.
12504     *
12505     * @deprecated replaced by `engine.detector`
12506     * @property grid
12507     * @type grid
12508     * @default a Matter.Grid instance
12509     */
12510
12511    /**
12512     * Replaced by and now alias for `engine.grid`.
12513     *
12514     * @deprecated replaced by `engine.detector`
12515     * @property broadphase
12516     * @type grid
12517     * @default a Matter.Grid instance
12518     */
12519
12520    /**
12521     * The root `Matter.Composite` instance that will contain all bodies, constraints and other composites to be simulated by this engine.
12522     *
12523     * @property world
12524     * @type composite
12525     * @default a Matter.Composite instance
12526     */
12527
12528    /**
12529     * An object reserved for storing plugin-specific properties.
12530     *
12531     * @property plugin
12532     * @type {}
12533     */
12534
12535    /**
12536     * An optional gravitational acceleration applied to all bodies in `engine.world` on every update.
12537     * 
12538     * This models a [uniform gravitational field](https://en.wikipedia.org/wiki/Gravity_of_Earth), similar to near the surface of a planet. For gravity in other contexts, disable this and apply forces as needed.
12539     * 
12540     * To disable set the `scale` component to `0`.
12541     * 
12542     * This is split into three components for ease of use:  
12543     * a normalised direction (`x` and `y`) and magnitude (`scale`).
12544     *
12545     * @property gravity
12546     * @type object
12547     */
12548
12549    /**
12550     * The gravitational direction normal `x` component, to be multiplied by `gravity.scale`.
12551     * 
12552     * @property gravity.x
12553     * @type object
12554     * @default 0
12555     */
12556
12557    /**
12558     * The gravitational direction normal `y` component, to be multiplied by `gravity.scale`.
12559     *
12560     * @property gravity.y
12561     * @type object
12562     * @default 1
12563     */
12564
12565    /**
12566     * The magnitude of the gravitational acceleration.
12567     * 
12568     * @property gravity.scale
12569     * @type object
12570     * @default 0.001
12571     */
12572
12573})();
12574
12575
12576/***/ }),
12577/* 18 */
12578/***/ (function(module, exports, __webpack_require__) {
12579
12580/**
12581* The `Matter.Resolver` module contains methods for resolving collision pairs.
12582*
12583* @class Resolver
12584*/
12585
12586var Resolver = {};
12587
12588module.exports = Resolver;
12589
12590var Vertices = __webpack_require__(3);
12591var Common = __webpack_require__(0);
12592var Bounds = __webpack_require__(1);
12593
12594(function() {
12595
12596    Resolver._restingThresh = 2;
12597    Resolver._restingThreshTangent = Math.sqrt(6);
12598    Resolver._positionDampen = 0.9;
12599    Resolver._positionWarming = 0.8;
12600    Resolver._frictionNormalMultiplier = 5;
12601    Resolver._frictionMaxStatic = Number.MAX_VALUE;
12602
12603    /**
12604     * Prepare pairs for position solving.
12605     * @method preSolvePosition
12606     * @param {pair[]} pairs
12607     */
12608    Resolver.preSolvePosition = function(pairs) {
12609        var i,
12610            pair,
12611            contactCount,
12612            pairsLength = pairs.length;
12613
12614        // find total contacts on each body
12615        for (i = 0; i < pairsLength; i++) {
12616            pair = pairs[i];
12617            
12618            if (!pair.isActive)
12619                continue;
12620            
12621            contactCount = pair.contactCount;
12622            pair.collision.parentA.totalContacts += contactCount;
12623            pair.collision.parentB.totalContacts += contactCount;
12624        }
12625    };
12626
12627    /**
12628     * Find a solution for pair positions.
12629     * @method solvePosition
12630     * @param {pair[]} pairs
12631     * @param {number} delta
12632     * @param {number} [damping=1]
12633     */
12634    Resolver.solvePosition = function(pairs, delta, damping) {
12635        var i,
12636            pair,
12637            collision,
12638            bodyA,
12639            bodyB,
12640            normal,
12641            contactShare,
12642            positionImpulse,
12643            positionDampen = Resolver._positionDampen * (damping || 1),
12644            slopDampen = Common.clamp(delta / Common._baseDelta, 0, 1),
12645            pairsLength = pairs.length;
12646
12647        // find impulses required to resolve penetration
12648        for (i = 0; i < pairsLength; i++) {
12649            pair = pairs[i];
12650            
12651            if (!pair.isActive || pair.isSensor)
12652                continue;
12653
12654            collision = pair.collision;
12655            bodyA = collision.parentA;
12656            bodyB = collision.parentB;
12657            normal = collision.normal;
12658
12659            // get current separation between body edges involved in collision
12660            pair.separation = 
12661                collision.depth + normal.x * (bodyB.positionImpulse.x - bodyA.positionImpulse.x)
12662                + normal.y * (bodyB.positionImpulse.y - bodyA.positionImpulse.y);
12663        }
12664        
12665        for (i = 0; i < pairsLength; i++) {
12666            pair = pairs[i];
12667
12668            if (!pair.isActive || pair.isSensor)
12669                continue;
12670            
12671            collision = pair.collision;
12672            bodyA = collision.parentA;
12673            bodyB = collision.parentB;
12674            normal = collision.normal;
12675            positionImpulse = pair.separation - pair.slop * slopDampen;
12676
12677            if (bodyA.isStatic || bodyB.isStatic)
12678                positionImpulse *= 2;
12679            
12680            if (!(bodyA.isStatic || bodyA.isSleeping)) {
12681                contactShare = positionDampen / bodyA.totalContacts;
12682                bodyA.positionImpulse.x += normal.x * positionImpulse * contactShare;
12683                bodyA.positionImpulse.y += normal.y * positionImpulse * contactShare;
12684            }
12685
12686            if (!(bodyB.isStatic || bodyB.isSleeping)) {
12687                contactShare = positionDampen / bodyB.totalContacts;
12688                bodyB.positionImpulse.x -= normal.x * positionImpulse * contactShare;
12689                bodyB.positionImpulse.y -= normal.y * positionImpulse * contactShare;
12690            }
12691        }
12692    };
12693
12694    /**
12695     * Apply position resolution.
12696     * @method postSolvePosition
12697     * @param {body[]} bodies
12698     */
12699    Resolver.postSolvePosition = function(bodies) {
12700        var positionWarming = Resolver._positionWarming,
12701            bodiesLength = bodies.length,
12702            verticesTranslate = Vertices.translate,
12703            boundsUpdate = Bounds.update;
12704
12705        for (var i = 0; i < bodiesLength; i++) {
12706            var body = bodies[i],
12707                positionImpulse = body.positionImpulse,
12708                positionImpulseX = positionImpulse.x,
12709                positionImpulseY = positionImpulse.y,
12710                velocity = body.velocity;
12711
12712            // reset contact count
12713            body.totalContacts = 0;
12714
12715            if (positionImpulseX !== 0 || positionImpulseY !== 0) {
12716                // update body geometry
12717                for (var j = 0; j < body.parts.length; j++) {
12718                    var part = body.parts[j];
12719                    verticesTranslate(part.vertices, positionImpulse);
12720                    boundsUpdate(part.bounds, part.vertices, velocity);
12721                    part.position.x += positionImpulseX;
12722                    part.position.y += positionImpulseY;
12723                }
12724
12725                // move the body without changing velocity
12726                body.positionPrev.x += positionImpulseX;
12727                body.positionPrev.y += positionImpulseY;
12728
12729                if (positionImpulseX * velocity.x + positionImpulseY * velocity.y < 0) {
12730                    // reset cached impulse if the body has velocity along it
12731                    positionImpulse.x = 0;
12732                    positionImpulse.y = 0;
12733                } else {
12734                    // warm the next iteration
12735                    positionImpulse.x *= positionWarming;
12736                    positionImpulse.y *= positionWarming;
12737                }
12738            }
12739        }
12740    };
12741
12742    /**
12743     * Prepare pairs for velocity solving.
12744     * @method preSolveVelocity
12745     * @param {pair[]} pairs
12746     */
12747    Resolver.preSolveVelocity = function(pairs) {
12748        var pairsLength = pairs.length,
12749            i,
12750            j;
12751        
12752        for (i = 0; i < pairsLength; i++) {
12753            var pair = pairs[i];
12754            
12755            if (!pair.isActive || pair.isSensor)
12756                continue;
12757            
12758            var contacts = pair.contacts,
12759                contactCount = pair.contactCount,
12760                collision = pair.collision,
12761                bodyA = collision.parentA,
12762                bodyB = collision.parentB,
12763                normal = collision.normal,
12764                tangent = collision.tangent;
12765    
12766            // resolve each contact
12767            for (j = 0; j < contactCount; j++) {
12768                var contact = contacts[j],
12769                    contactVertex = contact.vertex,
12770                    normalImpulse = contact.normalImpulse,
12771                    tangentImpulse = contact.tangentImpulse;
12772    
12773                if (normalImpulse !== 0 || tangentImpulse !== 0) {
12774                    // total impulse from contact
12775                    var impulseX = normal.x * normalImpulse + tangent.x * tangentImpulse,
12776                        impulseY = normal.y * normalImpulse + tangent.y * tangentImpulse;
12777                    
12778                    // apply impulse from contact
12779                    if (!(bodyA.isStatic || bodyA.isSleeping)) {
12780                        bodyA.positionPrev.x += impulseX * bodyA.inverseMass;
12781                        bodyA.positionPrev.y += impulseY * bodyA.inverseMass;
12782                        bodyA.anglePrev += bodyA.inverseInertia * (
12783                            (contactVertex.x - bodyA.position.x) * impulseY
12784                            - (contactVertex.y - bodyA.position.y) * impulseX
12785                        );
12786                    }
12787    
12788                    if (!(bodyB.isStatic || bodyB.isSleeping)) {
12789                        bodyB.positionPrev.x -= impulseX * bodyB.inverseMass;
12790                        bodyB.positionPrev.y -= impulseY * bodyB.inverseMass;
12791                        bodyB.anglePrev -= bodyB.inverseInertia * (
12792                            (contactVertex.x - bodyB.position.x) * impulseY 
12793                            - (contactVertex.y - bodyB.position.y) * impulseX
12794                        );
12795                    }
12796                }
12797            }
12798        }
12799    };
12800
12801    /**
12802     * Find a solution for pair velocities.
12803     * @method solveVelocity
12804     * @param {pair[]} pairs
12805     * @param {number} delta
12806     */
12807    Resolver.solveVelocity = function(pairs, delta) {
12808        var timeScale = delta / Common._baseDelta,
12809            timeScaleSquared = timeScale * timeScale,
12810            timeScaleCubed = timeScaleSquared * timeScale,
12811            restingThresh = -Resolver._restingThresh * timeScale,
12812            restingThreshTangent = Resolver._restingThreshTangent,
12813            frictionNormalMultiplier = Resolver._frictionNormalMultiplier * timeScale,
12814            frictionMaxStatic = Resolver._frictionMaxStatic,
12815            pairsLength = pairs.length,
12816            tangentImpulse,
12817            maxFriction,
12818            i,
12819            j;
12820
12821        for (i = 0; i < pairsLength; i++) {
12822            var pair = pairs[i];
12823            
12824            if (!pair.isActive || pair.isSensor)
12825                continue;
12826            
12827            var collision = pair.collision,
12828                bodyA = collision.parentA,
12829                bodyB = collision.parentB,
12830                normalX = collision.normal.x,
12831                normalY = collision.normal.y,
12832                tangentX = collision.tangent.x,
12833                tangentY = collision.tangent.y,
12834                inverseMassTotal = pair.inverseMass,
12835                friction = pair.friction * pair.frictionStatic * frictionNormalMultiplier,
12836                contacts = pair.contacts,
12837                contactCount = pair.contactCount,
12838                contactShare = 1 / contactCount;
12839
12840            // get body velocities
12841            var bodyAVelocityX = bodyA.position.x - bodyA.positionPrev.x,
12842                bodyAVelocityY = bodyA.position.y - bodyA.positionPrev.y,
12843                bodyAAngularVelocity = bodyA.angle - bodyA.anglePrev,
12844                bodyBVelocityX = bodyB.position.x - bodyB.positionPrev.x,
12845                bodyBVelocityY = bodyB.position.y - bodyB.positionPrev.y,
12846                bodyBAngularVelocity = bodyB.angle - bodyB.anglePrev;
12847
12848            // resolve each contact
12849            for (j = 0; j < contactCount; j++) {
12850                var contact = contacts[j],
12851                    contactVertex = contact.vertex;
12852
12853                var offsetAX = contactVertex.x - bodyA.position.x,
12854                    offsetAY = contactVertex.y - bodyA.position.y,
12855                    offsetBX = contactVertex.x - bodyB.position.x,
12856                    offsetBY = contactVertex.y - bodyB.position.y;
12857 
12858                var velocityPointAX = bodyAVelocityX - offsetAY * bodyAAngularVelocity,
12859                    velocityPointAY = bodyAVelocityY + offsetAX * bodyAAngularVelocity,
12860                    velocityPointBX = bodyBVelocityX - offsetBY * bodyBAngularVelocity,
12861                    velocityPointBY = bodyBVelocityY + offsetBX * bodyBAngularVelocity;
12862
12863                var relativeVelocityX = velocityPointAX - velocityPointBX,
12864                    relativeVelocityY = velocityPointAY - velocityPointBY;
12865
12866                var normalVelocity = normalX * relativeVelocityX + normalY * relativeVelocityY,
12867                    tangentVelocity = tangentX * relativeVelocityX + tangentY * relativeVelocityY;
12868
12869                // coulomb friction
12870                var normalOverlap = pair.separation + normalVelocity;
12871                var normalForce = Math.min(normalOverlap, 1);
12872                normalForce = normalOverlap < 0 ? 0 : normalForce;
12873
12874                var frictionLimit = normalForce * friction;
12875
12876                if (tangentVelocity < -frictionLimit || tangentVelocity > frictionLimit) {
12877                    maxFriction = (tangentVelocity > 0 ? tangentVelocity : -tangentVelocity);
12878                    tangentImpulse = pair.friction * (tangentVelocity > 0 ? 1 : -1) * timeScaleCubed;
12879                    
12880                    if (tangentImpulse < -maxFriction) {
12881                        tangentImpulse = -maxFriction;
12882                    } else if (tangentImpulse > maxFriction) {
12883                        tangentImpulse = maxFriction;
12884                    }
12885                } else {
12886                    tangentImpulse = tangentVelocity;
12887                    maxFriction = frictionMaxStatic;
12888                }
12889
12890                // account for mass, inertia and contact offset
12891                var oAcN = offsetAX * normalY - offsetAY * normalX,
12892                    oBcN = offsetBX * normalY - offsetBY * normalX,
12893                    share = contactShare / (inverseMassTotal + bodyA.inverseInertia * oAcN * oAcN + bodyB.inverseInertia * oBcN * oBcN);
12894
12895                // raw impulses
12896                var normalImpulse = (1 + pair.restitution) * normalVelocity * share;
12897                tangentImpulse *= share;
12898
12899                // handle high velocity and resting collisions separately
12900                if (normalVelocity < restingThresh) {
12901                    // high normal velocity so clear cached contact normal impulse
12902                    contact.normalImpulse = 0;
12903                } else {
12904                    // solve resting collision constraints using Erin Catto's method (GDC08)
12905                    // impulse constraint tends to 0
12906                    var contactNormalImpulse = contact.normalImpulse;
12907                    contact.normalImpulse += normalImpulse;
12908                    if (contact.normalImpulse > 0) contact.normalImpulse = 0;
12909                    normalImpulse = contact.normalImpulse - contactNormalImpulse;
12910                }
12911
12912                // handle high velocity and resting collisions separately
12913                if (tangentVelocity < -restingThreshTangent || tangentVelocity > restingThreshTangent) {
12914                    // high tangent velocity so clear cached contact tangent impulse
12915                    contact.tangentImpulse = 0;
12916                } else {
12917                    // solve resting collision constraints using Erin Catto's method (GDC08)
12918                    // tangent impulse tends to -tangentSpeed or +tangentSpeed
12919                    var contactTangentImpulse = contact.tangentImpulse;
12920                    contact.tangentImpulse += tangentImpulse;
12921                    if (contact.tangentImpulse < -maxFriction) contact.tangentImpulse = -maxFriction;
12922                    if (contact.tangentImpulse > maxFriction) contact.tangentImpulse = maxFriction;
12923                    tangentImpulse = contact.tangentImpulse - contactTangentImpulse;
12924                }
12925
12926                // total impulse from contact
12927                var impulseX = normalX * normalImpulse + tangentX * tangentImpulse,
12928                    impulseY = normalY * normalImpulse + tangentY * tangentImpulse;
12929                
12930                // apply impulse from contact
12931                if (!(bodyA.isStatic || bodyA.isSleeping)) {
12932                    bodyA.positionPrev.x += impulseX * bodyA.inverseMass;
12933                    bodyA.positionPrev.y += impulseY * bodyA.inverseMass;
12934                    bodyA.anglePrev += (offsetAX * impulseY - offsetAY * impulseX) * bodyA.inverseInertia;
12935                }
12936
12937                if (!(bodyB.isStatic || bodyB.isSleeping)) {
12938                    bodyB.positionPrev.x -= impulseX * bodyB.inverseMass;
12939                    bodyB.positionPrev.y -= impulseY * bodyB.inverseMass;
12940                    bodyB.anglePrev -= (offsetBX * impulseY - offsetBY * impulseX) * bodyB.inverseInertia;
12941                }
12942            }
12943        }
12944    };
12945
12946})();
12947
12948
12949/***/ }),
12950/* 19 */
12951/***/ (function(module, exports, __webpack_require__) {
12952
12953/**
12954* The `Matter.Pairs` module contains methods for creating and manipulating collision pair sets.
12955*
12956* @class Pairs
12957*/
12958
12959var Pairs = {};
12960
12961module.exports = Pairs;
12962
12963var Pair = __webpack_require__(9);
12964var Common = __webpack_require__(0);
12965
12966(function() {
12967
12968    /**
12969     * Creates a new pairs structure.
12970     * @method create
12971     * @param {object} options
12972     * @return {pairs} A new pairs structure
12973     */
12974    Pairs.create = function(options) {
12975        return Common.extend({ 
12976            table: {},
12977            list: [],
12978            collisionStart: [],
12979            collisionActive: [],
12980            collisionEnd: []
12981        }, options);
12982    };
12983
12984    /**
12985     * Updates pairs given a list of collisions.
12986     * @method update
12987     * @param {object} pairs
12988     * @param {collision[]} collisions
12989     * @param {number} timestamp
12990     */
12991    Pairs.update = function(pairs, collisions, timestamp) {
12992        var pairUpdate = Pair.update,
12993            pairCreate = Pair.create,
12994            pairSetActive = Pair.setActive,
12995            pairsTable = pairs.table,
12996            pairsList = pairs.list,
12997            pairsListLength = pairsList.length,
12998            pairsListIndex = pairsListLength,
12999            collisionStart = pairs.collisionStart,
13000            collisionEnd = pairs.collisionEnd,
13001            collisionActive = pairs.collisionActive,
13002            collisionsLength = collisions.length,
13003            collisionStartIndex = 0,
13004            collisionEndIndex = 0,
13005            collisionActiveIndex = 0,
13006            collision,
13007            pair,
13008            i;
13009
13010        for (i = 0; i < collisionsLength; i++) {
13011            collision = collisions[i];
13012            pair = collision.pair;
13013
13014            if (pair) {
13015                // pair already exists (but may or may not be active)
13016                if (pair.isActive) {
13017                    // pair exists and is active
13018                    collisionActive[collisionActiveIndex++] = pair;
13019                }
13020
13021                // update the pair
13022                pairUpdate(pair, collision, timestamp);
13023            } else {
13024                // pair did not exist, create a new pair
13025                pair = pairCreate(collision, timestamp);
13026                pairsTable[pair.id] = pair;
13027
13028                // add the new pair
13029                collisionStart[collisionStartIndex++] = pair;
13030                pairsList[pairsListIndex++] = pair;
13031            }
13032        }
13033
13034        // find pairs that are no longer active
13035        pairsListIndex = 0;
13036        pairsListLength = pairsList.length;
13037
13038        for (i = 0; i < pairsListLength; i++) {
13039            pair = pairsList[i];
13040            
13041            // pair is active if updated this timestep
13042            if (pair.timeUpdated >= timestamp) {
13043                // keep active pairs
13044                pairsList[pairsListIndex++] = pair;
13045            } else {
13046                pairSetActive(pair, false, timestamp);
13047
13048                // keep inactive pairs if both bodies may be sleeping
13049                if (pair.collision.bodyA.sleepCounter > 0 && pair.collision.bodyB.sleepCounter > 0) {
13050                    pairsList[pairsListIndex++] = pair;
13051                } else {
13052                    // remove inactive pairs if either body awake
13053                    collisionEnd[collisionEndIndex++] = pair;
13054                    delete pairsTable[pair.id];
13055                }
13056            }
13057        }
13058
13059        // update array lengths if changed
13060        if (pairsList.length !== pairsListIndex) {
13061            pairsList.length = pairsListIndex;
13062        }
13063
13064        if (collisionStart.length !== collisionStartIndex) {
13065            collisionStart.length = collisionStartIndex;
13066        }
13067
13068        if (collisionEnd.length !== collisionEndIndex) {
13069            collisionEnd.length = collisionEndIndex;
13070        }
13071
13072        if (collisionActive.length !== collisionActiveIndex) {
13073            collisionActive.length = collisionActiveIndex;
13074        }
13075    };
13076
13077    /**
13078     * Clears the given pairs structure.
13079     * @method clear
13080     * @param {pairs} pairs
13081     * @return {pairs} pairs
13082     */
13083    Pairs.clear = function(pairs) {
13084        pairs.table = {};
13085        pairs.list.length = 0;
13086        pairs.collisionStart.length = 0;
13087        pairs.collisionActive.length = 0;
13088        pairs.collisionEnd.length = 0;
13089        return pairs;
13090    };
13091
13092})();
13093
13094
13095/***/ }),
13096/* 20 */
13097/***/ (function(module, exports, __webpack_require__) {
13098
13099var Matter = module.exports = __webpack_require__(21);
vendor: 2,660 bytes, lines 13099-13189
13099
13100
13101Matter.Axes = __webpack_require__(11);
13102Matter.Bodies = __webpack_require__(12);
13103Matter.Body = __webpack_require__(4);
13104Matter.Bounds = __webpack_require__(1);
13105Matter.Collision = __webpack_require__(8);
13106Matter.Common = __webpack_require__(0);
13107Matter.Composite = __webpack_require__(6);
13108Matter.Composites = __webpack_require__(22);
13109Matter.Constraint = __webpack_require__(10);
13110Matter.Contact = __webpack_require__(16);
13111Matter.Detector = __webpack_require__(13);
13112Matter.Engine = __webpack_require__(17);
13113Matter.Events = __webpack_require__(5);
13114Matter.Grid = __webpack_require__(23);
13115Matter.Mouse = __webpack_require__(14);
13116Matter.MouseConstraint = __webpack_require__(24);
13117Matter.Pair = __webpack_require__(9);
13118Matter.Pairs = __webpack_require__(19);
13119Matter.Plugin = __webpack_require__(15);
13120Matter.Query = __webpack_require__(25);
13121Matter.Render = __webpack_require__(26);
13122Matter.Resolver = __webpack_require__(18);
13123Matter.Runner = __webpack_require__(27);
13124Matter.SAT = __webpack_require__(28);
13125Matter.Sleeping = __webpack_require__(7);
13126Matter.Svg = __webpack_require__(29);
13127Matter.Vector = __webpack_require__(2);
13128Matter.Vertices = __webpack_require__(3);
13129Matter.World = __webpack_require__(30);
13130
13131// temporary back compatibility
13132Matter.Engine.run = Matter.Runner.run;
13133Matter.Common.deprecated(Matter.Engine, 'run', 'Engine.run ➤ use Matter.Runner.run(engine) instead');
13134
13135
13136/***/ }),
13137/* 21 */
13138/***/ (function(module, exports, __webpack_require__) {
13139
13140/**
13141* The `Matter` module is the top level namespace. It also includes a function for installing plugins on top of the library.
13142*
13143* @class Matter
13144*/
13145
13146var Matter = {};
13147
13148module.exports = Matter;
13149
13150var Plugin = __webpack_require__(15);
13151var Common = __webpack_require__(0);
13152
13153(function() {
13154
13155    /**
13156     * The library name.
13157     * @property name
13158     * @readOnly
13159     * @type {String}
13160     */
13161    Matter.name = 'matter-js';
13162
13163    /**
13164     * The library version.
13165     * @property version
13166     * @readOnly
13167     * @type {String}
13168     */
13169    Matter.version =  true ? "0.20.0" : undefined;
13170
13171    /**
13172     * A list of plugin dependencies to be installed. These are normally set and installed through `Matter.use`.
13173     * Alternatively you may set `Matter.uses` manually and install them by calling `Plugin.use(Matter)`.
13174     * @property uses
13175     * @type {Array}
13176     */
13177    Matter.uses = [];
13178
13179    /**
13180     * The plugins that have been installed through `Matter.Plugin.install`. Read only.
13181     * @property used
13182     * @readOnly
13183     * @type {Array}
13184     */
13185    Matter.used = [];
13186
13187    /**
13188     * Installs the given plugins on the `Matter` namespace.
13189     * This is a short-hand for `Plugin.use`, see it for more information.
13190     * Call this function once at the start of your code, with all of the plugins you wish to install as arguments.
13191     * Avoid calling this function multiple times unless you intend to manually control installation order.
13192     * @method use
13193     * @param ...plugin {Function} The plugin(s) to install on `base` (multi-argument).
13194     */
13195    Matter.use = function() {
13196        Plugin.use(Matter, Array.prototype.slice.call(arguments));
13197    };
13198
13199    /**
13200     * Chains a function to excute before the original function on the given `path` relative to `Matter`.
13201     * See also docs for `Common.chain`.
13202     * @method before
13203     * @param {string} path The path relative to `Matter`
13204     * @param {function} func The function to chain before the original
13205     * @return {function} The chained function that replaced the original
13206     */
13207    Matter.before = function(path, func) {
13208        path = path.replace(/^Matter./, '');
13209        return Common.chainPathBefore(Matter, path, func);
13210    };
13211
13212    /**
13213     * Chains a function to excute after the original function on the given `path` relative to `Matter`.
13214     * See also docs for `Common.chain`.
13215     * @method after
13216     * @param {string} path The path relative to `Matter`
13217     * @param {function} func The function to chain after the original
13218     * @return {function} The chained function that replaced the original
13219     */
13220    Matter.after = function(path, func) {
13221        path = path.replace(/^Matter./, '');
13222        return Common.chainPathAfter(Matter, path, func);
13223    };
13224
13225})();
vendor: 122,435 bytes, lines 13225-17001
13225
13226
13227
13228/***/ }),
13229/* 22 */
13230/***/ (function(module, exports, __webpack_require__) {
13231
13232/**
13233* The `Matter.Composites` module contains factory methods for creating composite bodies
13234* with commonly used configurations (such as stacks and chains).
13235*
13236* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples).
13237*
13238* @class Composites
13239*/
13240
13241var Composites = {};
13242
13243module.exports = Composites;
13244
13245var Composite = __webpack_require__(6);
13246var Constraint = __webpack_require__(10);
13247var Common = __webpack_require__(0);
13248var Body = __webpack_require__(4);
13249var Bodies = __webpack_require__(12);
13250var deprecated = Common.deprecated;
13251
13252(function() {
13253
13254    /**
13255     * Create a new composite containing bodies created in the callback in a grid arrangement.
13256     * This function uses the body's bounds to prevent overlaps.
13257     * @method stack
13258     * @param {number} x Starting position in X.
13259     * @param {number} y Starting position in Y.
13260     * @param {number} columns
13261     * @param {number} rows
13262     * @param {number} columnGap
13263     * @param {number} rowGap
13264     * @param {function} callback
13265     * @return {composite} A new composite containing objects created in the callback
13266     */
13267    Composites.stack = function(x, y, columns, rows, columnGap, rowGap, callback) {
13268        var stack = Composite.create({ label: 'Stack' }),
13269            currentX = x,
13270            currentY = y,
13271            lastBody,
13272            i = 0;
13273
13274        for (var row = 0; row < rows; row++) {
13275            var maxHeight = 0;
13276            
13277            for (var column = 0; column < columns; column++) {
13278                var body = callback(currentX, currentY, column, row, lastBody, i);
13279                    
13280                if (body) {
13281                    var bodyHeight = body.bounds.max.y - body.bounds.min.y,
13282                        bodyWidth = body.bounds.max.x - body.bounds.min.x; 
13283
13284                    if (bodyHeight > maxHeight)
13285                        maxHeight = bodyHeight;
13286                    
13287                    Body.translate(body, { x: bodyWidth * 0.5, y: bodyHeight * 0.5 });
13288
13289                    currentX = body.bounds.max.x + columnGap;
13290
13291                    Composite.addBody(stack, body);
13292                    
13293                    lastBody = body;
13294                    i += 1;
13295                } else {
13296                    currentX += columnGap;
13297                }
13298            }
13299            
13300            currentY += maxHeight + rowGap;
13301            currentX = x;
13302        }
13303
13304        return stack;
13305    };
13306    
13307    /**
13308     * Chains all bodies in the given composite together using constraints.
13309     * @method chain
13310     * @param {composite} composite
13311     * @param {number} xOffsetA
13312     * @param {number} yOffsetA
13313     * @param {number} xOffsetB
13314     * @param {number} yOffsetB
13315     * @param {object} options
13316     * @return {composite} A new composite containing objects chained together with constraints
13317     */
13318    Composites.chain = function(composite, xOffsetA, yOffsetA, xOffsetB, yOffsetB, options) {
13319        var bodies = composite.bodies;
13320        
13321        for (var i = 1; i < bodies.length; i++) {
13322            var bodyA = bodies[i - 1],
13323                bodyB = bodies[i],
13324                bodyAHeight = bodyA.bounds.max.y - bodyA.bounds.min.y,
13325                bodyAWidth = bodyA.bounds.max.x - bodyA.bounds.min.x, 
13326                bodyBHeight = bodyB.bounds.max.y - bodyB.bounds.min.y,
13327                bodyBWidth = bodyB.bounds.max.x - bodyB.bounds.min.x;
13328        
13329            var defaults = {
13330                bodyA: bodyA,
13331                pointA: { x: bodyAWidth * xOffsetA, y: bodyAHeight * yOffsetA },
13332                bodyB: bodyB,
13333                pointB: { x: bodyBWidth * xOffsetB, y: bodyBHeight * yOffsetB }
13334            };
13335            
13336            var constraint = Common.extend(defaults, options);
13337        
13338            Composite.addConstraint(composite, Constraint.create(constraint));
13339        }
13340
13341        composite.label += ' Chain';
13342        
13343        return composite;
13344    };
13345
13346    /**
13347     * Connects bodies in the composite with constraints in a grid pattern, with optional cross braces.
13348     * @method mesh
13349     * @param {composite} composite
13350     * @param {number} columns
13351     * @param {number} rows
13352     * @param {boolean} crossBrace
13353     * @param {object} options
13354     * @return {composite} The composite containing objects meshed together with constraints
13355     */
13356    Composites.mesh = function(composite, columns, rows, crossBrace, options) {
13357        var bodies = composite.bodies,
13358            row,
13359            col,
13360            bodyA,
13361            bodyB,
13362            bodyC;
13363        
13364        for (row = 0; row < rows; row++) {
13365            for (col = 1; col < columns; col++) {
13366                bodyA = bodies[(col - 1) + (row * columns)];
13367                bodyB = bodies[col + (row * columns)];
13368                Composite.addConstraint(composite, Constraint.create(Common.extend({ bodyA: bodyA, bodyB: bodyB }, options)));
13369            }
13370
13371            if (row > 0) {
13372                for (col = 0; col < columns; col++) {
13373                    bodyA = bodies[col + ((row - 1) * columns)];
13374                    bodyB = bodies[col + (row * columns)];
13375                    Composite.addConstraint(composite, Constraint.create(Common.extend({ bodyA: bodyA, bodyB: bodyB }, options)));
13376
13377                    if (crossBrace && col > 0) {
13378                        bodyC = bodies[(col - 1) + ((row - 1) * columns)];
13379                        Composite.addConstraint(composite, Constraint.create(Common.extend({ bodyA: bodyC, bodyB: bodyB }, options)));
13380                    }
13381
13382                    if (crossBrace && col < columns - 1) {
13383                        bodyC = bodies[(col + 1) + ((row - 1) * columns)];
13384                        Composite.addConstraint(composite, Constraint.create(Common.extend({ bodyA: bodyC, bodyB: bodyB }, options)));
13385                    }
13386                }
13387            }
13388        }
13389
13390        composite.label += ' Mesh';
13391        
13392        return composite;
13393    };
13394    
13395    /**
13396     * Create a new composite containing bodies created in the callback in a pyramid arrangement.
13397     * This function uses the body's bounds to prevent overlaps.
13398     * @method pyramid
13399     * @param {number} x Starting position in X.
13400     * @param {number} y Starting position in Y.
13401     * @param {number} columns
13402     * @param {number} rows
13403     * @param {number} columnGap
13404     * @param {number} rowGap
13405     * @param {function} callback
13406     * @return {composite} A new composite containing objects created in the callback
13407     */
13408    Composites.pyramid = function(x, y, columns, rows, columnGap, rowGap, callback) {
13409        return Composites.stack(x, y, columns, rows, columnGap, rowGap, function(stackX, stackY, column, row, lastBody, i) {
13410            var actualRows = Math.min(rows, Math.ceil(columns / 2)),
13411                lastBodyWidth = lastBody ? lastBody.bounds.max.x - lastBody.bounds.min.x : 0;
13412            
13413            if (row > actualRows)
13414                return;
13415            
13416            // reverse row order
13417            row = actualRows - row;
13418            
13419            var start = row,
13420                end = columns - 1 - row;
13421
13422            if (column < start || column > end)
13423                return;
13424            
13425            // retroactively fix the first body's position, since width was unknown
13426            if (i === 1) {
13427                Body.translate(lastBody, { x: (column + (columns % 2 === 1 ? 1 : -1)) * lastBodyWidth, y: 0 });
13428            }
13429
13430            var xOffset = lastBody ? column * lastBodyWidth : 0;
13431            
13432            return callback(x + xOffset + column * columnGap, stackY, column, row, lastBody, i);
13433        });
13434    };
13435
13436    /**
13437     * This has now moved to the [newtonsCradle example](https://github.com/liabru/matter-js/blob/master/examples/newtonsCradle.js), follow that instead as this function is deprecated here.
13438     * @deprecated moved to newtonsCradle example
13439     * @method newtonsCradle
13440     * @param {number} x Starting position in X.
13441     * @param {number} y Starting position in Y.
13442     * @param {number} number
13443     * @param {number} size
13444     * @param {number} length
13445     * @return {composite} A new composite newtonsCradle body
13446     */
13447    Composites.newtonsCradle = function(x, y, number, size, length) {
13448        var newtonsCradle = Composite.create({ label: 'Newtons Cradle' });
13449
13450        for (var i = 0; i < number; i++) {
13451            var separation = 1.9,
13452                circle = Bodies.circle(x + i * (size * separation), y + length, size, 
13453                    { inertia: Infinity, restitution: 1, friction: 0, frictionAir: 0.0001, slop: 1 }),
13454                constraint = Constraint.create({ pointA: { x: x + i * (size * separation), y: y }, bodyB: circle });
13455
13456            Composite.addBody(newtonsCradle, circle);
13457            Composite.addConstraint(newtonsCradle, constraint);
13458        }
13459
13460        return newtonsCradle;
13461    };
13462
13463    deprecated(Composites, 'newtonsCradle', 'Composites.newtonsCradle ➤ moved to newtonsCradle example');
13464    
13465    /**
13466     * This has now moved to the [car example](https://github.com/liabru/matter-js/blob/master/examples/car.js), follow that instead as this function is deprecated here.
13467     * @deprecated moved to car example
13468     * @method car
13469     * @param {number} x Starting position in X.
13470     * @param {number} y Starting position in Y.
13471     * @param {number} width
13472     * @param {number} height
13473     * @param {number} wheelSize
13474     * @return {composite} A new composite car body
13475     */
13476    Composites.car = function(x, y, width, height, wheelSize) {
13477        var group = Body.nextGroup(true),
13478            wheelBase = 20,
13479            wheelAOffset = -width * 0.5 + wheelBase,
13480            wheelBOffset = width * 0.5 - wheelBase,
13481            wheelYOffset = 0;
13482    
13483        var car = Composite.create({ label: 'Car' }),
13484            body = Bodies.rectangle(x, y, width, height, { 
13485                collisionFilter: {
13486                    group: group
13487                },
13488                chamfer: {
13489                    radius: height * 0.5
13490                },
13491                density: 0.0002
13492            });
13493    
13494        var wheelA = Bodies.circle(x + wheelAOffset, y + wheelYOffset, wheelSize, { 
13495            collisionFilter: {
13496                group: group
13497            },
13498            friction: 0.8
13499        });
13500                    
13501        var wheelB = Bodies.circle(x + wheelBOffset, y + wheelYOffset, wheelSize, { 
13502            collisionFilter: {
13503                group: group
13504            },
13505            friction: 0.8
13506        });
13507                    
13508        var axelA = Constraint.create({
13509            bodyB: body,
13510            pointB: { x: wheelAOffset, y: wheelYOffset },
13511            bodyA: wheelA,
13512            stiffness: 1,
13513            length: 0
13514        });
13515                        
13516        var axelB = Constraint.create({
13517            bodyB: body,
13518            pointB: { x: wheelBOffset, y: wheelYOffset },
13519            bodyA: wheelB,
13520            stiffness: 1,
13521            length: 0
13522        });
13523        
13524        Composite.addBody(car, body);
13525        Composite.addBody(car, wheelA);
13526        Composite.addBody(car, wheelB);
13527        Composite.addConstraint(car, axelA);
13528        Composite.addConstraint(car, axelB);
13529
13530        return car;
13531    };
13532
13533    deprecated(Composites, 'car', 'Composites.car ➤ moved to car example');
13534
13535    /**
13536     * This has now moved to the [softBody example](https://github.com/liabru/matter-js/blob/master/examples/softBody.js)
13537     * and the [cloth example](https://github.com/liabru/matter-js/blob/master/examples/cloth.js), follow those instead as this function is deprecated here.
13538     * @deprecated moved to softBody and cloth examples
13539     * @method softBody
13540     * @param {number} x Starting position in X.
13541     * @param {number} y Starting position in Y.
13542     * @param {number} columns
13543     * @param {number} rows
13544     * @param {number} columnGap
13545     * @param {number} rowGap
13546     * @param {boolean} crossBrace
13547     * @param {number} particleRadius
13548     * @param {} particleOptions
13549     * @param {} constraintOptions
13550     * @return {composite} A new composite softBody
13551     */
13552    Composites.softBody = function(x, y, columns, rows, columnGap, rowGap, crossBrace, particleRadius, particleOptions, constraintOptions) {
13553        particleOptions = Common.extend({ inertia: Infinity }, particleOptions);
13554        constraintOptions = Common.extend({ stiffness: 0.2, render: { type: 'line', anchors: false } }, constraintOptions);
13555
13556        var softBody = Composites.stack(x, y, columns, rows, columnGap, rowGap, function(stackX, stackY) {
13557            return Bodies.circle(stackX, stackY, particleRadius, particleOptions);
13558        });
13559
13560        Composites.mesh(softBody, columns, rows, crossBrace, constraintOptions);
13561
13562        softBody.label = 'Soft Body';
13563
13564        return softBody;
13565    };
13566
13567    deprecated(Composites, 'softBody', 'Composites.softBody ➤ moved to softBody and cloth examples');
13568})();
13569
13570
13571/***/ }),
13572/* 23 */
13573/***/ (function(module, exports, __webpack_require__) {
13574
13575/**
13576* This module has now been replaced by `Matter.Detector`.
13577*
13578* All usage should be migrated to `Matter.Detector` or another alternative.
13579* For back-compatibility purposes this module will remain for a short term and then later removed in a future release.
13580*
13581* The `Matter.Grid` module contains methods for creating and manipulating collision broadphase grid structures.
13582*
13583* @class Grid
13584* @deprecated
13585*/
13586
13587var Grid = {};
13588
13589module.exports = Grid;
13590
13591var Pair = __webpack_require__(9);
13592var Common = __webpack_require__(0);
13593var deprecated = Common.deprecated;
13594
13595(function() {
13596
13597    /**
13598     * Creates a new grid.
13599     * @deprecated replaced by Matter.Detector
13600     * @method create
13601     * @param {} options
13602     * @return {grid} A new grid
13603     */
13604    Grid.create = function(options) {
13605        var defaults = {
13606            buckets: {},
13607            pairs: {},
13608            pairsList: [],
13609            bucketWidth: 48,
13610            bucketHeight: 48
13611        };
13612
13613        return Common.extend(defaults, options);
13614    };
13615
13616    /**
13617     * The width of a single grid bucket.
13618     *
13619     * @property bucketWidth
13620     * @type number
13621     * @default 48
13622     */
13623
13624    /**
13625     * The height of a single grid bucket.
13626     *
13627     * @property bucketHeight
13628     * @type number
13629     * @default 48
13630     */
13631
13632    /**
13633     * Updates the grid.
13634     * @deprecated replaced by Matter.Detector
13635     * @method update
13636     * @param {grid} grid
13637     * @param {body[]} bodies
13638     * @param {engine} engine
13639     * @param {boolean} forceUpdate
13640     */
13641    Grid.update = function(grid, bodies, engine, forceUpdate) {
13642        var i, col, row,
13643            world = engine.world,
13644            buckets = grid.buckets,
13645            bucket,
13646            bucketId,
13647            gridChanged = false;
13648
13649        for (i = 0; i < bodies.length; i++) {
13650            var body = bodies[i];
13651
13652            if (body.isSleeping && !forceUpdate)
13653                continue;
13654
13655            // temporary back compatibility bounds check
13656            if (world.bounds && (body.bounds.max.x < world.bounds.min.x || body.bounds.min.x > world.bounds.max.x
13657                || body.bounds.max.y < world.bounds.min.y || body.bounds.min.y > world.bounds.max.y))
13658                continue;
13659
13660            var newRegion = Grid._getRegion(grid, body);
13661
13662            // if the body has changed grid region
13663            if (!body.region || newRegion.id !== body.region.id || forceUpdate) {
13664
13665                if (!body.region || forceUpdate)
13666                    body.region = newRegion;
13667
13668                var union = Grid._regionUnion(newRegion, body.region);
13669
13670                // update grid buckets affected by region change
13671                // iterate over the union of both regions
13672                for (col = union.startCol; col <= union.endCol; col++) {
13673                    for (row = union.startRow; row <= union.endRow; row++) {
13674                        bucketId = Grid._getBucketId(col, row);
13675                        bucket = buckets[bucketId];
13676
13677                        var isInsideNewRegion = (col >= newRegion.startCol && col <= newRegion.endCol
13678                                                && row >= newRegion.startRow && row <= newRegion.endRow);
13679
13680                        var isInsideOldRegion = (col >= body.region.startCol && col <= body.region.endCol
13681                                                && row >= body.region.startRow && row <= body.region.endRow);
13682
13683                        // remove from old region buckets
13684                        if (!isInsideNewRegion && isInsideOldRegion) {
13685                            if (isInsideOldRegion) {
13686                                if (bucket)
13687                                    Grid._bucketRemoveBody(grid, bucket, body);
13688                            }
13689                        }
13690
13691                        // add to new region buckets
13692                        if (body.region === newRegion || (isInsideNewRegion && !isInsideOldRegion) || forceUpdate) {
13693                            if (!bucket)
13694                                bucket = Grid._createBucket(buckets, bucketId);
13695                            Grid._bucketAddBody(grid, bucket, body);
13696                        }
13697                    }
13698                }
13699
13700                // set the new region
13701                body.region = newRegion;
13702
13703                // flag changes so we can update pairs
13704                gridChanged = true;
13705            }
13706        }
13707
13708        // update pairs list only if pairs changed (i.e. a body changed region)
13709        if (gridChanged)
13710            grid.pairsList = Grid._createActivePairsList(grid);
13711    };
13712
13713    deprecated(Grid, 'update', 'Grid.update ➤ replaced by Matter.Detector');
13714
13715    /**
13716     * Clears the grid.
13717     * @deprecated replaced by Matter.Detector
13718     * @method clear
13719     * @param {grid} grid
13720     */
13721    Grid.clear = function(grid) {
13722        grid.buckets = {};
13723        grid.pairs = {};
13724        grid.pairsList = [];
13725    };
13726
13727    deprecated(Grid, 'clear', 'Grid.clear ➤ replaced by Matter.Detector');
13728
13729    /**
13730     * Finds the union of two regions.
13731     * @method _regionUnion
13732     * @deprecated replaced by Matter.Detector
13733     * @private
13734     * @param {} regionA
13735     * @param {} regionB
13736     * @return {} region
13737     */
13738    Grid._regionUnion = function(regionA, regionB) {
13739        var startCol = Math.min(regionA.startCol, regionB.startCol),
13740            endCol = Math.max(regionA.endCol, regionB.endCol),
13741            startRow = Math.min(regionA.startRow, regionB.startRow),
13742            endRow = Math.max(regionA.endRow, regionB.endRow);
13743
13744        return Grid._createRegion(startCol, endCol, startRow, endRow);
13745    };
13746
13747    /**
13748     * Gets the region a given body falls in for a given grid.
13749     * @method _getRegion
13750     * @deprecated replaced by Matter.Detector
13751     * @private
13752     * @param {} grid
13753     * @param {} body
13754     * @return {} region
13755     */
13756    Grid._getRegion = function(grid, body) {
13757        var bounds = body.bounds,
13758            startCol = Math.floor(bounds.min.x / grid.bucketWidth),
13759            endCol = Math.floor(bounds.max.x / grid.bucketWidth),
13760            startRow = Math.floor(bounds.min.y / grid.bucketHeight),
13761            endRow = Math.floor(bounds.max.y / grid.bucketHeight);
13762
13763        return Grid._createRegion(startCol, endCol, startRow, endRow);
13764    };
13765
13766    /**
13767     * Creates a region.
13768     * @method _createRegion
13769     * @deprecated replaced by Matter.Detector
13770     * @private
13771     * @param {} startCol
13772     * @param {} endCol
13773     * @param {} startRow
13774     * @param {} endRow
13775     * @return {} region
13776     */
13777    Grid._createRegion = function(startCol, endCol, startRow, endRow) {
13778        return { 
13779            id: startCol + ',' + endCol + ',' + startRow + ',' + endRow,
13780            startCol: startCol, 
13781            endCol: endCol, 
13782            startRow: startRow, 
13783            endRow: endRow 
13784        };
13785    };
13786
13787    /**
13788     * Gets the bucket id at the given position.
13789     * @method _getBucketId
13790     * @deprecated replaced by Matter.Detector
13791     * @private
13792     * @param {} column
13793     * @param {} row
13794     * @return {string} bucket id
13795     */
13796    Grid._getBucketId = function(column, row) {
13797        return 'C' + column + 'R' + row;
13798    };
13799
13800    /**
13801     * Creates a bucket.
13802     * @method _createBucket
13803     * @deprecated replaced by Matter.Detector
13804     * @private
13805     * @param {} buckets
13806     * @param {} bucketId
13807     * @return {} bucket
13808     */
13809    Grid._createBucket = function(buckets, bucketId) {
13810        var bucket = buckets[bucketId] = [];
13811        return bucket;
13812    };
13813
13814    /**
13815     * Adds a body to a bucket.
13816     * @method _bucketAddBody
13817     * @deprecated replaced by Matter.Detector
13818     * @private
13819     * @param {} grid
13820     * @param {} bucket
13821     * @param {} body
13822     */
13823    Grid._bucketAddBody = function(grid, bucket, body) {
13824        var gridPairs = grid.pairs,
13825            pairId = Pair.id,
13826            bucketLength = bucket.length,
13827            i;
13828
13829        // add new pairs
13830        for (i = 0; i < bucketLength; i++) {
13831            var bodyB = bucket[i];
13832
13833            if (body.id === bodyB.id || (body.isStatic && bodyB.isStatic))
13834                continue;
13835
13836            // keep track of the number of buckets the pair exists in
13837            // important for Grid.update to work
13838            var id = pairId(body, bodyB),
13839                pair = gridPairs[id];
13840
13841            if (pair) {
13842                pair[2] += 1;
13843            } else {
13844                gridPairs[id] = [body, bodyB, 1];
13845            }
13846        }
13847
13848        // add to bodies (after pairs, otherwise pairs with self)
13849        bucket.push(body);
13850    };
13851
13852    /**
13853     * Removes a body from a bucket.
13854     * @method _bucketRemoveBody
13855     * @deprecated replaced by Matter.Detector
13856     * @private
13857     * @param {} grid
13858     * @param {} bucket
13859     * @param {} body
13860     */
13861    Grid._bucketRemoveBody = function(grid, bucket, body) {
13862        var gridPairs = grid.pairs,
13863            pairId = Pair.id,
13864            i;
13865
13866        // remove from bucket
13867        bucket.splice(Common.indexOf(bucket, body), 1);
13868
13869        var bucketLength = bucket.length;
13870
13871        // update pair counts
13872        for (i = 0; i < bucketLength; i++) {
13873            // keep track of the number of buckets the pair exists in
13874            // important for _createActivePairsList to work
13875            var pair = gridPairs[pairId(body, bucket[i])];
13876
13877            if (pair)
13878                pair[2] -= 1;
13879        }
13880    };
13881
13882    /**
13883     * Generates a list of the active pairs in the grid.
13884     * @method _createActivePairsList
13885     * @deprecated replaced by Matter.Detector
13886     * @private
13887     * @param {} grid
13888     * @return [] pairs
13889     */
13890    Grid._createActivePairsList = function(grid) {
13891        var pair,
13892            gridPairs = grid.pairs,
13893            pairKeys = Common.keys(gridPairs),
13894            pairKeysLength = pairKeys.length,
13895            pairs = [],
13896            k;
13897
13898        // iterate over grid.pairs
13899        for (k = 0; k < pairKeysLength; k++) {
13900            pair = gridPairs[pairKeys[k]];
13901
13902            // if pair exists in at least one bucket
13903            // it is a pair that needs further collision testing so push it
13904            if (pair[2] > 0) {
13905                pairs.push(pair);
13906            } else {
13907                delete gridPairs[pairKeys[k]];
13908            }
13909        }
13910
13911        return pairs;
13912    };
13913    
13914})();
13915
13916
13917/***/ }),
13918/* 24 */
13919/***/ (function(module, exports, __webpack_require__) {
13920
13921/**
13922* The `Matter.MouseConstraint` module contains methods for creating mouse constraints.
13923* Mouse constraints are used for allowing user interaction, providing the ability to move bodies via the mouse or touch.
13924*
13925* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples).
13926*
13927* @class MouseConstraint
13928*/
13929
13930var MouseConstraint = {};
13931
13932module.exports = MouseConstraint;
13933
13934var Vertices = __webpack_require__(3);
13935var Sleeping = __webpack_require__(7);
13936var Mouse = __webpack_require__(14);
13937var Events = __webpack_require__(5);
13938var Detector = __webpack_require__(13);
13939var Constraint = __webpack_require__(10);
13940var Composite = __webpack_require__(6);
13941var Common = __webpack_require__(0);
13942var Bounds = __webpack_require__(1);
13943
13944(function() {
13945
13946    /**
13947     * Creates a new mouse constraint.
13948     * All properties have default values, and many are pre-calculated automatically based on other properties.
13949     * See the properties section below for detailed information on what you can pass via the `options` object.
13950     * @method create
13951     * @param {engine} engine
13952     * @param {} options
13953     * @return {MouseConstraint} A new MouseConstraint
13954     */
13955    MouseConstraint.create = function(engine, options) {
13956        var mouse = (engine ? engine.mouse : null) || (options ? options.mouse : null);
13957
13958        if (!mouse) {
13959            if (engine && engine.render && engine.render.canvas) {
13960                mouse = Mouse.create(engine.render.canvas);
13961            } else if (options && options.element) {
13962                mouse = Mouse.create(options.element);
13963            } else {
13964                mouse = Mouse.create();
13965                Common.warn('MouseConstraint.create: options.mouse was undefined, options.element was undefined, may not function as expected');
13966            }
13967        }
13968
13969        var constraint = Constraint.create({ 
13970            label: 'Mouse Constraint',
13971            pointA: mouse.position,
13972            pointB: { x: 0, y: 0 },
13973            length: 0.01, 
13974            stiffness: 0.1,
13975            angularStiffness: 1,
13976            render: {
13977                strokeStyle: '#90EE90',
13978                lineWidth: 3
13979            }
13980        });
13981
13982        var defaults = {
13983            type: 'mouseConstraint',
13984            mouse: mouse,
13985            element: null,
13986            body: null,
13987            constraint: constraint,
13988            collisionFilter: {
13989                category: 0x0001,
13990                mask: 0xFFFFFFFF,
13991                group: 0
13992            }
13993        };
13994
13995        var mouseConstraint = Common.extend(defaults, options);
13996
13997        Events.on(engine, 'beforeUpdate', function() {
13998            var allBodies = Composite.allBodies(engine.world);
13999            MouseConstraint.update(mouseConstraint, allBodies);
14000            MouseConstraint._triggerEvents(mouseConstraint);
14001        });
14002
14003        return mouseConstraint;
14004    };
14005
14006    /**
14007     * Updates the given mouse constraint.
14008     * @private
14009     * @method update
14010     * @param {MouseConstraint} mouseConstraint
14011     * @param {body[]} bodies
14012     */
14013    MouseConstraint.update = function(mouseConstraint, bodies) {
14014        var mouse = mouseConstraint.mouse,
14015            constraint = mouseConstraint.constraint,
14016            body = mouseConstraint.body;
14017
14018        if (mouse.button === 0) {
14019            if (!constraint.bodyB) {
14020                for (var i = 0; i < bodies.length; i++) {
14021                    body = bodies[i];
14022                    if (Bounds.contains(body.bounds, mouse.position) 
14023                            && Detector.canCollide(body.collisionFilter, mouseConstraint.collisionFilter)) {
14024                        for (var j = body.parts.length > 1 ? 1 : 0; j < body.parts.length; j++) {
14025                            var part = body.parts[j];
14026                            if (Vertices.contains(part.vertices, mouse.position)) {
14027                                constraint.pointA = mouse.position;
14028                                constraint.bodyB = mouseConstraint.body = body;
14029                                constraint.pointB = { x: mouse.position.x - body.position.x, y: mouse.position.y - body.position.y };
14030                                constraint.angleB = body.angle;
14031
14032                                Sleeping.set(body, false);
14033                                Events.trigger(mouseConstraint, 'startdrag', { mouse: mouse, body: body });
14034
14035                                break;
14036                            }
14037                        }
14038                    }
14039                }
14040            } else {
14041                Sleeping.set(constraint.bodyB, false);
14042                constraint.pointA = mouse.position;
14043            }
14044        } else {
14045            constraint.bodyB = mouseConstraint.body = null;
14046            constraint.pointB = null;
14047
14048            if (body)
14049                Events.trigger(mouseConstraint, 'enddrag', { mouse: mouse, body: body });
14050        }
14051    };
14052
14053    /**
14054     * Triggers mouse constraint events.
14055     * @method _triggerEvents
14056     * @private
14057     * @param {mouse} mouseConstraint
14058     */
14059    MouseConstraint._triggerEvents = function(mouseConstraint) {
14060        var mouse = mouseConstraint.mouse,
14061            mouseEvents = mouse.sourceEvents;
14062
14063        if (mouseEvents.mousemove)
14064            Events.trigger(mouseConstraint, 'mousemove', { mouse: mouse });
14065
14066        if (mouseEvents.mousedown)
14067            Events.trigger(mouseConstraint, 'mousedown', { mouse: mouse });
14068
14069        if (mouseEvents.mouseup)
14070            Events.trigger(mouseConstraint, 'mouseup', { mouse: mouse });
14071
14072        // reset the mouse state ready for the next step
14073        Mouse.clearSourceEvents(mouse);
14074    };
14075
14076    /*
14077    *
14078    *  Events Documentation
14079    *
14080    */
14081
14082    /**
14083    * Fired when the mouse has moved (or a touch moves) during the last step
14084    *
14085    * @event mousemove
14086    * @param {} event An event object
14087    * @param {mouse} event.mouse The engine's mouse instance
14088    * @param {} event.source The source object of the event
14089    * @param {} event.name The name of the event
14090    */
14091
14092    /**
14093    * Fired when the mouse is down (or a touch has started) during the last step
14094    *
14095    * @event mousedown
14096    * @param {} event An event object
14097    * @param {mouse} event.mouse The engine's mouse instance
14098    * @param {} event.source The source object of the event
14099    * @param {} event.name The name of the event
14100    */
14101
14102    /**
14103    * Fired when the mouse is up (or a touch has ended) during the last step
14104    *
14105    * @event mouseup
14106    * @param {} event An event object
14107    * @param {mouse} event.mouse The engine's mouse instance
14108    * @param {} event.source The source object of the event
14109    * @param {} event.name The name of the event
14110    */
14111
14112    /**
14113    * Fired when the user starts dragging a body
14114    *
14115    * @event startdrag
14116    * @param {} event An event object
14117    * @param {mouse} event.mouse The engine's mouse instance
14118    * @param {body} event.body The body being dragged
14119    * @param {} event.source The source object of the event
14120    * @param {} event.name The name of the event
14121    */
14122
14123    /**
14124    * Fired when the user ends dragging a body
14125    *
14126    * @event enddrag
14127    * @param {} event An event object
14128    * @param {mouse} event.mouse The engine's mouse instance
14129    * @param {body} event.body The body that has stopped being dragged
14130    * @param {} event.source The source object of the event
14131    * @param {} event.name The name of the event
14132    */
14133
14134    /*
14135    *
14136    *  Properties Documentation
14137    *
14138    */
14139
14140    /**
14141     * A `String` denoting the type of object.
14142     *
14143     * @property type
14144     * @type string
14145     * @default "constraint"
14146     * @readOnly
14147     */
14148
14149    /**
14150     * The `Mouse` instance in use. If not supplied in `MouseConstraint.create`, one will be created.
14151     *
14152     * @property mouse
14153     * @type mouse
14154     * @default mouse
14155     */
14156
14157    /**
14158     * The `Body` that is currently being moved by the user, or `null` if no body.
14159     *
14160     * @property body
14161     * @type body
14162     * @default null
14163     */
14164
14165    /**
14166     * The `Constraint` object that is used to move the body during interaction.
14167     *
14168     * @property constraint
14169     * @type constraint
14170     */
14171
14172    /**
14173     * An `Object` that specifies the collision filter properties.
14174     * The collision filter allows the user to define which types of body this mouse constraint can interact with.
14175     * See `body.collisionFilter` for more information.
14176     *
14177     * @property collisionFilter
14178     * @type object
14179     */
14180
14181})();
14182
14183
14184/***/ }),
14185/* 25 */
14186/***/ (function(module, exports, __webpack_require__) {
14187
14188/**
14189* The `Matter.Query` module contains methods for performing collision queries.
14190*
14191* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples).
14192*
14193* @class Query
14194*/
14195
14196var Query = {};
14197
14198module.exports = Query;
14199
14200var Vector = __webpack_require__(2);
14201var Collision = __webpack_require__(8);
14202var Bounds = __webpack_require__(1);
14203var Bodies = __webpack_require__(12);
14204var Vertices = __webpack_require__(3);
14205
14206(function() {
14207
14208    /**
14209     * Returns a list of collisions between `body` and `bodies`.
14210     * @method collides
14211     * @param {body} body
14212     * @param {body[]} bodies
14213     * @return {collision[]} Collisions
14214     */
14215    Query.collides = function(body, bodies) {
14216        var collisions = [],
14217            bodiesLength = bodies.length,
14218            bounds = body.bounds,
14219            collides = Collision.collides,
14220            overlaps = Bounds.overlaps;
14221
14222        for (var i = 0; i < bodiesLength; i++) {
14223            var bodyA = bodies[i],
14224                partsALength = bodyA.parts.length,
14225                partsAStart = partsALength === 1 ? 0 : 1;
14226            
14227            if (overlaps(bodyA.bounds, bounds)) {
14228                for (var j = partsAStart; j < partsALength; j++) {
14229                    var part = bodyA.parts[j];
14230
14231                    if (overlaps(part.bounds, bounds)) {
14232                        var collision = collides(part, body);
14233
14234                        if (collision) {
14235                            collisions.push(collision);
14236                            break;
14237                        }
14238                    }
14239                }
14240            }
14241        }
14242
14243        return collisions;
14244    };
14245
14246    /**
14247     * Casts a ray segment against a set of bodies and returns all collisions, ray width is optional. Intersection points are not provided.
14248     * @method ray
14249     * @param {body[]} bodies
14250     * @param {vector} startPoint
14251     * @param {vector} endPoint
14252     * @param {number} [rayWidth]
14253     * @return {collision[]} Collisions
14254     */
14255    Query.ray = function(bodies, startPoint, endPoint, rayWidth) {
14256        rayWidth = rayWidth || 1e-100;
14257
14258        var rayAngle = Vector.angle(startPoint, endPoint),
14259            rayLength = Vector.magnitude(Vector.sub(startPoint, endPoint)),
14260            rayX = (endPoint.x + startPoint.x) * 0.5,
14261            rayY = (endPoint.y + startPoint.y) * 0.5,
14262            ray = Bodies.rectangle(rayX, rayY, rayLength, rayWidth, { angle: rayAngle }),
14263            collisions = Query.collides(ray, bodies);
14264
14265        for (var i = 0; i < collisions.length; i += 1) {
14266            var collision = collisions[i];
14267            collision.body = collision.bodyB = collision.bodyA;            
14268        }
14269
14270        return collisions;
14271    };
14272
14273    /**
14274     * Returns all bodies whose bounds are inside (or outside if set) the given set of bounds, from the given set of bodies.
14275     * @method region
14276     * @param {body[]} bodies
14277     * @param {bounds} bounds
14278     * @param {bool} [outside=false]
14279     * @return {body[]} The bodies matching the query
14280     */
14281    Query.region = function(bodies, bounds, outside) {
14282        var result = [];
14283
14284        for (var i = 0; i < bodies.length; i++) {
14285            var body = bodies[i],
14286                overlaps = Bounds.overlaps(body.bounds, bounds);
14287            if ((overlaps && !outside) || (!overlaps && outside))
14288                result.push(body);
14289        }
14290
14291        return result;
14292    };
14293
14294    /**
14295     * Returns all bodies whose vertices contain the given point, from the given set of bodies.
14296     * @method point
14297     * @param {body[]} bodies
14298     * @param {vector} point
14299     * @return {body[]} The bodies matching the query
14300     */
14301    Query.point = function(bodies, point) {
14302        var result = [];
14303
14304        for (var i = 0; i < bodies.length; i++) {
14305            var body = bodies[i];
14306            
14307            if (Bounds.contains(body.bounds, point)) {
14308                for (var j = body.parts.length === 1 ? 0 : 1; j < body.parts.length; j++) {
14309                    var part = body.parts[j];
14310
14311                    if (Bounds.contains(part.bounds, point)
14312                        && Vertices.contains(part.vertices, point)) {
14313                        result.push(body);
14314                        break;
14315                    }
14316                }
14317            }
14318        }
14319
14320        return result;
14321    };
14322
14323})();
14324
14325
14326/***/ }),
14327/* 26 */
14328/***/ (function(module, exports, __webpack_require__) {
14329
14330/**
14331* The `Matter.Render` module is a lightweight, optional utility which provides a simple canvas based renderer for visualising instances of `Matter.Engine`.
14332* It is intended for development and debugging purposes, but may also be suitable for simple games.
14333* It includes a number of drawing options including wireframe, vector with support for sprites and viewports.
14334*
14335* @class Render
14336*/
14337
14338var Render = {};
14339
14340module.exports = Render;
14341
14342var Body = __webpack_require__(4);
14343var Common = __webpack_require__(0);
14344var Composite = __webpack_require__(6);
14345var Bounds = __webpack_require__(1);
14346var Events = __webpack_require__(5);
14347var Vector = __webpack_require__(2);
14348var Mouse = __webpack_require__(14);
14349
14350(function() {
14351
14352    var _requestAnimationFrame,
14353        _cancelAnimationFrame;
14354
14355    if (typeof window !== 'undefined') {
14356        _requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame
14357                                      || window.mozRequestAnimationFrame || window.msRequestAnimationFrame
14358                                      || function(callback){ window.setTimeout(function() { callback(Common.now()); }, 1000 / 60); };
14359
14360        _cancelAnimationFrame = window.cancelAnimationFrame || window.mozCancelAnimationFrame
14361                                      || window.webkitCancelAnimationFrame || window.msCancelAnimationFrame;
14362    }
14363
14364    Render._goodFps = 30;
14365    Render._goodDelta = 1000 / 60;
14366
14367    /**
14368     * Creates a new renderer. The options parameter is an object that specifies any properties you wish to override the defaults.
14369     * All properties have default values, and many are pre-calculated automatically based on other properties.
14370     * See the properties section below for detailed information on what you can pass via the `options` object.
14371     * @method create
14372     * @param {object} [options]
14373     * @return {render} A new renderer
14374     */
14375    Render.create = function(options) {
14376        var defaults = {
14377            engine: null,
14378            element: null,
14379            canvas: null,
14380            mouse: null,
14381            frameRequestId: null,
14382            timing: {
14383                historySize: 60,
14384                delta: 0,
14385                deltaHistory: [],
14386                lastTime: 0,
14387                lastTimestamp: 0,
14388                lastElapsed: 0,
14389                timestampElapsed: 0,
14390                timestampElapsedHistory: [],
14391                engineDeltaHistory: [],
14392                engineElapsedHistory: [],
14393                engineUpdatesHistory: [],
14394                elapsedHistory: []
14395            },
14396            options: {
14397                width: 800,
14398                height: 600,
14399                pixelRatio: 1,
14400                background: '#14151f',
14401                wireframeBackground: '#14151f',
14402                wireframeStrokeStyle: '#bbb',
14403                hasBounds: !!options.bounds,
14404                enabled: true,
14405                wireframes: true,
14406                showSleeping: true,
14407                showDebug: false,
14408                showStats: false,
14409                showPerformance: false,
14410                showBounds: false,
14411                showVelocity: false,
14412                showCollisions: false,
14413                showSeparations: false,
14414                showAxes: false,
14415                showPositions: false,
14416                showAngleIndicator: false,
14417                showIds: false,
14418                showVertexNumbers: false,
14419                showConvexHulls: false,
14420                showInternalEdges: false,
14421                showMousePosition: false
14422            }
14423        };
14424
14425        var render = Common.extend(defaults, options);
14426
14427        if (render.canvas) {
14428            render.canvas.width = render.options.width || render.canvas.width;
14429            render.canvas.height = render.options.height || render.canvas.height;
14430        }
14431
14432        render.mouse = options.mouse;
14433        render.engine = options.engine;
14434        render.canvas = render.canvas || _createCanvas(render.options.width, render.options.height);
14435        render.context = render.canvas.getContext('2d');
14436        render.textures = {};
14437
14438        render.bounds = render.bounds || {
14439            min: {
14440                x: 0,
14441                y: 0
14442            },
14443            max: {
14444                x: render.canvas.width,
14445                y: render.canvas.height
14446            }
14447        };
14448
14449        // for temporary back compatibility only
14450        render.controller = Render;
14451        render.options.showBroadphase = false;
14452
14453        if (render.options.pixelRatio !== 1) {
14454            Render.setPixelRatio(render, render.options.pixelRatio);
14455        }
14456
14457        if (Common.isElement(render.element)) {
14458            render.element.appendChild(render.canvas);
14459        }
14460
14461        return render;
14462    };
14463
14464    /**
14465     * Continuously updates the render canvas on the `requestAnimationFrame` event.
14466     * @method run
14467     * @param {render} render
14468     */
14469    Render.run = function(render) {
14470        (function loop(time){
14471            render.frameRequestId = _requestAnimationFrame(loop);
14472            
14473            _updateTiming(render, time);
14474
14475            Render.world(render, time);
14476
14477            render.context.setTransform(render.options.pixelRatio, 0, 0, render.options.pixelRatio, 0, 0);
14478
14479            if (render.options.showStats || render.options.showDebug) {
14480                Render.stats(render, render.context, time);
14481            }
14482
14483            if (render.options.showPerformance || render.options.showDebug) {
14484                Render.performance(render, render.context, time);
14485            }
14486
14487            render.context.setTransform(1, 0, 0, 1, 0, 0);
14488        })();
14489    };
14490
14491    /**
14492     * Ends execution of `Render.run` on the given `render`, by canceling the animation frame request event loop.
14493     * @method stop
14494     * @param {render} render
14495     */
14496    Render.stop = function(render) {
14497        _cancelAnimationFrame(render.frameRequestId);
14498    };
14499
14500    /**
14501     * Sets the pixel ratio of the renderer and updates the canvas.
14502     * To automatically detect the correct ratio, pass the string `'auto'` for `pixelRatio`.
14503     * @method setPixelRatio
14504     * @param {render} render
14505     * @param {number} pixelRatio
14506     */
14507    Render.setPixelRatio = function(render, pixelRatio) {
14508        var options = render.options,
14509            canvas = render.canvas;
14510
14511        if (pixelRatio === 'auto') {
14512            pixelRatio = _getPixelRatio(canvas);
14513        }
14514
14515        options.pixelRatio = pixelRatio;
14516        canvas.setAttribute('data-pixel-ratio', pixelRatio);
14517        canvas.width = options.width * pixelRatio;
14518        canvas.height = options.height * pixelRatio;
14519        canvas.style.width = options.width + 'px';
14520        canvas.style.height = options.height + 'px';
14521    };
14522
14523    /**
14524     * Sets the render `width` and `height`.
14525     * 
14526     * Updates the canvas accounting for `render.options.pixelRatio`.  
14527     * 
14528     * Updates the bottom right render bound `render.bounds.max` relative to the provided `width` and `height`.
14529     * The top left render bound `render.bounds.min` isn't changed.
14530     * 
14531     * Follow this call with `Render.lookAt` if you need to change the render bounds.
14532     * 
14533     * See also `Render.setPixelRatio`.
14534     * @method setSize
14535     * @param {render} render
14536     * @param {number} width The width (in CSS pixels)
14537     * @param {number} height The height (in CSS pixels)
14538     */
14539    Render.setSize = function(render, width, height) {
14540        render.options.width = width;
14541        render.options.height = height;
14542        render.bounds.max.x = render.bounds.min.x + width;
14543        render.bounds.max.y = render.bounds.min.y + height;
14544
14545        if (render.options.pixelRatio !== 1) {
14546            Render.setPixelRatio(render, render.options.pixelRatio);
14547        } else {
14548            render.canvas.width = width;
14549            render.canvas.height = height;
14550        }
14551    };
14552
14553    /**
14554     * Positions and sizes the viewport around the given object bounds.
14555     * Objects must have at least one of the following properties:
14556     * - `object.bounds`
14557     * - `object.position`
14558     * - `object.min` and `object.max`
14559     * - `object.x` and `object.y`
14560     * @method lookAt
14561     * @param {render} render
14562     * @param {object[]} objects
14563     * @param {vector} [padding]
14564     * @param {bool} [center=true]
14565     */
14566    Render.lookAt = function(render, objects, padding, center) {
14567        center = typeof center !== 'undefined' ? center : true;
14568        objects = Common.isArray(objects) ? objects : [objects];
14569        padding = padding || {
14570            x: 0,
14571            y: 0
14572        };
14573
14574        // find bounds of all objects
14575        var bounds = {
14576            min: { x: Infinity, y: Infinity },
14577            max: { x: -Infinity, y: -Infinity }
14578        };
14579
14580        for (var i = 0; i < objects.length; i += 1) {
14581            var object = objects[i],
14582                min = object.bounds ? object.bounds.min : (object.min || object.position || object),
14583                max = object.bounds ? object.bounds.max : (object.max || object.position || object);
14584
14585            if (min && max) {
14586                if (min.x < bounds.min.x)
14587                    bounds.min.x = min.x;
14588
14589                if (max.x > bounds.max.x)
14590                    bounds.max.x = max.x;
14591
14592                if (min.y < bounds.min.y)
14593                    bounds.min.y = min.y;
14594
14595                if (max.y > bounds.max.y)
14596                    bounds.max.y = max.y;
14597            }
14598        }
14599
14600        // find ratios
14601        var width = (bounds.max.x - bounds.min.x) + 2 * padding.x,
14602            height = (bounds.max.y - bounds.min.y) + 2 * padding.y,
14603            viewHeight = render.canvas.height,
14604            viewWidth = render.canvas.width,
14605            outerRatio = viewWidth / viewHeight,
14606            innerRatio = width / height,
14607            scaleX = 1,
14608            scaleY = 1;
14609
14610        // find scale factor
14611        if (innerRatio > outerRatio) {
14612            scaleY = innerRatio / outerRatio;
14613        } else {
14614            scaleX = outerRatio / innerRatio;
14615        }
14616
14617        // enable bounds
14618        render.options.hasBounds = true;
14619
14620        // position and size
14621        render.bounds.min.x = bounds.min.x;
14622        render.bounds.max.x = bounds.min.x + width * scaleX;
14623        render.bounds.min.y = bounds.min.y;
14624        render.bounds.max.y = bounds.min.y + height * scaleY;
14625
14626        // center
14627        if (center) {
14628            render.bounds.min.x += width * 0.5 - (width * scaleX) * 0.5;
14629            render.bounds.max.x += width * 0.5 - (width * scaleX) * 0.5;
14630            render.bounds.min.y += height * 0.5 - (height * scaleY) * 0.5;
14631            render.bounds.max.y += height * 0.5 - (height * scaleY) * 0.5;
14632        }
14633
14634        // padding
14635        render.bounds.min.x -= padding.x;
14636        render.bounds.max.x -= padding.x;
14637        render.bounds.min.y -= padding.y;
14638        render.bounds.max.y -= padding.y;
14639
14640        // update mouse
14641        if (render.mouse) {
14642            Mouse.setScale(render.mouse, {
14643                x: (render.bounds.max.x - render.bounds.min.x) / render.canvas.width,
14644                y: (render.bounds.max.y - render.bounds.min.y) / render.canvas.height
14645            });
14646
14647            Mouse.setOffset(render.mouse, render.bounds.min);
14648        }
14649    };
14650
14651    /**
14652     * Applies viewport transforms based on `render.bounds` to a render context.
14653     * @method startViewTransform
14654     * @param {render} render
14655     */
14656    Render.startViewTransform = function(render) {
14657        var boundsWidth = render.bounds.max.x - render.bounds.min.x,
14658            boundsHeight = render.bounds.max.y - render.bounds.min.y,
14659            boundsScaleX = boundsWidth / render.options.width,
14660            boundsScaleY = boundsHeight / render.options.height;
14661
14662        render.context.setTransform(
14663            render.options.pixelRatio / boundsScaleX, 0, 0, 
14664            render.options.pixelRatio / boundsScaleY, 0, 0
14665        );
14666        
14667        render.context.translate(-render.bounds.min.x, -render.bounds.min.y);
14668    };
14669
14670    /**
14671     * Resets all transforms on the render context.
14672     * @method endViewTransform
14673     * @param {render} render
14674     */
14675    Render.endViewTransform = function(render) {
14676        render.context.setTransform(render.options.pixelRatio, 0, 0, render.options.pixelRatio, 0, 0);
14677    };
14678
14679    /**
14680     * Renders the given `engine`'s `Matter.World` object.
14681     * This is the entry point for all rendering and should be called every time the scene changes.
14682     * @method world
14683     * @param {render} render
14684     */
14685    Render.world = function(render, time) {
14686        var startTime = Common.now(),
14687            engine = render.engine,
14688            world = engine.world,
14689            canvas = render.canvas,
14690            context = render.context,
14691            options = render.options,
14692            timing = render.timing;
14693
14694        var allBodies = Composite.allBodies(world),
14695            allConstraints = Composite.allConstraints(world),
14696            background = options.wireframes ? options.wireframeBackground : options.background,
14697            bodies = [],
14698            constraints = [],
14699            i;
14700
14701        var event = {
14702            timestamp: engine.timing.timestamp
14703        };
14704
14705        Events.trigger(render, 'beforeRender', event);
14706
14707        // apply background if it has changed
14708        if (render.currentBackground !== background)
14709            _applyBackground(render, background);
14710
14711        // clear the canvas with a transparent fill, to allow the canvas background to show
14712        context.globalCompositeOperation = 'source-in';
14713        context.fillStyle = "transparent";
14714        context.fillRect(0, 0, canvas.width, canvas.height);
14715        context.globalCompositeOperation = 'source-over';
14716
14717        // handle bounds
14718        if (options.hasBounds) {
14719            // filter out bodies that are not in view
14720            for (i = 0; i < allBodies.length; i++) {
14721                var body = allBodies[i];
14722                if (Bounds.overlaps(body.bounds, render.bounds))
14723                    bodies.push(body);
14724            }
14725
14726            // filter out constraints that are not in view
14727            for (i = 0; i < allConstraints.length; i++) {
14728                var constraint = allConstraints[i],
14729                    bodyA = constraint.bodyA,
14730                    bodyB = constraint.bodyB,
14731                    pointAWorld = constraint.pointA,
14732                    pointBWorld = constraint.pointB;
14733
14734                if (bodyA) pointAWorld = Vector.add(bodyA.position, constraint.pointA);
14735                if (bodyB) pointBWorld = Vector.add(bodyB.position, constraint.pointB);
14736
14737                if (!pointAWorld || !pointBWorld)
14738                    continue;
14739
14740                if (Bounds.contains(render.bounds, pointAWorld) || Bounds.contains(render.bounds, pointBWorld))
14741                    constraints.push(constraint);
14742            }
14743
14744            // transform the view
14745            Render.startViewTransform(render);
14746
14747            // update mouse
14748            if (render.mouse) {
14749                Mouse.setScale(render.mouse, {
14750                    x: (render.bounds.max.x - render.bounds.min.x) / render.options.width,
14751                    y: (render.bounds.max.y - render.bounds.min.y) / render.options.height
14752                });
14753
14754                Mouse.setOffset(render.mouse, render.bounds.min);
14755            }
14756        } else {
14757            constraints = allConstraints;
14758            bodies = allBodies;
14759
14760            if (render.options.pixelRatio !== 1) {
14761                render.context.setTransform(render.options.pixelRatio, 0, 0, render.options.pixelRatio, 0, 0);
14762            }
14763        }
14764
14765        if (!options.wireframes || (engine.enableSleeping && options.showSleeping)) {
14766            // fully featured rendering of bodies
14767            Render.bodies(render, bodies, context);
14768        } else {
14769            if (options.showConvexHulls)
14770                Render.bodyConvexHulls(render, bodies, context);
14771
14772            // optimised method for wireframes only
14773            Render.bodyWireframes(render, bodies, context);
14774        }
14775
14776        if (options.showBounds)
14777            Render.bodyBounds(render, bodies, context);
14778
14779        if (options.showAxes || options.showAngleIndicator)
14780            Render.bodyAxes(render, bodies, context);
14781
14782        if (options.showPositions)
14783            Render.bodyPositions(render, bodies, context);
14784
14785        if (options.showVelocity)
14786            Render.bodyVelocity(render, bodies, context);
14787
14788        if (options.showIds)
14789            Render.bodyIds(render, bodies, context);
14790
14791        if (options.showSeparations)
14792            Render.separations(render, engine.pairs.list, context);
14793
14794        if (options.showCollisions)
14795            Render.collisions(render, engine.pairs.list, context);
14796
14797        if (options.showVertexNumbers)
14798            Render.vertexNumbers(render, bodies, context);
14799
14800        if (options.showMousePosition)
14801            Render.mousePosition(render, render.mouse, context);
14802
14803        Render.constraints(constraints, context);
14804
14805        if (options.hasBounds) {
14806            // revert view transforms
14807            Render.endViewTransform(render);
14808        }
14809
14810        Events.trigger(render, 'afterRender', event);
14811
14812        // log the time elapsed computing this update
14813        timing.lastElapsed = Common.now() - startTime;
14814    };
14815
14816    /**
14817     * Renders statistics about the engine and world useful for debugging.
14818     * @private
14819     * @method stats
14820     * @param {render} render
14821     * @param {RenderingContext} context
14822     * @param {Number} time
14823     */
14824    Render.stats = function(render, context, time) {
14825        var engine = render.engine,
14826            world = engine.world,
14827            bodies = Composite.allBodies(world),
14828            parts = 0,
14829            width = 55,
14830            height = 44,
14831            x = 0,
14832            y = 0;
14833        
14834        // count parts
14835        for (var i = 0; i < bodies.length; i += 1) {
14836            parts += bodies[i].parts.length;
14837        }
14838
14839        // sections
14840        var sections = {
14841            'Part': parts,
14842            'Body': bodies.length,
14843            'Cons': Composite.allConstraints(world).length,
14844            'Comp': Composite.allComposites(world).length,
14845            'Pair': engine.pairs.list.length
14846        };
14847
14848        // background
14849        context.fillStyle = '#0e0f19';
14850        context.fillRect(x, y, width * 5.5, height);
14851
14852        context.font = '12px Arial';
14853        context.textBaseline = 'top';
14854        context.textAlign = 'right';
14855
14856        // sections
14857        for (var key in sections) {
14858            var section = sections[key];
14859            // label
14860            context.fillStyle = '#aaa';
14861            context.fillText(key, x + width, y + 8);
14862
14863            // value
14864            context.fillStyle = '#eee';
14865            context.fillText(section, x + width, y + 26);
14866
14867            x += width;
14868        }
14869    };
14870
14871    /**
14872     * Renders engine and render performance information.
14873     * @private
14874     * @method performance
14875     * @param {render} render
14876     * @param {RenderingContext} context
14877     */
14878    Render.performance = function(render, context) {
14879        var engine = render.engine,
14880            timing = render.timing,
14881            deltaHistory = timing.deltaHistory,
14882            elapsedHistory = timing.elapsedHistory,
14883            timestampElapsedHistory = timing.timestampElapsedHistory,
14884            engineDeltaHistory = timing.engineDeltaHistory,
14885            engineUpdatesHistory = timing.engineUpdatesHistory,
14886            engineElapsedHistory = timing.engineElapsedHistory,
14887            lastEngineUpdatesPerFrame = engine.timing.lastUpdatesPerFrame,
14888            lastEngineDelta = engine.timing.lastDelta;
14889        
14890        var deltaMean = _mean(deltaHistory),
14891            elapsedMean = _mean(elapsedHistory),
14892            engineDeltaMean = _mean(engineDeltaHistory),
14893            engineUpdatesMean = _mean(engineUpdatesHistory),
14894            engineElapsedMean = _mean(engineElapsedHistory),
14895            timestampElapsedMean = _mean(timestampElapsedHistory),
14896            rateMean = (timestampElapsedMean / deltaMean) || 0,
14897            neededUpdatesPerFrame = Math.round(deltaMean / lastEngineDelta),
14898            fps = (1000 / deltaMean) || 0;
14899
14900        var graphHeight = 4,
14901            gap = 12,
14902            width = 60,
14903            height = 34,
14904            x = 10,
14905            y = 69;
14906
14907        // background
14908        context.fillStyle = '#0e0f19';
14909        context.fillRect(0, 50, gap * 5 + width * 6 + 22, height);
14910
14911        // show FPS
14912        Render.status(
14913            context, x, y, width, graphHeight, deltaHistory.length, 
14914            Math.round(fps) + ' fps', 
14915            fps / Render._goodFps,
14916            function(i) { return (deltaHistory[i] / deltaMean) - 1; }
14917        );
14918
14919        // show engine delta
14920        Render.status(
14921            context, x + gap + width, y, width, graphHeight, engineDeltaHistory.length,
14922            lastEngineDelta.toFixed(2) + ' dt', 
14923            Render._goodDelta / lastEngineDelta,
14924            function(i) { return (engineDeltaHistory[i] / engineDeltaMean) - 1; }
14925        );
14926
14927        // show engine updates per frame
14928        Render.status(
14929            context, x + (gap + width) * 2, y, width, graphHeight, engineUpdatesHistory.length,
14930            lastEngineUpdatesPerFrame + ' upf', 
14931            Math.pow(Common.clamp((engineUpdatesMean / neededUpdatesPerFrame) || 1, 0, 1), 4),
14932            function(i) { return (engineUpdatesHistory[i] / engineUpdatesMean) - 1; }
14933        );
14934
14935        // show engine update time
14936        Render.status(
14937            context, x + (gap + width) * 3, y, width, graphHeight, engineElapsedHistory.length,
14938            engineElapsedMean.toFixed(2) + ' ut', 
14939            1 - (lastEngineUpdatesPerFrame * engineElapsedMean / Render._goodFps),
14940            function(i) { return (engineElapsedHistory[i] / engineElapsedMean) - 1; }
14941        );
14942
14943        // show render time
14944        Render.status(
14945            context, x + (gap + width) * 4, y, width, graphHeight, elapsedHistory.length,
14946            elapsedMean.toFixed(2) + ' rt', 
14947            1 - (elapsedMean / Render._goodFps),
14948            function(i) { return (elapsedHistory[i] / elapsedMean) - 1; }
14949        );
14950
14951        // show effective speed
14952        Render.status(
14953            context, x + (gap + width) * 5, y, width, graphHeight, timestampElapsedHistory.length, 
14954            rateMean.toFixed(2) + ' x', 
14955            rateMean * rateMean * rateMean,
14956            function(i) { return (((timestampElapsedHistory[i] / deltaHistory[i]) / rateMean) || 0) - 1; }
14957        );
14958    };
14959
14960    /**
14961     * Renders a label, indicator and a chart.
14962     * @private
14963     * @method status
14964     * @param {RenderingContext} context
14965     * @param {number} x
14966     * @param {number} y
14967     * @param {number} width
14968     * @param {number} height
14969     * @param {number} count
14970     * @param {string} label
14971     * @param {string} indicator
14972     * @param {function} plotY
14973     */
14974    Render.status = function(context, x, y, width, height, count, label, indicator, plotY) {
14975        // background
14976        context.strokeStyle = '#888';
14977        context.fillStyle = '#444';
14978        context.lineWidth = 1;
14979        context.fillRect(x, y + 7, width, 1);
14980
14981        // chart
14982        context.beginPath();
14983        context.moveTo(x, y + 7 - height * Common.clamp(0.4 * plotY(0), -2, 2));
14984        for (var i = 0; i < width; i += 1) {
14985            context.lineTo(x + i, y + 7 - (i < count ? height * Common.clamp(0.4 * plotY(i), -2, 2) : 0));
14986        }
14987        context.stroke();
14988
14989        // indicator
14990        context.fillStyle = 'hsl(' + Common.clamp(25 + 95 * indicator, 0, 120) + ',100%,60%)';
14991        context.fillRect(x, y - 7, 4, 4);
14992
14993        // label
14994        context.font = '12px Arial';
14995        context.textBaseline = 'middle';
14996        context.textAlign = 'right';
14997        context.fillStyle = '#eee';
14998        context.fillText(label, x + width, y - 5);
14999    };
15000
15001    /**
15002     * Description
15003     * @private
15004     * @method constraints
15005     * @param {constraint[]} constraints
15006     * @param {RenderingContext} context
15007     */
15008    Render.constraints = function(constraints, context) {
15009        var c = context;
15010
15011        for (var i = 0; i < constraints.length; i++) {
15012            var constraint = constraints[i];
15013
15014            if (!constraint.render.visible || !constraint.pointA || !constraint.pointB)
15015                continue;
15016
15017            var bodyA = constraint.bodyA,
15018                bodyB = constraint.bodyB,
15019                start,
15020                end;
15021
15022            if (bodyA) {
15023                start = Vector.add(bodyA.position, constraint.pointA);
15024            } else {
15025                start = constraint.pointA;
15026            }
15027
15028            if (constraint.render.type === 'pin') {
15029                c.beginPath();
15030                c.arc(start.x, start.y, 3, 0, 2 * Math.PI);
15031                c.closePath();
15032            } else {
15033                if (bodyB) {
15034                    end = Vector.add(bodyB.position, constraint.pointB);
15035                } else {
15036                    end = constraint.pointB;
15037                }
15038
15039                c.beginPath();
15040                c.moveTo(start.x, start.y);
15041
15042                if (constraint.render.type === 'spring') {
15043                    var delta = Vector.sub(end, start),
15044                        normal = Vector.perp(Vector.normalise(delta)),
15045                        coils = Math.ceil(Common.clamp(constraint.length / 5, 12, 20)),
15046                        offset;
15047
15048                    for (var j = 1; j < coils; j += 1) {
15049                        offset = j % 2 === 0 ? 1 : -1;
15050
15051                        c.lineTo(
15052                            start.x + delta.x * (j / coils) + normal.x * offset * 4,
15053                            start.y + delta.y * (j / coils) + normal.y * offset * 4
15054                        );
15055                    }
15056                }
15057
15058                c.lineTo(end.x, end.y);
15059            }
15060
15061            if (constraint.render.lineWidth) {
15062                c.lineWidth = constraint.render.lineWidth;
15063                c.strokeStyle = constraint.render.strokeStyle;
15064                c.stroke();
15065            }
15066
15067            if (constraint.render.anchors) {
15068                c.fillStyle = constraint.render.strokeStyle;
15069                c.beginPath();
15070                c.arc(start.x, start.y, 3, 0, 2 * Math.PI);
15071                c.arc(end.x, end.y, 3, 0, 2 * Math.PI);
15072                c.closePath();
15073                c.fill();
15074            }
15075        }
15076    };
15077
15078    /**
15079     * Description
15080     * @private
15081     * @method bodies
15082     * @param {render} render
15083     * @param {body[]} bodies
15084     * @param {RenderingContext} context
15085     */
15086    Render.bodies = function(render, bodies, context) {
15087        var c = context,
15088            engine = render.engine,
15089            options = render.options,
15090            showInternalEdges = options.showInternalEdges || !options.wireframes,
15091            body,
15092            part,
15093            i,
15094            k;
15095
15096        for (i = 0; i < bodies.length; i++) {
15097            body = bodies[i];
15098
15099            if (!body.render.visible)
15100                continue;
15101
15102            // handle compound parts
15103            for (k = body.parts.length > 1 ? 1 : 0; k < body.parts.length; k++) {
15104                part = body.parts[k];
15105
15106                if (!part.render.visible)
15107                    continue;
15108
15109                if (options.showSleeping && body.isSleeping) {
15110                    c.globalAlpha = 0.5 * part.render.opacity;
15111                } else if (part.render.opacity !== 1) {
15112                    c.globalAlpha = part.render.opacity;
15113                }
15114
15115                if (part.render.sprite && part.render.sprite.texture && !options.wireframes) {
15116                    // part sprite
15117                    var sprite = part.render.sprite,
15118                        texture = _getTexture(render, sprite.texture);
15119
15120                    c.translate(part.position.x, part.position.y);
15121                    c.rotate(part.angle);
15122
15123                    c.drawImage(
15124                        texture,
15125                        texture.width * -sprite.xOffset * sprite.xScale,
15126                        texture.height * -sprite.yOffset * sprite.yScale,
15127                        texture.width * sprite.xScale,
15128                        texture.height * sprite.yScale
15129                    );
15130
15131                    // revert translation, hopefully faster than save / restore
15132                    c.rotate(-part.angle);
15133                    c.translate(-part.position.x, -part.position.y);
15134                } else {
15135                    // part polygon
15136                    if (part.circleRadius) {
15137                        c.beginPath();
15138                        c.arc(part.position.x, part.position.y, part.circleRadius, 0, 2 * Math.PI);
15139                    } else {
15140                        c.beginPath();
15141                        c.moveTo(part.vertices[0].x, part.vertices[0].y);
15142
15143                        for (var j = 1; j < part.vertices.length; j++) {
15144                            if (!part.vertices[j - 1].isInternal || showInternalEdges) {
15145                                c.lineTo(part.vertices[j].x, part.vertices[j].y);
15146                            } else {
15147                                c.moveTo(part.vertices[j].x, part.vertices[j].y);
15148                            }
15149
15150                            if (part.vertices[j].isInternal && !showInternalEdges) {
15151                                c.moveTo(part.vertices[(j + 1) % part.vertices.length].x, part.vertices[(j + 1) % part.vertices.length].y);
15152                            }
15153                        }
15154
15155                        c.lineTo(part.vertices[0].x, part.vertices[0].y);
15156                        c.closePath();
15157                    }
15158
15159                    if (!options.wireframes) {
15160                        c.fillStyle = part.render.fillStyle;
15161
15162                        if (part.render.lineWidth) {
15163                            c.lineWidth = part.render.lineWidth;
15164                            c.strokeStyle = part.render.strokeStyle;
15165                            c.stroke();
15166                        }
15167
15168                        c.fill();
15169                    } else {
15170                        c.lineWidth = 1;
15171                        c.strokeStyle = render.options.wireframeStrokeStyle;
15172                        c.stroke();
15173                    }
15174                }
15175
15176                c.globalAlpha = 1;
15177            }
15178        }
15179    };
15180
15181    /**
15182     * Optimised method for drawing body wireframes in one pass
15183     * @private
15184     * @method bodyWireframes
15185     * @param {render} render
15186     * @param {body[]} bodies
15187     * @param {RenderingContext} context
15188     */
15189    Render.bodyWireframes = function(render, bodies, context) {
15190        var c = context,
15191            showInternalEdges = render.options.showInternalEdges,
15192            body,
15193            part,
15194            i,
15195            j,
15196            k;
15197
15198        c.beginPath();
15199
15200        // render all bodies
15201        for (i = 0; i < bodies.length; i++) {
15202            body = bodies[i];
15203
15204            if (!body.render.visible)
15205                continue;
15206
15207            // handle compound parts
15208            for (k = body.parts.length > 1 ? 1 : 0; k < body.parts.length; k++) {
15209                part = body.parts[k];
15210
15211                c.moveTo(part.vertices[0].x, part.vertices[0].y);
15212
15213                for (j = 1; j < part.vertices.length; j++) {
15214                    if (!part.vertices[j - 1].isInternal || showInternalEdges) {
15215                        c.lineTo(part.vertices[j].x, part.vertices[j].y);
15216                    } else {
15217                        c.moveTo(part.vertices[j].x, part.vertices[j].y);
15218                    }
15219
15220                    if (part.vertices[j].isInternal && !showInternalEdges) {
15221                        c.moveTo(part.vertices[(j + 1) % part.vertices.length].x, part.vertices[(j + 1) % part.vertices.length].y);
15222                    }
15223                }
15224
15225                c.lineTo(part.vertices[0].x, part.vertices[0].y);
15226            }
15227        }
15228
15229        c.lineWidth = 1;
15230        c.strokeStyle = render.options.wireframeStrokeStyle;
15231        c.stroke();
15232    };
15233
15234    /**
15235     * Optimised method for drawing body convex hull wireframes in one pass
15236     * @private
15237     * @method bodyConvexHulls
15238     * @param {render} render
15239     * @param {body[]} bodies
15240     * @param {RenderingContext} context
15241     */
15242    Render.bodyConvexHulls = function(render, bodies, context) {
15243        var c = context,
15244            body,
15245            part,
15246            i,
15247            j,
15248            k;
15249
15250        c.beginPath();
15251
15252        // render convex hulls
15253        for (i = 0; i < bodies.length; i++) {
15254            body = bodies[i];
15255
15256            if (!body.render.visible || body.parts.length === 1)
15257                continue;
15258
15259            c.moveTo(body.vertices[0].x, body.vertices[0].y);
15260
15261            for (j = 1; j < body.vertices.length; j++) {
15262                c.lineTo(body.vertices[j].x, body.vertices[j].y);
15263            }
15264
15265            c.lineTo(body.vertices[0].x, body.vertices[0].y);
15266        }
15267
15268        c.lineWidth = 1;
15269        c.strokeStyle = 'rgba(255,255,255,0.2)';
15270        c.stroke();
15271    };
15272
15273    /**
15274     * Renders body vertex numbers.
15275     * @private
15276     * @method vertexNumbers
15277     * @param {render} render
15278     * @param {body[]} bodies
15279     * @param {RenderingContext} context
15280     */
15281    Render.vertexNumbers = function(render, bodies, context) {
15282        var c = context,
15283            i,
15284            j,
15285            k;
15286
15287        for (i = 0; i < bodies.length; i++) {
15288            var parts = bodies[i].parts;
15289            for (k = parts.length > 1 ? 1 : 0; k < parts.length; k++) {
15290                var part = parts[k];
15291                for (j = 0; j < part.vertices.length; j++) {
15292                    c.fillStyle = 'rgba(255,255,255,0.2)';
15293                    c.fillText(i + '_' + j, part.position.x + (part.vertices[j].x - part.position.x) * 0.8, part.position.y + (part.vertices[j].y - part.position.y) * 0.8);
15294                }
15295            }
15296        }
15297    };
15298
15299    /**
15300     * Renders mouse position.
15301     * @private
15302     * @method mousePosition
15303     * @param {render} render
15304     * @param {mouse} mouse
15305     * @param {RenderingContext} context
15306     */
15307    Render.mousePosition = function(render, mouse, context) {
15308        var c = context;
15309        c.fillStyle = 'rgba(255,255,255,0.8)';
15310        c.fillText(mouse.position.x + '  ' + mouse.position.y, mouse.position.x + 5, mouse.position.y - 5);
15311    };
15312
15313    /**
15314     * Draws body bounds
15315     * @private
15316     * @method bodyBounds
15317     * @param {render} render
15318     * @param {body[]} bodies
15319     * @param {RenderingContext} context
15320     */
15321    Render.bodyBounds = function(render, bodies, context) {
15322        var c = context,
15323            engine = render.engine,
15324            options = render.options;
15325
15326        c.beginPath();
15327
15328        for (var i = 0; i < bodies.length; i++) {
15329            var body = bodies[i];
15330
15331            if (body.render.visible) {
15332                var parts = bodies[i].parts;
15333                for (var j = parts.length > 1 ? 1 : 0; j < parts.length; j++) {
15334                    var part = parts[j];
15335                    c.rect(part.bounds.min.x, part.bounds.min.y, part.bounds.max.x - part.bounds.min.x, part.bounds.max.y - part.bounds.min.y);
15336                }
15337            }
15338        }
15339
15340        if (options.wireframes) {
15341            c.strokeStyle = 'rgba(255,255,255,0.08)';
15342        } else {
15343            c.strokeStyle = 'rgba(0,0,0,0.1)';
15344        }
15345
15346        c.lineWidth = 1;
15347        c.stroke();
15348    };
15349
15350    /**
15351     * Draws body angle indicators and axes
15352     * @private
15353     * @method bodyAxes
15354     * @param {render} render
15355     * @param {body[]} bodies
15356     * @param {RenderingContext} context
15357     */
15358    Render.bodyAxes = function(render, bodies, context) {
15359        var c = context,
15360            engine = render.engine,
15361            options = render.options,
15362            part,
15363            i,
15364            j,
15365            k;
15366
15367        c.beginPath();
15368
15369        for (i = 0; i < bodies.length; i++) {
15370            var body = bodies[i],
15371                parts = body.parts;
15372
15373            if (!body.render.visible)
15374                continue;
15375
15376            if (options.showAxes) {
15377                // render all axes
15378                for (j = parts.length > 1 ? 1 : 0; j < parts.length; j++) {
15379                    part = parts[j];
15380                    for (k = 0; k < part.axes.length; k++) {
15381                        var axis = part.axes[k];
15382                        c.moveTo(part.position.x, part.position.y);
15383                        c.lineTo(part.position.x + axis.x * 20, part.position.y + axis.y * 20);
15384                    }
15385                }
15386            } else {
15387                for (j = parts.length > 1 ? 1 : 0; j < parts.length; j++) {
15388                    part = parts[j];
15389                    for (k = 0; k < part.axes.length; k++) {
15390                        // render a single axis indicator
15391                        c.moveTo(part.position.x, part.position.y);
15392                        c.lineTo((part.vertices[0].x + part.vertices[part.vertices.length-1].x) / 2,
15393                            (part.vertices[0].y + part.vertices[part.vertices.length-1].y) / 2);
15394                    }
15395                }
15396            }
15397        }
15398
15399        if (options.wireframes) {
15400            c.strokeStyle = 'indianred';
15401            c.lineWidth = 1;
15402        } else {
15403            c.strokeStyle = 'rgba(255, 255, 255, 0.4)';
15404            c.globalCompositeOperation = 'overlay';
15405            c.lineWidth = 2;
15406        }
15407
15408        c.stroke();
15409        c.globalCompositeOperation = 'source-over';
15410    };
15411
15412    /**
15413     * Draws body positions
15414     * @private
15415     * @method bodyPositions
15416     * @param {render} render
15417     * @param {body[]} bodies
15418     * @param {RenderingContext} context
15419     */
15420    Render.bodyPositions = function(render, bodies, context) {
15421        var c = context,
15422            engine = render.engine,
15423            options = render.options,
15424            body,
15425            part,
15426            i,
15427            k;
15428
15429        c.beginPath();
15430
15431        // render current positions
15432        for (i = 0; i < bodies.length; i++) {
15433            body = bodies[i];
15434
15435            if (!body.render.visible)
15436                continue;
15437
15438            // handle compound parts
15439            for (k = 0; k < body.parts.length; k++) {
15440                part = body.parts[k];
15441                c.arc(part.position.x, part.position.y, 3, 0, 2 * Math.PI, false);
15442                c.closePath();
15443            }
15444        }
15445
15446        if (options.wireframes) {
15447            c.fillStyle = 'indianred';
15448        } else {
15449            c.fillStyle = 'rgba(0,0,0,0.5)';
15450        }
15451        c.fill();
15452
15453        c.beginPath();
15454
15455        // render previous positions
15456        for (i = 0; i < bodies.length; i++) {
15457            body = bodies[i];
15458            if (body.render.visible) {
15459                c.arc(body.positionPrev.x, body.positionPrev.y, 2, 0, 2 * Math.PI, false);
15460                c.closePath();
15461            }
15462        }
15463
15464        c.fillStyle = 'rgba(255,165,0,0.8)';
15465        c.fill();
15466    };
15467
15468    /**
15469     * Draws body velocity
15470     * @private
15471     * @method bodyVelocity
15472     * @param {render} render
15473     * @param {body[]} bodies
15474     * @param {RenderingContext} context
15475     */
15476    Render.bodyVelocity = function(render, bodies, context) {
15477        var c = context;
15478
15479        c.beginPath();
15480
15481        for (var i = 0; i < bodies.length; i++) {
15482            var body = bodies[i];
15483
15484            if (!body.render.visible)
15485                continue;
15486
15487            var velocity = Body.getVelocity(body);
15488
15489            c.moveTo(body.position.x, body.position.y);
15490            c.lineTo(body.position.x + velocity.x, body.position.y + velocity.y);
15491        }
15492
15493        c.lineWidth = 3;
15494        c.strokeStyle = 'cornflowerblue';
15495        c.stroke();
15496    };
15497
15498    /**
15499     * Draws body ids
15500     * @private
15501     * @method bodyIds
15502     * @param {render} render
15503     * @param {body[]} bodies
15504     * @param {RenderingContext} context
15505     */
15506    Render.bodyIds = function(render, bodies, context) {
15507        var c = context,
15508            i,
15509            j;
15510
15511        for (i = 0; i < bodies.length; i++) {
15512            if (!bodies[i].render.visible)
15513                continue;
15514
15515            var parts = bodies[i].parts;
15516            for (j = parts.length > 1 ? 1 : 0; j < parts.length; j++) {
15517                var part = parts[j];
15518                c.font = "12px Arial";
15519                c.fillStyle = 'rgba(255,255,255,0.5)';
15520                c.fillText(part.id, part.position.x + 10, part.position.y - 10);
15521            }
15522        }
15523    };
15524
15525    /**
15526     * Description
15527     * @private
15528     * @method collisions
15529     * @param {render} render
15530     * @param {pair[]} pairs
15531     * @param {RenderingContext} context
15532     */
15533    Render.collisions = function(render, pairs, context) {
15534        var c = context,
15535            options = render.options,
15536            pair,
15537            collision,
15538            corrected,
15539            bodyA,
15540            bodyB,
15541            i,
15542            j;
15543
15544        c.beginPath();
15545
15546        // render collision positions
15547        for (i = 0; i < pairs.length; i++) {
15548            pair = pairs[i];
15549
15550            if (!pair.isActive)
15551                continue;
15552
15553            collision = pair.collision;
15554            for (j = 0; j < pair.contactCount; j++) {
15555                var contact = pair.contacts[j],
15556                    vertex = contact.vertex;
15557                c.rect(vertex.x - 1.5, vertex.y - 1.5, 3.5, 3.5);
15558            }
15559        }
15560
15561        if (options.wireframes) {
15562            c.fillStyle = 'rgba(255,255,255,0.7)';
15563        } else {
15564            c.fillStyle = 'orange';
15565        }
15566        c.fill();
15567
15568        c.beginPath();
15569
15570        // render collision normals
15571        for (i = 0; i < pairs.length; i++) {
15572            pair = pairs[i];
15573
15574            if (!pair.isActive)
15575                continue;
15576
15577            collision = pair.collision;
15578
15579            if (pair.contactCount > 0) {
15580                var normalPosX = pair.contacts[0].vertex.x,
15581                    normalPosY = pair.contacts[0].vertex.y;
15582
15583                if (pair.contactCount === 2) {
15584                    normalPosX = (pair.contacts[0].vertex.x + pair.contacts[1].vertex.x) / 2;
15585                    normalPosY = (pair.contacts[0].vertex.y + pair.contacts[1].vertex.y) / 2;
15586                }
15587
15588                if (collision.bodyB === collision.supports[0].body || collision.bodyA.isStatic === true) {
15589                    c.moveTo(normalPosX - collision.normal.x * 8, normalPosY - collision.normal.y * 8);
15590                } else {
15591                    c.moveTo(normalPosX + collision.normal.x * 8, normalPosY + collision.normal.y * 8);
15592                }
15593
15594                c.lineTo(normalPosX, normalPosY);
15595            }
15596        }
15597
15598        if (options.wireframes) {
15599            c.strokeStyle = 'rgba(255,165,0,0.7)';
15600        } else {
15601            c.strokeStyle = 'orange';
15602        }
15603
15604        c.lineWidth = 1;
15605        c.stroke();
15606    };
15607
15608    /**
15609     * Description
15610     * @private
15611     * @method separations
15612     * @param {render} render
15613     * @param {pair[]} pairs
15614     * @param {RenderingContext} context
15615     */
15616    Render.separations = function(render, pairs, context) {
15617        var c = context,
15618            options = render.options,
15619            pair,
15620            collision,
15621            corrected,
15622            bodyA,
15623            bodyB,
15624            i,
15625            j;
15626
15627        c.beginPath();
15628
15629        // render separations
15630        for (i = 0; i < pairs.length; i++) {
15631            pair = pairs[i];
15632
15633            if (!pair.isActive)
15634                continue;
15635
15636            collision = pair.collision;
15637            bodyA = collision.bodyA;
15638            bodyB = collision.bodyB;
15639
15640            var k = 1;
15641
15642            if (!bodyB.isStatic && !bodyA.isStatic) k = 0.5;
15643            if (bodyB.isStatic) k = 0;
15644
15645            c.moveTo(bodyB.position.x, bodyB.position.y);
15646            c.lineTo(bodyB.position.x - collision.penetration.x * k, bodyB.position.y - collision.penetration.y * k);
15647
15648            k = 1;
15649
15650            if (!bodyB.isStatic && !bodyA.isStatic) k = 0.5;
15651            if (bodyA.isStatic) k = 0;
15652
15653            c.moveTo(bodyA.position.x, bodyA.position.y);
15654            c.lineTo(bodyA.position.x + collision.penetration.x * k, bodyA.position.y + collision.penetration.y * k);
15655        }
15656
15657        if (options.wireframes) {
15658            c.strokeStyle = 'rgba(255,165,0,0.5)';
15659        } else {
15660            c.strokeStyle = 'orange';
15661        }
15662        c.stroke();
15663    };
15664
15665    /**
15666     * Description
15667     * @private
15668     * @method inspector
15669     * @param {inspector} inspector
15670     * @param {RenderingContext} context
15671     */
15672    Render.inspector = function(inspector, context) {
15673        var engine = inspector.engine,
15674            selected = inspector.selected,
15675            render = inspector.render,
15676            options = render.options,
15677            bounds;
15678
15679        if (options.hasBounds) {
15680            var boundsWidth = render.bounds.max.x - render.bounds.min.x,
15681                boundsHeight = render.bounds.max.y - render.bounds.min.y,
15682                boundsScaleX = boundsWidth / render.options.width,
15683                boundsScaleY = boundsHeight / render.options.height;
15684
15685            context.scale(1 / boundsScaleX, 1 / boundsScaleY);
15686            context.translate(-render.bounds.min.x, -render.bounds.min.y);
15687        }
15688
15689        for (var i = 0; i < selected.length; i++) {
15690            var item = selected[i].data;
15691
15692            context.translate(0.5, 0.5);
15693            context.lineWidth = 1;
15694            context.strokeStyle = 'rgba(255,165,0,0.9)';
15695            context.setLineDash([1,2]);
15696
15697            switch (item.type) {
15698
15699            case 'body':
15700
15701                // render body selections
15702                bounds = item.bounds;
15703                context.beginPath();
15704                context.rect(Math.floor(bounds.min.x - 3), Math.floor(bounds.min.y - 3),
15705                    Math.floor(bounds.max.x - bounds.min.x + 6), Math.floor(bounds.max.y - bounds.min.y + 6));
15706                context.closePath();
15707                context.stroke();
15708
15709                break;
15710
15711            case 'constraint':
15712
15713                // render constraint selections
15714                var point = item.pointA;
15715                if (item.bodyA)
15716                    point = item.pointB;
15717                context.beginPath();
15718                context.arc(point.x, point.y, 10, 0, 2 * Math.PI);
15719                context.closePath();
15720                context.stroke();
15721
15722                break;
15723
15724            }
15725
15726            context.setLineDash([]);
15727            context.translate(-0.5, -0.5);
15728        }
15729
15730        // render selection region
15731        if (inspector.selectStart !== null) {
15732            context.translate(0.5, 0.5);
15733            context.lineWidth = 1;
15734            context.strokeStyle = 'rgba(255,165,0,0.6)';
15735            context.fillStyle = 'rgba(255,165,0,0.1)';
15736            bounds = inspector.selectBounds;
15737            context.beginPath();
15738            context.rect(Math.floor(bounds.min.x), Math.floor(bounds.min.y),
15739                Math.floor(bounds.max.x - bounds.min.x), Math.floor(bounds.max.y - bounds.min.y));
15740            context.closePath();
15741            context.stroke();
15742            context.fill();
15743            context.translate(-0.5, -0.5);
15744        }
15745
15746        if (options.hasBounds)
15747            context.setTransform(1, 0, 0, 1, 0, 0);
15748    };
15749
15750    /**
15751     * Updates render timing.
15752     * @method _updateTiming
15753     * @private
15754     * @param {render} render
15755     * @param {number} time
15756     */
15757    var _updateTiming = function(render, time) {
15758        var engine = render.engine,
15759            timing = render.timing,
15760            historySize = timing.historySize,
15761            timestamp = engine.timing.timestamp;
15762
15763        timing.delta = time - timing.lastTime || Render._goodDelta;
15764        timing.lastTime = time;
15765
15766        timing.timestampElapsed = timestamp - timing.lastTimestamp || 0;
15767        timing.lastTimestamp = timestamp;
15768
15769        timing.deltaHistory.unshift(timing.delta);
15770        timing.deltaHistory.length = Math.min(timing.deltaHistory.length, historySize);
15771
15772        timing.engineDeltaHistory.unshift(engine.timing.lastDelta);
15773        timing.engineDeltaHistory.length = Math.min(timing.engineDeltaHistory.length, historySize);
15774
15775        timing.timestampElapsedHistory.unshift(timing.timestampElapsed);
15776        timing.timestampElapsedHistory.length = Math.min(timing.timestampElapsedHistory.length, historySize);
15777
15778        timing.engineUpdatesHistory.unshift(engine.timing.lastUpdatesPerFrame);
15779        timing.engineUpdatesHistory.length = Math.min(timing.engineUpdatesHistory.length, historySize);
15780
15781        timing.engineElapsedHistory.unshift(engine.timing.lastElapsed);
15782        timing.engineElapsedHistory.length = Math.min(timing.engineElapsedHistory.length, historySize);
15783
15784        timing.elapsedHistory.unshift(timing.lastElapsed);
15785        timing.elapsedHistory.length = Math.min(timing.elapsedHistory.length, historySize);
15786    };
15787
15788    /**
15789     * Returns the mean value of the given numbers.
15790     * @method _mean
15791     * @private
15792     * @param {Number[]} values
15793     * @return {Number} the mean of given values
15794     */
15795    var _mean = function(values) {
15796        var result = 0;
15797        for (var i = 0; i < values.length; i += 1) {
15798            result += values[i];
15799        }
15800        return (result / values.length) || 0;
15801    };
15802
15803    /**
15804     * @method _createCanvas
15805     * @private
15806     * @param {} width
15807     * @param {} height
15808     * @return canvas
15809     */
15810    var _createCanvas = function(width, height) {
15811        var canvas = document.createElement('canvas');
15812        canvas.width = width;
15813        canvas.height = height;
15814        canvas.oncontextmenu = function() { return false; };
15815        canvas.onselectstart = function() { return false; };
15816        return canvas;
15817    };
15818
15819    /**
15820     * Gets the pixel ratio of the canvas.
15821     * @method _getPixelRatio
15822     * @private
15823     * @param {HTMLElement} canvas
15824     * @return {Number} pixel ratio
15825     */
15826    var _getPixelRatio = function(canvas) {
15827        var context = canvas.getContext('2d'),
15828            devicePixelRatio = window.devicePixelRatio || 1,
15829            backingStorePixelRatio = context.webkitBackingStorePixelRatio || context.mozBackingStorePixelRatio
15830                                      || context.msBackingStorePixelRatio || context.oBackingStorePixelRatio
15831                                      || context.backingStorePixelRatio || 1;
15832
15833        return devicePixelRatio / backingStorePixelRatio;
15834    };
15835
15836    /**
15837     * Gets the requested texture (an Image) via its path
15838     * @method _getTexture
15839     * @private
15840     * @param {render} render
15841     * @param {string} imagePath
15842     * @return {Image} texture
15843     */
15844    var _getTexture = function(render, imagePath) {
15845        var image = render.textures[imagePath];
15846
15847        if (image)
15848            return image;
15849
15850        image = render.textures[imagePath] = new Image();
15851        image.src = imagePath;
15852
15853        return image;
15854    };
15855
15856    /**
15857     * Applies the background to the canvas using CSS.
15858     * @method applyBackground
15859     * @private
15860     * @param {render} render
15861     * @param {string} background
15862     */
15863    var _applyBackground = function(render, background) {
15864        var cssBackground = background;
15865
15866        if (/(jpg|gif|png)$/.test(background))
15867            cssBackground = 'url(' + background + ')';
15868
15869        render.canvas.style.background = cssBackground;
15870        render.canvas.style.backgroundSize = "contain";
15871        render.currentBackground = background;
15872    };
15873
15874    /*
15875    *
15876    *  Events Documentation
15877    *
15878    */
15879
15880    /**
15881    * Fired before rendering
15882    *
15883    * @event beforeRender
15884    * @param {} event An event object
15885    * @param {number} event.timestamp The engine.timing.timestamp of the event
15886    * @param {} event.source The source object of the event
15887    * @param {} event.name The name of the event
15888    */
15889
15890    /**
15891    * Fired after rendering
15892    *
15893    * @event afterRender
15894    * @param {} event An event object
15895    * @param {number} event.timestamp The engine.timing.timestamp of the event
15896    * @param {} event.source The source object of the event
15897    * @param {} event.name The name of the event
15898    */
15899
15900    /*
15901    *
15902    *  Properties Documentation
15903    *
15904    */
15905
15906    /**
15907     * A back-reference to the `Matter.Render` module.
15908     *
15909     * @deprecated
15910     * @property controller
15911     * @type render
15912     */
15913
15914    /**
15915     * A reference to the `Matter.Engine` instance to be used.
15916     *
15917     * @property engine
15918     * @type engine
15919     */
15920
15921    /**
15922     * A reference to the element where the canvas is to be inserted (if `render.canvas` has not been specified)
15923     *
15924     * @property element
15925     * @type HTMLElement
15926     * @default null
15927     */
15928
15929    /**
15930     * The canvas element to render to. If not specified, one will be created if `render.element` has been specified.
15931     *
15932     * @property canvas
15933     * @type HTMLCanvasElement
15934     * @default null
15935     */
15936
15937    /**
15938     * A `Bounds` object that specifies the drawing view region.
15939     * Rendering will be automatically transformed and scaled to fit within the canvas size (`render.options.width` and `render.options.height`).
15940     * This allows for creating views that can pan or zoom around the scene.
15941     * You must also set `render.options.hasBounds` to `true` to enable bounded rendering.
15942     *
15943     * @property bounds
15944     * @type bounds
15945     */
15946
15947    /**
15948     * The 2d rendering context from the `render.canvas` element.
15949     *
15950     * @property context
15951     * @type CanvasRenderingContext2D
15952     */
15953
15954    /**
15955     * The sprite texture cache.
15956     *
15957     * @property textures
15958     * @type {}
15959     */
15960
15961    /**
15962     * The mouse to render if `render.options.showMousePosition` is enabled.
15963     *
15964     * @property mouse
15965     * @type mouse
15966     * @default null
15967     */
15968
15969    /**
15970     * The configuration options of the renderer.
15971     *
15972     * @property options
15973     * @type {}
15974     */
15975
15976    /**
15977     * The target width in pixels of the `render.canvas` to be created.
15978     * See also the `options.pixelRatio` property to change render quality.
15979     *
15980     * @property options.width
15981     * @type number
15982     * @default 800
15983     */
15984
15985    /**
15986     * The target height in pixels of the `render.canvas` to be created.
15987     * See also the `options.pixelRatio` property to change render quality.
15988     *
15989     * @property options.height
15990     * @type number
15991     * @default 600
15992     */
15993
15994    /**
15995     * The [pixel ratio](https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio) to use when rendering.
15996     *
15997     * @property options.pixelRatio
15998     * @type number
15999     * @default 1
16000     */
16001
16002    /**
16003     * A CSS background color string to use when `render.options.wireframes` is disabled.
16004     * This may be also set to `'transparent'` or equivalent.
16005     *
16006     * @property options.background
16007     * @type string
16008     * @default '#14151f'
16009     */
16010
16011    /**
16012     * A CSS color string to use for background when `render.options.wireframes` is enabled.
16013     * This may be also set to `'transparent'` or equivalent.
16014     *
16015     * @property options.wireframeBackground
16016     * @type string
16017     * @default '#14151f'
16018     */
16019
16020    /**
16021     * A CSS color string to use for stroke when `render.options.wireframes` is enabled.
16022     * This may be also set to `'transparent'` or equivalent.
16023     *
16024     * @property options.wireframeStrokeStyle
16025     * @type string
16026     * @default '#bbb'
16027     */
16028
16029    /**
16030     * A flag that specifies if `render.bounds` should be used when rendering.
16031     *
16032     * @property options.hasBounds
16033     * @type boolean
16034     * @default false
16035     */
16036
16037    /**
16038     * A flag to enable or disable all debug information overlays together.  
16039     * This includes and has priority over the values of:
16040     *
16041     * - `render.options.showStats`
16042     * - `render.options.showPerformance`
16043     *
16044     * @property options.showDebug
16045     * @type boolean
16046     * @default false
16047     */
16048
16049    /**
16050     * A flag to enable or disable the engine stats info overlay.  
16051     * From left to right, the values shown are:
16052     *
16053     * - body parts total
16054     * - body total
16055     * - constraints total
16056     * - composites total
16057     * - collision pairs total
16058     *
16059     * @property options.showStats
16060     * @type boolean
16061     * @default false
16062     */
16063
16064    /**
16065     * A flag to enable or disable performance charts.  
16066     * From left to right, the values shown are:
16067     *
16068     * - average render frequency (e.g. 60 fps)
16069     * - exact engine delta time used for last update (e.g. 16.66ms)
16070     * - average updates per frame (e.g. 1)
16071     * - average engine execution duration (e.g. 5.00ms)
16072     * - average render execution duration (e.g. 0.40ms)
16073     * - average effective play speed (e.g. '1.00x' is 'real-time')
16074     *
16075     * Each value is recorded over a fixed sample of past frames (60 frames).
16076     *
16077     * A chart shown below each value indicates the variance from the average over the sample.
16078     * The more stable or fixed the value is the flatter the chart will appear.
16079     *
16080     * @property options.showPerformance
16081     * @type boolean
16082     * @default false
16083     */
16084    
16085    /**
16086     * A flag to enable or disable rendering entirely.
16087     *
16088     * @property options.enabled
16089     * @type boolean
16090     * @default false
16091     */
16092
16093    /**
16094     * A flag to toggle wireframe rendering otherwise solid fill rendering is used.
16095     *
16096     * @property options.wireframes
16097     * @type boolean
16098     * @default true
16099     */
16100
16101    /**
16102     * A flag to enable or disable sleeping bodies indicators.
16103     *
16104     * @property options.showSleeping
16105     * @type boolean
16106     * @default true
16107     */
16108
16109    /**
16110     * A flag to enable or disable the debug information overlay.
16111     *
16112     * @property options.showDebug
16113     * @type boolean
16114     * @default false
16115     */
16116
16117    /**
16118     * A flag to enable or disable the collision broadphase debug overlay.
16119     *
16120     * @deprecated no longer implemented
16121     * @property options.showBroadphase
16122     * @type boolean
16123     * @default false
16124     */
16125
16126    /**
16127     * A flag to enable or disable the body bounds debug overlay.
16128     *
16129     * @property options.showBounds
16130     * @type boolean
16131     * @default false
16132     */
16133
16134    /**
16135     * A flag to enable or disable the body velocity debug overlay.
16136     *
16137     * @property options.showVelocity
16138     * @type boolean
16139     * @default false
16140     */
16141
16142    /**
16143     * A flag to enable or disable the body collisions debug overlay.
16144     *
16145     * @property options.showCollisions
16146     * @type boolean
16147     * @default false
16148     */
16149
16150    /**
16151     * A flag to enable or disable the collision resolver separations debug overlay.
16152     *
16153     * @property options.showSeparations
16154     * @type boolean
16155     * @default false
16156     */
16157
16158    /**
16159     * A flag to enable or disable the body axes debug overlay.
16160     *
16161     * @property options.showAxes
16162     * @type boolean
16163     * @default false
16164     */
16165
16166    /**
16167     * A flag to enable or disable the body positions debug overlay.
16168     *
16169     * @property options.showPositions
16170     * @type boolean
16171     * @default false
16172     */
16173
16174    /**
16175     * A flag to enable or disable the body angle debug overlay.
16176     *
16177     * @property options.showAngleIndicator
16178     * @type boolean
16179     * @default false
16180     */
16181
16182    /**
16183     * A flag to enable or disable the body and part ids debug overlay.
16184     *
16185     * @property options.showIds
16186     * @type boolean
16187     * @default false
16188     */
16189
16190    /**
16191     * A flag to enable or disable the body vertex numbers debug overlay.
16192     *
16193     * @property options.showVertexNumbers
16194     * @type boolean
16195     * @default false
16196     */
16197
16198    /**
16199     * A flag to enable or disable the body convex hulls debug overlay.
16200     *
16201     * @property options.showConvexHulls
16202     * @type boolean
16203     * @default false
16204     */
16205
16206    /**
16207     * A flag to enable or disable the body internal edges debug overlay.
16208     *
16209     * @property options.showInternalEdges
16210     * @type boolean
16211     * @default false
16212     */
16213
16214    /**
16215     * A flag to enable or disable the mouse position debug overlay.
16216     *
16217     * @property options.showMousePosition
16218     * @type boolean
16219     * @default false
16220     */
16221
16222})();
16223
16224
16225/***/ }),
16226/* 27 */
16227/***/ (function(module, exports, __webpack_require__) {
16228
16229/**
16230* The `Matter.Runner` module is an optional utility that provides a game loop for running a `Matter.Engine` inside a browser environment.
16231* A runner will continuously update a `Matter.Engine` whilst synchronising engine updates with the browser frame rate.
16232* This runner favours a smoother user experience over perfect time keeping.
16233* This runner is optional and is used for development and debugging but could be useful as a starting point for implementing some games and experiences.
16234* Alternatively see `Engine.update` to step the engine directly inside your own game loop implementation as may be needed inside other environments.
16235*
16236* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples).
16237*
16238* @class Runner
16239*/
16240
16241var Runner = {};
16242
16243module.exports = Runner;
16244
16245var Events = __webpack_require__(5);
16246var Engine = __webpack_require__(17);
16247var Common = __webpack_require__(0);
16248
16249(function() {
16250
16251    Runner._maxFrameDelta = 1000 / 15;
16252    Runner._frameDeltaFallback = 1000 / 60;
16253    Runner._timeBufferMargin = 1.5;
16254    Runner._elapsedNextEstimate = 1;
16255    Runner._smoothingLowerBound = 0.1;
16256    Runner._smoothingUpperBound = 0.9;
16257
16258    /**
16259     * Creates a new Runner. 
16260     * See the properties section below for detailed information on what you can pass via the `options` object.
16261     * @method create
16262     * @param {} options
16263     */
16264    Runner.create = function(options) {
16265        var defaults = {
16266            delta: 1000 / 60,
16267            frameDelta: null,
16268            frameDeltaSmoothing: true,
16269            frameDeltaSnapping: true,
16270            frameDeltaHistory: [],
16271            frameDeltaHistorySize: 100,
16272            frameRequestId: null,
16273            timeBuffer: 0,
16274            timeLastTick: null,
16275            maxUpdates: null,
16276            maxFrameTime: 1000 / 30,
16277            lastUpdatesDeferred: 0,
16278            enabled: true
16279        };
16280
16281        var runner = Common.extend(defaults, options);
16282
16283        // for temporary back compatibility only
16284        runner.fps = 0;
16285
16286        return runner;
16287    };
16288
16289    /**
16290     * Runs a `Matter.Engine` whilst synchronising engine updates with the browser frame rate. 
16291     * See module and properties descriptions for more information on this runner.
16292     * Alternatively see `Engine.update` to step the engine directly inside your own game loop implementation.
16293     * @method run
16294     * @param {runner} runner
16295     * @param {engine} [engine]
16296     * @return {runner} runner
16297     */
16298    Runner.run = function(runner, engine) {
16299        // initial time buffer for the first frame
16300        runner.timeBuffer = Runner._frameDeltaFallback;
16301
16302        (function onFrame(time){
16303            runner.frameRequestId = Runner._onNextFrame(runner, onFrame);
16304
16305            if (time && runner.enabled) {
16306                Runner.tick(runner, engine, time);
16307            }
16308        })();
16309
16310        return runner;
16311    };
16312
16313    /**
16314     * Performs a single runner tick as used inside `Runner.run`.
16315     * See module and properties descriptions for more information on this runner.
16316     * Alternatively see `Engine.update` to step the engine directly inside your own game loop implementation.
16317     * @method tick
16318     * @param {runner} runner
16319     * @param {engine} engine
16320     * @param {number} time
16321     */
16322    Runner.tick = function(runner, engine, time) {
16323        var tickStartTime = Common.now(),
16324            engineDelta = runner.delta,
16325            updateCount = 0;
16326
16327        // find frame delta time since last call
16328        var frameDelta = time - runner.timeLastTick;
16329
16330        // fallback for unusable frame delta values (e.g. 0, NaN, on first frame or long pauses)
16331        if (!frameDelta || !runner.timeLastTick || frameDelta > Math.max(Runner._maxFrameDelta, runner.maxFrameTime)) {
16332            // reuse last accepted frame delta else fallback
16333            frameDelta = runner.frameDelta || Runner._frameDeltaFallback;
16334        }
16335
16336        if (runner.frameDeltaSmoothing) {
16337            // record frame delta over a number of frames
16338            runner.frameDeltaHistory.push(frameDelta);
16339            runner.frameDeltaHistory = runner.frameDeltaHistory.slice(-runner.frameDeltaHistorySize);
16340
16341            // sort frame delta history
16342            var deltaHistorySorted = runner.frameDeltaHistory.slice(0).sort();
16343
16344            // sample a central window to limit outliers
16345            var deltaHistoryWindow = runner.frameDeltaHistory.slice(
16346                deltaHistorySorted.length * Runner._smoothingLowerBound, 
16347                deltaHistorySorted.length * Runner._smoothingUpperBound
16348            );
16349
16350            // take the mean of the central window
16351            var frameDeltaSmoothed = _mean(deltaHistoryWindow);
16352            frameDelta = frameDeltaSmoothed || frameDelta;
16353        }
16354
16355        if (runner.frameDeltaSnapping) {
16356            // snap frame delta to the nearest 1 Hz
16357            frameDelta = 1000 / Math.round(1000 / frameDelta);
16358        }
16359
16360        // update runner values for next call
16361        runner.frameDelta = frameDelta;
16362        runner.timeLastTick = time;
16363
16364        // accumulate elapsed time
16365        runner.timeBuffer += runner.frameDelta;
16366
16367        // limit time buffer size to a single frame of updates
16368        runner.timeBuffer = Common.clamp(
16369            runner.timeBuffer, 0, runner.frameDelta + engineDelta * Runner._timeBufferMargin
16370        );
16371
16372        // reset count of over budget updates
16373        runner.lastUpdatesDeferred = 0;
16374
16375        // get max updates per frame
16376        var maxUpdates = runner.maxUpdates || Math.ceil(runner.maxFrameTime / engineDelta);
16377
16378        // create event object
16379        var event = {
16380            timestamp: engine.timing.timestamp
16381        };
16382
16383        // tick events before update
16384        Events.trigger(runner, 'beforeTick', event);
16385        Events.trigger(runner, 'tick', event);
16386
16387        var updateStartTime = Common.now();
16388
16389        // simulate time elapsed between calls
16390        while (engineDelta > 0 && runner.timeBuffer >= engineDelta * Runner._timeBufferMargin) {
16391            // update the engine
16392            Events.trigger(runner, 'beforeUpdate', event);
16393            Engine.update(engine, engineDelta);
16394            Events.trigger(runner, 'afterUpdate', event);
16395
16396            // consume time simulated from buffer
16397            runner.timeBuffer -= engineDelta;
16398            updateCount += 1;
16399
16400            // find elapsed time during this tick
16401            var elapsedTimeTotal = Common.now() - tickStartTime,
16402                elapsedTimeUpdates = Common.now() - updateStartTime,
16403                elapsedNextEstimate = elapsedTimeTotal + Runner._elapsedNextEstimate * elapsedTimeUpdates / updateCount;
16404
16405            // defer updates if over performance budgets for this frame
16406            if (updateCount >= maxUpdates || elapsedNextEstimate > runner.maxFrameTime) {
16407                runner.lastUpdatesDeferred = Math.round(Math.max(0, (runner.timeBuffer / engineDelta) - Runner._timeBufferMargin));
16408                break;
16409            }
16410        }
16411
16412        // track timing metrics
16413        engine.timing.lastUpdatesPerFrame = updateCount;
16414
16415        // tick events after update
16416        Events.trigger(runner, 'afterTick', event);
16417
16418        // show useful warnings if needed
16419        if (runner.frameDeltaHistory.length >= 100) {
16420            if (runner.lastUpdatesDeferred && Math.round(runner.frameDelta / engineDelta) > maxUpdates) {
16421                Common.warnOnce('Matter.Runner: runner reached runner.maxUpdates, see docs.');
16422            } else if (runner.lastUpdatesDeferred) {
16423                Common.warnOnce('Matter.Runner: runner reached runner.maxFrameTime, see docs.');
16424            }
16425
16426            if (typeof runner.isFixed !== 'undefined') {
16427                Common.warnOnce('Matter.Runner: runner.isFixed is now redundant, see docs.');
16428            }
16429
16430            if (runner.deltaMin || runner.deltaMax) {
16431                Common.warnOnce('Matter.Runner: runner.deltaMin and runner.deltaMax were removed, see docs.');
16432            }
16433
16434            if (runner.fps !== 0) {
16435                Common.warnOnce('Matter.Runner: runner.fps was replaced by runner.delta, see docs.');
16436            }
16437        }
16438    };
16439
16440    /**
16441     * Ends execution of `Runner.run` on the given `runner` by canceling the frame loop.
16442     * Alternatively to temporarily pause the runner, see `runner.enabled`.
16443     * @method stop
16444     * @param {runner} runner
16445     */
16446    Runner.stop = function(runner) {
16447        Runner._cancelNextFrame(runner);
16448    };
16449
16450    /**
16451     * Schedules the `callback` on this `runner` for the next animation frame.
16452     * @private
16453     * @method _onNextFrame
16454     * @param {runner} runner
16455     * @param {function} callback
16456     * @return {number} frameRequestId
16457     */
16458    Runner._onNextFrame = function(runner, callback) {
16459        if (typeof window !== 'undefined' && window.requestAnimationFrame) {
16460            runner.frameRequestId = window.requestAnimationFrame(callback);
16461        } else {
16462            throw new Error('Matter.Runner: missing required global window.requestAnimationFrame.');
16463        }
16464
16465        return runner.frameRequestId;
16466    };
16467
16468    /**
16469     * Cancels the last callback scheduled by `Runner._onNextFrame` on this `runner`.
16470     * @private
16471     * @method _cancelNextFrame
16472     * @param {runner} runner
16473     */
16474    Runner._cancelNextFrame = function(runner) {
16475        if (typeof window !== 'undefined' && window.cancelAnimationFrame) {
16476            window.cancelAnimationFrame(runner.frameRequestId);
16477        } else {
16478            throw new Error('Matter.Runner: missing required global window.cancelAnimationFrame.');
16479        }
16480    };
16481
16482    /**
16483     * Returns the mean of the given numbers.
16484     * @method _mean
16485     * @private
16486     * @param {Number[]} values
16487     * @return {Number} the mean of given values.
16488     */
16489    var _mean = function(values) {
16490        var result = 0,
16491            valuesLength = values.length;
16492
16493        for (var i = 0; i < valuesLength; i += 1) {
16494            result += values[i];
16495        }
16496
16497        return (result / valuesLength) || 0;
16498    };
16499
16500    /*
16501    *
16502    *  Events Documentation
16503    *
16504    */
16505
16506    /**
16507    * Fired once at the start of the browser frame, before any engine updates.
16508    *
16509    * @event beforeTick
16510    * @param {} event An event object
16511    * @param {number} event.timestamp The engine.timing.timestamp of the event
16512    * @param {} event.source The source object of the event
16513    * @param {} event.name The name of the event
16514    */
16515
16516    /**
16517    * Fired once at the start of the browser frame, after `beforeTick`.
16518    *
16519    * @event tick
16520    * @param {} event An event object
16521    * @param {number} event.timestamp The engine.timing.timestamp of the event
16522    * @param {} event.source The source object of the event
16523    * @param {} event.name The name of the event
16524    */
16525
16526    /**
16527    * Fired once at the end of the browser frame, after `beforeTick`, `tick` and after any engine updates.
16528    *
16529    * @event afterTick
16530    * @param {} event An event object
16531    * @param {number} event.timestamp The engine.timing.timestamp of the event
16532    * @param {} event.source The source object of the event
16533    * @param {} event.name The name of the event
16534    */
16535
16536    /**
16537    * Fired before each and every engine update in this browser frame (if any). 
16538    * There may be multiple engine update calls per browser frame (or none) depending on framerate and timestep delta.
16539    *
16540    * @event beforeUpdate
16541    * @param {} event An event object
16542    * @param {number} event.timestamp The engine.timing.timestamp of the event
16543    * @param {} event.source The source object of the event
16544    * @param {} event.name The name of the event
16545    */
16546
16547    /**
16548    * Fired after each and every engine update in this browser frame (if any). 
16549    * There may be multiple engine update calls per browser frame (or none) depending on framerate and timestep delta.
16550    *
16551    * @event afterUpdate
16552    * @param {} event An event object
16553    * @param {number} event.timestamp The engine.timing.timestamp of the event
16554    * @param {} event.source The source object of the event
16555    * @param {} event.name The name of the event
16556    */
16557
16558    /*
16559    *
16560    *  Properties Documentation
16561    *
16562    */
16563
16564    /**
16565     * The fixed timestep size used for `Engine.update` calls in milliseconds, known as `delta`.
16566     * 
16567     * This value is recommended to be `1000 / 60` ms or smaller (i.e. equivalent to at least 60hz).
16568     * 
16569     * Smaller `delta` values provide higher quality results at the cost of performance.
16570     * 
16571     * You should usually avoid changing `delta` during running, otherwise quality may be affected. 
16572     * 
16573     * For smoother frame pacing choose a `delta` that is an even multiple of each display FPS you target, i.e. `1000 / (n * fps)` as this helps distribute an equal number of updates over each display frame.
16574     * 
16575     * For example with a 60 Hz `delta` i.e. `1000 / 60` the runner will on average perform one update per frame on displays running 60 FPS and one update every two frames on displays running 120 FPS, etc.
16576     * 
16577     * Where as e.g. using a 240 Hz `delta` i.e. `1000 / 240` the runner will on average perform four updates per frame on displays running 60 FPS and two updates per frame on displays running 120 FPS, etc.
16578     * 
16579     * Therefore `Runner.run` will call multiple engine updates (or none) as needed to simulate the time elapsed between browser frames. 
16580     * 
16581     * In practice the number of updates in any particular frame may be restricted to respect the runner's performance budgets. These are specified by `runner.maxFrameTime` and `runner.maxUpdates`, see those properties for details.
16582     * 
16583     * @property delta
16584     * @type number
16585     * @default 1000 / 60
16586     */
16587
16588    /**
16589     * A flag that can be toggled to enable or disable tick calls on this runner, therefore pausing engine updates and events while the runner loop remains running.
16590     *
16591     * @property enabled
16592     * @type boolean
16593     * @default true
16594     */
16595
16596    /**
16597     * The accumulated time elapsed that has yet to be simulated in milliseconds.
16598     * This value is clamped within certain limits (see `Runner.tick` code).
16599     *
16600     * @private
16601     * @property timeBuffer
16602     * @type number
16603     * @default 0
16604     */
16605
16606    /**
16607     * The measured time elapsed between the last two browser frames measured in milliseconds.
16608     * This is useful e.g. to estimate the current browser FPS using `1000 / runner.frameDelta`.
16609     *
16610     * @readonly
16611     * @property frameDelta
16612     * @type number
16613     */
16614
16615    /**
16616     * Enables averaging to smooth frame rate measurements and therefore stabilise play rate.
16617     *
16618     * @property frameDeltaSmoothing
16619     * @type boolean
16620     * @default true
16621     */
16622
16623    /**
16624     * Rounds measured browser frame delta to the nearest 1 Hz.
16625     * This option can help smooth frame rate measurements and simplify handling hardware timing differences e.g. 59.94Hz and 60Hz displays.
16626     * For best results you should also round your `runner.delta` equivalent to the nearest 1 Hz.
16627     *
16628     * @property frameDeltaSnapping
16629     * @type boolean
16630     * @default true
16631     */
16632
16633    /**
16634     * A performance budget that limits execution time allowed for this runner per browser frame in milliseconds.
16635     * 
16636     * To calculate the effective browser FPS at which this throttle is applied use `1000 / runner.maxFrameTime`.
16637     * 
16638     * This performance budget is intended to help maintain browser interactivity and help improve framerate recovery during temporary high CPU usage.
16639     * 
16640     * This budget only covers the measured time elapsed executing the functions called in the scope of the runner tick, including `Engine.update` and its related user event callbacks.
16641     * 
16642     * You may also reduce this budget to allow for any significant additional processing you perform on the same thread outside the scope of this runner tick, e.g. rendering time.
16643     * 
16644     * See also `runner.maxUpdates`.
16645     *
16646     * @property maxFrameTime
16647     * @type number
16648     * @default 1000 / 30
16649     */
16650
16651    /**
16652     * An optional limit for maximum engine update count allowed per frame tick in addition to `runner.maxFrameTime`.
16653     * 
16654     * Unless you set a value it is automatically chosen based on `runner.delta` and `runner.maxFrameTime`.
16655     * 
16656     * See also `runner.maxFrameTime`.
16657     * 
16658     * @property maxUpdates
16659     * @type number
16660     * @default null
16661     */
16662
16663    /**
16664     * The timestamp of the last call to `Runner.tick` used to measure `frameDelta`.
16665     *
16666     * @private
16667     * @property timeLastTick
16668     * @type number
16669     * @default 0
16670     */
16671
16672    /**
16673     * The id of the last call to `Runner._onNextFrame`.
16674     *
16675     * @private
16676     * @property frameRequestId
16677     * @type number
16678     * @default null
16679     */
16680
16681})();
16682
16683
16684/***/ }),
16685/* 28 */
16686/***/ (function(module, exports, __webpack_require__) {
16687
16688/**
16689* This module has now been replaced by `Matter.Collision`.
16690*
16691* All usage should be migrated to `Matter.Collision`.
16692* For back-compatibility purposes this module will remain for a short term and then later removed in a future release.
16693*
16694* The `Matter.SAT` module contains methods for detecting collisions using the Separating Axis Theorem.
16695*
16696* @class SAT
16697* @deprecated
16698*/
16699
16700var SAT = {};
16701
16702module.exports = SAT;
16703
16704var Collision = __webpack_require__(8);
16705var Common = __webpack_require__(0);
16706var deprecated = Common.deprecated;
16707
16708(function() {
16709
16710    /**
16711     * Detect collision between two bodies using the Separating Axis Theorem.
16712     * @deprecated replaced by Collision.collides
16713     * @method collides
16714     * @param {body} bodyA
16715     * @param {body} bodyB
16716     * @return {collision} collision
16717     */
16718    SAT.collides = function(bodyA, bodyB) {
16719        return Collision.collides(bodyA, bodyB);
16720    };
16721
16722    deprecated(SAT, 'collides', 'SAT.collides ➤ replaced by Collision.collides');
16723
16724})();
16725
16726
16727/***/ }),
16728/* 29 */
16729/***/ (function(module, exports, __webpack_require__) {
16730
16731/**
16732* The `Matter.Svg` module contains methods for converting SVG images into an array of vector points.
16733*
16734* To use this module you also need the SVGPathSeg polyfill: https://github.com/progers/pathseg
16735*
16736* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples).
16737*
16738* @class Svg
16739*/
16740
16741var Svg = {};
16742
16743module.exports = Svg;
16744
16745var Bounds = __webpack_require__(1);
16746var Common = __webpack_require__(0);
16747
16748(function() {
16749
16750    /**
16751     * Converts an SVG path into an array of vector points.
16752     * If the input path forms a concave shape, you must decompose the result into convex parts before use.
16753     * See `Bodies.fromVertices` which provides support for this.
16754     * Note that this function is not guaranteed to support complex paths (such as those with holes).
16755     * You must load the `pathseg.js` polyfill on newer browsers.
16756     * @method pathToVertices
16757     * @param {SVGPathElement} path
16758     * @param {Number} [sampleLength=15]
16759     * @return {Vector[]} points
16760     */
16761    Svg.pathToVertices = function(path, sampleLength) {
16762        if (typeof window !== 'undefined' && !('SVGPathSeg' in window)) {
16763            Common.warn('Svg.pathToVertices: SVGPathSeg not defined, a polyfill is required.');
16764        }
16765
16766        // https://github.com/wout/svg.topoly.js/blob/master/svg.topoly.js
16767        var i, il, total, point, segment, segments, 
16768            segmentsQueue, lastSegment, 
16769            lastPoint, segmentIndex, points = [],
16770            lx, ly, length = 0, x = 0, y = 0;
16771
16772        sampleLength = sampleLength || 15;
16773
16774        var addPoint = function(px, py, pathSegType) {
16775            // all odd-numbered path types are relative except PATHSEG_CLOSEPATH (1)
16776            var isRelative = pathSegType % 2 === 1 && pathSegType > 1;
16777
16778            // when the last point doesn't equal the current point add the current point
16779            if (!lastPoint || px != lastPoint.x || py != lastPoint.y) {
16780                if (lastPoint && isRelative) {
16781                    lx = lastPoint.x;
16782                    ly = lastPoint.y;
16783                } else {
16784                    lx = 0;
16785                    ly = 0;
16786                }
16787
16788                var point = {
16789                    x: lx + px,
16790                    y: ly + py
16791                };
16792
16793                // set last point
16794                if (isRelative || !lastPoint) {
16795                    lastPoint = point;
16796                }
16797
16798                points.push(point);
16799
16800                x = lx + px;
16801                y = ly + py;
16802            }
16803        };
16804
16805        var addSegmentPoint = function(segment) {
16806            var segType = segment.pathSegTypeAsLetter.toUpperCase();
16807
16808            // skip path ends
16809            if (segType === 'Z') 
16810                return;
16811
16812            // map segment to x and y
16813            switch (segType) {
16814
16815            case 'M':
16816            case 'L':
16817            case 'T':
16818            case 'C':
16819            case 'S':
16820            case 'Q':
16821                x = segment.x;
16822                y = segment.y;
16823                break;
16824            case 'H':
16825                x = segment.x;
16826                break;
16827            case 'V':
16828                y = segment.y;
16829                break;
16830            }
16831
16832            addPoint(x, y, segment.pathSegType);
16833        };
16834
16835        // ensure path is absolute
16836        Svg._svgPathToAbsolute(path);
16837
16838        // get total length
16839        total = path.getTotalLength();
16840
16841        // queue segments
16842        segments = [];
16843        for (i = 0; i < path.pathSegList.numberOfItems; i += 1)
16844            segments.push(path.pathSegList.getItem(i));
16845
16846        segmentsQueue = segments.concat();
16847
16848        // sample through path
16849        while (length < total) {
16850            // get segment at position
16851            segmentIndex = path.getPathSegAtLength(length);
16852            segment = segments[segmentIndex];
16853
16854            // new segment
16855            if (segment != lastSegment) {
16856                while (segmentsQueue.length && segmentsQueue[0] != segment)
16857                    addSegmentPoint(segmentsQueue.shift());
16858
16859                lastSegment = segment;
16860            }
16861
16862            // add points in between when curving
16863            // TODO: adaptive sampling
16864            switch (segment.pathSegTypeAsLetter.toUpperCase()) {
16865
16866            case 'C':
16867            case 'T':
16868            case 'S':
16869            case 'Q':
16870            case 'A':
16871                point = path.getPointAtLength(length);
16872                addPoint(point.x, point.y, 0);
16873                break;
16874
16875            }
16876
16877            // increment by sample value
16878            length += sampleLength;
16879        }
16880
16881        // add remaining segments not passed by sampling
16882        for (i = 0, il = segmentsQueue.length; i < il; ++i)
16883            addSegmentPoint(segmentsQueue[i]);
16884
16885        return points;
16886    };
16887
16888    Svg._svgPathToAbsolute = function(path) {
16889        // http://phrogz.net/convert-svg-path-to-all-absolute-commands
16890        // Copyright (c) Gavin Kistner
16891        // http://phrogz.net/js/_ReuseLicense.txt
16892        // Modifications: tidy formatting and naming
16893        var x0, y0, x1, y1, x2, y2, segs = path.pathSegList,
16894            x = 0, y = 0, len = segs.numberOfItems;
16895
16896        for (var i = 0; i < len; ++i) {
16897            var seg = segs.getItem(i),
16898                segType = seg.pathSegTypeAsLetter;
16899
16900            if (/[MLHVCSQTA]/.test(segType)) {
16901                if ('x' in seg) x = seg.x;
16902                if ('y' in seg) y = seg.y;
16903            } else {
16904                if ('x1' in seg) x1 = x + seg.x1;
16905                if ('x2' in seg) x2 = x + seg.x2;
16906                if ('y1' in seg) y1 = y + seg.y1;
16907                if ('y2' in seg) y2 = y + seg.y2;
16908                if ('x' in seg) x += seg.x;
16909                if ('y' in seg) y += seg.y;
16910
16911                switch (segType) {
16912
16913                case 'm':
16914                    segs.replaceItem(path.createSVGPathSegMovetoAbs(x, y), i);
16915                    break;
16916                case 'l':
16917                    segs.replaceItem(path.createSVGPathSegLinetoAbs(x, y), i);
16918                    break;
16919                case 'h':
16920                    segs.replaceItem(path.createSVGPathSegLinetoHorizontalAbs(x), i);
16921                    break;
16922                case 'v':
16923                    segs.replaceItem(path.createSVGPathSegLinetoVerticalAbs(y), i);
16924                    break;
16925                case 'c':
16926                    segs.replaceItem(path.createSVGPathSegCurvetoCubicAbs(x, y, x1, y1, x2, y2), i);
16927                    break;
16928                case 's':
16929                    segs.replaceItem(path.createSVGPathSegCurvetoCubicSmoothAbs(x, y, x2, y2), i);
16930                    break;
16931                case 'q':
16932                    segs.replaceItem(path.createSVGPathSegCurvetoQuadraticAbs(x, y, x1, y1), i);
16933                    break;
16934                case 't':
16935                    segs.replaceItem(path.createSVGPathSegCurvetoQuadraticSmoothAbs(x, y), i);
16936                    break;
16937                case 'a':
16938                    segs.replaceItem(path.createSVGPathSegArcAbs(x, y, seg.r1, seg.r2, seg.angle, seg.largeArcFlag, seg.sweepFlag), i);
16939                    break;
16940                case 'z':
16941                case 'Z':
16942                    x = x0;
16943                    y = y0;
16944                    break;
16945
16946                }
16947            }
16948
16949            if (segType == 'M' || segType == 'm') {
16950                x0 = x;
16951                y0 = y;
16952            }
16953        }
16954    };
16955
16956})();
16957
16958/***/ }),
16959/* 30 */
16960/***/ (function(module, exports, __webpack_require__) {
16961
16962/**
16963* This module has now been replaced by `Matter.Composite`.
16964*
16965* All usage should be migrated to the equivalent functions found on `Matter.Composite`.
16966* For example `World.add(world, body)` now becomes `Composite.add(world, body)`.
16967*
16968* The property `world.gravity` has been moved to `engine.gravity`.
16969*
16970* For back-compatibility purposes this module will remain as a direct alias to `Matter.Composite` in the short term during migration.
16971* Eventually this alias module will be marked as deprecated and then later removed in a future release.
16972*
16973* @class World
16974*/
16975
16976var World = {};
16977
16978module.exports = World;
16979
16980var Composite = __webpack_require__(6);
16981var Common = __webpack_require__(0);
16982
16983(function() {
16984
16985    /**
16986     * See above, aliases for back compatibility only
16987     */
16988    World.create = Composite.create;
16989    World.add = Composite.add;
16990    World.remove = Composite.remove;
16991    World.clear = Composite.clear;
16992    World.addComposite = Composite.addComposite;
16993    World.addBody = Composite.addBody;
16994    World.addConstraint = Composite.addConstraint;
16995
16996})();
16997
16998
16999/***/ })
17000/******/ ]);
17001});
17001
17002/**
17003 * fitty v2.4.2 (beautified + ECMA5-compatible)
17004 * Snugly resizes text to fit its parent container
17005 * Copyright (c) 2023 Rik Schennink
17006 */
17007
17008(function (root, factory) {
17009  if (typeof exports === "object" && typeof module !== "undefined") {
17010    module.exports = factory();
17011  } else if (typeof define === "function" && define.amd) {
17012    define(factory);
17013  } else {
17014    root.fitty = factory();
17015  }
17016})(typeof self !== "undefined" ? self : this, function () {
17017  "use strict";
17018
17019  return function (win) {
17020    if (!win) return;
17021
17022    // -------------------------------------------------------------------------
17023    // Helpers (ES5-safe)
17024    // -------------------------------------------------------------------------
17025
17026    function toArray(list) {
17027      return [].slice.call(list);
17028    }
17029
17030    function extend(target) {
17031      target = target || {};
17032      for (var i = 1; i < arguments.length; i++) {
17033        var src = arguments[i];
17034        if (!src) continue;
17035        for (var k in src) {
17036          if (Object.prototype.hasOwnProperty.call(src, k)) {
17037            target[k] = src[k];
17038          }
17039        }
17040      }
17041      return target;
17042    }
17043
17044    function createCustomEvent(name, detail) {
17045      // CustomEvent is not supported in older browsers, fallback to document.createEvent
17046      try {
17047        return new CustomEvent(name, { detail: detail });
17048      } catch (e) {
17049        var ev = document.createEvent("CustomEvent");
17050        ev.initCustomEvent(name, false, false, detail);
17051        return ev;
17052      }
17053    }
17054
17055    // -------------------------------------------------------------------------
17056    // Internal state
17057    // -------------------------------------------------------------------------
17058
17059    var DIRTY_INIT = 0;
17060    var DIRTY_MUTATION = 1;
17061    var DIRTY_LAYOUT = 2;
17062    var DIRTY_FORCE = 3;
17063
17064    var instances = [];
17065    var rafId = null;
17066
17067    // requestAnimationFrame wrapper
17068    var requestTick =
17069      "requestAnimationFrame" in win
17070        ? function (opts) {
17071            opts = opts || { sync: false };
17072
17073            win.cancelAnimationFrame(rafId);
17074
17075            function run() {
17076              var activeDirty = instances.filter(function (item) {
17077                return item.dirty && item.active;
17078              });
17079              return process(activeDirty);
17080            }
17081
17082            if (opts.sync) return run();
17083
17084            rafId = win.requestAnimationFrame(run);
17085          }
17086        : function () {};
17087
17088    // Marks all instances as dirty (type) and triggers a tick
17089    function markAllDirty(type) {
17090      return function (opts) {
17091        instances.forEach(function (item) {
17092          item.dirty = type;
17093        });
17094        requestTick(opts);
17095      };
17096    }
17097
17098    // Process a batch of instances
17099    function process(batch) {
17100      // Compute styles once
17101      batch
17102        .filter(function (item) {
17103          return !item.styleComputed;
17104        })
17105        .forEach(function (item) {
17106          item.styleComputed = computeStyle(item);
17107        });
17108
17109      // Pre-style test and apply fixes if needed
17110      batch.filter(needsPreStyleFix).forEach(applyStyles);
17111
17112      // Items that need layout recalculation
17113      var toLayout = batch.filter(needsLayout);
17114      toLayout.forEach(calcLayout);
17115      toLayout.forEach(function (item) {
17116        applyStyles(item);
17117        clean(item);
17118      });
17119      toLayout.forEach(dispatchFitEvent);
17120    }
17121
17122    function clean(item) {
17123      item.dirty = DIRTY_INIT;
17124      return item.dirty;
17125    }
17126
17127    function calcLayout(item) {
17128      item.availableWidth = item.element.parentNode.clientWidth;
17129      item.currentWidth = item.element.scrollWidth;
17130
17131      item.previousFontSize = item.currentFontSize;
17132
17133      // Scale font size into [minSize, maxSize]
17134      var scaled = (item.availableWidth / item.currentWidth) * item.previousFontSize;
17135      var clamped = Math.min(Math.max(item.minSize, scaled), item.maxSize);
17136      item.currentFontSize = clamped;
17137
17138      item.whiteSpace =
17139        item.multiLine && item.currentFontSize === item.minSize ? "normal" : "nowrap";
17140    }
17141
17142    function needsLayout(item) {
17143      return (
17144        item.dirty !== DIRTY_LAYOUT ||
17145        (item.dirty === DIRTY_LAYOUT &&
17146          item.element.parentNode.clientWidth !== item.availableWidth)
17147      );
17148    }
17149
17150    function computeStyle(item) {
17151      var cs = win.getComputedStyle(item.element, null);
17152      item.currentFontSize = parseFloat(cs.getPropertyValue("font-size"));
17153      item.display = cs.getPropertyValue("display");
17154      item.whiteSpace = cs.getPropertyValue("white-space");
17155      return true;
17156    }
17157
17158    function needsPreStyleFix(item) {
17159      var changed = false;
17160
17161      if (!item.preStyleTestCompleted) {
17162        // Force a measurable layout for inline elements
17163        if (/inline-/.test(item.display)) {
17164          changed = true;
17165          item.display = "inline-block";
17166        }
17167
17168        // Force nowrap while measuring
17169        if (item.whiteSpace !== "nowrap") {
17170          changed = true;
17171          item.whiteSpace = "nowrap";
17172        }
17173
17174        item.preStyleTestCompleted = true;
17175      }
17176
17177      return changed;
17178    }
17179
17180    function applyStyles(item) {
17181      item.element.style.whiteSpace = item.whiteSpace;
17182      item.element.style.display = item.display;
17183      item.element.style.fontSize = item.currentFontSize + "px";
17184    }
17185
17186    function dispatchFitEvent(item) {
17187      var detail = {
17188        oldValue: item.previousFontSize,
17189        newValue: item.currentFontSize,
17190        scaleFactor: item.currentFontSize / item.previousFontSize
17191      };
17192
17193      item.element.dispatchEvent(createCustomEvent("fit", detail));
17194    }
17195
17196    function onMutation(item, dirtyType) {
17197      return function (opts) {
17198        item.dirty = dirtyType;
17199        if (item.active) requestTick(opts);
17200      };
17201    }
17202
17203    function unsubscribe(item) {
17204      return function () {
17205        instances = instances.filter(function (x) {
17206          return x.element !== item.element;
17207        });
17208
17209        if (item.observeMutations && item.observer) {
17210          item.observer.disconnect();
17211        }
17212
17213        item.element.style.whiteSpace = item.originalStyle.whiteSpace;
17214        item.element.style.display = item.originalStyle.display;
17215        item.element.style.fontSize = item.originalStyle.fontSize;
17216      };
17217    }
17218
17219    function unfreeze(item) {
17220      return function () {
17221        if (!item.active) {
17222          item.active = true;
17223          requestTick();
17224        }
17225      };
17226    }
17227
17228    function freeze(item) {
17229      return function () {
17230        item.active = false;
17231      };
17232    }
17233
17234    function observeMutations(item) {
17235      if (item.observeMutations) {
17236        item.observer = new MutationObserver(onMutation(item, DIRTY_MUTATION));
17237        item.observer.observe(item.element, item.observeMutations);
17238      }
17239    }
17240
17241    // -------------------------------------------------------------------------
17242    // Defaults + public API
17243    // -------------------------------------------------------------------------
17244
17245    var defaults = {
17246      minSize: 16,
17247      maxSize: 512,
17248      multiLine: true,
17249      observeMutations:
17250        "MutationObserver" in win && {
17251          subtree: true,
17252          childList: true,
17253          characterData: true
17254        }
17255    };
17256
17257    var windowDelayTimer = null;
17258
17259    function onWindowResize() {
17260      win.clearTimeout(windowDelayTimer);
17261      windowDelayTimer = win.setTimeout(markAllDirty(DIRTY_LAYOUT), api.observeWindowDelay);
17262    }
17263
17264    var windowEvents = ["resize", "orientationchange"];
17265
17266    function createInstances(elements, options) {
17267      var config = extend({}, defaults, options);
17268
17269      var result = elements.map(function (el) {
17270        var item = extend({}, config, { element: el, active: true });
17271
17272        // Init
17273        item.originalStyle = {
17274          whiteSpace: item.element.style.whiteSpace,
17275          display: item.element.style.display,
17276          fontSize: item.element.style.fontSize
17277        };
17278
17279        observeMutations(item);
17280
17281        item.newbie = true;
17282        item.dirty = true;
17283
17284        instances.push(item);
17285
17286        return {
17287          element: el,
17288          fit: onMutation(item, DIRTY_FORCE),
17289          unfreeze: unfreeze(item),
17290          freeze: freeze(item),
17291          unsubscribe: unsubscribe(item)
17292        };
17293      });
17294
17295      requestTick();
17296      return result;
17297    }
17298
17299    function api(input, options) {
17300      options = options || {};
17301
17302      if (typeof input === "string") {
17303        return createInstances(toArray(document.querySelectorAll(input)), options);
17304      }
17305
17306      // Single element
17307      return createInstances([input], options)[0];
17308    }
17309
17310    // Observe window changes (setter)
17311    Object.defineProperty(api, "observeWindow", {
17312      set: function (enabled) {
17313        var method = (enabled ? "add" : "remove") + "EventListener";
17314        windowEvents.forEach(function (evt) {
17315          win[method](evt, onWindowResize);
17316        });
17317      }
17318    });
17319
17320    api.observeWindow = true;
17321    api.observeWindowDelay = 100;
17322
17323    api.fitAll = markAllDirty(DIRTY_FORCE);
17324
17325    return api;
17326  }(typeof window === "undefined" ? null : window);
17327});
17328"use strict";
17329
17330function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
17331function _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, _toPropertyKey(descriptor.key), descriptor); } }
17332function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
17333function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
17334function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
17335function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
17336(function (global, factory) {
17337  (typeof exports === "undefined" ? "undefined" : _typeof(exports)) === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Lenis = factory());
17338})(void 0, function () {
17339  'use strict';
17340
17341  var version = "1.1.9";
17342
17343  // Clamp a value between a minimum and maximum value
17344  function clamp(min, input, max) {
17345    return Math.max(min, Math.min(input, max));
17346  }
17347
17348  // Linearly interpolate between two values using an amount (0 <= t <= 1)
17349  function lerp(x, y, t) {
17350    return (1 - t) * x + t * y;
17351  }
17352
17353  // http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/
17354  function damp(x, y, lambda, dt) {
17355    return lerp(x, y, 1 - Math.exp(-lambda * dt));
17356  }
17357
17358  // Calculate the modulo of the dividend and divisor while keeping the result within the same sign as the divisor
17359  // https://anguscroll.com/just/just-modulo
17360  function modulo(n, d) {
17361    return (n % d + d) % d;
17362  }
17363  var Animate = /*#__PURE__*/function () {
17364    function Animate() {
17365      _classCallCheck(this, Animate);
17366      this.isRunning = false;
17367      this.value = 0;
17368      this.from = 0;
17369      this.to = 0;
17370      this.duration = 0;
17371      this.currentTime = 0;
17372    }
17373    _createClass(Animate, [{
17374      key: "advance",
17375      value: function advance(deltaTime) {
17376        var _a;
17377        if (!this.isRunning) return;
17378        var completed = false;
17379        if (this.duration && this.easing) {
17380          this.currentTime += deltaTime;
17381          var linearProgress = clamp(0, this.currentTime / this.duration, 1);
17382          completed = linearProgress >= 1;
17383          var easedProgress = completed ? 1 : this.easing(linearProgress);
17384          this.value = this.from + (this.to - this.from) * easedProgress;
17385        } else if (this.lerp) {
17386          this.value = damp(this.value, this.to, this.lerp * 60, deltaTime);
17387          if (Math.round(this.value) === this.to) {
17388            this.value = this.to;
17389            completed = true;
17390          }
17391        } else {
17392          this.value = this.to;
17393          completed = true;
17394        }
17395        if (completed) {
17396          this.stop();
17397        }
17398        (_a = this.onUpdate) === null || _a === void 0 ? void 0 : _a.call(this, this.value, completed);
17399      }
17400    }, {
17401      key: "stop",
17402      value: function stop() {
17403        this.isRunning = false;
17404      }
17405    }, {
17406      key: "fromTo",
17407      value: function fromTo(from, to, _ref) {
17408        var lerp = _ref.lerp,
17409          duration = _ref.duration,
17410          easing = _ref.easing,
17411          onStart = _ref.onStart,
17412          onUpdate = _ref.onUpdate;
17413        this.from = this.value = from;
17414        this.to = to;
17415        this.lerp = lerp;
17416        this.duration = duration;
17417        this.easing = easing;
17418        this.currentTime = 0;
17419        this.isRunning = true;
17420        onStart === null || onStart === void 0 ? void 0 : onStart();
17421        this.onUpdate = onUpdate;
17422      }
17423    }]);
17424    return Animate;
17425  }();
17426  function debounce(callback, delay) {
17427    var timer;
17428    return function () {
17429      var args = arguments;
17430      var context = this;
17431      clearTimeout(timer);
17432      timer = setTimeout(function () {
17433        callback.apply(context, args);
17434      }, delay);
17435    };
17436  }
17437  var Dimensions = /*#__PURE__*/function () {
17438    function Dimensions() {
17439      var _this = this;
17440      var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
17441        wrapper = _ref2.wrapper,
17442        content = _ref2.content,
17443        _ref2$autoResize = _ref2.autoResize,
17444        autoResize = _ref2$autoResize === void 0 ? true : _ref2$autoResize,
17445        _ref2$debounce = _ref2.debounce,
17446        debounceValue = _ref2$debounce === void 0 ? 250 : _ref2$debounce;
17447      _classCallCheck(this, Dimensions);
17448      this.width = 0;
17449      this.height = 0;
17450      this.scrollWidth = 0;
17451      this.scrollHeight = 0;
17452      this.resize = function () {
17453        _this.onWrapperResize();
17454        _this.onContentResize();
17455      };
17456      this.onWrapperResize = function () {
17457        if (_this.wrapper === window) {
17458          _this.width = window.innerWidth;
17459          _this.height = window.innerHeight;
17460        } else if (_this.wrapper instanceof HTMLElement) {
17461          _this.width = _this.wrapper.clientWidth;
17462          _this.height = _this.wrapper.clientHeight;
17463        }
17464      };
17465      this.onContentResize = function () {
17466        if (_this.wrapper === window) {
17467          _this.scrollHeight = _this.content.scrollHeight;
17468          _this.scrollWidth = _this.content.scrollWidth;
17469        } else if (_this.wrapper instanceof HTMLElement) {
17470          _this.scrollHeight = _this.wrapper.scrollHeight;
17471          _this.scrollWidth = _this.wrapper.scrollWidth;
17472        }
17473      };
17474      this.wrapper = wrapper;
17475      this.content = content;
17476      if (autoResize) {
17477        this.debouncedResize = debounce(this.resize, debounceValue);
17478        if (this.wrapper === window) {
17479          window.addEventListener('resize', this.debouncedResize, false);
17480        } else {
17481          this.wrapperResizeObserver = new ResizeObserver(this.debouncedResize);
17482          this.wrapperResizeObserver.observe(this.wrapper);
17483        }
17484        this.contentResizeObserver = new ResizeObserver(this.debouncedResize);
17485        this.contentResizeObserver.observe(this.content);
17486      }
17487      this.resize();
17488    }
17489    _createClass(Dimensions, [{
17490      key: "destroy",
17491      value: function destroy() {
17492        var _a, _b;
17493        (_a = this.wrapperResizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
17494        (_b = this.contentResizeObserver) === null || _b === void 0 ? void 0 : _b.disconnect();
17495        window.removeEventListener('resize', this.debouncedResize, false);
17496      }
17497    }, {
17498      key: "limit",
17499      get: function get() {
17500        return {
17501          x: this.scrollWidth - this.width,
17502          y: this.scrollHeight - this.height
17503        };
17504      }
17505    }]);
17506    return Dimensions;
17507  }();
17508  var Emitter = /*#__PURE__*/function () {
17509    function Emitter() {
17510      _classCallCheck(this, Emitter);
17511      this.events = {};
17512    }
17513    _createClass(Emitter, [{
17514      key: "emit",
17515      value: function emit(event) {
17516        var callbacks = this.events[event] || [];
17517        for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
17518          args[_key - 1] = arguments[_key];
17519        }
17520        for (var i = 0, length = callbacks.length; i < length; i++) {
17521          callbacks[i].apply(callbacks, args);
17522        }
17523      }
17524    }, {
17525      key: "on",
17526      value: function on(event, callback) {
17527        var _this2 = this;
17528        var _a;
17529        ((_a = this.events[event]) === null || _a === void 0 ? void 0 : _a.push(callback)) || (this.events[event] = [callback]);
17530        return function () {
17531          var _a;
17532          _this2.events[event] = (_a = _this2.events[event]) === null || _a === void 0 ? void 0 : _a.filter(function (i) {
17533            return callback !== i;
17534          });
17535        };
17536      }
17537    }, {
17538      key: "off",
17539      value: function off(event, callback) {
17540        var _a;
17541        this.events[event] = (_a = this.events[event]) === null || _a === void 0 ? void 0 : _a.filter(function (i) {
17542          return callback !== i;
17543        });
17544      }
17545    }, {
17546      key: "destroy",
17547      value: function destroy() {
17548        this.events = {};
17549      }
17550    }]);
17551    return Emitter;
17552  }();
17553  var LINE_HEIGHT = 100 / 6;
17554  var VirtualScroll = /*#__PURE__*/function () {
17555    function VirtualScroll(element, _ref3) {
17556      var _this3 = this;
17557      var _ref3$wheelMultiplier = _ref3.wheelMultiplier,
17558        wheelMultiplier = _ref3$wheelMultiplier === void 0 ? 1 : _ref3$wheelMultiplier,
17559        _ref3$touchMultiplier = _ref3.touchMultiplier,
17560        touchMultiplier = _ref3$touchMultiplier === void 0 ? 1 : _ref3$touchMultiplier;
17561      _classCallCheck(this, VirtualScroll);
17562      this.lastDelta = {
17563        x: 0,
17564        y: 0
17565      };
17566      this.windowWidth = 0;
17567      this.windowHeight = 0;
17568      this.onTouchStart = function (event) {
17569        var _ref4 = event.targetTouches ? event.targetTouches[0] : event,
17570          clientX = _ref4.clientX,
17571          clientY = _ref4.clientY;
17572        _this3.touchStart.x = clientX;
17573        _this3.touchStart.y = clientY;
17574        _this3.lastDelta = {
17575          x: 0,
17576          y: 0
17577        };
17578        _this3.emitter.emit('scroll', {
17579          deltaX: 0,
17580          deltaY: 0,
17581          event: event
17582        });
17583      };
17584      this.onTouchMove = function (event) {
17585        var _a, _b, _c, _d;
17586        var _ref5 = event.targetTouches ? event.targetTouches[0] : event,
17587          clientX = _ref5.clientX,
17588          clientY = _ref5.clientY;
17589        var deltaX = -(clientX - ((_b = (_a = _this3.touchStart) === null || _a === void 0 ? void 0 : _a.x) !== null && _b !== void 0 ? _b : 0)) * _this3.touchMultiplier;
17590        var deltaY = -(clientY - ((_d = (_c = _this3.touchStart) === null || _c === void 0 ? void 0 : _c.y) !== null && _d !== void 0 ? _d : 0)) * _this3.touchMultiplier;
17591        _this3.touchStart.x = clientX;
17592        _this3.touchStart.y = clientY;
17593        _this3.lastDelta = {
17594          x: deltaX,
17595          y: deltaY
17596        };
17597        _this3.emitter.emit('scroll', {
17598          deltaX: deltaX,
17599          deltaY: deltaY,
17600          event: event
17601        });
17602      };
17603      this.onTouchEnd = function (event) {
17604        _this3.emitter.emit('scroll', {
17605          deltaX: _this3.lastDelta.x,
17606          deltaY: _this3.lastDelta.y,
17607          event: event
17608        });
17609      };
17610      this.onWheel = function (event) {
17611        var deltaX = event.deltaX,
17612          deltaY = event.deltaY,
17613          deltaMode = event.deltaMode;
17614        var multiplierX = deltaMode === 1 ? LINE_HEIGHT : deltaMode === 2 ? _this3.windowWidth : 1;
17615        var multiplierY = deltaMode === 1 ? LINE_HEIGHT : deltaMode === 2 ? _this3.windowHeight : 1;
17616        deltaX *= multiplierX;
17617        deltaY *= multiplierY;
17618        deltaX *= _this3.wheelMultiplier;
17619        deltaY *= _this3.wheelMultiplier;
17620        _this3.emitter.emit('scroll', {
17621          deltaX: deltaX,
17622          deltaY: deltaY,
17623          event: event
17624        });
17625      };
17626      this.onWindowResize = function () {
17627        _this3.windowWidth = window.innerWidth;
17628        _this3.windowHeight = window.innerHeight;
17629      };
17630      this.element = element;
17631      this.wheelMultiplier = wheelMultiplier;
17632      this.touchMultiplier = touchMultiplier;
17633      this.touchStart = {
17634        x: null,
17635        y: null
17636      };
17637      this.emitter = new Emitter();
17638      window.addEventListener('resize', this.onWindowResize, false);
17639      this.onWindowResize();
17640      this.element.addEventListener('wheel', this.onWheel, {
17641        passive: false
17642      });
17643      this.element.addEventListener('touchstart', this.onTouchStart, {
17644        passive: false
17645      });
17646      this.element.addEventListener('touchmove', this.onTouchMove, {
17647        passive: false
17648      });
17649      this.element.addEventListener('touchend', this.onTouchEnd, {
17650        passive: false
17651      });
17652    }
17653    _createClass(VirtualScroll, [{
17654      key: "on",
17655      value: function on(event, callback) {
17656        return this.emitter.on(event, callback);
17657      }
17658    }, {
17659      key: "destroy",
17660      value: function destroy() {
17661        this.emitter.destroy();
17662        window.removeEventListener('resize', this.onWindowResize, false);
17663        this.element.removeEventListener('wheel', this.onWheel);
17664        this.element.removeEventListener('touchstart', this.onTouchStart);
17665        this.element.removeEventListener('touchmove', this.onTouchMove);
17666        this.element.removeEventListener('touchend', this.onTouchEnd);
17667      }
17668    }]);
17669    return VirtualScroll;
17670  }();
17671  var Lenis = /*#__PURE__*/function () {
17672    function Lenis() {
17673      var _this4 = this;
17674      var _ref6 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
17675        _ref6$wrapper = _ref6.wrapper,
17676        wrapper = _ref6$wrapper === void 0 ? window : _ref6$wrapper,
17677        _ref6$content = _ref6.content,
17678        content = _ref6$content === void 0 ? document.documentElement : _ref6$content,
17679        _ref6$wheelEventsTarg = _ref6.wheelEventsTarget,
17680        wheelEventsTarget = _ref6$wheelEventsTarg === void 0 ? wrapper : _ref6$wheelEventsTarg,
17681        _ref6$eventsTarget = _ref6.eventsTarget,
17682        eventsTarget = _ref6$eventsTarget === void 0 ? wheelEventsTarget : _ref6$eventsTarget,
17683        _ref6$smoothWheel = _ref6.smoothWheel,
17684        smoothWheel = _ref6$smoothWheel === void 0 ? true : _ref6$smoothWheel,
17685        _ref6$syncTouch = _ref6.syncTouch,
17686        syncTouch = _ref6$syncTouch === void 0 ? false : _ref6$syncTouch,
17687        _ref6$syncTouchLerp = _ref6.syncTouchLerp,
17688        syncTouchLerp = _ref6$syncTouchLerp === void 0 ? 0.075 : _ref6$syncTouchLerp,
17689        _ref6$touchInertiaMul = _ref6.touchInertiaMultiplier,
17690        touchInertiaMultiplier = _ref6$touchInertiaMul === void 0 ? 35 : _ref6$touchInertiaMul,
17691        duration = _ref6.duration,
17692        _ref6$easing = _ref6.easing,
17693        easing = _ref6$easing === void 0 ? function (t) {
17694          return Math.min(1, 1.001 - Math.pow(2, -10 * t));
17695        } : _ref6$easing,
17696        _ref6$lerp = _ref6.lerp,
17697        lerp = _ref6$lerp === void 0 ? 0.1 : _ref6$lerp,
17698        _ref6$infinite = _ref6.infinite,
17699        infinite = _ref6$infinite === void 0 ? false : _ref6$infinite,
17700        _ref6$orientation = _ref6.orientation,
17701        orientation = _ref6$orientation === void 0 ? 'vertical' : _ref6$orientation,
17702        _ref6$gestureOrientat = _ref6.gestureOrientation,
17703        gestureOrientation = _ref6$gestureOrientat === void 0 ? 'vertical' : _ref6$gestureOrientat,
17704        _ref6$touchMultiplier = _ref6.touchMultiplier,
17705        touchMultiplier = _ref6$touchMultiplier === void 0 ? 1 : _ref6$touchMultiplier,
17706        _ref6$wheelMultiplier = _ref6.wheelMultiplier,
17707        wheelMultiplier = _ref6$wheelMultiplier === void 0 ? 1 : _ref6$wheelMultiplier,
17708        _ref6$autoResize = _ref6.autoResize,
17709        autoResize = _ref6$autoResize === void 0 ? true : _ref6$autoResize,
17710        prevent = _ref6.prevent,
17711        virtualScroll = _ref6.virtualScroll,
17712        _ref6$__experimental_ = _ref6.__experimental__naiveDimensions,
17713        __experimental__naiveDimensions = _ref6$__experimental_ === void 0 ? false : _ref6$__experimental_;
17714      _classCallCheck(this, Lenis);
17715      this.__isScrolling = false;
17716      this.__isStopped = false;
17717      this.__isLocked = false;
17718      this.userData = {};
17719      this.lastVelocity = 0;
17720      this.velocity = 0;
17721      this.direction = 0;
17722      this.onPointerDown = function (event) {
17723        if (event.button === 1) {
17724          _this4.reset();
17725        }
17726      };
17727      this.onVirtualScroll = function (data) {
17728        if (typeof _this4.options.virtualScroll === 'function' && _this4.options.virtualScroll(data) === false) return;
17729        var deltaX = data.deltaX,
17730          deltaY = data.deltaY,
17731          event = data.event;
17732        _this4.emitter.emit('virtual-scroll', {
17733          deltaX: deltaX,
17734          deltaY: deltaY,
17735          event: event
17736        });
17737        if (event.ctrlKey) return;
17738        var isTouch = event.type.includes('touch');
17739        var isWheel = event.type.includes('wheel');
17740        _this4.isTouching = event.type === 'touchstart' || event.type === 'touchmove';
17741        var isTapToStop = _this4.options.syncTouch && isTouch && event.type === 'touchstart' && !_this4.isStopped && !_this4.isLocked;
17742        if (isTapToStop) {
17743          _this4.reset();
17744          return;
17745        }
17746        var isClick = deltaX === 0 && deltaY === 0;
17747        var isUnknownGesture = _this4.options.gestureOrientation === 'vertical' && deltaY === 0 || _this4.options.gestureOrientation === 'horizontal' && deltaX === 0;
17748        if (isClick || isUnknownGesture) {
17749          return;
17750        }
17751        var composedPath = event.composedPath();
17752        composedPath = composedPath.slice(0, composedPath.indexOf(_this4.rootElement));
17753        var prevent = _this4.options.prevent;
17754        if (!!composedPath.find(function (node) {
17755          var _a, _b, _c, _d, _e;
17756          return node instanceof Element && (typeof prevent === 'function' && (prevent === null || prevent === void 0 ? void 0 : prevent(node)) || ((_a = node.hasAttribute) === null || _a === void 0 ? void 0 : _a.call(node, 'data-lenis-prevent')) || isTouch && ((_b = node.hasAttribute) === null || _b === void 0 ? void 0 : _b.call(node, 'data-lenis-prevent-touch')) || isWheel && ((_c = node.hasAttribute) === null || _c === void 0 ? void 0 : _c.call(node, 'data-lenis-prevent-wheel')) || ((_d = node.classList) === null || _d === void 0 ? void 0 : _d.contains('lenis')) && !((_e = node.classList) === null || _e === void 0 ? void 0 : _e.contains('lenis-stopped')));
17757        })) return;
17758        if (_this4.isStopped || _this4.isLocked) {
17759          event.preventDefault();
17760          return;
17761        }
17762        var isSmooth = _this4.options.syncTouch && isTouch || _this4.options.smoothWheel && isWheel;
17763        if (!isSmooth) {
17764          _this4.isScrolling = 'native';
17765          _this4.animate.stop();
17766          return;
17767        }
17768        event.preventDefault();
17769        var delta = deltaY;
17770        if (_this4.options.gestureOrientation === 'both') {
17771          delta = Math.abs(deltaY) > Math.abs(deltaX) ? deltaY : deltaX;
17772        } else if (_this4.options.gestureOrientation === 'horizontal') {
17773          delta = deltaX;
17774        }
17775        var syncTouch = isTouch && _this4.options.syncTouch;
17776        var isTouchEnd = isTouch && event.type === 'touchend';
17777        var hasTouchInertia = isTouchEnd && Math.abs(delta) > 5;
17778        if (hasTouchInertia) {
17779          delta = _this4.velocity * _this4.options.touchInertiaMultiplier;
17780        }
17781        _this4.scrollTo(_this4.targetScroll + delta, Object.assign({
17782          programmatic: false
17783        }, syncTouch ? {
17784          lerp: hasTouchInertia ? _this4.options.syncTouchLerp : 1
17785        } : {
17786          lerp: _this4.options.lerp,
17787          duration: _this4.options.duration,
17788          easing: _this4.options.easing
17789        }));
17790      };
17791      this.onNativeScroll = function () {
17792        clearTimeout(_this4.__resetVelocityTimeout);
17793        delete _this4.__resetVelocityTimeout;
17794        if (_this4.__preventNextNativeScrollEvent) {
17795          delete _this4.__preventNextNativeScrollEvent;
17796          return;
17797        }
17798        if (_this4.isScrolling === false || _this4.isScrolling === 'native') {
17799          var lastScroll = _this4.animatedScroll;
17800          _this4.animatedScroll = _this4.targetScroll = _this4.actualScroll;
17801          _this4.lastVelocity = _this4.velocity;
17802          _this4.velocity = _this4.animatedScroll - lastScroll;
17803          _this4.direction = Math.sign(_this4.animatedScroll - lastScroll);
17804          _this4.isScrolling = 'native';
17805          _this4.emit();
17806          if (_this4.velocity !== 0) {
17807            _this4.__resetVelocityTimeout = setTimeout(function () {
17808              _this4.lastVelocity = _this4.velocity;
17809              _this4.velocity = 0;
17810              _this4.isScrolling = false;
17811              _this4.emit();
17812            }, 400);
17813          }
17814        }
17815      };
17816      window.lenisVersion = version;
17817      if (!wrapper || wrapper === document.documentElement || wrapper === document.body) {
17818        wrapper = window;
17819      }
17820      this.options = {
17821        wrapper: wrapper,
17822        content: content,
17823        wheelEventsTarget: wheelEventsTarget,
17824        eventsTarget: eventsTarget,
17825        smoothWheel: smoothWheel,
17826        syncTouch: syncTouch,
17827        syncTouchLerp: syncTouchLerp,
17828        touchInertiaMultiplier: touchInertiaMultiplier,
17829        duration: duration,
17830        easing: easing,
17831        lerp: lerp,
17832        infinite: infinite,
17833        gestureOrientation: gestureOrientation,
17834        orientation: orientation,
17835        touchMultiplier: touchMultiplier,
17836        wheelMultiplier: wheelMultiplier,
17837        autoResize: autoResize,
17838        prevent: prevent,
17839        virtualScroll: virtualScroll,
17840        __experimental__naiveDimensions: __experimental__naiveDimensions
17841      };
17842      this.animate = new Animate();
17843      this.emitter = new Emitter();
17844      this.dimensions = new Dimensions({
17845        wrapper: wrapper,
17846        content: content,
17847        autoResize: autoResize
17848      });
17849      this.updateClassName();
17850      this.userData = {};
17851      this.time = 0;
17852      this.velocity = this.lastVelocity = 0;
17853      this.isLocked = false;
17854      this.isStopped = false;
17855      this.isScrolling = false;
17856      this.targetScroll = this.animatedScroll = this.actualScroll;
17857      this.options.wrapper.addEventListener('scroll', this.onNativeScroll, false);
17858      this.options.wrapper.addEventListener('pointerdown', this.onPointerDown, false);
17859      this.virtualScroll = new VirtualScroll(eventsTarget, {
17860        touchMultiplier: touchMultiplier,
17861        wheelMultiplier: wheelMultiplier
17862      });
17863      this.virtualScroll.on('scroll', this.onVirtualScroll);
17864    }
17865    _createClass(Lenis, [{
17866      key: "destroy",
17867      value: function destroy() {
17868        this.emitter.destroy();
17869        this.options.wrapper.removeEventListener('scroll', this.onNativeScroll, false);
17870        this.options.wrapper.removeEventListener('pointerdown', this.onPointerDown, false);
17871        this.virtualScroll.destroy();
17872        this.dimensions.destroy();
17873        this.cleanUpClassName();
17874      }
17875    }, {
17876      key: "on",
17877      value: function on(event, callback) {
17878        return this.emitter.on(event, callback);
17879      }
17880    }, {
17881      key: "off",
17882      value: function off(event, callback) {
17883        return this.emitter.off(event, callback);
17884      }
17885    }, {
17886      key: "setScroll",
17887      value: function setScroll(scroll) {
17888        if (this.isHorizontal) {
17889          this.rootElement.scrollLeft = scroll;
17890        } else {
17891          this.rootElement.scrollTop = scroll;
17892        }
17893      }
17894    }, {
17895      key: "resize",
17896      value: function resize() {
17897        this.dimensions.resize();
17898      }
17899    }, {
17900      key: "emit",
17901      value: function emit() {
17902        this.emitter.emit('scroll', this);
17903      }
17904    }, {
17905      key: "reset",
17906      value: function reset() {
17907        this.isLocked = false;
17908        this.isScrolling = false;
17909        this.animatedScroll = this.targetScroll = this.actualScroll;
17910        this.lastVelocity = this.velocity = 0;
17911        this.animate.stop();
17912      }
17913    }, {
17914      key: "start",
17915      value: function start() {
17916        if (!this.isStopped) return;
17917        this.isStopped = false;
17918        this.reset();
17919      }
17920    }, {
17921      key: "stop",
17922      value: function stop() {
17923        if (this.isStopped) return;
17924        this.isStopped = true;
17925        this.animate.stop();
17926        this.reset();
17927      }
17928    }, {
17929      key: "raf",
17930      value: function raf(time) {
17931        var deltaTime = time - (this.time || time);
17932        this.time = time;
17933        this.animate.advance(deltaTime * 0.001);
17934      }
17935    }, {
17936      key: "scrollTo",
17937      value: function scrollTo(target) {
17938        var _this5 = this;
17939        var _ref7 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
17940          _ref7$offset = _ref7.offset,
17941          offset = _ref7$offset === void 0 ? 0 : _ref7$offset,
17942          _ref7$immediate = _ref7.immediate,
17943          immediate = _ref7$immediate === void 0 ? false : _ref7$immediate,
17944          _ref7$lock = _ref7.lock,
17945          lock = _ref7$lock === void 0 ? false : _ref7$lock,
17946          _ref7$duration = _ref7.duration,
17947          duration = _ref7$duration === void 0 ? this.options.duration : _ref7$duration,
17948          _ref7$easing = _ref7.easing,
17949          easing = _ref7$easing === void 0 ? this.options.easing : _ref7$easing,
17950          _ref7$lerp = _ref7.lerp,
17951          lerp = _ref7$lerp === void 0 ? this.options.lerp : _ref7$lerp,
17952          _onStart = _ref7.onStart,
17953          onComplete = _ref7.onComplete,
17954          _ref7$force = _ref7.force,
17955          force = _ref7$force === void 0 ? false : _ref7$force,
17956          _ref7$programmatic = _ref7.programmatic,
17957          programmatic = _ref7$programmatic === void 0 ? true : _ref7$programmatic,
17958          _ref7$userData = _ref7.userData,
17959          userData = _ref7$userData === void 0 ? {} : _ref7$userData;
17960        if ((this.isStopped || this.isLocked) && !force) return;
17961        if (typeof target === 'string' && ['top', 'left', 'start'].includes(target)) {
17962          target = 0;
17963        } else if (typeof target === 'string' && ['bottom', 'right', 'end'].includes(target)) {
17964          target = this.limit;
17965        } else {
17966          var node;
17967          if (typeof target === 'string') {
17968            node = document.querySelector(target);
17969          } else if (target instanceof HTMLElement && (target === null || target === void 0 ? void 0 : target.nodeType)) {
17970            node = target;
17971          }
17972          if (node) {
17973            if (this.options.wrapper !== window) {
17974              var wrapperRect = this.rootElement.getBoundingClientRect();
17975              offset -= this.isHorizontal ? wrapperRect.left : wrapperRect.top;
17976            }
17977            var rect = node.getBoundingClientRect();
17978            target = (this.isHorizontal ? rect.left : rect.top) + this.animatedScroll;
17979          }
17980        }
17981        if (typeof target !== 'number') return;
17982        target += offset;
17983        target = Math.round(target);
17984        if (this.options.infinite) {
17985          if (programmatic) {
17986            this.targetScroll = this.animatedScroll = this.scroll;
17987          }
17988        } else {
17989          target = clamp(0, target, this.limit);
17990        }
17991        if (target === this.targetScroll) return;
17992        this.userData = userData;
17993        if (immediate) {
17994          this.animatedScroll = this.targetScroll = target;
17995          this.setScroll(this.scroll);
17996          this.reset();
17997          this.preventNextNativeScrollEvent();
17998          this.emit();
17999          onComplete === null || onComplete === void 0 ? void 0 : onComplete(this);
18000          this.userData = {};
18001          return;
18002        }
18003        if (!programmatic) {
18004          this.targetScroll = target;
18005        }
18006        this.animate.fromTo(this.animatedScroll, target, {
18007          duration: duration,
18008          easing: easing,
18009          lerp: lerp,
18010          onStart: function onStart() {
18011            if (lock) _this5.isLocked = true;
18012            _this5.isScrolling = 'smooth';
18013            _onStart === null || _onStart === void 0 ? void 0 : _onStart(_this5);
18014          },
18015          onUpdate: function onUpdate(value, completed) {
18016            _this5.isScrolling = 'smooth';
18017            _this5.lastVelocity = _this5.velocity;
18018            _this5.velocity = value - _this5.animatedScroll;
18019            _this5.direction = Math.sign(_this5.velocity);
18020            _this5.animatedScroll = value;
18021            _this5.setScroll(_this5.scroll);
18022            if (programmatic) {
18023              _this5.targetScroll = value;
18024            }
18025            if (!completed) _this5.emit();
18026            if (completed) {
18027              _this5.reset();
18028              _this5.emit();
18029              onComplete === null || onComplete === void 0 ? void 0 : onComplete(_this5);
18030              _this5.userData = {};
18031              _this5.preventNextNativeScrollEvent();
18032            }
18033          }
18034        });
18035      }
18036    }, {
18037      key: "preventNextNativeScrollEvent",
18038      value: function preventNextNativeScrollEvent() {
18039        var _this6 = this;
18040        this.__preventNextNativeScrollEvent = true;
18041        requestAnimationFrame(function () {
18042          delete _this6.__preventNextNativeScrollEvent;
18043        });
18044      }
18045    }, {
18046      key: "rootElement",
18047      get: function get() {
18048        return this.options.wrapper === window ? document.documentElement : this.options.wrapper;
18049      }
18050    }, {
18051      key: "limit",
18052      get: function get() {
18053        if (this.options.__experimental__naiveDimensions) {
18054          if (this.isHorizontal) {
18055            return this.rootElement.scrollWidth - this.rootElement.clientWidth;
18056          } else {
18057            return this.rootElement.scrollHeight - this.rootElement.clientHeight;
18058          }
18059        } else {
18060          return this.dimensions.limit[this.isHorizontal ? 'x' : 'y'];
18061        }
18062      }
18063    }, {
18064      key: "isHorizontal",
18065      get: function get() {
18066        return this.options.orientation === 'horizontal';
18067      }
18068    }, {
18069      key: "actualScroll",
18070      get: function get() {
18071        return this.isHorizontal ? this.rootElement.scrollLeft : this.rootElement.scrollTop;
18072      }
18073    }, {
18074      key: "scroll",
18075      get: function get() {
18076        return this.options.infinite ? modulo(this.animatedScroll, this.limit) : this.animatedScroll;
18077      }
18078    }, {
18079      key: "progress",
18080      get: function get() {
18081        return this.limit === 0 ? 1 : this.scroll / this.limit;
18082      }
18083    }, {
18084      key: "isScrolling",
18085      get: function get() {
18086        return this.__isScrolling;
18087      },
18088      set: function set(value) {
18089        if (this.__isScrolling !== value) {
18090          this.__isScrolling = value;
18091          this.updateClassName();
18092        }
18093      }
18094    }, {
18095      key: "isStopped",
18096      get: function get() {
18097        return this.__isStopped;
18098      },
18099      set: function set(value) {
18100        if (this.__isStopped !== value) {
18101          this.__isStopped = value;
18102          this.updateClassName();
18103        }
18104      }
18105    }, {
18106      key: "isLocked",
18107      get: function get() {
18108        return this.__isLocked;
18109      },
18110      set: function set(value) {
18111        if (this.__isLocked !== value) {
18112          this.__isLocked = value;
18113          this.updateClassName();
18114        }
18115      }
18116    }, {
18117      key: "isSmooth",
18118      get: function get() {
18119        return this.isScrolling === 'smooth';
18120      }
18121    }, {
18122      key: "className",
18123      get: function get() {
18124        var className = 'lenis';
18125        if (this.isStopped) className += ' lenis-stopped';
18126        if (this.isLocked) className += ' lenis-locked';
18127        if (this.isScrolling) className += ' lenis-scrolling';
18128        if (this.isScrolling === 'smooth') className += ' lenis-smooth';
18129        return className;
18130      }
18131    }, {
18132      key: "updateClassName",
18133      value: function updateClassName() {
18134        this.cleanUpClassName();
18135        this.rootElement.className = "".concat(this.rootElement.className, " ").concat(this.className).trim();
18136      }
18137    }, {
18138      key: "cleanUpClassName",
18139      value: function cleanUpClassName() {
18140        this.rootElement.className = this.rootElement.className.replace(/lenis(-\w+)?/g, '').trim();
18141      }
18142    }]);
18143    return Lenis;
18144  }();
18145  return Lenis;
18146});
18147(function(window, $) {
18148  "use strict";
18149
18150  var counter = 0,
18151    $headCache = $('head'),
18152    oldBigText = window.BigText,
18153    oldjQueryMethod = $.fn.bigtext,
18154    BigText = {
18155      DEBUG_MODE: false,
18156      DEFAULT_MIN_FONT_SIZE_PX: null,
18157      DEFAULT_MAX_FONT_SIZE_PX: 1056,
18158      GLOBAL_STYLE_ID: 'bigtext-style',
18159      STYLE_ID: 'bigtext-id',
18160      LINE_CLASS_PREFIX: 'bigtext-line',
18161      EXEMPT_CLASS: 'bigtext-exempt',
18162      noConflict: function(restore)
18163      {
18164        if(restore) {
18165          $.fn.bigtext = oldjQueryMethod;
18166          window.BigText = oldBigText;
18167        }
18168        return BigText;
18169      },
18170      supports: {
18171        wholeNumberFontSizeOnly: (function() {
18172          if( !( 'getComputedStyle' in window ) ) {
18173            return true;
18174          }
18175          var test = $('<div/>').css({
18176              position: 'absolute',
18177              'font-size': '14.1px'
18178            }).insertBefore( $('script').eq(0) ),
18179            computedStyle = window.getComputedStyle( test[0], null );
18180
18181          var ret = computedStyle && computedStyle.getPropertyValue( 'font-size' ) === '14px';
18182          test.remove();
18183          return ret;
18184        })()
18185      },
18186      init: function() {
18187        if(!$('#'+BigText.GLOBAL_STYLE_ID).length) {
18188          $headCache.append(BigText.generateStyleTag(BigText.GLOBAL_STYLE_ID, ['.bigtext * { white-space: nowrap; } .bigtext > * { display: block; }',
18189                                          '.bigtext .' + BigText.EXEMPT_CLASS + ', .bigtext .' + BigText.EXEMPT_CLASS + ' * { white-space: normal; }']));
18190        }
18191      },
18192      bindResize: function(eventName, resizeFunction) {
18193        var timeoutId;
18194        $(window).off(eventName).on(eventName, function() {
18195          if( timeoutId ) {
18196            clearTimeout( timeoutId );
18197          }
18198          timeoutId = setTimeout( resizeFunction, 100 );
18199        });
18200      },
18201      getStyleId: function(id)
18202      {
18203        return BigText.STYLE_ID + '-' + id;
18204      },
18205      generateStyleTag: function(id, css)
18206      {
18207        return $('<style>' + css.join('\n') + '</style>').attr('id', id);
18208      },
18209      clearCss: function(id)
18210      {
18211        var styleId = BigText.getStyleId(id);
18212        $('#' + styleId).remove();
18213      },
18214      generateCss: function(id, linesFontSizes, lineWordSpacings, minFontSizes)
18215      {
18216        var css = [];
18217
18218        BigText.clearCss(id);
18219
18220        for(var j=0, k=linesFontSizes.length; j<k; j++) {
18221          css.push('#' + id + ' .' + BigText.LINE_CLASS_PREFIX + j + ' {' +
18222            (minFontSizes[j] ? ' white-space: normal;' : '') +
18223            (linesFontSizes[j] ? ' font-size: ' + linesFontSizes[j] + 'px;' : '') +
18224            (lineWordSpacings[j] ? ' word-spacing: ' + lineWordSpacings[j] + 'px;' : '') +
18225            '}');
18226        }
18227
18228        return BigText.generateStyleTag(BigText.getStyleId(id), css);
18229      },
18230      jQueryMethod: function(options)
18231      {
18232        BigText.init();
18233
18234        options = $.extend({
18235          minfontsize: BigText.DEFAULT_MIN_FONT_SIZE_PX,
18236          maxfontsize: BigText.DEFAULT_MAX_FONT_SIZE_PX,
18237          childSelector: '',
18238          resize: true
18239        }, options || {});
18240
18241        this.each(function()
18242        {
18243          var $t = $(this).addClass('bigtext'),
18244            maxWidth = $t.width(),
18245            id = $t.attr('id'),
18246            $children = options.childSelector ? $t.find( options.childSelector ) : $t.children();
18247
18248          if(!id) {
18249            id = 'bigtext-id' + (counter++);
18250            $t.attr('id', id);
18251          }
18252
18253          if(options.resize) {
18254            BigText.bindResize('resize.bigtext-event-' + id, function()
18255            {
18256              // TODO only call this if the width has changed.
18257              BigText.jQueryMethod.call($('#' + id), options);
18258            });
18259          }
18260
18261          BigText.clearCss(id);
18262
18263          $children.addClass(function(lineNumber, className)
18264          {
18265            // remove existing line classes.
18266            return [className.replace(new RegExp('\\b' + BigText.LINE_CLASS_PREFIX + '\\d+\\b'), ''),
18267                BigText.LINE_CLASS_PREFIX + lineNumber].join(' ');
18268          });
18269
18270          var sizes = BigText.calculateSizes($t, $children, maxWidth, options.maxfontsize, options.minfontsize);
18271          $headCache.append(BigText.generateCss(id, sizes.fontSizes, sizes.wordSpacings, sizes.minFontSizes));
18272        });
18273
18274        return this.trigger('bigtext:complete');
18275      },
18276      testLineDimensions: function($line, maxWidth, property, size, interval, units, previousWidth)
18277      {
18278        var width;
18279        previousWidth = typeof previousWidth === 'number' ? previousWidth : 0;
18280        $line.css(property, size + units);
18281
18282        width = $line.width();
18283
18284        if(width >= maxWidth) {
18285    // console.log(width, ' previous: ' + previousWidth, property + ' at ' + interval, 'prior: ' + (parseFloat(size) - interval), 'new:' + parseFloat(size));
18286          $line.css(property, '');
18287
18288          if(width === maxWidth) {
18289            return {
18290              match: 'exact',
18291              size: parseFloat((parseFloat(size) - 0.1).toFixed(3))
18292            };
18293          }
18294
18295          // Since this is an estimate, we calculate how far over the width we went with the new value.
18296          // If this is word-spacing (our last resort guess) and the over is less than the under, we keep the higher value.
18297          // Otherwise, we revert to the underestimate.
18298          var under = maxWidth - previousWidth,
18299            over = width - maxWidth;
18300
18301          return {
18302            match: 'estimate',
18303            size: parseFloat((parseFloat(size) - (property === 'word-spacing' && previousWidth && ( over < under ) ? 0 : interval)).toFixed(3))
18304          };
18305        }
18306
18307        return width;
18308      },
18309      calculateSizes: function($t, $children, maxWidth, maxFontSize, minFontSize)
18310      {
18311        var $c = $t.clone(true)
18312          .addClass('bigtext-cloned')
18313          .css({
18314            fontFamily: $t.css('font-family'),
18315            textTransform: $t.css('text-transform'),
18316            wordSpacing: $t.css('word-spacing'),
18317            letterSpacing: $t.css('letter-spacing'),
18318            position: 'absolute',
18319            left: BigText.DEBUG_MODE ? 0 : -9999,
18320            top: BigText.DEBUG_MODE ? 0 : -9999
18321          })
18322          .appendTo(document.body);
18323
18324        // font-size isn't the only thing we can modify, we can also mess with:
18325        // word-spacing and letter-spacing. WebKit does not respect subpixel
18326        // letter-spacing, word-spacing, or font-size.
18327        // TODO try -webkit-transform: scale() as a workaround.
18328        var fontSizes = [],
18329          wordSpacings = [],
18330          minFontSizes = [],
18331          ratios = [];
18332
18333        $children.css('float', 'left').each(function() {
18334          var $line = $(this),
18335            // TODO replace 8, 4 with a proportional size to the calculated font-size.
18336            intervals = BigText.supports.wholeNumberFontSizeOnly ? [8, 4, 1] : [8, 4, 1, 0.1],
18337            lineMax,
18338            newFontSize;
18339
18340          if($line.hasClass(BigText.EXEMPT_CLASS)) {
18341            fontSizes.push(null);
18342            ratios.push(null);
18343            minFontSizes.push(false);
18344            return;
18345          }
18346
18347          // TODO we can cache this ratio?
18348          var autoGuessSubtraction = 32, // font size in px
18349            currentFontSize = parseFloat($line.css('font-size')),
18350            ratio = ( $line.width() / currentFontSize ).toFixed(6);
18351
18352          newFontSize = parseInt( maxWidth / ratio, 10 ) - autoGuessSubtraction;
18353
18354          outer: for(var m=0, n=intervals.length; m<n; m++) {
18355            inner: for(var j=1, k=10; j<=k; j++) {
18356              if(newFontSize + j*intervals[m] > maxFontSize) {
18357                newFontSize = maxFontSize;
18358                break outer;
18359              }
18360
18361              lineMax = BigText.testLineDimensions($line, maxWidth, 'font-size', newFontSize + j*intervals[m], intervals[m], 'px', lineMax);
18362              if(typeof lineMax !== 'number') {
18363                newFontSize = lineMax.size;
18364
18365                if(lineMax.match === 'exact') {
18366                  break outer;
18367                }
18368                break inner;
18369              }
18370            }
18371          }
18372
18373          ratios.push(maxWidth / newFontSize);
18374
18375          if(newFontSize > maxFontSize) {
18376            fontSizes.push(maxFontSize);
18377            minFontSizes.push(false);
18378          } else if(!!minFontSize && newFontSize < minFontSize) {
18379            fontSizes.push(minFontSize);
18380            minFontSizes.push(true);
18381          } else {
18382            fontSizes.push(newFontSize);
18383            minFontSizes.push(false);
18384          }
18385        }).each(function(lineNumber) {
18386          var $line = $(this),
18387            wordSpacing = 0,
18388            interval = 1,
18389            maxWordSpacing;
18390
18391          if($line.hasClass(BigText.EXEMPT_CLASS)) {
18392            wordSpacings.push(null);
18393            return;
18394          }
18395
18396          // must re-use font-size, even though it was removed above.
18397          $line.css('font-size', fontSizes[lineNumber] + 'px');
18398
18399          for(var m=1, n=3; m<n; m+=interval) {
18400            maxWordSpacing = BigText.testLineDimensions($line, maxWidth, 'word-spacing', m, interval, 'px', maxWordSpacing);
18401            if(typeof maxWordSpacing !== 'number') {
18402              wordSpacing = maxWordSpacing.size;
18403              break;
18404            }
18405          }
18406
18407          $line.css('font-size', '');
18408          wordSpacings.push(wordSpacing);
18409        }).removeAttr('style');
18410
18411        if( !BigText.DEBUG_MODE ) {
18412          $c.remove();
18413        } else {
18414          $c.css({
18415            'background-color': 'rgba(255,255,255,.4)'
18416          });
18417        }
18418
18419        return {
18420          fontSizes: fontSizes,
18421          wordSpacings: wordSpacings,
18422          ratios: ratios,
18423          minFontSizes: minFontSizes
18424        };
18425      }
18426    };
18427
18428  $.fn.bigtext = BigText.jQueryMethod;
18429  window.BigText = BigText;
18430
18431})(this, jQuery);
18432/*!
18433 * Isotope PACKAGED v3.0.6
18434 *
18435 * Licensed GPLv3 for open source use
18436 * or Isotope Commercial License for commercial use
18437 *
18438 * https://isotope.metafizzy.co
18439 * Copyright 2010-2018 Metafizzy
vendor: 15,902 bytes, lines 18439-19089
18439
18440 */
18441
18442/**
18443 * Bridget makes jQuery widgets
18444 * v2.0.1
18445 * MIT license
18446 */
18447
18448/* jshint browser: true, strict: true, undef: true, unused: true */
18449
18450( function( window, factory ) {
18451  // universal module definition
18452  /*jshint strict: false */ /* globals define, module, require */
18453  if ( typeof define == 'function' && define.amd ) {
18454    // AMD
18455    define( 'jquery-bridget/jquery-bridget',[ 'jquery' ], function( jQuery ) {
18456      return factory( window, jQuery );
18457    });
18458  } else if ( typeof module == 'object' && module.exports ) {
18459    // CommonJS
18460    module.exports = factory(
18461      window,
18462      require('jquery')
18463    );
18464  } else {
18465    // browser global
18466    window.jQueryBridget = factory(
18467      window,
18468      window.jQuery
18469    );
18470  }
18471
18472}( window, function factory( window, jQuery ) {
18473'use strict';
18474
18475// ----- utils ----- //
18476
18477var arraySlice = Array.prototype.slice;
18478
18479// helper function for logging errors
18480// $.error breaks jQuery chaining
18481var console = window.console;
18482var logError = typeof console == 'undefined' ? function() {} :
18483  function( message ) {
18484    console.error( message );
18485  };
18486
18487// ----- jQueryBridget ----- //
18488
18489function jQueryBridget( namespace, PluginClass, $ ) {
18490  $ = $ || jQuery || window.jQuery;
18491  if ( !$ ) {
18492    return;
18493  }
18494
18495  // add option method -> $().plugin('option', {...})
18496  if ( !PluginClass.prototype.option ) {
18497    // option setter
18498    PluginClass.prototype.option = function( opts ) {
18499      // bail out if not an object
18500      if ( !$.isPlainObject( opts ) ){
18501        return;
18502      }
18503      this.options = $.extend( true, this.options, opts );
18504    };
18505  }
18506
18507  // make jQuery plugin
18508  $.fn[ namespace ] = function( arg0 /*, arg1 */ ) {
18509    if ( typeof arg0 == 'string' ) {
18510      // method call $().plugin( 'methodName', { options } )
18511      // shift arguments by 1
18512      var args = arraySlice.call( arguments, 1 );
18513      return methodCall( this, arg0, args );
18514    }
18515    // just $().plugin({ options })
18516    plainCall( this, arg0 );
18517    return this;
18518  };
18519
18520  // $().plugin('methodName')
18521  function methodCall( $elems, methodName, args ) {
18522    var returnValue;
18523    var pluginMethodStr = '$().' + namespace + '("' + methodName + '")';
18524
18525    $elems.each( function( i, elem ) {
18526      // get instance
18527      var instance = $.data( elem, namespace );
18528      if ( !instance ) {
18529        logError( namespace + ' not initialized. Cannot call methods, i.e. ' +
18530          pluginMethodStr );
18531        return;
18532      }
18533
18534      var method = instance[ methodName ];
18535      if ( !method || methodName.charAt(0) == '_' ) {
18536        logError( pluginMethodStr + ' is not a valid method' );
18537        return;
18538      }
18539
18540      // apply method, get return value
18541      var value = method.apply( instance, args );
18542      // set return value if value is returned, use only first value
18543      returnValue = returnValue === undefined ? value : returnValue;
18544    });
18545
18546    return returnValue !== undefined ? returnValue : $elems;
18547  }
18548
18549  function plainCall( $elems, options ) {
18550    $elems.each( function( i, elem ) {
18551      var instance = $.data( elem, namespace );
18552      if ( instance ) {
18553        // set options & init
18554        instance.option( options );
18555        instance._init();
18556      } else {
18557        // initialize new instance
18558        instance = new PluginClass( elem, options );
18559        $.data( elem, namespace, instance );
18560      }
18561    });
18562  }
18563
18564  updateJQuery( $ );
18565
18566}
18567
18568// ----- updateJQuery ----- //
18569
18570// set $.bridget for v1 backwards compatibility
18571function updateJQuery( $ ) {
18572  if ( !$ || ( $ && $.bridget ) ) {
18573    return;
18574  }
18575  $.bridget = jQueryBridget;
18576}
18577
18578updateJQuery( jQuery || window.jQuery );
18579
18580// -----  ----- //
18581
18582return jQueryBridget;
18583
18584}));
18585
18586/**
18587 * EvEmitter v1.1.0
18588 * Lil' event emitter
18589 * MIT License
18590 */
18591
18592/* jshint unused: true, undef: true, strict: true */
18593
18594( function( global, factory ) {
18595  // universal module definition
18596  /* jshint strict: false */ /* globals define, module, window */
18597  if ( typeof define == 'function' && define.amd ) {
18598    // AMD - RequireJS
18599    define( 'ev-emitter/ev-emitter',factory );
18600  } else if ( typeof module == 'object' && module.exports ) {
18601    // CommonJS - Browserify, Webpack
18602    module.exports = factory();
18603  } else {
18604    // Browser globals
18605    global.EvEmitter = factory();
18606  }
18607
18608}( typeof window != 'undefined' ? window : this, function() {
18609
18610
18611
18612function EvEmitter() {}
18613
18614var proto = EvEmitter.prototype;
18615
18616proto.on = function( eventName, listener ) {
18617  if ( !eventName || !listener ) {
18618    return;
18619  }
18620  // set events hash
18621  var events = this._events = this._events || {};
18622  // set listeners array
18623  var listeners = events[ eventName ] = events[ eventName ] || [];
18624  // only add once
18625  if ( listeners.indexOf( listener ) == -1 ) {
18626    listeners.push( listener );
18627  }
18628
18629  return this;
18630};
18631
18632proto.once = function( eventName, listener ) {
18633  if ( !eventName || !listener ) {
18634    return;
18635  }
18636  // add event
18637  this.on( eventName, listener );
18638  // set once flag
18639  // set onceEvents hash
18640  var onceEvents = this._onceEvents = this._onceEvents || {};
18641  // set onceListeners object
18642  var onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {};
18643  // set flag
18644  onceListeners[ listener ] = true;
18645
18646  return this;
18647};
18648
18649proto.off = function( eventName, listener ) {
18650  var listeners = this._events && this._events[ eventName ];
18651  if ( !listeners || !listeners.length ) {
18652    return;
18653  }
18654  var index = listeners.indexOf( listener );
18655  if ( index != -1 ) {
18656    listeners.splice( index, 1 );
18657  }
18658
18659  return this;
18660};
18661
18662proto.emitEvent = function( eventName, args ) {
18663  var listeners = this._events && this._events[ eventName ];
18664  if ( !listeners || !listeners.length ) {
18665    return;
18666  }
18667  // copy over to avoid interference if .off() in listener
18668  listeners = listeners.slice(0);
18669  args = args || [];
18670  // once stuff
18671  var onceListeners = this._onceEvents && this._onceEvents[ eventName ];
18672
18673  for ( var i=0; i < listeners.length; i++ ) {
18674    var listener = listeners[i]
18675    var isOnce = onceListeners && onceListeners[ listener ];
18676    if ( isOnce ) {
18677      // remove listener
18678      // remove before trigger to prevent recursion
18679      this.off( eventName, listener );
18680      // unset once flag
18681      delete onceListeners[ listener ];
18682    }
18683    // trigger listener
18684    listener.apply( this, args );
18685  }
18686
18687  return this;
18688};
18689
18690proto.allOff = function() {
18691  delete this._events;
18692  delete this._onceEvents;
18693};
18694
18695return EvEmitter;
18696
18697}));
18698
18699/*!
18700 * getSize v2.0.3
18701 * measure size of elements
18702 * MIT license
18703 */
18704
18705/* jshint browser: true, strict: true, undef: true, unused: true */
18706/* globals console: false */
18707
18708( function( window, factory ) {
18709  /* jshint strict: false */ /* globals define, module */
18710  if ( typeof define == 'function' && define.amd ) {
18711    // AMD
18712    define( 'get-size/get-size',factory );
18713  } else if ( typeof module == 'object' && module.exports ) {
18714    // CommonJS
18715    module.exports = factory();
18716  } else {
18717    // browser global
18718    window.getSize = factory();
18719  }
18720
18721})( window, function factory() {
18722'use strict';
18723
18724// -------------------------- helpers -------------------------- //
18725
18726// get a number from a string, not a percentage
18727function getStyleSize( value ) {
18728  var num = parseFloat( value );
18729  // not a percent like '100%', and a number
18730  var isValid = value.indexOf('%') == -1 && !isNaN( num );
18731  return isValid && num;
18732}
18733
18734function noop() {}
18735
18736var logError = typeof console == 'undefined' ? noop :
18737  function( message ) {
18738    console.error( message );
18739  };
18740
18741// -------------------------- measurements -------------------------- //
18742
18743var measurements = [
18744  'paddingLeft',
18745  'paddingRight',
18746  'paddingTop',
18747  'paddingBottom',
18748  'marginLeft',
18749  'marginRight',
18750  'marginTop',
18751  'marginBottom',
18752  'borderLeftWidth',
18753  'borderRightWidth',
18754  'borderTopWidth',
18755  'borderBottomWidth'
18756];
18757
18758var measurementsLength = measurements.length;
18759
18760function getZeroSize() {
18761  var size = {
18762    width: 0,
18763    height: 0,
18764    innerWidth: 0,
18765    innerHeight: 0,
18766    outerWidth: 0,
18767    outerHeight: 0
18768  };
18769  for ( var i=0; i < measurementsLength; i++ ) {
18770    var measurement = measurements[i];
18771    size[ measurement ] = 0;
18772  }
18773  return size;
18774}
18775
18776// -------------------------- getStyle -------------------------- //
18777
18778/**
18779 * getStyle, get style of element, check for Firefox bug
18780 * https://bugzilla.mozilla.org/show_bug.cgi?id=548397
18781 */
18782function getStyle( elem ) {
18783  var style = getComputedStyle( elem );
18784  if ( !style ) {
18785    logError( 'Style returned ' + style +
18786      '. Are you running this code in a hidden iframe on Firefox? ' +
18787      'See https://bit.ly/getsizebug1' );
18788  }
18789  return style;
18790}
18791
18792// -------------------------- setup -------------------------- //
18793
18794var isSetup = false;
18795
18796var isBoxSizeOuter;
18797
18798/**
18799 * setup
18800 * check isBoxSizerOuter
18801 * do on first getSize() rather than on page load for Firefox bug
18802 */
18803function setup() {
18804  // setup once
18805  if ( isSetup ) {
18806    return;
18807  }
18808  isSetup = true;
18809
18810  // -------------------------- box sizing -------------------------- //
18811
18812  /**
18813   * Chrome & Safari measure the outer-width on style.width on border-box elems
18814   * IE11 & Firefox<29 measures the inner-width
18815   */
18816  var div = document.createElement('div');
18817  div.style.width = '200px';
18818  div.style.padding = '1px 2px 3px 4px';
18819  div.style.borderStyle = 'solid';
18820  div.style.borderWidth = '1px 2px 3px 4px';
18821  div.style.boxSizing = 'border-box';
18822
18823  var body = document.body || document.documentElement;
18824  body.appendChild( div );
18825  var style = getStyle( div );
18826  // round value for browser zoom. desandro/masonry#928
18827  isBoxSizeOuter = Math.round( getStyleSize( style.width ) ) == 200;
18828  getSize.isBoxSizeOuter = isBoxSizeOuter;
18829
18830  body.removeChild( div );
18831}
18832
18833// -------------------------- getSize -------------------------- //
18834
18835function getSize( elem ) {
18836  setup();
18837
18838  // use querySeletor if elem is string
18839  if ( typeof elem == 'string' ) {
18840    elem = document.querySelector( elem );
18841  }
18842
18843  // do not proceed on non-objects
18844  if ( !elem || typeof elem != 'object' || !elem.nodeType ) {
18845    return;
18846  }
18847
18848  var style = getStyle( elem );
18849
18850  // if hidden, everything is 0
18851  if ( style.display == 'none' ) {
18852    return getZeroSize();
18853  }
18854
18855  var size = {};
18856  size.width = elem.offsetWidth;
18857  size.height = elem.offsetHeight;
18858
18859  var isBorderBox = size.isBorderBox = style.boxSizing == 'border-box';
18860
18861  // get all measurements
18862  for ( var i=0; i < measurementsLength; i++ ) {
18863    var measurement = measurements[i];
18864    var value = style[ measurement ];
18865    var num = parseFloat( value );
18866    // any 'auto', 'medium' value will be 0
18867    size[ measurement ] = !isNaN( num ) ? num : 0;
18868  }
18869
18870  var paddingWidth = size.paddingLeft + size.paddingRight;
18871  var paddingHeight = size.paddingTop + size.paddingBottom;
18872  var marginWidth = size.marginLeft + size.marginRight;
18873  var marginHeight = size.marginTop + size.marginBottom;
18874  var borderWidth = size.borderLeftWidth + size.borderRightWidth;
18875  var borderHeight = size.borderTopWidth + size.borderBottomWidth;
18876
18877  var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter;
18878
18879  // overwrite width and height if we can get it from style
18880  var styleWidth = getStyleSize( style.width );
18881  if ( styleWidth !== false ) {
18882    size.width = styleWidth +
18883      // add padding and border unless it's already including it
18884      ( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth );
18885  }
18886
18887  var styleHeight = getStyleSize( style.height );
18888  if ( styleHeight !== false ) {
18889    size.height = styleHeight +
18890      // add padding and border unless it's already including it
18891      ( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight );
18892  }
18893
18894  size.innerWidth = size.width - ( paddingWidth + borderWidth );
18895  size.innerHeight = size.height - ( paddingHeight + borderHeight );
18896
18897  size.outerWidth = size.width + marginWidth;
18898  size.outerHeight = size.height + marginHeight;
18899
18900  return size;
18901}
18902
18903return getSize;
18904
18905});
18906
18907/**
18908 * matchesSelector v2.0.2
18909 * matchesSelector( element, '.selector' )
18910 * MIT license
18911 */
18912
18913/*jshint browser: true, strict: true, undef: true, unused: true */
18914
18915( function( window, factory ) {
18916  /*global define: false, module: false */
18917  'use strict';
18918  // universal module definition
18919  if ( typeof define == 'function' && define.amd ) {
18920    // AMD
18921    define( 'desandro-matches-selector/matches-selector',factory );
18922  } else if ( typeof module == 'object' && module.exports ) {
18923    // CommonJS
18924    module.exports = factory();
18925  } else {
18926    // browser global
18927    window.matchesSelector = factory();
18928  }
18929
18930}( window, function factory() {
18931  'use strict';
18932
18933  var matchesMethod = ( function() {
18934    var ElemProto = window.Element.prototype;
18935    // check for the standard method name first
18936    if ( ElemProto.matches ) {
18937      return 'matches';
18938    }
18939    // check un-prefixed
18940    if ( ElemProto.matchesSelector ) {
18941      return 'matchesSelector';
18942    }
18943    // check vendor prefixes
18944    var prefixes = [ 'webkit', 'moz', 'ms', 'o' ];
18945
18946    for ( var i=0; i < prefixes.length; i++ ) {
18947      var prefix = prefixes[i];
18948      var method = prefix + 'MatchesSelector';
18949      if ( ElemProto[ method ] ) {
18950        return method;
18951      }
18952    }
18953  })();
18954
18955  return function matchesSelector( elem, selector ) {
18956    return elem[ matchesMethod ]( selector );
18957  };
18958
18959}));
18960
18961/**
18962 * Fizzy UI utils v2.0.7
18963 * MIT license
18964 */
18965
18966/*jshint browser: true, undef: true, unused: true, strict: true */
18967
18968( function( window, factory ) {
18969  // universal module definition
18970  /*jshint strict: false */ /*globals define, module, require */
18971
18972  if ( typeof define == 'function' && define.amd ) {
18973    // AMD
18974    define( 'fizzy-ui-utils/utils',[
18975      'desandro-matches-selector/matches-selector'
18976    ], function( matchesSelector ) {
18977      return factory( window, matchesSelector );
18978    });
18979  } else if ( typeof module == 'object' && module.exports ) {
18980    // CommonJS
18981    module.exports = factory(
18982      window,
18983      require('desandro-matches-selector')
18984    );
18985  } else {
18986    // browser global
18987    window.fizzyUIUtils = factory(
18988      window,
18989      window.matchesSelector
18990    );
18991  }
18992
18993}( window, function factory( window, matchesSelector ) {
18994
18995
18996
18997var utils = {};
18998
18999// ----- extend ----- //
19000
19001// extends objects
19002utils.extend = function( a, b ) {
19003  for ( var prop in b ) {
19004    a[ prop ] = b[ prop ];
19005  }
19006  return a;
19007};
19008
19009// ----- modulo ----- //
19010
19011utils.modulo = function( num, div ) {
19012  return ( ( num % div ) + div ) % div;
19013};
19014
19015// ----- makeArray ----- //
19016
19017var arraySlice = Array.prototype.slice;
19018
19019// turn element or nodeList into an array
19020utils.makeArray = function( obj ) {
19021  if ( Array.isArray( obj ) ) {
19022    // use object if already an array
19023    return obj;
19024  }
19025  // return empty array if undefined or null. #6
19026  if ( obj === null || obj === undefined ) {
19027    return [];
19028  }
19029
19030  var isArrayLike = typeof obj == 'object' && typeof obj.length == 'number';
19031  if ( isArrayLike ) {
19032    // convert nodeList to array
19033    return arraySlice.call( obj );
19034  }
19035
19036  // array of single index
19037  return [ obj ];
19038};
19039
19040// ----- removeFrom ----- //
19041
19042utils.removeFrom = function( ary, obj ) {
19043  var index = ary.indexOf( obj );
19044  if ( index != -1 ) {
19045    ary.splice( index, 1 );
19046  }
19047};
19048
19049// ----- getParent ----- //
19050
19051utils.getParent = function( elem, selector ) {
19052  while ( elem.parentNode && elem != document.body ) {
19053    elem = elem.parentNode;
19054    if ( matchesSelector( elem, selector ) ) {
19055      return elem;
19056    }
19057  }
19058};
19059
19060// ----- getQueryElement ----- //
19061
19062// use element as selector string
19063utils.getQueryElement = function( elem ) {
19064  if ( typeof elem == 'string' ) {
19065    return document.querySelector( elem );
19066  }
19067  return elem;
19068};
19069
19070// ----- handleEvent ----- //
19071
19072// enable .ontype to trigger from .addEventListener( elem, 'type' )
19073utils.handleEvent = function( event ) {
19074  var method = 'on' + event.type;
19075  if ( this[ method ] ) {
19076    this[ method ]( event );
19077  }
19078};
19079
19080// ----- filterFindElements ----- //
19081
19082utils.filterFindElements = function( elems, selector ) {
19083  // make array of elems
19084  elems = utils.makeArray( elems );
19085  var ffElems = [];
19086
19087  elems.forEach( function( elem ) {
19088    // check that elem is an actual element
19089    
19089// START UNCODE EDIT
19090    // if ( !( elem instanceof HTMLElement ) ) {
19091    if ( !( elem instanceof HTMLElement ) && !SiteParameters.is_frontend_editor ) {
19092    // END UNCODE EDIT
vendor: 23,480 bytes, lines 19092-20004
19092
19093      return;
19094    }
19095    // add elem if no selector
19096    if ( !selector ) {
19097      ffElems.push( elem );
19098      return;
19099    }
19100    // filter & find items if we have a selector
19101    // filter
19102    if ( matchesSelector( elem, selector ) ) {
19103      ffElems.push( elem );
19104    }
19105    // find children
19106    var childElems = elem.querySelectorAll( selector );
19107    // concat childElems to filterFound array
19108    for ( var i=0; i < childElems.length; i++ ) {
19109      ffElems.push( childElems[i] );
19110    }
19111  });
19112
19113  return ffElems;
19114};
19115
19116// ----- debounceMethod ----- //
19117
19118utils.debounceMethod = function( _class, methodName, threshold ) {
19119  threshold = threshold || 100;
19120  // original method
19121  var method = _class.prototype[ methodName ];
19122  var timeoutName = methodName + 'Timeout';
19123
19124  _class.prototype[ methodName ] = function() {
19125    var timeout = this[ timeoutName ];
19126    clearTimeout( timeout );
19127
19128    var args = arguments;
19129    var _this = this;
19130    this[ timeoutName ] = setTimeout( function() {
19131      method.apply( _this, args );
19132      delete _this[ timeoutName ];
19133    }, threshold );
19134  };
19135};
19136
19137// ----- docReady ----- //
19138
19139utils.docReady = function( callback ) {
19140  var readyState = document.readyState;
19141  if ( readyState == 'complete' || readyState == 'interactive' ) {
19142    // do async to allow for other scripts to run. metafizzy/flickity#441
19143    setTimeout( callback );
19144  } else {
19145    document.addEventListener( 'DOMContentLoaded', callback );
19146  }
19147};
19148
19149// ----- htmlInit ----- //
19150
19151// http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/
19152utils.toDashed = function( str ) {
19153  return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) {
19154    return $1 + '-' + $2;
19155  }).toLowerCase();
19156};
19157
19158var console = window.console;
19159/**
19160 * allow user to initialize classes via [data-namespace] or .js-namespace class
19161 * htmlInit( Widget, 'widgetName' )
19162 * options are parsed from data-namespace-options
19163 */
19164utils.htmlInit = function( WidgetClass, namespace ) {
19165  utils.docReady( function() {
19166    var dashedNamespace = utils.toDashed( namespace );
19167    var dataAttr = 'data-' + dashedNamespace;
19168    var dataAttrElems = document.querySelectorAll( '[' + dataAttr + ']' );
19169    var jsDashElems = document.querySelectorAll( '.js-' + dashedNamespace );
19170    var elems = utils.makeArray( dataAttrElems )
19171      .concat( utils.makeArray( jsDashElems ) );
19172    var dataOptionsAttr = dataAttr + '-options';
19173    var jQuery = window.jQuery;
19174
19175    elems.forEach( function( elem ) {
19176      var attr = elem.getAttribute( dataAttr ) ||
19177        elem.getAttribute( dataOptionsAttr );
19178      var options;
19179      try {
19180        options = attr && JSON.parse( attr );
19181      } catch ( error ) {
19182        // log error, do not initialize
19183        if ( console ) {
19184          console.error( 'Error parsing ' + dataAttr + ' on ' + elem.className +
19185          ': ' + error );
19186        }
19187        return;
19188      }
19189      // initialize
19190      var instance = new WidgetClass( elem, options );
19191      // make available via $().data('namespace')
19192      if ( jQuery ) {
19193        jQuery.data( elem, namespace, instance );
19194      }
19195    });
19196
19197  });
19198};
19199
19200// -----  ----- //
19201
19202return utils;
19203
19204}));
19205
19206/**
19207 * Outlayer Item
19208 */
19209
19210( function( window, factory ) {
19211  // universal module definition
19212  /* jshint strict: false */ /* globals define, module, require */
19213  if ( typeof define == 'function' && define.amd ) {
19214    // AMD - RequireJS
19215    define( 'outlayer/item',[
19216        'ev-emitter/ev-emitter',
19217        'get-size/get-size'
19218      ],
19219      factory
19220    );
19221  } else if ( typeof module == 'object' && module.exports ) {
19222    // CommonJS - Browserify, Webpack
19223    module.exports = factory(
19224      require('ev-emitter'),
19225      require('get-size')
19226    );
19227  } else {
19228    // browser global
19229    window.Outlayer = {};
19230    window.Outlayer.Item = factory(
19231      window.EvEmitter,
19232      window.getSize
19233    );
19234  }
19235
19236}( window, function factory( EvEmitter, getSize ) {
19237'use strict';
19238
19239// ----- helpers ----- //
19240
19241function isEmptyObj( obj ) {
19242  for ( var prop in obj ) {
19243    return false;
19244  }
19245  prop = null;
19246  return true;
19247}
19248
19249// -------------------------- CSS3 support -------------------------- //
19250
19251
19252var docElemStyle = document.documentElement.style;
19253
19254var transitionProperty = typeof docElemStyle.transition == 'string' ?
19255  'transition' : 'WebkitTransition';
19256var transformProperty = typeof docElemStyle.transform == 'string' ?
19257  'transform' : 'WebkitTransform';
19258
19259var transitionEndEvent = {
19260  WebkitTransition: 'webkitTransitionEnd',
19261  transition: 'transitionend'
19262}[ transitionProperty ];
19263
19264// cache all vendor properties that could have vendor prefix
19265var vendorProperties = {
19266  transform: transformProperty,
19267  transition: transitionProperty,
19268  transitionDuration: transitionProperty + 'Duration',
19269  transitionProperty: transitionProperty + 'Property',
19270  transitionDelay: transitionProperty + 'Delay'
19271};
19272
19273// -------------------------- Item -------------------------- //
19274
19275function Item( element, layout ) {
19276  if ( !element ) {
19277    return;
19278  }
19279
19280  this.element = element;
19281  // parent layout class, i.e. Masonry, Isotope, or Packery
19282  this.layout = layout;
19283  this.position = {
19284    x: 0,
19285    y: 0
19286  };
19287
19288  this._create();
19289}
19290
19291// inherit EvEmitter
19292var proto = Item.prototype = Object.create( EvEmitter.prototype );
19293proto.constructor = Item;
19294
19295proto._create = function() {
19296  // transition objects
19297  this._transn = {
19298    ingProperties: {},
19299    clean: {},
19300    onEnd: {}
19301  };
19302
19303  this.css({
19304    position: 'absolute'
19305  });
19306};
19307
19308// trigger specified handler for event type
19309proto.handleEvent = function( event ) {
19310  var method = 'on' + event.type;
19311  if ( this[ method ] ) {
19312    this[ method ]( event );
19313  }
19314};
19315
19316proto.getSize = function() {
19317  this.size = getSize( this.element );
19318};
19319
19320/**
19321 * apply CSS styles to element
19322 * @param {Object} style
19323 */
19324proto.css = function( style ) {
19325  var elemStyle = this.element.style;
19326
19327  for ( var prop in style ) {
19328    // use vendor property if available
19329    var supportedProp = vendorProperties[ prop ] || prop;
19330    elemStyle[ supportedProp ] = style[ prop ];
19331  }
19332};
19333
19334 // measure position, and sets it
19335proto.getPosition = function() {
19336  var style = getComputedStyle( this.element );
19337  var isOriginLeft = this.layout._getOption('originLeft');
19338  var isOriginTop = this.layout._getOption('originTop');
19339  var xValue = style[ isOriginLeft ? 'left' : 'right' ];
19340  var yValue = style[ isOriginTop ? 'top' : 'bottom' ];
19341  var x = parseFloat( xValue );
19342  var y = parseFloat( yValue );
19343  // convert percent to pixels
19344  var layoutSize = this.layout.size;
19345  if ( xValue.indexOf('%') != -1 ) {
19346    x = ( x / 100 ) * layoutSize.width;
19347  }
19348  if ( yValue.indexOf('%') != -1 ) {
19349    y = ( y / 100 ) * layoutSize.height;
19350  }
19351  // clean up 'auto' or other non-integer values
19352  x = isNaN( x ) ? 0 : x;
19353  y = isNaN( y ) ? 0 : y;
19354  // remove padding from measurement
19355  x -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight;
19356  y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom;
19357
19358  this.position.x = x;
19359  this.position.y = y;
19360};
19361
19362// set settled position, apply padding
19363proto.layoutPosition = function() {
19364  var layoutSize = this.layout.size;
19365  var style = {};
19366  var isOriginLeft = this.layout._getOption('originLeft');
19367  var isOriginTop = this.layout._getOption('originTop');
19368
19369  // x
19370  var xPadding = isOriginLeft ? 'paddingLeft' : 'paddingRight';
19371  var xProperty = isOriginLeft ? 'left' : 'right';
19372  var xResetProperty = isOriginLeft ? 'right' : 'left';
19373
19374  var x = this.position.x + layoutSize[ xPadding ];
19375  // set in percentage or pixels
19376  style[ xProperty ] = this.getXValue( x );
19377  // reset other property
19378  style[ xResetProperty ] = '';
19379
19380  // y
19381  var yPadding = isOriginTop ? 'paddingTop' : 'paddingBottom';
19382  var yProperty = isOriginTop ? 'top' : 'bottom';
19383  var yResetProperty = isOriginTop ? 'bottom' : 'top';
19384
19385  var y = this.position.y + layoutSize[ yPadding ];
19386  // set in percentage or pixels
19387  style[ yProperty ] = this.getYValue( y );
19388  // reset other property
19389  style[ yResetProperty ] = '';
19390
19391  this.css( style );
19392  this.emitEvent( 'layout', [ this ] );
19393};
19394
19395proto.getXValue = function( x ) {
19396  var isHorizontal = this.layout._getOption('horizontal');
19397  return this.layout.options.percentPosition && !isHorizontal ?
19398    ( ( x / this.layout.size.width ) * 100 ) + '%' : x + 'px';
19399};
19400
19401proto.getYValue = function( y ) {
19402  var isHorizontal = this.layout._getOption('horizontal');
19403  return this.layout.options.percentPosition && isHorizontal ?
19404    ( ( y / this.layout.size.height ) * 100 ) + '%' : y + 'px';
19405};
19406
19407proto._transitionTo = function( x, y ) {
19408  this.getPosition();
19409  // get current x & y from top/left
19410  var curX = this.position.x;
19411  var curY = this.position.y;
19412
19413  var didNotMove = x == this.position.x && y == this.position.y;
19414
19415  // save end position
19416  this.setPosition( x, y );
19417
19418  // if did not move and not transitioning, just go to layout
19419  if ( didNotMove && !this.isTransitioning ) {
19420    this.layoutPosition();
19421    return;
19422  }
19423
19424  var transX = x - curX;
19425  var transY = y - curY;
19426  var transitionStyle = {};
19427  transitionStyle.transform = this.getTranslate( transX, transY );
19428
19429  this.transition({
19430    to: transitionStyle,
19431    onTransitionEnd: {
19432      transform: this.layoutPosition
19433    },
19434    isCleaning: true
19435  });
19436};
19437
19438proto.getTranslate = function( x, y ) {
19439  // flip cooridinates if origin on right or bottom
19440  var isOriginLeft = this.layout._getOption('originLeft');
19441  var isOriginTop = this.layout._getOption('originTop');
19442  x = isOriginLeft ? x : -x;
19443  y = isOriginTop ? y : -y;
19444  return 'translate3d(' + x + 'px, ' + y + 'px, 0)';
19445};
19446
19447// non transition + transform support
19448proto.goTo = function( x, y ) {
19449  this.setPosition( x, y );
19450  this.layoutPosition();
19451};
19452
19453proto.moveTo = proto._transitionTo;
19454
19455proto.setPosition = function( x, y ) {
19456  this.position.x = parseFloat( x );
19457  this.position.y = parseFloat( y );
19458};
19459
19460// ----- transition ----- //
19461
19462/**
19463 * @param {Object} style - CSS
19464 * @param {Function} onTransitionEnd
19465 */
19466
19467// non transition, just trigger callback
19468proto._nonTransition = function( args ) {
19469  this.css( args.to );
19470  if ( args.isCleaning ) {
19471    this._removeStyles( args.to );
19472  }
19473  for ( var prop in args.onTransitionEnd ) {
19474    args.onTransitionEnd[ prop ].call( this );
19475  }
19476};
19477
19478/**
19479 * proper transition
19480 * @param {Object} args - arguments
19481 *   @param {Object} to - style to transition to
19482 *   @param {Object} from - style to start transition from
19483 *   @param {Boolean} isCleaning - removes transition styles after transition
19484 *   @param {Function} onTransitionEnd - callback
19485 */
19486proto.transition = function( args ) {
19487  // redirect to nonTransition if no transition duration
19488  if ( !parseFloat( this.layout.options.transitionDuration ) ) {
19489    this._nonTransition( args );
19490    return;
19491  }
19492
19493  var _transition = this._transn;
19494  // keep track of onTransitionEnd callback by css property
19495  for ( var prop in args.onTransitionEnd ) {
19496    _transition.onEnd[ prop ] = args.onTransitionEnd[ prop ];
19497  }
19498  // keep track of properties that are transitioning
19499  for ( prop in args.to ) {
19500    _transition.ingProperties[ prop ] = true;
19501    // keep track of properties to clean up when transition is done
19502    if ( args.isCleaning ) {
19503      _transition.clean[ prop ] = true;
19504    }
19505  }
19506
19507  // set from styles
19508  if ( args.from ) {
19509    this.css( args.from );
19510    // force redraw. http://blog.alexmaccaw.com/css-transitions
19511    var h = this.element.offsetHeight;
19512    // hack for JSHint to hush about unused var
19513    h = null;
19514  }
19515  // enable transition
19516  this.enableTransition( args.to );
19517  // set styles that are transitioning
19518  this.css( args.to );
19519
19520  this.isTransitioning = true;
19521
19522};
19523
19524// dash before all cap letters, including first for
19525// WebkitTransform => -webkit-transform
19526function toDashedAll( str ) {
19527  return str.replace( /([A-Z])/g, function( $1 ) {
19528    return '-' + $1.toLowerCase();
19529  });
19530}
19531
19532var transitionProps = 'opacity,' + toDashedAll( transformProperty );
19533
19534proto.enableTransition = function(/* style */) {
19535  // HACK changing transitionProperty during a transition
19536  // will cause transition to jump
19537  if ( this.isTransitioning ) {
19538    return;
19539  }
19540
19541  // make `transition: foo, bar, baz` from style object
19542  // HACK un-comment this when enableTransition can work
19543  // while a transition is happening
19544  // var transitionValues = [];
19545  // for ( var prop in style ) {
19546  //   // dash-ify camelCased properties like WebkitTransition
19547  //   prop = vendorProperties[ prop ] || prop;
19548  //   transitionValues.push( toDashedAll( prop ) );
19549  // }
19550  // munge number to millisecond, to match stagger
19551  var duration = this.layout.options.transitionDuration;
19552  duration = typeof duration == 'number' ? duration + 'ms' : duration;
19553  // enable transition styles
19554  this.css({
19555    transitionProperty: transitionProps,
19556    transitionDuration: duration,
19557    transitionDelay: this.staggerDelay || 0
19558  });
19559  // listen for transition end event
19560  this.element.addEventListener( transitionEndEvent, this, false );
19561};
19562
19563// ----- events ----- //
19564
19565proto.onwebkitTransitionEnd = function( event ) {
19566  this.ontransitionend( event );
19567};
19568
19569proto.onotransitionend = function( event ) {
19570  this.ontransitionend( event );
19571};
19572
19573// properties that I munge to make my life easier
19574var dashedVendorProperties = {
19575  '-webkit-transform': 'transform'
19576};
19577
19578proto.ontransitionend = function( event ) {
19579  // disregard bubbled events from children
19580  if ( event.target !== this.element ) {
19581    return;
19582  }
19583  var _transition = this._transn;
19584  // get property name of transitioned property, convert to prefix-free
19585  var propertyName = dashedVendorProperties[ event.propertyName ] || event.propertyName;
19586
19587  // remove property that has completed transitioning
19588  delete _transition.ingProperties[ propertyName ];
19589  // check if any properties are still transitioning
19590  if ( isEmptyObj( _transition.ingProperties ) ) {
19591    // all properties have completed transitioning
19592    this.disableTransition();
19593  }
19594  // clean style
19595  if ( propertyName in _transition.clean ) {
19596    // clean up style
19597    this.element.style[ event.propertyName ] = '';
19598    delete _transition.clean[ propertyName ];
19599  }
19600  // trigger onTransitionEnd callback
19601  if ( propertyName in _transition.onEnd ) {
19602    var onTransitionEnd = _transition.onEnd[ propertyName ];
19603    onTransitionEnd.call( this );
19604    delete _transition.onEnd[ propertyName ];
19605  }
19606
19607  this.emitEvent( 'transitionEnd', [ this ] );
19608};
19609
19610proto.disableTransition = function() {
19611  this.removeTransitionStyles();
19612  this.element.removeEventListener( transitionEndEvent, this, false );
19613  this.isTransitioning = false;
19614};
19615
19616/**
19617 * removes style property from element
19618 * @param {Object} style
19619**/
19620proto._removeStyles = function( style ) {
19621  // clean up transition styles
19622  var cleanStyle = {};
19623  for ( var prop in style ) {
19624    cleanStyle[ prop ] = '';
19625  }
19626  this.css( cleanStyle );
19627};
19628
19629var cleanTransitionStyle = {
19630  transitionProperty: '',
19631  transitionDuration: '',
19632  transitionDelay: ''
19633};
19634
19635proto.removeTransitionStyles = function() {
19636  // remove transition
19637  this.css( cleanTransitionStyle );
19638};
19639
19640// ----- stagger ----- //
19641
19642proto.stagger = function( delay ) {
19643  delay = isNaN( delay ) ? 0 : delay;
19644  this.staggerDelay = delay + 'ms';
19645};
19646
19647// ----- show/hide/remove ----- //
19648
19649// remove element from DOM
19650proto.removeElem = function() {
19651  this.element.parentNode.removeChild( this.element );
19652  // remove display: none
19653  this.css({ display: '' });
19654  this.emitEvent( 'remove', [ this ] );
19655};
19656
19657proto.remove = function() {
19658  // just remove element if no transition support or no transition
19659  if ( !transitionProperty || !parseFloat( this.layout.options.transitionDuration ) ) {
19660    this.removeElem();
19661    return;
19662  }
19663
19664  // start transition
19665  this.once( 'transitionEnd', function() {
19666    this.removeElem();
19667  });
19668  this.hide();
19669};
19670
19671proto.reveal = function() {
19672  delete this.isHidden;
19673  // remove display: none
19674  this.css({ display: '' });
19675
19676  var options = this.layout.options;
19677
19678  var onTransitionEnd = {};
19679  var transitionEndProperty = this.getHideRevealTransitionEndProperty('visibleStyle');
19680  onTransitionEnd[ transitionEndProperty ] = this.onRevealTransitionEnd;
19681
19682  this.transition({
19683    from: options.hiddenStyle,
19684    to: options.visibleStyle,
19685    isCleaning: true,
19686    onTransitionEnd: onTransitionEnd
19687  });
19688};
19689
19690proto.onRevealTransitionEnd = function() {
19691  // check if still visible
19692  // during transition, item may have been hidden
19693  if ( !this.isHidden ) {
19694    this.emitEvent('reveal');
19695  }
19696};
19697
19698/**
19699 * get style property use for hide/reveal transition end
19700 * @param {String} styleProperty - hiddenStyle/visibleStyle
19701 * @returns {String}
19702 */
19703proto.getHideRevealTransitionEndProperty = function( styleProperty ) {
19704  var optionStyle = this.layout.options[ styleProperty ];
19705  // use opacity
19706  if ( optionStyle.opacity ) {
19707    return 'opacity';
19708  }
19709  // get first property
19710  for ( var prop in optionStyle ) {
19711    return prop;
19712  }
19713};
19714
19715proto.hide = function() {
19716  // set flag
19717  this.isHidden = true;
19718  // remove display: none
19719  this.css({ display: '' });
19720
19721  var options = this.layout.options;
19722
19723  var onTransitionEnd = {};
19724  var transitionEndProperty = this.getHideRevealTransitionEndProperty('hiddenStyle');
19725  onTransitionEnd[ transitionEndProperty ] = this.onHideTransitionEnd;
19726
19727  this.transition({
19728    from: options.visibleStyle,
19729    to: options.hiddenStyle,
19730    // keep hidden stuff hidden
19731    isCleaning: true,
19732    onTransitionEnd: onTransitionEnd
19733  });
19734};
19735
19736proto.onHideTransitionEnd = function() {
19737  // check if still hidden
19738  // during transition, item may have been un-hidden
19739  if ( this.isHidden ) {
19740    this.css({ display: 'none' });
19741    this.emitEvent('hide');
19742  }
19743};
19744
19745proto.destroy = function() {
19746  this.css({
19747    position: '',
19748    left: '',
19749    right: '',
19750    top: '',
19751    bottom: '',
19752    transition: '',
19753    transform: ''
19754  });
19755};
19756
19757return Item;
19758
19759}));
19760
19761/*!
19762 * Outlayer v2.1.1
19763 * the brains and guts of a layout library
19764 * MIT license
19765 */
19766
19767( function( window, factory ) {
19768  'use strict';
19769  // universal module definition
19770  /* jshint strict: false */ /* globals define, module, require */
19771  if ( typeof define == 'function' && define.amd ) {
19772    // AMD - RequireJS
19773    define( 'outlayer/outlayer',[
19774        'ev-emitter/ev-emitter',
19775        'get-size/get-size',
19776        'fizzy-ui-utils/utils',
19777        './item'
19778      ],
19779      function( EvEmitter, getSize, utils, Item ) {
19780        return factory( window, EvEmitter, getSize, utils, Item);
19781      }
19782    );
19783  } else if ( typeof module == 'object' && module.exports ) {
19784    // CommonJS - Browserify, Webpack
19785    module.exports = factory(
19786      window,
19787      require('ev-emitter'),
19788      require('get-size'),
19789      require('fizzy-ui-utils'),
19790      require('./item')
19791    );
19792  } else {
19793    // browser global
19794    window.Outlayer = factory(
19795      window,
19796      window.EvEmitter,
19797      window.getSize,
19798      window.fizzyUIUtils,
19799      window.Outlayer.Item
19800    );
19801  }
19802
19803}( window, function factory( window, EvEmitter, getSize, utils, Item ) {
19804'use strict';
19805
19806// ----- vars ----- //
19807
19808var console = window.console;
19809var jQuery = window.jQuery;
19810var noop = function() {};
19811
19812// -------------------------- Outlayer -------------------------- //
19813
19814// globally unique identifiers
19815var GUID = 0;
19816// internal store of all Outlayer intances
19817var instances = {};
19818
19819
19820/**
19821 * @param {Element, String} element
19822 * @param {Object} options
19823 * @constructor
19824 */
19825function Outlayer( element, options ) {
19826  var queryElement = utils.getQueryElement( element );
19827  if ( !queryElement ) {
19828    if ( console ) {
19829      console.error( 'Bad element for ' + this.constructor.namespace +
19830        ': ' + ( queryElement || element ) );
19831    }
19832    return;
19833  }
19834  this.element = queryElement;
19835  // add jQuery
19836  if ( jQuery ) {
19837    this.$element = jQuery( this.element );
19838  }
19839
19840  // options
19841  this.options = utils.extend( {}, this.constructor.defaults );
19842  this.option( options );
19843
19844  // add id for Outlayer.getFromElement
19845  var id = ++GUID;
19846  this.element.outlayerGUID = id; // expando
19847  instances[ id ] = this; // associate via id
19848
19849  // kick it off
19850  this._create();
19851
19852  var isInitLayout = this._getOption('initLayout');
19853  if ( isInitLayout ) {
19854    this.layout();
19855  }
19856}
19857
19858// settings are for internal use only
19859Outlayer.namespace = 'outlayer';
19860Outlayer.Item = Item;
19861
19862// default options
19863Outlayer.defaults = {
19864  containerStyle: {
19865    position: 'relative'
19866  },
19867  initLayout: true,
19868  originLeft: true,
19869  originTop: true,
19870  resize: true,
19871  resizeContainer: true,
19872  // item options
19873  transitionDuration: '0.4s',
19874  hiddenStyle: {
19875    opacity: 0,
19876    transform: 'scale(0.001)'
19877  },
19878  visibleStyle: {
19879    opacity: 1,
19880    transform: 'scale(1)'
19881  }
19882};
19883
19884var proto = Outlayer.prototype;
19885// inherit EvEmitter
19886utils.extend( proto, EvEmitter.prototype );
19887
19888/**
19889 * set options
19890 * @param {Object} opts
19891 */
19892proto.option = function( opts ) {
19893  utils.extend( this.options, opts );
19894};
19895
19896/**
19897 * get backwards compatible option value, check old name
19898 */
19899proto._getOption = function( option ) {
19900  var oldOption = this.constructor.compatOptions[ option ];
19901  return oldOption && this.options[ oldOption ] !== undefined ?
19902    this.options[ oldOption ] : this.options[ option ];
19903};
19904
19905Outlayer.compatOptions = {
19906  // currentName: oldName
19907  initLayout: 'isInitLayout',
19908  horizontal: 'isHorizontal',
19909  layoutInstant: 'isLayoutInstant',
19910  originLeft: 'isOriginLeft',
19911  originTop: 'isOriginTop',
19912  resize: 'isResizeBound',
19913  resizeContainer: 'isResizingContainer'
19914};
19915
19916proto._create = function() {
19917  // get items from children
19918  this.reloadItems();
19919  // elements that affect layout, but are not laid out
19920  this.stamps = [];
19921  this.stamp( this.options.stamp );
19922  // set container style
19923  utils.extend( this.element.style, this.options.containerStyle );
19924
19925  // bind resize method
19926  var canBindResize = this._getOption('resize');
19927  if ( canBindResize ) {
19928    this.bindResize();
19929  }
19930};
19931
19932// goes through all children again and gets bricks in proper order
19933proto.reloadItems = function() {
19934  // collection of item elements
19935  this.items = this._itemize( this.element.children );
19936};
19937
19938
19939/**
19940 * turn elements into Outlayer.Items to be used in layout
19941 * @param {Array or NodeList or HTMLElement} elems
19942 * @returns {Array} items - collection of new Outlayer Items
19943 */
19944proto._itemize = function( elems ) {
19945
19946  var itemElems = this._filterFindItemElements( elems );
19947  var Item = this.constructor.Item;
19948
19949  // create new Outlayer Items for collection
19950  var items = [];
19951  for ( var i=0; i < itemElems.length; i++ ) {
19952    var elem = itemElems[i];
19953    var item = new Item( elem, this );
19954    items.push( item );
19955  }
19956
19957  return items;
19958};
19959
19960/**
19961 * get item elements to be used in layout
19962 * @param {Array or NodeList or HTMLElement} elems
19963 * @returns {Array} items - item elements
19964 */
19965proto._filterFindItemElements = function( elems ) {
19966  return utils.filterFindElements( elems, this.options.itemSelector );
19967};
19968
19969/**
19970 * getter method for getting item elements
19971 * @returns {Array} elems - collection of item elements
19972 */
19973proto.getItemElements = function() {
19974  return this.items.map( function( item ) {
19975    return item.element;
19976  });
19977};
19978
19979// ----- init & layout ----- //
19980
19981/**
19982 * lays out all items
19983 */
19984proto.layout = function() {
19985  this._resetLayout();
19986  this._manageStamps();
19987
19988  // don't animate first layout
19989  var layoutInstant = this._getOption('layoutInstant');
19990  var isInstant = layoutInstant !== undefined ?
19991    layoutInstant : !this._isLayoutInited;
19992  this.layoutItems( this.items, isInstant );
19993
19994  // flag for initalized
19995  this._isLayoutInited = true;
19996};
19997
19998// _init is alias for layout
19999proto._init = proto.layout;
20000
20001/**
20002 * logic before any new layout
20003 */
20004proto._resetLayout = function() {
vendor: 13,499 bytes, lines 20005-20573
20005  this.getSize();
20006};
20007
20008
20009proto.getSize = function() {
20010  this.size = getSize( this.element );
20011};
20012
20013/**
20014 * get measurement from option, for columnWidth, rowHeight, gutter
20015 * if option is String -> get element from selector string, & get size of element
20016 * if option is Element -> get size of element
20017 * else use option as a number
20018 *
20019 * @param {String} measurement
20020 * @param {String} size - width or height
20021 * @private
20022 */
20023proto._getMeasurement = function( measurement, size ) {
20024  var option = this.options[ measurement ];
20025  var elem;
20026  if ( !option ) {
20027    // default to 0
20028    this[ measurement ] = 0;
20029  } else {
20030    // use option as an element
20031    if ( typeof option == 'string' ) {
20032      elem = this.element.querySelector( option );
20033    } else if ( option instanceof HTMLElement ) {
20034      elem = option;
20035    }
20036    // use size of element, if element
20037    this[ measurement ] = elem ? getSize( elem )[ size ] : option;
20038  }
20039};
20040
20041/**
20042 * layout a collection of item elements
20043 * @api public
20044 */
20045proto.layoutItems = function( items, isInstant ) {
20046  items = this._getItemsForLayout( items );
20047
20048  this._layoutItems( items, isInstant );
20049
20050  this._postLayout();
20051};
20052
20053/**
20054 * get the items to be laid out
20055 * you may want to skip over some items
20056 * @param {Array} items
20057 * @returns {Array} items
20058 */
20059proto._getItemsForLayout = function( items ) {
20060  return items.filter( function( item ) {
20061    return !item.isIgnored;
20062  });
20063};
20064
20065/**
20066 * layout items
20067 * @param {Array} items
20068 * @param {Boolean} isInstant
20069 */
20070proto._layoutItems = function( items, isInstant ) {
20071  this._emitCompleteOnItems( 'layout', items );
20072
20073  if ( !items || !items.length ) {
20074    // no items, emit event with empty array
20075    return;
20076  }
20077
20078  var queue = [];
20079
20080  items.forEach( function( item ) {
20081    // get x/y object from method
20082    var position = this._getItemLayoutPosition( item );
20083    // enqueue
20084    position.item = item;
20085    position.isInstant = isInstant || item.isLayoutInstant;
20086    queue.push( position );
20087  }, this );
20088
20089  this._processLayoutQueue( queue );
20090};
20091
20092/**
20093 * get item layout position
20094 * @param {Outlayer.Item} item
20095 * @returns {Object} x and y position
20096 */
20097proto._getItemLayoutPosition = function( /* item */ ) {
20098  return {
20099    x: 0,
20100    y: 0
20101  };
20102};
20103
20104/**
20105 * iterate over array and position each item
20106 * Reason being - separating this logic prevents 'layout invalidation'
20107 * thx @paul_irish
20108 * @param {Array} queue
20109 */
20110proto._processLayoutQueue = function( queue ) {
20111  this.updateStagger();
20112  queue.forEach( function( obj, i ) {
20113    this._positionItem( obj.item, obj.x, obj.y, obj.isInstant, i );
20114  }, this );
20115};
20116
20117// set stagger from option in milliseconds number
20118proto.updateStagger = function() {
20119  var stagger = this.options.stagger;
20120  if ( stagger === null || stagger === undefined ) {
20121    this.stagger = 0;
20122    return;
20123  }
20124  this.stagger = getMilliseconds( stagger );
20125  return this.stagger;
20126};
20127
20128/**
20129 * Sets position of item in DOM
20130 * @param {Outlayer.Item} item
20131 * @param {Number} x - horizontal position
20132 * @param {Number} y - vertical position
20133 * @param {Boolean} isInstant - disables transitions
20134 */
20135proto._positionItem = function( item, x, y, isInstant, i ) {
20136  if ( isInstant ) {
20137    // if not transition, just set CSS
20138    item.goTo( x, y );
20139  } else {
20140    item.stagger( i * this.stagger );
20141    item.moveTo( x, y );
20142  }
20143};
20144
20145/**
20146 * Any logic you want to do after each layout,
20147 * i.e. size the container
20148 */
20149proto._postLayout = function() {
20150  this.resizeContainer();
20151};
20152
20153proto.resizeContainer = function() {
20154  var isResizingContainer = this._getOption('resizeContainer');
20155  if ( !isResizingContainer ) {
20156    return;
20157  }
20158  var size = this._getContainerSize();
20159  if ( size ) {
20160    this._setContainerMeasure( size.width, true );
20161    this._setContainerMeasure( size.height, false );
20162  }
20163};
20164
20165/**
20166 * Sets width or height of container if returned
20167 * @returns {Object} size
20168 *   @param {Number} width
20169 *   @param {Number} height
20170 */
20171proto._getContainerSize = noop;
20172
20173/**
20174 * @param {Number} measure - size of width or height
20175 * @param {Boolean} isWidth
20176 */
20177proto._setContainerMeasure = function( measure, isWidth ) {
20178  if ( measure === undefined ) {
20179    return;
20180  }
20181
20182  var elemSize = this.size;
20183  // add padding and border width if border box
20184  if ( elemSize.isBorderBox ) {
20185    measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight +
20186      elemSize.borderLeftWidth + elemSize.borderRightWidth :
20187      elemSize.paddingBottom + elemSize.paddingTop +
20188      elemSize.borderTopWidth + elemSize.borderBottomWidth;
20189  }
20190
20191  measure = Math.max( measure, 0 );
20192  this.element.style[ isWidth ? 'width' : 'height' ] = measure + 'px';
20193};
20194
20195/**
20196 * emit eventComplete on a collection of items events
20197 * @param {String} eventName
20198 * @param {Array} items - Outlayer.Items
20199 */
20200proto._emitCompleteOnItems = function( eventName, items ) {
20201  var _this = this;
20202  function onComplete() {
20203    _this.dispatchEvent( eventName + 'Complete', null, [ items ] );
20204  }
20205
20206  var count = items.length;
20207  if ( !items || !count ) {
20208    onComplete();
20209    return;
20210  }
20211
20212  var doneCount = 0;
20213  function tick() {
20214    doneCount++;
20215    if ( doneCount == count ) {
20216      onComplete();
20217    }
20218  }
20219
20220  // bind callback
20221  items.forEach( function( item ) {
20222    item.once( eventName, tick );
20223  });
20224};
20225
20226/**
20227 * emits events via EvEmitter and jQuery events
20228 * @param {String} type - name of event
20229 * @param {Event} event - original event
20230 * @param {Array} args - extra arguments
20231 */
20232proto.dispatchEvent = function( type, event, args ) {
20233  // add original event to arguments
20234  var emitArgs = event ? [ event ].concat( args ) : args;
20235  this.emitEvent( type, emitArgs );
20236
20237  if ( jQuery ) {
20238    // set this.$element
20239    this.$element = this.$element || jQuery( this.element );
20240    if ( event ) {
20241      // create jQuery event
20242      var $event = jQuery.Event( event );
20243      $event.type = type;
20244      this.$element.trigger( $event, args );
20245    } else {
20246      // just trigger with type if no event available
20247      this.$element.trigger( type, args );
20248    }
20249  }
20250};
20251
20252// -------------------------- ignore & stamps -------------------------- //
20253
20254
20255/**
20256 * keep item in collection, but do not lay it out
20257 * ignored items do not get skipped in layout
20258 * @param {Element} elem
20259 */
20260proto.ignore = function( elem ) {
20261  var item = this.getItem( elem );
20262  if ( item ) {
20263    item.isIgnored = true;
20264  }
20265};
20266
20267/**
20268 * return item to layout collection
20269 * @param {Element} elem
20270 */
20271proto.unignore = function( elem ) {
20272  var item = this.getItem( elem );
20273  if ( item ) {
20274    delete item.isIgnored;
20275  }
20276};
20277
20278/**
20279 * adds elements to stamps
20280 * @param {NodeList, Array, Element, or String} elems
20281 */
20282proto.stamp = function( elems ) {
20283  elems = this._find( elems );
20284  if ( !elems ) {
20285    return;
20286  }
20287
20288  this.stamps = this.stamps.concat( elems );
20289  // ignore
20290  elems.forEach( this.ignore, this );
20291};
20292
20293/**
20294 * removes elements to stamps
20295 * @param {NodeList, Array, or Element} elems
20296 */
20297proto.unstamp = function( elems ) {
20298  elems = this._find( elems );
20299  if ( !elems ){
20300    return;
20301  }
20302
20303  elems.forEach( function( elem ) {
20304    // filter out removed stamp elements
20305    utils.removeFrom( this.stamps, elem );
20306    this.unignore( elem );
20307  }, this );
20308};
20309
20310/**
20311 * finds child elements
20312 * @param {NodeList, Array, Element, or String} elems
20313 * @returns {Array} elems
20314 */
20315proto._find = function( elems ) {
20316  if ( !elems ) {
20317    return;
20318  }
20319  // if string, use argument as selector string
20320  if ( typeof elems == 'string' ) {
20321    elems = this.element.querySelectorAll( elems );
20322  }
20323  elems = utils.makeArray( elems );
20324  return elems;
20325};
20326
20327proto._manageStamps = function() {
20328  if ( !this.stamps || !this.stamps.length ) {
20329    return;
20330  }
20331
20332  this._getBoundingRect();
20333
20334  this.stamps.forEach( this._manageStamp, this );
20335};
20336
20337// update boundingLeft / Top
20338proto._getBoundingRect = function() {
20339  // get bounding rect for container element
20340  var boundingRect = this.element.getBoundingClientRect();
20341  var size = this.size;
20342  this._boundingRect = {
20343    left: boundingRect.left + size.paddingLeft + size.borderLeftWidth,
20344    top: boundingRect.top + size.paddingTop + size.borderTopWidth,
20345    right: boundingRect.right - ( size.paddingRight + size.borderRightWidth ),
20346    bottom: boundingRect.bottom - ( size.paddingBottom + size.borderBottomWidth )
20347  };
20348};
20349
20350/**
20351 * @param {Element} stamp
20352**/
20353proto._manageStamp = noop;
20354
20355/**
20356 * get x/y position of element relative to container element
20357 * @param {Element} elem
20358 * @returns {Object} offset - has left, top, right, bottom
20359 */
20360proto._getElementOffset = function( elem ) {
20361  var boundingRect = elem.getBoundingClientRect();
20362  var thisRect = this._boundingRect;
20363  var size = getSize( elem );
20364  var offset = {
20365    left: boundingRect.left - thisRect.left - size.marginLeft,
20366    top: boundingRect.top - thisRect.top - size.marginTop,
20367    right: thisRect.right - boundingRect.right - size.marginRight,
20368    bottom: thisRect.bottom - boundingRect.bottom - size.marginBottom
20369  };
20370  return offset;
20371};
20372
20373// -------------------------- resize -------------------------- //
20374
20375// enable event handlers for listeners
20376// i.e. resize -> onresize
20377proto.handleEvent = utils.handleEvent;
20378
20379/**
20380 * Bind layout to window resizing
20381 */
20382proto.bindResize = function() {
20383  window.addEventListener( 'resize', this );
20384  this.isResizeBound = true;
20385};
20386
20387/**
20388 * Unbind layout to window resizing
20389 */
20390proto.unbindResize = function() {
20391  window.removeEventListener( 'resize', this );
20392  this.isResizeBound = false;
20393};
20394
20395proto.onresize = function() {
20396  this.resize();
20397};
20398
20399utils.debounceMethod( Outlayer, 'onresize', 100 );
20400
20401proto.resize = function() {
20402  // don't trigger if size did not change
20403  // or if resize was unbound. See #9
20404  if ( !this.isResizeBound || !this.needsResizeLayout() ) {
20405    return;
20406  }
20407
20408  this.layout();
20409};
20410
20411/**
20412 * check if layout is needed post layout
20413 * @returns Boolean
20414 */
20415proto.needsResizeLayout = function() {
20416  var size = getSize( this.element );
20417  // check that this.size and size are there
20418  // IE8 triggers resize on body size change, so they might not be
20419  var hasSizes = this.size && size;
20420  return hasSizes && size.innerWidth !== this.size.innerWidth;
20421};
20422
20423// -------------------------- methods -------------------------- //
20424
20425/**
20426 * add items to Outlayer instance
20427 * @param {Array or NodeList or Element} elems
20428 * @returns {Array} items - Outlayer.Items
20429**/
20430proto.addItems = function( elems ) {
20431  var items = this._itemize( elems );
20432  // add items to collection
20433  if ( items.length ) {
20434    this.items = this.items.concat( items );
20435  }
20436  return items;
20437};
20438
20439/**
20440 * Layout newly-appended item elements
20441 * @param {Array or NodeList or Element} elems
20442 */
20443proto.appended = function( elems ) {
20444  var items = this.addItems( elems );
20445  if ( !items.length ) {
20446    return;
20447  }
20448  // layout and reveal just the new items
20449  this.layoutItems( items, true );
20450  this.reveal( items );
20451};
20452
20453/**
20454 * Layout prepended elements
20455 * @param {Array or NodeList or Element} elems
20456 */
20457proto.prepended = function( elems ) {
20458  var items = this._itemize( elems );
20459  if ( !items.length ) {
20460    return;
20461  }
20462  // add items to beginning of collection
20463  var previousItems = this.items.slice(0);
20464  this.items = items.concat( previousItems );
20465  // start new layout
20466  this._resetLayout();
20467  this._manageStamps();
20468  // layout new stuff without transition
20469  this.layoutItems( items, true );
20470  this.reveal( items );
20471  // layout previous items
20472  this.layoutItems( previousItems );
20473};
20474
20475/**
20476 * reveal a collection of items
20477 * @param {Array of Outlayer.Items} items
20478 */
20479proto.reveal = function( items ) {
20480  this._emitCompleteOnItems( 'reveal', items );
20481  if ( !items || !items.length ) {
20482    return;
20483  }
20484  var stagger = this.updateStagger();
20485  items.forEach( function( item, i ) {
20486    item.stagger( i * stagger );
20487    item.reveal();
20488  });
20489};
20490
20491/**
20492 * hide a collection of items
20493 * @param {Array of Outlayer.Items} items
20494 */
20495proto.hide = function( items ) {
20496  this._emitCompleteOnItems( 'hide', items );
20497  if ( !items || !items.length ) {
20498    return;
20499  }
20500  var stagger = this.updateStagger();
20501  items.forEach( function( item, i ) {
20502    item.stagger( i * stagger );
20503    item.hide();
20504  });
20505};
20506
20507/**
20508 * reveal item elements
20509 * @param {Array}, {Element}, {NodeList} items
20510 */
20511proto.revealItemElements = function( elems ) {
20512  var items = this.getItems( elems );
20513  this.reveal( items );
20514};
20515
20516/**
20517 * hide item elements
20518 * @param {Array}, {Element}, {NodeList} items
20519 */
20520proto.hideItemElements = function( elems ) {
20521  var items = this.getItems( elems );
20522  this.hide( items );
20523};
20524
20525/**
20526 * get Outlayer.Item, given an Element
20527 * @param {Element} elem
20528 * @param {Function} callback
20529 * @returns {Outlayer.Item} item
20530 */
20531proto.getItem = function( elem ) {
20532  // loop through items to get the one that matches
20533  for ( var i=0; i < this.items.length; i++ ) {
20534    var item = this.items[i];
20535    if ( item.element == elem ) {
20536      // return item
20537      return item;
20538    }
20539  }
20540};
20541
20542/**
20543 * get collection of Outlayer.Items, given Elements
20544 * @param {Array} elems
20545 * @returns {Array} items - Outlayer.Items
20546 */
20547proto.getItems = function( elems ) {
20548  elems = utils.makeArray( elems );
20549  var items = [];
20550  elems.forEach( function( elem ) {
20551    var item = this.getItem( elem );
20552    if ( item ) {
20553      items.push( item );
20554    }
20555  }, this );
20556
20557  return items;
20558};
20559
20560/**
20561 * remove element(s) from instance and DOM
20562 * @param {Array or NodeList or Element} elems
20563 */
20564proto.remove = function( elems ) {
20565  var removeItems = this.getItems( elems );
20566
20567  this._emitCompleteOnItems( 'remove', removeItems );
20568
20569  // bail if no items to remove
20570  if ( !removeItems || !removeItems.length ) {
20571    return;
20572  }
20573
vendor: 38,285 bytes, lines 20574-21997
20574  removeItems.forEach( function( item ) {
20575    item.remove();
20576    // remove item from collection
20577    utils.removeFrom( this.items, item );
20578  }, this );
20579};
20580
20581// ----- destroy ----- //
20582
20583// remove and disable Outlayer instance
20584proto.destroy = function() {
20585  // clean up dynamic styles
20586  var style = this.element.style;
20587  style.height = '';
20588  style.position = '';
20589  style.width = '';
20590  // destroy items
20591  this.items.forEach( function( item ) {
20592    item.destroy();
20593  });
20594
20595  this.unbindResize();
20596
20597  var id = this.element.outlayerGUID;
20598  delete instances[ id ]; // remove reference to instance by id
20599  delete this.element.outlayerGUID;
20600  // remove data for jQuery
20601  if ( jQuery ) {
20602    jQuery.removeData( this.element, this.constructor.namespace );
20603  }
20604
20605};
20606
20607// -------------------------- data -------------------------- //
20608
20609/**
20610 * get Outlayer instance from element
20611 * @param {Element} elem
20612 * @returns {Outlayer}
20613 */
20614Outlayer.data = function( elem ) {
20615  elem = utils.getQueryElement( elem );
20616  var id = elem && elem.outlayerGUID;
20617  return id && instances[ id ];
20618};
20619
20620
20621// -------------------------- create Outlayer class -------------------------- //
20622
20623/**
20624 * create a layout class
20625 * @param {String} namespace
20626 */
20627Outlayer.create = function( namespace, options ) {
20628  // sub-class Outlayer
20629  var Layout = subclass( Outlayer );
20630  // apply new options and compatOptions
20631  Layout.defaults = utils.extend( {}, Outlayer.defaults );
20632  utils.extend( Layout.defaults, options );
20633  Layout.compatOptions = utils.extend( {}, Outlayer.compatOptions  );
20634
20635  Layout.namespace = namespace;
20636
20637  Layout.data = Outlayer.data;
20638
20639  // sub-class Item
20640  Layout.Item = subclass( Item );
20641
20642  // -------------------------- declarative -------------------------- //
20643
20644  utils.htmlInit( Layout, namespace );
20645
20646  // -------------------------- jQuery bridge -------------------------- //
20647
20648  // make into jQuery plugin
20649  if ( jQuery && jQuery.bridget ) {
20650    jQuery.bridget( namespace, Layout );
20651  }
20652
20653  return Layout;
20654};
20655
20656function subclass( Parent ) {
20657  function SubClass() {
20658    Parent.apply( this, arguments );
20659  }
20660
20661  SubClass.prototype = Object.create( Parent.prototype );
20662  SubClass.prototype.constructor = SubClass;
20663
20664  return SubClass;
20665}
20666
20667// ----- helpers ----- //
20668
20669// how many milliseconds are in each unit
20670var msUnits = {
20671  ms: 1,
20672  s: 1000
20673};
20674
20675// munge time-like parameter into millisecond number
20676// '0.4s' -> 40
20677function getMilliseconds( time ) {
20678  if ( typeof time == 'number' ) {
20679    return time;
20680  }
20681  var matches = time.match( /(^\d*\.?\d*)(\w*)/ );
20682  var num = matches && matches[1];
20683  var unit = matches && matches[2];
20684  if ( !num.length ) {
20685    return 0;
20686  }
20687  num = parseFloat( num );
20688  var mult = msUnits[ unit ] || 1;
20689  return num * mult;
20690}
20691
20692// ----- fin ----- //
20693
20694// back in global
20695Outlayer.Item = Item;
20696
20697return Outlayer;
20698
20699}));
20700
20701/**
20702 * Isotope Item
20703**/
20704
20705( function( window, factory ) {
20706  // universal module definition
20707  /* jshint strict: false */ /*globals define, module, require */
20708  if ( typeof define == 'function' && define.amd ) {
20709    // AMD
20710    define( 'isotope-layout/js/item',[
20711        'outlayer/outlayer'
20712      ],
20713      factory );
20714  } else if ( typeof module == 'object' && module.exports ) {
20715    // CommonJS
20716    module.exports = factory(
20717      require('outlayer')
20718    );
20719  } else {
20720    // browser global
20721    window.Isotope = window.Isotope || {};
20722    window.Isotope.Item = factory(
20723      window.Outlayer
20724    );
20725  }
20726
20727}( window, function factory( Outlayer ) {
20728'use strict';
20729
20730// -------------------------- Item -------------------------- //
20731
20732// sub-class Outlayer Item
20733function Item() {
20734  Outlayer.Item.apply( this, arguments );
20735}
20736
20737var proto = Item.prototype = Object.create( Outlayer.Item.prototype );
20738
20739var _create = proto._create;
20740proto._create = function() {
20741  // assign id, used for original-order sorting
20742  this.id = this.layout.itemGUID++;
20743  _create.call( this );
20744  this.sortData = {};
20745};
20746
20747proto.updateSortData = function() {
20748  if ( this.isIgnored ) {
20749    return;
20750  }
20751  // default sorters
20752  this.sortData.id = this.id;
20753  // for backward compatibility
20754  this.sortData['original-order'] = this.id;
20755  this.sortData.random = Math.random();
20756  // go thru getSortData obj and apply the sorters
20757  var getSortData = this.layout.options.getSortData;
20758  var sorters = this.layout._sorters;
20759  for ( var key in getSortData ) {
20760    var sorter = sorters[ key ];
20761    this.sortData[ key ] = sorter( this.element, this );
20762  }
20763};
20764
20765var _destroy = proto.destroy;
20766proto.destroy = function() {
20767  // call super
20768  _destroy.apply( this, arguments );
20769  // reset display, #741
20770  this.css({
20771    display: ''
20772  });
20773};
20774
20775return Item;
20776
20777}));
20778
20779/**
20780 * Isotope LayoutMode
20781 */
20782
20783( function( window, factory ) {
20784  // universal module definition
20785  /* jshint strict: false */ /*globals define, module, require */
20786  if ( typeof define == 'function' && define.amd ) {
20787    // AMD
20788    define( 'isotope-layout/js/layout-mode',[
20789        'get-size/get-size',
20790        'outlayer/outlayer'
20791      ],
20792      factory );
20793  } else if ( typeof module == 'object' && module.exports ) {
20794    // CommonJS
20795    module.exports = factory(
20796      require('get-size'),
20797      require('outlayer')
20798    );
20799  } else {
20800    // browser global
20801    window.Isotope = window.Isotope || {};
20802    window.Isotope.LayoutMode = factory(
20803      window.getSize,
20804      window.Outlayer
20805    );
20806  }
20807
20808}( window, function factory( getSize, Outlayer ) {
20809  'use strict';
20810
20811  // layout mode class
20812  function LayoutMode( isotope ) {
20813    this.isotope = isotope;
20814    // link properties
20815    if ( isotope ) {
20816      this.options = isotope.options[ this.namespace ];
20817      this.element = isotope.element;
20818      this.items = isotope.filteredItems;
20819      this.size = isotope.size;
20820    }
20821  }
20822
20823  var proto = LayoutMode.prototype;
20824
20825  /**
20826   * some methods should just defer to default Outlayer method
20827   * and reference the Isotope instance as `this`
20828  **/
20829  var facadeMethods = [
20830    '_resetLayout',
20831    '_getItemLayoutPosition',
20832    '_manageStamp',
20833    '_getContainerSize',
20834    '_getElementOffset',
20835    'needsResizeLayout',
20836    '_getOption'
20837  ];
20838
20839  facadeMethods.forEach( function( methodName ) {
20840    proto[ methodName ] = function() {
20841      return Outlayer.prototype[ methodName ].apply( this.isotope, arguments );
20842    };
20843  });
20844
20845  // -----  ----- //
20846
20847  // for horizontal layout modes, check vertical size
20848  proto.needsVerticalResizeLayout = function() {
20849    // don't trigger if size did not change
20850    var size = getSize( this.isotope.element );
20851    // check that this.size and size are there
20852    // IE8 triggers resize on body size change, so they might not be
20853    var hasSizes = this.isotope.size && size;
20854    return hasSizes && size.innerHeight != this.isotope.size.innerHeight;
20855  };
20856
20857  // ----- measurements ----- //
20858
20859  proto._getMeasurement = function() {
20860    this.isotope._getMeasurement.apply( this, arguments );
20861  };
20862
20863  proto.getColumnWidth = function() {
20864    this.getSegmentSize( 'column', 'Width' );
20865  };
20866
20867  proto.getRowHeight = function() {
20868    this.getSegmentSize( 'row', 'Height' );
20869  };
20870
20871  /**
20872   * get columnWidth or rowHeight
20873   * segment: 'column' or 'row'
20874   * size 'Width' or 'Height'
20875  **/
20876  proto.getSegmentSize = function( segment, size ) {
20877    var segmentName = segment + size;
20878    var outerSize = 'outer' + size;
20879    // columnWidth / outerWidth // rowHeight / outerHeight
20880    this._getMeasurement( segmentName, outerSize );
20881    // got rowHeight or columnWidth, we can chill
20882    if ( this[ segmentName ] ) {
20883      return;
20884    }
20885    // fall back to item of first element
20886    var firstItemSize = this.getFirstItemSize();
20887    this[ segmentName ] = firstItemSize && firstItemSize[ outerSize ] ||
20888      // or size of container
20889      this.isotope.size[ 'inner' + size ];
20890  };
20891
20892  proto.getFirstItemSize = function() {
20893    var firstItem = this.isotope.filteredItems[0];
20894    return firstItem && firstItem.element && getSize( firstItem.element );
20895  };
20896
20897  // ----- methods that should reference isotope ----- //
20898
20899  proto.layout = function() {
20900    this.isotope.layout.apply( this.isotope, arguments );
20901  };
20902
20903  proto.getSize = function() {
20904    this.isotope.getSize();
20905    this.size = this.isotope.size;
20906  };
20907
20908  // -------------------------- create -------------------------- //
20909
20910  LayoutMode.modes = {};
20911
20912  LayoutMode.create = function( namespace, options ) {
20913
20914    function Mode() {
20915      LayoutMode.apply( this, arguments );
20916    }
20917
20918    Mode.prototype = Object.create( proto );
20919    Mode.prototype.constructor = Mode;
20920
20921    // default options
20922    if ( options ) {
20923      Mode.options = options;
20924    }
20925
20926    Mode.prototype.namespace = namespace;
20927    // register in Isotope
20928    LayoutMode.modes[ namespace ] = Mode;
20929
20930    return Mode;
20931  };
20932
20933  return LayoutMode;
20934
20935}));
20936
20937/*!
20938 * Masonry v4.2.1
20939 * Cascading grid layout library
20940 * https://masonry.desandro.com
20941 * MIT License
20942 * by David DeSandro
20943 */
20944
20945( function( window, factory ) {
20946  // universal module definition
20947  /* jshint strict: false */ /*globals define, module, require */
20948  if ( typeof define == 'function' && define.amd ) {
20949    // AMD
20950    define( 'masonry-layout/masonry',[
20951        'outlayer/outlayer',
20952        'get-size/get-size'
20953      ],
20954      factory );
20955  } else if ( typeof module == 'object' && module.exports ) {
20956    // CommonJS
20957    module.exports = factory(
20958      require('outlayer'),
20959      require('get-size')
20960    );
20961  } else {
20962    // browser global
20963    window.Masonry = factory(
20964      window.Outlayer,
20965      window.getSize
20966    );
20967  }
20968
20969}( window, function factory( Outlayer, getSize ) {
20970
20971
20972
20973// -------------------------- masonryDefinition -------------------------- //
20974
20975  // create an Outlayer layout class
20976  var Masonry = Outlayer.create('masonry');
20977  // isFitWidth -> fitWidth
20978  Masonry.compatOptions.fitWidth = 'isFitWidth';
20979
20980  var proto = Masonry.prototype;
20981
20982  proto._resetLayout = function() {
20983    this.getSize();
20984    this._getMeasurement( 'columnWidth', 'outerWidth' );
20985    this._getMeasurement( 'gutter', 'outerWidth' );
20986    this.measureColumns();
20987
20988    // reset column Y
20989    this.colYs = [];
20990    for ( var i=0; i < this.cols; i++ ) {
20991      this.colYs.push( 0 );
20992    }
20993
20994    this.maxY = 0;
20995    this.horizontalColIndex = 0;
20996  };
20997
20998  proto.measureColumns = function() {
20999    this.getContainerWidth();
21000    // if columnWidth is 0, default to outerWidth of first item
21001    if ( !this.columnWidth ) {
21002      var firstItem = this.items[0];
21003      var firstItemElem = firstItem && firstItem.element;
21004      // columnWidth fall back to item of first element
21005      this.columnWidth = firstItemElem && getSize( firstItemElem ).outerWidth ||
21006        // if first elem has no width, default to size of container
21007        this.containerWidth;
21008    }
21009
21010    var columnWidth = this.columnWidth += this.gutter;
21011
21012    // calculate columns
21013    var containerWidth = this.containerWidth + this.gutter;
21014    var cols = containerWidth / columnWidth;
21015    // fix rounding errors, typically with gutters
21016    var excess = columnWidth - containerWidth % columnWidth;
21017    // if overshoot is less than a pixel, round up, otherwise floor it
21018    var mathMethod = excess && excess < 1 ? 'round' : 'floor';
21019    cols = Math[ mathMethod ]( cols );
21020    this.cols = Math.max( cols, 1 );
21021  };
21022
21023  proto.getContainerWidth = function() {
21024    // container is parent if fit width
21025    var isFitWidth = this._getOption('fitWidth');
21026    var container = isFitWidth ? this.element.parentNode : this.element;
21027    // check that this.size and size are there
21028    // IE8 triggers resize on body size change, so they might not be
21029    var size = getSize( container );
21030    this.containerWidth = size && size.innerWidth;
21031  };
21032
21033  proto._getItemLayoutPosition = function( item ) {
21034    item.getSize();
21035    // how many columns does this brick span
21036    var remainder = item.size.outerWidth % this.columnWidth;
21037    var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil';
21038    // round if off by 1 pixel, otherwise use ceil
21039    var colSpan = Math[ mathMethod ]( item.size.outerWidth / this.columnWidth );
21040    colSpan = Math.min( colSpan, this.cols );
21041    // use horizontal or top column position
21042    var colPosMethod = this.options.horizontalOrder ?
21043      '_getHorizontalColPosition' : '_getTopColPosition';
21044    var colPosition = this[ colPosMethod ]( colSpan, item );
21045    // position the brick
21046    var position = {
21047      x: this.columnWidth * colPosition.col,
21048      y: colPosition.y
21049    };
21050    // apply setHeight to necessary columns
21051    var setHeight = colPosition.y + item.size.outerHeight;
21052    var setMax = colSpan + colPosition.col;
21053    for ( var i = colPosition.col; i < setMax; i++ ) {
21054      this.colYs[i] = setHeight;
21055    }
21056
21057    return position;
21058  };
21059
21060  proto._getTopColPosition = function( colSpan ) {
21061    var colGroup = this._getTopColGroup( colSpan );
21062    // get the minimum Y value from the columns
21063    var minimumY = Math.min.apply( Math, colGroup );
21064
21065    return {
21066      col: colGroup.indexOf( minimumY ),
21067      y: minimumY,
21068    };
21069  };
21070
21071  /**
21072   * @param {Number} colSpan - number of columns the element spans
21073   * @returns {Array} colGroup
21074   */
21075  proto._getTopColGroup = function( colSpan ) {
21076    if ( colSpan < 2 ) {
21077      // if brick spans only one column, use all the column Ys
21078      return this.colYs;
21079    }
21080
21081    var colGroup = [];
21082    // how many different places could this brick fit horizontally
21083    var groupCount = this.cols + 1 - colSpan;
21084    // for each group potential horizontal position
21085    for ( var i = 0; i < groupCount; i++ ) {
21086      colGroup[i] = this._getColGroupY( i, colSpan );
21087    }
21088    return colGroup;
21089  };
21090
21091  proto._getColGroupY = function( col, colSpan ) {
21092    if ( colSpan < 2 ) {
21093      return this.colYs[ col ];
21094    }
21095    // make an array of colY values for that one group
21096    var groupColYs = this.colYs.slice( col, col + colSpan );
21097    // and get the max value of the array
21098    return Math.max.apply( Math, groupColYs );
21099  };
21100
21101  // get column position based on horizontal index. #873
21102  proto._getHorizontalColPosition = function( colSpan, item ) {
21103    var col = this.horizontalColIndex % this.cols;
21104    var isOver = colSpan > 1 && col + colSpan > this.cols;
21105    // shift to next row if item can't fit on current row
21106    col = isOver ? 0 : col;
21107    // don't let zero-size items take up space
21108    var hasSize = item.size.outerWidth && item.size.outerHeight;
21109    this.horizontalColIndex = hasSize ? col + colSpan : this.horizontalColIndex;
21110
21111    return {
21112      col: col,
21113      y: this._getColGroupY( col, colSpan ),
21114    };
21115  };
21116
21117  proto._manageStamp = function( stamp ) {
21118    var stampSize = getSize( stamp );
21119    var offset = this._getElementOffset( stamp );
21120    // get the columns that this stamp affects
21121    var isOriginLeft = this._getOption('originLeft');
21122    var firstX = isOriginLeft ? offset.left : offset.right;
21123    var lastX = firstX + stampSize.outerWidth;
21124    var firstCol = Math.floor( firstX / this.columnWidth );
21125    firstCol = Math.max( 0, firstCol );
21126    var lastCol = Math.floor( lastX / this.columnWidth );
21127    // lastCol should not go over if multiple of columnWidth #425
21128    lastCol -= lastX % this.columnWidth ? 0 : 1;
21129    lastCol = Math.min( this.cols - 1, lastCol );
21130    // set colYs to bottom of the stamp
21131
21132    var isOriginTop = this._getOption('originTop');
21133    var stampMaxY = ( isOriginTop ? offset.top : offset.bottom ) +
21134      stampSize.outerHeight;
21135    for ( var i = firstCol; i <= lastCol; i++ ) {
21136      this.colYs[i] = Math.max( stampMaxY, this.colYs[i] );
21137    }
21138  };
21139
21140  proto._getContainerSize = function() {
21141    this.maxY = Math.max.apply( Math, this.colYs );
21142    var size = {
21143      height: this.maxY
21144    };
21145
21146    if ( this._getOption('fitWidth') ) {
21147      size.width = this._getContainerFitWidth();
21148    }
21149
21150    return size;
21151  };
21152
21153  proto._getContainerFitWidth = function() {
21154    var unusedCols = 0;
21155    // count unused columns
21156    var i = this.cols;
21157    while ( --i ) {
21158      if ( this.colYs[i] !== 0 ) {
21159        break;
21160      }
21161      unusedCols++;
21162    }
21163    // fit container to columns that have been used
21164    return ( this.cols - unusedCols ) * this.columnWidth - this.gutter;
21165  };
21166
21167  proto.needsResizeLayout = function() {
21168    var previousWidth = this.containerWidth;
21169    this.getContainerWidth();
21170    return previousWidth != this.containerWidth;
21171  };
21172
21173  return Masonry;
21174
21175}));
21176
21177/*!
21178 * Masonry layout mode
21179 * sub-classes Masonry
21180 * https://masonry.desandro.com
21181 */
21182
21183( function( window, factory ) {
21184  // universal module definition
21185  /* jshint strict: false */ /*globals define, module, require */
21186  if ( typeof define == 'function' && define.amd ) {
21187    // AMD
21188    define( 'isotope-layout/js/layout-modes/masonry',[
21189        '../layout-mode',
21190        'masonry-layout/masonry'
21191      ],
21192      factory );
21193  } else if ( typeof module == 'object' && module.exports ) {
21194    // CommonJS
21195    module.exports = factory(
21196      require('../layout-mode'),
21197      require('masonry-layout')
21198    );
21199  } else {
21200    // browser global
21201    factory(
21202      window.Isotope.LayoutMode,
21203      window.Masonry
21204    );
21205  }
21206
21207}( window, function factory( LayoutMode, Masonry ) {
21208'use strict';
21209
21210// -------------------------- masonryDefinition -------------------------- //
21211
21212  // create an Outlayer layout class
21213  var MasonryMode = LayoutMode.create('masonry');
21214
21215  var proto = MasonryMode.prototype;
21216
21217  var keepModeMethods = {
21218    _getElementOffset: true,
21219    layout: true,
21220    _getMeasurement: true
21221  };
21222
21223  // inherit Masonry prototype
21224  for ( var method in Masonry.prototype ) {
21225    // do not inherit mode methods
21226    if ( !keepModeMethods[ method ] ) {
21227      proto[ method ] = Masonry.prototype[ method ];
21228    }
21229  }
21230
21231  var measureColumns = proto.measureColumns;
21232  proto.measureColumns = function() {
21233    // set items, used if measuring first item
21234    this.items = this.isotope.filteredItems;
21235    measureColumns.call( this );
21236  };
21237
21238  // point to mode options for fitWidth
21239  var _getOption = proto._getOption;
21240  proto._getOption = function( option ) {
21241    if ( option == 'fitWidth' ) {
21242      return this.options.isFitWidth !== undefined ?
21243        this.options.isFitWidth : this.options.fitWidth;
21244    }
21245    return _getOption.apply( this.isotope, arguments );
21246  };
21247
21248  return MasonryMode;
21249
21250}));
21251
21252/**
21253 * fitRows layout mode
21254 */
21255
21256( function( window, factory ) {
21257  // universal module definition
21258  /* jshint strict: false */ /*globals define, module, require */
21259  if ( typeof define == 'function' && define.amd ) {
21260    // AMD
21261    define( 'isotope-layout/js/layout-modes/fit-rows',[
21262        '../layout-mode'
21263      ],
21264      factory );
21265  } else if ( typeof exports == 'object' ) {
21266    // CommonJS
21267    module.exports = factory(
21268      require('../layout-mode')
21269    );
21270  } else {
21271    // browser global
21272    factory(
21273      window.Isotope.LayoutMode
21274    );
21275  }
21276
21277}( window, function factory( LayoutMode ) {
21278'use strict';
21279
21280var FitRows = LayoutMode.create('fitRows');
21281
21282var proto = FitRows.prototype;
21283
21284proto._resetLayout = function() {
21285  this.x = 0;
21286  this.y = 0;
21287  this.maxY = 0;
21288  this._getMeasurement( 'gutter', 'outerWidth' );
21289};
21290
21291proto._getItemLayoutPosition = function( item ) {
21292  item.getSize();
21293
21294  var itemWidth = item.size.outerWidth + this.gutter;
21295  // if this element cannot fit in the current row
21296  var containerWidth = this.isotope.size.innerWidth + this.gutter;
21297  if ( this.x !== 0 && itemWidth + this.x > containerWidth ) {
21298    this.x = 0;
21299    this.y = this.maxY;
21300  }
21301
21302  var position = {
21303    x: this.x,
21304    y: this.y
21305  };
21306
21307  this.maxY = Math.max( this.maxY, this.y + item.size.outerHeight );
21308  this.x += itemWidth;
21309
21310  return position;
21311};
21312
21313proto._getContainerSize = function() {
21314  return { height: this.maxY };
21315};
21316
21317return FitRows;
21318
21319}));
21320
21321/**
21322 * vertical layout mode
21323 */
21324
21325( function( window, factory ) {
21326  // universal module definition
21327  /* jshint strict: false */ /*globals define, module, require */
21328  if ( typeof define == 'function' && define.amd ) {
21329    // AMD
21330    define( 'isotope-layout/js/layout-modes/vertical',[
21331        '../layout-mode'
21332      ],
21333      factory );
21334  } else if ( typeof module == 'object' && module.exports ) {
21335    // CommonJS
21336    module.exports = factory(
21337      require('../layout-mode')
21338    );
21339  } else {
21340    // browser global
21341    factory(
21342      window.Isotope.LayoutMode
21343    );
21344  }
21345
21346}( window, function factory( LayoutMode ) {
21347'use strict';
21348
21349var Vertical = LayoutMode.create( 'vertical', {
21350  horizontalAlignment: 0
21351});
21352
21353var proto = Vertical.prototype;
21354
21355proto._resetLayout = function() {
21356  this.y = 0;
21357};
21358
21359proto._getItemLayoutPosition = function( item ) {
21360  item.getSize();
21361  var x = ( this.isotope.size.innerWidth - item.size.outerWidth ) *
21362    this.options.horizontalAlignment;
21363  var y = this.y;
21364  this.y += item.size.outerHeight;
21365  return { x: x, y: y };
21366};
21367
21368proto._getContainerSize = function() {
21369  return { height: this.y };
21370};
21371
21372return Vertical;
21373
21374}));
21375
21376/*!
21377 * Isotope v3.0.6
21378 *
21379 * Licensed GPLv3 for open source use
21380 * or Isotope Commercial License for commercial use
21381 *
21382 * https://isotope.metafizzy.co
21383 * Copyright 2010-2018 Metafizzy
21384 */
21385
21386( function( window, factory ) {
21387  // universal module definition
21388  /* jshint strict: false */ /*globals define, module, require */
21389  if ( typeof define == 'function' && define.amd ) {
21390    // AMD
21391    define( [
21392        'outlayer/outlayer',
21393        'get-size/get-size',
21394        'desandro-matches-selector/matches-selector',
21395        'fizzy-ui-utils/utils',
21396        'isotope-layout/js/item',
21397        'isotope-layout/js/layout-mode',
21398        // include default layout modes
21399        'isotope-layout/js/layout-modes/masonry',
21400        'isotope-layout/js/layout-modes/fit-rows',
21401        'isotope-layout/js/layout-modes/vertical'
21402      ],
21403      function( Outlayer, getSize, matchesSelector, utils, Item, LayoutMode ) {
21404        return factory( window, Outlayer, getSize, matchesSelector, utils, Item, LayoutMode );
21405      });
21406  } else if ( typeof module == 'object' && module.exports ) {
21407    // CommonJS
21408    module.exports = factory(
21409      window,
21410      require('outlayer'),
21411      require('get-size'),
21412      require('desandro-matches-selector'),
21413      require('fizzy-ui-utils'),
21414      require('isotope-layout/js/item'),
21415      require('isotope-layout/js/layout-mode'),
21416      // include default layout modes
21417      require('isotope-layout/js/layout-modes/masonry'),
21418      require('isotope-layout/js/layout-modes/fit-rows'),
21419      require('isotope-layout/js/layout-modes/vertical')
21420    );
21421  } else {
21422    // browser global
21423    window.Isotope = factory(
21424      window,
21425      window.Outlayer,
21426      window.getSize,
21427      window.matchesSelector,
21428      window.fizzyUIUtils,
21429      window.Isotope.Item,
21430      window.Isotope.LayoutMode
21431    );
21432  }
21433
21434}( window, function factory( window, Outlayer, getSize, matchesSelector, utils,
21435  Item, LayoutMode ) {
21436
21437
21438
21439// -------------------------- vars -------------------------- //
21440
21441var jQuery = window.jQuery;
21442
21443// -------------------------- helpers -------------------------- //
21444
21445var trim = String.prototype.trim ?
21446  function( str ) {
21447    return str.trim();
21448  } :
21449  function( str ) {
21450    return str.replace( /^\s+|\s+$/g, '' );
21451  };
21452
21453// -------------------------- isotopeDefinition -------------------------- //
21454
21455  // create an Outlayer layout class
21456  var Isotope = Outlayer.create( 'isotope', {
21457    layoutMode: 'masonry',
21458    isJQueryFiltering: true,
21459    sortAscending: true
21460  });
21461
21462  Isotope.Item = Item;
21463  Isotope.LayoutMode = LayoutMode;
21464
21465  var proto = Isotope.prototype;
21466
21467  proto._create = function() {
21468    this.itemGUID = 0;
21469    // functions that sort items
21470    this._sorters = {};
21471    this._getSorters();
21472    // call super
21473    Outlayer.prototype._create.call( this );
21474
21475    // create layout modes
21476    this.modes = {};
21477    // start filteredItems with all items
21478    this.filteredItems = this.items;
21479    // keep of track of sortBys
21480    this.sortHistory = [ 'original-order' ];
21481    // create from registered layout modes
21482    for ( var name in LayoutMode.modes ) {
21483      this._initLayoutMode( name );
21484    }
21485  };
21486
21487  proto.reloadItems = function() {
21488    // reset item ID counter
21489    this.itemGUID = 0;
21490    // call super
21491    Outlayer.prototype.reloadItems.call( this );
21492  };
21493
21494  proto._itemize = function() {
21495    var items = Outlayer.prototype._itemize.apply( this, arguments );
21496    // assign ID for original-order
21497    for ( var i=0; i < items.length; i++ ) {
21498      var item = items[i];
21499      item.id = this.itemGUID++;
21500    }
21501    this._updateItemsSortData( items );
21502    return items;
21503  };
21504
21505
21506  // -------------------------- layout -------------------------- //
21507
21508  proto._initLayoutMode = function( name ) {
21509    var Mode = LayoutMode.modes[ name ];
21510    // set mode options
21511    // HACK extend initial options, back-fill in default options
21512    var initialOpts = this.options[ name ] || {};
21513    this.options[ name ] = Mode.options ?
21514      utils.extend( Mode.options, initialOpts ) : initialOpts;
21515    // init layout mode instance
21516    this.modes[ name ] = new Mode( this );
21517  };
21518
21519
21520  proto.layout = function() {
21521    // if first time doing layout, do all magic
21522    if ( !this._isLayoutInited && this._getOption('initLayout') ) {
21523      this.arrange();
21524      return;
21525    }
21526    this._layout();
21527  };
21528
21529  // private method to be used in layout() & magic()
21530  proto._layout = function() {
21531    // don't animate first layout
21532    var isInstant = this._getIsInstant();
21533    // layout flow
21534    this._resetLayout();
21535    this._manageStamps();
21536    this.layoutItems( this.filteredItems, isInstant );
21537
21538    // flag for initalized
21539    this._isLayoutInited = true;
21540  };
21541
21542  // filter + sort + layout
21543  proto.arrange = function( opts ) {
21544    // set any options pass
21545    this.option( opts );
21546    this._getIsInstant();
21547    // filter, sort, and layout
21548
21549    // filter
21550    var filtered = this._filter( this.items );
21551    this.filteredItems = filtered.matches;
21552
21553    this._bindArrangeComplete();
21554
21555    if ( this._isInstant ) {
21556      this._noTransition( this._hideReveal, [ filtered ] );
21557    } else {
21558      this._hideReveal( filtered );
21559    }
21560
21561    this._sort();
21562    this._layout();
21563  };
21564  // alias to _init for main plugin method
21565  proto._init = proto.arrange;
21566
21567  proto._hideReveal = function( filtered ) {
21568    this.reveal( filtered.needReveal );
21569    this.hide( filtered.needHide );
21570  };
21571
21572  // HACK
21573  // Don't animate/transition first layout
21574  // Or don't animate/transition other layouts
21575  proto._getIsInstant = function() {
21576    var isLayoutInstant = this._getOption('layoutInstant');
21577    var isInstant = isLayoutInstant !== undefined ? isLayoutInstant :
21578      !this._isLayoutInited;
21579    this._isInstant = isInstant;
21580    return isInstant;
21581  };
21582
21583  // listen for layoutComplete, hideComplete and revealComplete
21584  // to trigger arrangeComplete
21585  proto._bindArrangeComplete = function() {
21586    // listen for 3 events to trigger arrangeComplete
21587    var isLayoutComplete, isHideComplete, isRevealComplete;
21588    var _this = this;
21589    function arrangeParallelCallback() {
21590      if ( isLayoutComplete && isHideComplete && isRevealComplete ) {
21591        _this.dispatchEvent( 'arrangeComplete', null, [ _this.filteredItems ] );
21592      }
21593    }
21594    this.once( 'layoutComplete', function() {
21595      isLayoutComplete = true;
21596      arrangeParallelCallback();
21597    });
21598    this.once( 'hideComplete', function() {
21599      isHideComplete = true;
21600      arrangeParallelCallback();
21601    });
21602    this.once( 'revealComplete', function() {
21603      isRevealComplete = true;
21604      arrangeParallelCallback();
21605    });
21606  };
21607
21608  // -------------------------- filter -------------------------- //
21609
21610  proto._filter = function( items ) {
21611    var filter = this.options.filter;
21612    filter = filter || '*';
21613    var matches = [];
21614    var hiddenMatched = [];
21615    var visibleUnmatched = [];
21616
21617    var test = this._getFilterTest( filter );
21618
21619    // test each item
21620    for ( var i=0; i < items.length; i++ ) {
21621      var item = items[i];
21622      if ( item.isIgnored ) {
21623        continue;
21624      }
21625      // add item to either matched or unmatched group
21626      var isMatched = test( item );
21627      // item.isFilterMatched = isMatched;
21628      // add to matches if its a match
21629      if ( isMatched ) {
21630        matches.push( item );
21631      }
21632      // add to additional group if item needs to be hidden or revealed
21633      if ( isMatched && item.isHidden ) {
21634        hiddenMatched.push( item );
21635      } else if ( !isMatched && !item.isHidden ) {
21636        visibleUnmatched.push( item );
21637      }
21638    }
21639
21640    // return collections of items to be manipulated
21641    return {
21642      matches: matches,
21643      needReveal: hiddenMatched,
21644      needHide: visibleUnmatched
21645    };
21646  };
21647
21648  // get a jQuery, function, or a matchesSelector test given the filter
21649  proto._getFilterTest = function( filter ) {
21650    if ( jQuery && this.options.isJQueryFiltering ) {
21651      // use jQuery
21652      return function( item ) {
21653        return jQuery( item.element ).is( filter );
21654      };
21655    }
21656    if ( typeof filter == 'function' ) {
21657      // use filter as function
21658      return function( item ) {
21659        return filter( item.element );
21660      };
21661    }
21662    // default, use filter as selector string
21663    return function( item ) {
21664      return matchesSelector( item.element, filter );
21665    };
21666  };
21667
21668  // -------------------------- sorting -------------------------- //
21669
21670  /**
21671   * @params {Array} elems
21672   * @public
21673   */
21674  proto.updateSortData = function( elems ) {
21675    // get items
21676    var items;
21677    if ( elems ) {
21678      elems = utils.makeArray( elems );
21679      items = this.getItems( elems );
21680    } else {
21681      // update all items if no elems provided
21682      items = this.items;
21683    }
21684
21685    this._getSorters();
21686    this._updateItemsSortData( items );
21687  };
21688
21689  proto._getSorters = function() {
21690    var getSortData = this.options.getSortData;
21691    for ( var key in getSortData ) {
21692      var sorter = getSortData[ key ];
21693      this._sorters[ key ] = mungeSorter( sorter );
21694    }
21695  };
21696
21697  /**
21698   * @params {Array} items - of Isotope.Items
21699   * @private
21700   */
21701  proto._updateItemsSortData = function( items ) {
21702    // do not update if no items
21703    var len = items && items.length;
21704
21705    for ( var i=0; len && i < len; i++ ) {
21706      var item = items[i];
21707      item.updateSortData();
21708    }
21709  };
21710
21711  // ----- munge sorter ----- //
21712
21713  // encapsulate this, as we just need mungeSorter
21714  // other functions in here are just for munging
21715  var mungeSorter = ( function() {
21716    // add a magic layer to sorters for convienent shorthands
21717    // `.foo-bar` will use the text of .foo-bar querySelector
21718    // `[foo-bar]` will use attribute
21719    // you can also add parser
21720    // `.foo-bar parseInt` will parse that as a number
21721    function mungeSorter( sorter ) {
21722      // if not a string, return function or whatever it is
21723      if ( typeof sorter != 'string' ) {
21724        return sorter;
21725      }
21726      // parse the sorter string
21727      var args = trim( sorter ).split(' ');
21728      var query = args[0];
21729      // check if query looks like [an-attribute]
21730      var attrMatch = query.match( /^\[(.+)\]$/ );
21731      var attr = attrMatch && attrMatch[1];
21732      var getValue = getValueGetter( attr, query );
21733      // use second argument as a parser
21734      var parser = Isotope.sortDataParsers[ args[1] ];
21735      // parse the value, if there was a parser
21736      sorter = parser ? function( elem ) {
21737        return elem && parser( getValue( elem ) );
21738      } :
21739      // otherwise just return value
21740      function( elem ) {
21741        return elem && getValue( elem );
21742      };
21743
21744      return sorter;
21745    }
21746
21747    // get an attribute getter, or get text of the querySelector
21748    function getValueGetter( attr, query ) {
21749      // if query looks like [foo-bar], get attribute
21750      if ( attr ) {
21751        return function getAttribute( elem ) {
21752          return elem.getAttribute( attr );
21753        };
21754      }
21755
21756      // otherwise, assume its a querySelector, and get its text
21757      return function getChildText( elem ) {
21758        var child = elem.querySelector( query );
21759        return child && child.textContent;
21760      };
21761    }
21762
21763    return mungeSorter;
21764  })();
21765
21766  // parsers used in getSortData shortcut strings
21767  Isotope.sortDataParsers = {
21768    'parseInt': function( val ) {
21769      return parseInt( val, 10 );
21770    },
21771    'parseFloat': function( val ) {
21772      return parseFloat( val );
21773    }
21774  };
21775
21776  // ----- sort method ----- //
21777
21778  // sort filteredItem order
21779  proto._sort = function() {
21780    if ( !this.options.sortBy ) {
21781      return;
21782    }
21783    // keep track of sortBy History
21784    var sortBys = utils.makeArray( this.options.sortBy );
21785    if ( !this._getIsSameSortBy( sortBys ) ) {
21786      // concat all sortBy and sortHistory, add to front, oldest goes in last
21787      this.sortHistory = sortBys.concat( this.sortHistory );
21788    }
21789    // sort magic
21790    var itemSorter = getItemSorter( this.sortHistory, this.options.sortAscending );
21791    this.filteredItems.sort( itemSorter );
21792  };
21793
21794  // check if sortBys is same as start of sortHistory
21795  proto._getIsSameSortBy = function( sortBys ) {
21796    for ( var i=0; i < sortBys.length; i++ ) {
21797      if ( sortBys[i] != this.sortHistory[i] ) {
21798        return false;
21799      }
21800    }
21801    return true;
21802  };
21803
21804  // returns a function used for sorting
21805  function getItemSorter( sortBys, sortAsc ) {
21806    return function sorter( itemA, itemB ) {
21807      // cycle through all sortKeys
21808      for ( var i = 0; i < sortBys.length; i++ ) {
21809        var sortBy = sortBys[i];
21810        var a = itemA.sortData[ sortBy ];
21811        var b = itemB.sortData[ sortBy ];
21812        if ( a > b || a < b ) {
21813          // if sortAsc is an object, use the value given the sortBy key
21814          var isAscending = sortAsc[ sortBy ] !== undefined ? sortAsc[ sortBy ] : sortAsc;
21815          var direction = isAscending ? 1 : -1;
21816          return ( a > b ? 1 : -1 ) * direction;
21817        }
21818      }
21819      return 0;
21820    };
21821  }
21822
21823  // -------------------------- methods -------------------------- //
21824
21825  // get layout mode
21826  proto._mode = function() {
21827    var layoutMode = this.options.layoutMode;
21828    var mode = this.modes[ layoutMode ];
21829    if ( !mode ) {
21830      // TODO console.error
21831      throw new Error( 'No layout mode: ' + layoutMode );
21832    }
21833    // HACK sync mode's options
21834    // any options set after init for layout mode need to be synced
21835    mode.options = this.options[ layoutMode ];
21836    return mode;
21837  };
21838
21839  proto._resetLayout = function() {
21840    // trigger original reset layout
21841    Outlayer.prototype._resetLayout.call( this );
21842    this._mode()._resetLayout();
21843  };
21844
21845  proto._getItemLayoutPosition = function( item  ) {
21846    return this._mode()._getItemLayoutPosition( item );
21847  };
21848
21849  proto._manageStamp = function( stamp ) {
21850    this._mode()._manageStamp( stamp );
21851  };
21852
21853  proto._getContainerSize = function() {
21854    return this._mode()._getContainerSize();
21855  };
21856
21857  proto.needsResizeLayout = function() {
21858    return this._mode().needsResizeLayout();
21859  };
21860
21861  // -------------------------- adding & removing -------------------------- //
21862
21863  // HEADS UP overwrites default Outlayer appended
21864  proto.appended = function( elems ) {
21865    var items = this.addItems( elems );
21866    if ( !items.length ) {
21867      return;
21868    }
21869    // filter, layout, reveal new items
21870    var filteredItems = this._filterRevealAdded( items );
21871    // add to filteredItems
21872    this.filteredItems = this.filteredItems.concat( filteredItems );
21873  };
21874
21875  // HEADS UP overwrites default Outlayer prepended
21876  proto.prepended = function( elems ) {
21877    var items = this._itemize( elems );
21878    if ( !items.length ) {
21879      return;
21880    }
21881    // start new layout
21882    this._resetLayout();
21883    this._manageStamps();
21884    // filter, layout, reveal new items
21885    var filteredItems = this._filterRevealAdded( items );
21886    // layout previous items
21887    this.layoutItems( this.filteredItems );
21888    // add to items and filteredItems
21889    this.filteredItems = filteredItems.concat( this.filteredItems );
21890    this.items = items.concat( this.items );
21891  };
21892
21893  proto._filterRevealAdded = function( items ) {
21894    var filtered = this._filter( items );
21895    this.hide( filtered.needHide );
21896    // reveal all new items
21897    this.reveal( filtered.matches );
21898    // layout new items, no transition
21899    this.layoutItems( filtered.matches, true );
21900    return filtered.matches;
21901  };
21902
21903  /**
21904   * Filter, sort, and layout newly-appended item elements
21905   * @param {Array or NodeList or Element} elems
21906   */
21907  proto.insert = function( elems ) {
21908    var items = this.addItems( elems );
21909    if ( !items.length ) {
21910      return;
21911    }
21912    // append item elements
21913    var i, item;
21914    var len = items.length;
21915    for ( i=0; i < len; i++ ) {
21916      item = items[i];
21917      this.element.appendChild( item.element );
21918    }
21919    // filter new stuff
21920    var filteredInsertItems = this._filter( items ).matches;
21921    // set flag
21922    for ( i=0; i < len; i++ ) {
21923      items[i].isLayoutInstant = true;
21924    }
21925    this.arrange();
21926    // reset flag
21927    for ( i=0; i < len; i++ ) {
21928      delete items[i].isLayoutInstant;
21929    }
21930    this.reveal( filteredInsertItems );
21931  };
21932
21933  var _remove = proto.remove;
21934  proto.remove = function( elems ) {
21935    elems = utils.makeArray( elems );
21936    var removeItems = this.getItems( elems );
21937    // do regular thing
21938    _remove.call( this, elems );
21939    // bail if no items to remove
21940    var len = removeItems && removeItems.length;
21941    // remove elems from filteredItems
21942    for ( var i=0; len && i < len; i++ ) {
21943      var item = removeItems[i];
21944      // remove item from collection
21945      utils.removeFrom( this.filteredItems, item );
21946    }
21947  };
21948
21949  proto.shuffle = function() {
21950    // update random sortData
21951    for ( var i=0; i < this.items.length; i++ ) {
21952      var item = this.items[i];
21953      item.sortData.random = Math.random();
21954    }
21955    this.options.sortBy = 'random';
21956    this._sort();
21957    this._layout();
21958  };
21959
21960  /**
21961   * trigger fn without transition
21962   * kind of hacky to have this in the first place
21963   * @param {Function} fn
21964   * @param {Array} args
21965   * @returns ret
21966   * @private
21967   */
21968  proto._noTransition = function( fn, args ) {
21969    // save transitionDuration before disabling
21970    var transitionDuration = this.options.transitionDuration;
21971    // disable transition
21972    this.options.transitionDuration = 0;
21973    // do it
21974    var returnValue = fn.apply( this, args );
21975    // re-enable transition for reveal
21976    this.options.transitionDuration = transitionDuration;
21977    return returnValue;
21978  };
21979
21980  // ----- helper methods ----- //
21981
21982  /**
21983   * getter method for getting filtered item elements
21984   * @returns {Array} elems - collection of item elements
21985   */
21986  proto.getFilteredItemElements = function() {
21987    return this.filteredItems.map( function( item ) {
21988      return item.element;
21989    });
21990  };
21991
21992  // -----  ----- //
21993
21994  return Isotope;
21995
21996}));
21997
vendor: 29,252 bytes, lines 21998-23154
21998/*!
21999 * Packery layout mode PACKAGED v2.0.1
22000 * sub-classes Packery
22001 */
22002
22003/**
22004 * Rect
22005 * low-level utility class for basic geometry
22006 */
22007
22008( function( window, factory ) {
22009  // universal module definition
22010  /* jshint strict: false */ /* globals define, module */
22011  if ( typeof define == 'function' && define.amd ) {
22012    // AMD
22013    define( 'packery/js/rect',factory );
22014  } else if ( typeof module == 'object' && module.exports ) {
22015    // CommonJS
22016    module.exports = factory();
22017  } else {
22018    // browser global
22019    window.Packery = window.Packery || {};
22020    window.Packery.Rect = factory();
22021  }
22022
22023}( window, function factory() {
22024
22025
22026// -------------------------- Rect -------------------------- //
22027
22028function Rect( props ) {
22029  // extend properties from defaults
22030  for ( var prop in Rect.defaults ) {
22031    this[ prop ] = Rect.defaults[ prop ];
22032  }
22033
22034  for ( prop in props ) {
22035    this[ prop ] = props[ prop ];
22036  }
22037
22038}
22039
22040Rect.defaults = {
22041  x: 0,
22042  y: 0,
22043  width: 0,
22044  height: 0
22045};
22046
22047var proto = Rect.prototype;
22048
22049/**
22050 * Determines whether or not this rectangle wholly encloses another rectangle or point.
22051 * @param {Rect} rect
22052 * @returns {Boolean}
22053**/
22054proto.contains = function( rect ) {
22055  // points don't have width or height
22056  var otherWidth = rect.width || 0;
22057  var otherHeight = rect.height || 0;
22058  return this.x <= rect.x &&
22059    this.y <= rect.y &&
22060    this.x + this.width >= rect.x + otherWidth &&
22061    this.y + this.height >= rect.y + otherHeight;
22062};
22063
22064/**
22065 * Determines whether or not the rectangle intersects with another.
22066 * @param {Rect} rect
22067 * @returns {Boolean}
22068**/
22069proto.overlaps = function( rect ) {
22070  var thisRight = this.x + this.width;
22071  var thisBottom = this.y + this.height;
22072  var rectRight = rect.x + rect.width;
22073  var rectBottom = rect.y + rect.height;
22074
22075  // http://stackoverflow.com/a/306332
22076  return this.x < rectRight &&
22077    thisRight > rect.x &&
22078    this.y < rectBottom &&
22079    thisBottom > rect.y;
22080};
22081
22082/**
22083 * @param {Rect} rect - the overlapping rect
22084 * @returns {Array} freeRects - rects representing the area around the rect
22085**/
22086proto.getMaximalFreeRects = function( rect ) {
22087
22088  // if no intersection, return false
22089  if ( !this.overlaps( rect ) ) {
22090    return false;
22091  }
22092
22093  var freeRects = [];
22094  var freeRect;
22095
22096  var thisRight = this.x + this.width;
22097  var thisBottom = this.y + this.height;
22098  var rectRight = rect.x + rect.width;
22099  var rectBottom = rect.y + rect.height;
22100
22101  // top
22102  if ( this.y < rect.y ) {
22103    freeRect = new Rect({
22104      x: this.x,
22105      y: this.y,
22106      width: this.width,
22107      height: rect.y - this.y
22108    });
22109    freeRects.push( freeRect );
22110  }
22111
22112  // right
22113  if ( thisRight > rectRight ) {
22114    freeRect = new Rect({
22115      x: rectRight,
22116      y: this.y,
22117      width: thisRight - rectRight,
22118      height: this.height
22119    });
22120    freeRects.push( freeRect );
22121  }
22122
22123  // bottom
22124  if ( thisBottom > rectBottom ) {
22125    freeRect = new Rect({
22126      x: this.x,
22127      y: rectBottom,
22128      width: this.width,
22129      height: thisBottom - rectBottom
22130    });
22131    freeRects.push( freeRect );
22132  }
22133
22134  // left
22135  if ( this.x < rect.x ) {
22136    freeRect = new Rect({
22137      x: this.x,
22138      y: this.y,
22139      width: rect.x - this.x,
22140      height: this.height
22141    });
22142    freeRects.push( freeRect );
22143  }
22144
22145  return freeRects;
22146};
22147
22148proto.canFit = function( rect ) {
22149  return this.width >= rect.width && this.height >= rect.height;
22150};
22151
22152return Rect;
22153
22154}));
22155
22156/**
22157 * Packer
22158 * bin-packing algorithm
22159 */
22160
22161( function( window, factory ) {
22162  // universal module definition
22163  /* jshint strict: false */ /* globals define, module, require */
22164  if ( typeof define == 'function' && define.amd ) {
22165    // AMD
22166    define( 'packery/js/packer',[ './rect' ], factory );
22167  } else if ( typeof module == 'object' && module.exports ) {
22168    // CommonJS
22169    module.exports = factory(
22170      require('./rect')
22171    );
22172  } else {
22173    // browser global
22174    var Packery = window.Packery = window.Packery || {};
22175    Packery.Packer = factory( Packery.Rect );
22176  }
22177
22178}( window, function factory( Rect ) {
22179
22180
22181// -------------------------- Packer -------------------------- //
22182
22183/**
22184 * @param {Number} width
22185 * @param {Number} height
22186 * @param {String} sortDirection
22187 *   topLeft for vertical, leftTop for horizontal
22188 */
22189function Packer( width, height, sortDirection ) {
22190  this.width = width || 0;
22191  this.height = height || 0;
22192  this.sortDirection = sortDirection || 'downwardLeftToRight';
22193
22194  this.reset();
22195}
22196
22197var proto = Packer.prototype;
22198
22199proto.reset = function() {
22200  this.spaces = [];
22201
22202  var initialSpace = new Rect({
22203    x: 0,
22204    y: 0,
22205    width: this.width,
22206    height: this.height
22207  });
22208
22209  this.spaces.push( initialSpace );
22210  // set sorter
22211  this.sorter = sorters[ this.sortDirection ] || sorters.downwardLeftToRight;
22212};
22213
22214// change x and y of rect to fit with in Packer's available spaces
22215proto.pack = function( rect ) {
22216  for ( var i=0; i < this.spaces.length; i++ ) {
22217    var space = this.spaces[i];
22218    if ( space.canFit( rect ) ) {
22219      this.placeInSpace( rect, space );
22220      break;
22221    }
22222  }
22223};
22224
22225proto.columnPack = function( rect ) {
22226  for ( var i=0; i < this.spaces.length; i++ ) {
22227    var space = this.spaces[i];
22228    var canFitInSpaceColumn = space.x <= rect.x &&
22229      space.x + space.width >= rect.x + rect.width &&
22230      space.height >= rect.height - 0.01; // fudge number for rounding error
22231    if ( canFitInSpaceColumn ) {
22232      rect.y = space.y;
22233      this.placed( rect );
22234      break;
22235    }
22236  }
22237};
22238
22239proto.rowPack = function( rect ) {
22240  for ( var i=0; i < this.spaces.length; i++ ) {
22241    var space = this.spaces[i];
22242    var canFitInSpaceRow = space.y <= rect.y &&
22243      space.y + space.height >= rect.y + rect.height &&
22244      space.width >= rect.width - 0.01; // fudge number for rounding error
22245    if ( canFitInSpaceRow ) {
22246      rect.x = space.x;
22247      this.placed( rect );
22248      break;
22249    }
22250  }
22251};
22252
22253proto.placeInSpace = function( rect, space ) {
22254  // place rect in space
22255  rect.x = space.x;
22256  rect.y = space.y;
22257
22258  this.placed( rect );
22259};
22260
22261// update spaces with placed rect
22262proto.placed = function( rect ) {
22263  // update spaces
22264  var revisedSpaces = [];
22265  for ( var i=0; i < this.spaces.length; i++ ) {
22266    var space = this.spaces[i];
22267    var newSpaces = space.getMaximalFreeRects( rect );
22268    // add either the original space or the new spaces to the revised spaces
22269    if ( newSpaces ) {
22270      revisedSpaces.push.apply( revisedSpaces, newSpaces );
22271    } else {
22272      revisedSpaces.push( space );
22273    }
22274  }
22275
22276  this.spaces = revisedSpaces;
22277
22278  this.mergeSortSpaces();
22279};
22280
22281proto.mergeSortSpaces = function() {
22282  // remove redundant spaces
22283  Packer.mergeRects( this.spaces );
22284  this.spaces.sort( this.sorter );
22285};
22286
22287// add a space back
22288proto.addSpace = function( rect ) {
22289  this.spaces.push( rect );
22290  this.mergeSortSpaces();
22291};
22292
22293// -------------------------- utility functions -------------------------- //
22294
22295/**
22296 * Remove redundant rectangle from array of rectangles
22297 * @param {Array} rects: an array of Rects
22298 * @returns {Array} rects: an array of Rects
22299**/
22300Packer.mergeRects = function( rects ) {
22301  var i = 0;
22302  var rect = rects[i];
22303
22304  rectLoop:
22305  while ( rect ) {
22306    var j = 0;
22307    var compareRect = rects[ i + j ];
22308
22309    while ( compareRect ) {
22310      if  ( compareRect == rect ) {
22311        j++; // next
22312      } else if ( compareRect.contains( rect ) ) {
22313        // remove rect
22314        rects.splice( i, 1 );
22315        rect = rects[i]; // set next rect
22316        continue rectLoop; // bail on compareLoop
22317      } else if ( rect.contains( compareRect ) ) {
22318        // remove compareRect
22319        rects.splice( i + j, 1 );
22320      } else {
22321        j++;
22322      }
22323      compareRect = rects[ i + j ]; // set next compareRect
22324    }
22325    i++;
22326    rect = rects[i];
22327  }
22328
22329  return rects;
22330};
22331
22332
22333// -------------------------- sorters -------------------------- //
22334
22335// functions for sorting rects in order
22336var sorters = {
22337  // top down, then left to right
22338  downwardLeftToRight: function( a, b ) {
22339    return a.y - b.y || a.x - b.x;
22340  },
22341  // left to right, then top down
22342  rightwardTopToBottom: function( a, b ) {
22343    return a.x - b.x || a.y - b.y;
22344  }
22345};
22346
22347
22348// --------------------------  -------------------------- //
22349
22350return Packer;
22351
22352}));
22353
22354/**
22355 * Packery Item Element
22356**/
22357
22358( function( window, factory ) {
22359  // universal module definition
22360  /* jshint strict: false */ /* globals define, module, require */
22361  if ( typeof define == 'function' && define.amd ) {
22362    // AMD
22363    define( 'packery/js/item',[
22364        'outlayer/outlayer',
22365        './rect'
22366      ],
22367      factory );
22368  } else if ( typeof module == 'object' && module.exports ) {
22369    // CommonJS
22370    module.exports = factory(
22371      require('outlayer'),
22372      require('./rect')
22373    );
22374  } else {
22375    // browser global
22376    window.Packery.Item = factory(
22377      window.Outlayer,
22378      window.Packery.Rect
22379    );
22380  }
22381
22382}( window, function factory( Outlayer, Rect ) {
22383
22384
22385// -------------------------- Item -------------------------- //
22386
22387var docElemStyle = document.documentElement.style;
22388
22389var transformProperty = typeof docElemStyle.transform == 'string' ?
22390  'transform' : 'WebkitTransform';
22391
22392// sub-class Item
22393var Item = function PackeryItem() {
22394  Outlayer.Item.apply( this, arguments );
22395};
22396
22397var proto = Item.prototype = Object.create( Outlayer.Item.prototype );
22398
22399var __create = proto._create;
22400proto._create = function() {
22401  // call default _create logic
22402  __create.call( this );
22403  this.rect = new Rect();
22404};
22405
22406var _moveTo = proto.moveTo;
22407proto.moveTo = function( x, y ) {
22408  // don't shift 1px while dragging
22409  var dx = Math.abs( this.position.x - x );
22410  var dy = Math.abs( this.position.y - y );
22411
22412  var canHackGoTo = this.layout.dragItemCount && !this.isPlacing &&
22413    !this.isTransitioning && dx < 1 && dy < 1;
22414  if ( canHackGoTo ) {
22415    this.goTo( x, y );
22416    return;
22417  }
22418  _moveTo.apply( this, arguments );
22419};
22420
22421// -------------------------- placing -------------------------- //
22422
22423proto.enablePlacing = function() {
22424  this.removeTransitionStyles();
22425  // remove transform property from transition
22426  if ( this.isTransitioning && transformProperty ) {
22427    this.element.style[ transformProperty ] = 'none';
22428  }
22429  this.isTransitioning = false;
22430  this.getSize();
22431  this.layout._setRectSize( this.element, this.rect );
22432  this.isPlacing = true;
22433};
22434
22435proto.disablePlacing = function() {
22436  this.isPlacing = false;
22437};
22438
22439// -----  ----- //
22440
22441// remove element from DOM
22442proto.removeElem = function() {
22443  this.element.parentNode.removeChild( this.element );
22444  // add space back to packer
22445  this.layout.packer.addSpace( this.rect );
22446  this.emitEvent( 'remove', [ this ] );
22447};
22448
22449// ----- dropPlaceholder ----- //
22450
22451proto.showDropPlaceholder = function() {
22452  var dropPlaceholder = this.dropPlaceholder;
22453  if ( !dropPlaceholder ) {
22454    // create dropPlaceholder
22455    dropPlaceholder = this.dropPlaceholder = document.createElement('div');
22456    dropPlaceholder.className = 'packery-drop-placeholder';
22457    dropPlaceholder.style.position = 'absolute';
22458  }
22459
22460  dropPlaceholder.style.width = this.size.width + 'px';
22461  dropPlaceholder.style.height = this.size.height + 'px';
22462  this.positionDropPlaceholder();
22463  this.layout.element.appendChild( dropPlaceholder );
22464};
22465
22466proto.positionDropPlaceholder = function() {
22467  this.dropPlaceholder.style[ transformProperty ] = 'translate(' +
22468    this.rect.x + 'px, ' + this.rect.y + 'px)';
22469};
22470
22471proto.hideDropPlaceholder = function() {
22472  this.layout.element.removeChild( this.dropPlaceholder );
22473};
22474
22475// -----  ----- //
22476
22477return Item;
22478
22479}));
22480
22481/*!
22482 * Packery v2.0.0
22483 * Gapless, draggable grid layouts
22484 *
22485 * Licensed GPLv3 for open source use
22486 * or Packery Commercial License for commercial use
22487 *
22488 * http://packery.metafizzy.co
22489 * Copyright 2016 Metafizzy
22490 */
22491
22492( function( window, factory ) {
22493  // universal module definition
22494  /* jshint strict: false */ /* globals define, module, require */
22495  if ( typeof define == 'function' && define.amd ) {
22496    // AMD
22497    define( 'packery/js/packery',[
22498        'get-size/get-size',
22499        'outlayer/outlayer',
22500        './rect',
22501        './packer',
22502        './item'
22503      ],
22504      factory );
22505  } else if ( typeof module == 'object' && module.exports ) {
22506    // CommonJS
22507    module.exports = factory(
22508      require('get-size'),
22509      require('outlayer'),
22510      require('./rect'),
22511      require('./packer'),
22512      require('./item')
22513    );
22514  } else {
22515    // browser global
22516    window.Packery = factory(
22517      window.getSize,
22518      window.Outlayer,
22519      window.Packery.Rect,
22520      window.Packery.Packer,
22521      window.Packery.Item
22522    );
22523  }
22524
22525}( window, function factory( getSize, Outlayer, Rect, Packer, Item ) {
22526
22527
22528// ----- Rect ----- //
22529
22530// allow for pixel rounding errors IE8-IE11 & Firefox; #227
22531Rect.prototype.canFit = function( rect ) {
22532  return this.width >= rect.width - 1 && this.height >= rect.height - 1;
22533};
22534
22535// -------------------------- Packery -------------------------- //
22536
22537// create an Outlayer layout class
22538var Packery = Outlayer.create('packery');
22539Packery.Item = Item;
22540
22541var proto = Packery.prototype;
22542
22543proto._create = function() {
22544  // call super
22545  Outlayer.prototype._create.call( this );
22546
22547  // initial properties
22548  this.packer = new Packer();
22549  // packer for drop targets
22550  this.shiftPacker = new Packer();
22551  this.isEnabled = true;
22552
22553  this.dragItemCount = 0;
22554
22555  // create drag handlers
22556  var _this = this;
22557  this.handleDraggabilly = {
22558    dragStart: function() {
22559      _this.itemDragStart( this.element );
22560    },
22561    dragMove: function() {
22562      _this.itemDragMove( this.element, this.position.x, this.position.y );
22563    },
22564    dragEnd: function() {
22565      _this.itemDragEnd( this.element );
22566    }
22567  };
22568
22569  this.handleUIDraggable = {
22570    start: function handleUIDraggableStart( event, ui ) {
22571      // HTML5 may trigger dragstart, dismiss HTML5 dragging
22572      if ( !ui ) {
22573        return;
22574      }
22575      _this.itemDragStart( event.currentTarget );
22576    },
22577    drag: function handleUIDraggableDrag( event, ui ) {
22578      if ( !ui ) {
22579        return;
22580      }
22581      _this.itemDragMove( event.currentTarget, ui.position.left, ui.position.top );
22582    },
22583    stop: function handleUIDraggableStop( event, ui ) {
22584      if ( !ui ) {
22585        return;
22586      }
22587      _this.itemDragEnd( event.currentTarget );
22588    }
22589  };
22590
22591};
22592
22593
22594// ----- init & layout ----- //
22595
22596/**
22597 * logic before any new layout
22598 */
22599proto._resetLayout = function() {
22600  this.getSize();
22601
22602  this._getMeasurements();
22603
22604  // reset packer
22605  var width, height, sortDirection;
22606  // packer settings, if horizontal or vertical
22607  if ( this._getOption('horizontal') ) {
22608    width = Infinity;
22609    height = this.size.innerHeight + this.gutter;
22610    sortDirection = 'rightwardTopToBottom';
22611  } else {
22612    width = this.size.innerWidth + this.gutter;
22613    height = Infinity;
22614    sortDirection = 'downwardLeftToRight';
22615  }
22616
22617  this.packer.width = this.shiftPacker.width = width;
22618  this.packer.height = this.shiftPacker.height = height;
22619  this.packer.sortDirection = this.shiftPacker.sortDirection = sortDirection;
22620
22621  this.packer.reset();
22622
22623  // layout
22624  this.maxY = 0;
22625  this.maxX = 0;
22626};
22627
22628/**
22629 * update columnWidth, rowHeight, & gutter
22630 * @private
22631 */
22632proto._getMeasurements = function() {
22633  this._getMeasurement( 'columnWidth', 'width' );
22634  this._getMeasurement( 'rowHeight', 'height' );
22635  this._getMeasurement( 'gutter', 'width' );
22636};
22637
22638proto._getItemLayoutPosition = function( item ) {
22639  this._setRectSize( item.element, item.rect );
22640  if ( this.isShifting || this.dragItemCount > 0 ) {
22641    var packMethod = this._getPackMethod();
22642    this.packer[ packMethod ]( item.rect );
22643  } else {
22644    this.packer.pack( item.rect );
22645  }
22646
22647  this._setMaxXY( item.rect );
22648  return item.rect;
22649};
22650
22651proto.shiftLayout = function() {
22652  this.isShifting = true;
22653  this.layout();
22654  delete this.isShifting;
22655};
22656
22657proto._getPackMethod = function() {
22658  return this._getOption('horizontal') ? 'rowPack' : 'columnPack';
22659};
22660
22661
22662/**
22663 * set max X and Y value, for size of container
22664 * @param {Packery.Rect} rect
22665 * @private
22666 */
22667proto._setMaxXY = function( rect ) {
22668  this.maxX = Math.max( rect.x + rect.width, this.maxX );
22669  this.maxY = Math.max( rect.y + rect.height, this.maxY );
22670};
22671
22672/**
22673 * set the width and height of a rect, applying columnWidth and rowHeight
22674 * @param {Element} elem
22675 * @param {Packery.Rect} rect
22676 */
22677proto._setRectSize = function( elem, rect ) {
22678  var size = getSize( elem );
22679  var w = size.outerWidth;
22680  var h = size.outerHeight;
22681  // size for columnWidth and rowHeight, if available
22682  // only check if size is non-zero, #177
22683  if ( w || h ) {
22684    w = this._applyGridGutter( w, this.columnWidth );
22685    h = this._applyGridGutter( h, this.rowHeight );
22686  }
22687  // rect must fit in packer
22688  rect.width = Math.min( w, this.packer.width );
22689  rect.height = Math.min( h, this.packer.height );
22690};
22691
22692/**
22693 * fits item to columnWidth/rowHeight and adds gutter
22694 * @param {Number} measurement - item width or height
22695 * @param {Number} gridSize - columnWidth or rowHeight
22696 * @returns measurement
22697 */
22698proto._applyGridGutter = function( measurement, gridSize ) {
22699  // just add gutter if no gridSize
22700  if ( !gridSize ) {
22701    return measurement + this.gutter;
22702  }
22703  gridSize += this.gutter;
22704  // fit item to columnWidth/rowHeight
22705  var remainder = measurement % gridSize;
22706  var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil';
22707  measurement = Math[ mathMethod ]( measurement / gridSize ) * gridSize;
22708  return measurement;
22709};
22710
22711proto._getContainerSize = function() {
22712  if ( this._getOption('horizontal') ) {
22713    return {
22714      width: this.maxX - this.gutter
22715    };
22716  } else {
22717    return {
22718      height: this.maxY - this.gutter
22719    };
22720  }
22721};
22722
22723
22724// -------------------------- stamp -------------------------- //
22725
22726/**
22727 * makes space for element
22728 * @param {Element} elem
22729 */
22730proto._manageStamp = function( elem ) {
22731
22732  var item = this.getItem( elem );
22733  var rect;
22734  if ( item && item.isPlacing ) {
22735    rect = item.rect;
22736  } else {
22737    var offset = this._getElementOffset( elem );
22738    rect = new Rect({
22739      x: this._getOption('originLeft') ? offset.left : offset.right,
22740      y: this._getOption('originTop') ? offset.top : offset.bottom
22741    });
22742  }
22743
22744  this._setRectSize( elem, rect );
22745  // save its space in the packer
22746  this.packer.placed( rect );
22747  this._setMaxXY( rect );
22748};
22749
22750// -------------------------- methods -------------------------- //
22751
22752function verticalSorter( a, b ) {
22753  return a.position.y - b.position.y || a.position.x - b.position.x;
22754}
22755
22756function horizontalSorter( a, b ) {
22757  return a.position.x - b.position.x || a.position.y - b.position.y;
22758}
22759
22760proto.sortItemsByPosition = function() {
22761  var sorter = this._getOption('horizontal') ? horizontalSorter : verticalSorter;
22762  this.items.sort( sorter );
22763};
22764
22765/**
22766 * Fit item element in its current position
22767 * Packery will position elements around it
22768 * useful for expanding elements
22769 *
22770 * @param {Element} elem
22771 * @param {Number} x - horizontal destination position, optional
22772 * @param {Number} y - vertical destination position, optional
22773 */
22774proto.fit = function( elem, x, y ) {
22775  var item = this.getItem( elem );
22776  if ( !item ) {
22777    return;
22778  }
22779
22780  // stamp item to get it out of layout
22781  this.stamp( item.element );
22782  // set placing flag
22783  item.enablePlacing();
22784  this.updateShiftTargets( item );
22785  // fall back to current position for fitting
22786  x = x === undefined ? item.rect.x: x;
22787  y = y === undefined ? item.rect.y: y;
22788  // position it best at its destination
22789  this.shift( item, x, y );
22790  this._bindFitEvents( item );
22791  item.moveTo( item.rect.x, item.rect.y );
22792  // layout everything else
22793  this.shiftLayout();
22794  // return back to regularly scheduled programming
22795  this.unstamp( item.element );
22796  this.sortItemsByPosition();
22797  item.disablePlacing();
22798};
22799
22800/**
22801 * emit event when item is fit and other items are laid out
22802 * @param {Packery.Item} item
22803 * @private
22804 */
22805proto._bindFitEvents = function( item ) {
22806  var _this = this;
22807  var ticks = 0;
22808  function onLayout() {
22809    ticks++;
22810    if ( ticks != 2 ) {
22811      return;
22812    }
22813    _this.dispatchEvent( 'fitComplete', null, [ item ] );
22814  }
22815  // when item is laid out
22816  item.once( 'layout', onLayout );
22817  // when all items are laid out
22818  this.once( 'layoutComplete', onLayout );
22819};
22820
22821// -------------------------- resize -------------------------- //
22822
22823// debounced, layout on resize
22824proto.resize = function() {
22825  // don't trigger if size did not change
22826  // or if resize was unbound. See #285, outlayer#9
22827  if ( !this.isResizeBound || !this.needsResizeLayout() ) {
22828    return;
22829  }
22830
22831  if ( this.options.shiftPercentResize ) {
22832    this.resizeShiftPercentLayout();
22833  } else {
22834    this.layout();
22835  }
22836};
22837
22838/**
22839 * check if layout is needed post layout
22840 * @returns Boolean
22841 */
22842proto.needsResizeLayout = function() {
22843  var size = getSize( this.element );
22844  var innerSize = this._getOption('horizontal') ? 'innerHeight' : 'innerWidth';
22845  return size[ innerSize ] != this.size[ innerSize ];
22846};
22847
22848proto.resizeShiftPercentLayout = function() {
22849  var items = this._getItemsForLayout( this.items );
22850
22851  var isHorizontal = this._getOption('horizontal');
22852  var coord = isHorizontal ? 'y' : 'x';
22853  var measure = isHorizontal ? 'height' : 'width';
22854  var segmentName = isHorizontal ? 'rowHeight' : 'columnWidth';
22855  var innerSize = isHorizontal ? 'innerHeight' : 'innerWidth';
22856
22857  // proportional re-align items
22858  var previousSegment = this[ segmentName ];
22859  previousSegment = previousSegment && previousSegment + this.gutter;
22860
22861  if ( previousSegment ) {
22862    this._getMeasurements();
22863    var currentSegment = this[ segmentName ] + this.gutter;
22864    items.forEach( function( item ) {
22865      var seg = Math.round( item.rect[ coord ] / previousSegment );
22866      item.rect[ coord ] = seg * currentSegment;
22867    });
22868  } else {
22869    var currentSize = getSize( this.element )[ innerSize ] + this.gutter;
22870    var previousSize = this.packer[ measure ];
22871    items.forEach( function( item ) {
22872      item.rect[ coord ] = ( item.rect[ coord ] / previousSize ) * currentSize;
22873    });
22874  }
22875
22876  this.shiftLayout();
22877};
22878
22879// -------------------------- drag -------------------------- //
22880
22881/**
22882 * handle an item drag start event
22883 * @param {Element} elem
22884 */
22885proto.itemDragStart = function( elem ) {
22886  if ( !this.isEnabled ) {
22887    return;
22888  }
22889  this.stamp( elem );
22890  // this.ignore( elem );
22891  var item = this.getItem( elem );
22892  if ( !item ) {
22893    return;
22894  }
22895
22896  item.enablePlacing();
22897  item.showDropPlaceholder();
22898  this.dragItemCount++;
22899  this.updateShiftTargets( item );
22900};
22901
22902proto.updateShiftTargets = function( dropItem ) {
22903  this.shiftPacker.reset();
22904
22905  // pack stamps
22906  this._getBoundingRect();
22907  var isOriginLeft = this._getOption('originLeft');
22908  var isOriginTop = this._getOption('originTop');
22909  this.stamps.forEach( function( stamp ) {
22910    // ignore dragged item
22911    var item = this.getItem( stamp );
22912    if ( item && item.isPlacing ) {
22913      return;
22914    }
22915    var offset = this._getElementOffset( stamp );
22916    var rect = new Rect({
22917      x: isOriginLeft ? offset.left : offset.right,
22918      y: isOriginTop ? offset.top : offset.bottom
22919    });
22920    this._setRectSize( stamp, rect );
22921    // save its space in the packer
22922    this.shiftPacker.placed( rect );
22923  }, this );
22924
22925  // reset shiftTargets
22926  var isHorizontal = this._getOption('horizontal');
22927  var segmentName = isHorizontal ? 'rowHeight' : 'columnWidth';
22928  var measure = isHorizontal ? 'height' : 'width';
22929
22930  this.shiftTargetKeys = [];
22931  this.shiftTargets = [];
22932  var boundsSize;
22933  var segment = this[ segmentName ];
22934  segment = segment && segment + this.gutter;
22935
22936  if ( segment ) {
22937    var segmentSpan = Math.ceil( dropItem.rect[ measure ] / segment );
22938    var segs = Math.floor( ( this.shiftPacker[ measure ] + this.gutter ) / segment );
22939    boundsSize = ( segs - segmentSpan ) * segment;
22940    // add targets on top
22941    for ( var i=0; i < segs; i++ ) {
22942      this._addShiftTarget( i * segment, 0, boundsSize );
22943    }
22944  } else {
22945    boundsSize = ( this.shiftPacker[ measure ] + this.gutter ) - dropItem.rect[ measure ];
22946    this._addShiftTarget( 0, 0, boundsSize );
22947  }
22948
22949  // pack each item to measure where shiftTargets are
22950  var items = this._getItemsForLayout( this.items );
22951  var packMethod = this._getPackMethod();
22952  items.forEach( function( item ) {
22953    var rect = item.rect;
22954    this._setRectSize( item.element, rect );
22955    this.shiftPacker[ packMethod ]( rect );
22956
22957    // add top left corner
22958    this._addShiftTarget( rect.x, rect.y, boundsSize );
22959    // add bottom left / top right corner
22960    var cornerX = isHorizontal ? rect.x + rect.width : rect.x;
22961    var cornerY = isHorizontal ? rect.y : rect.y + rect.height;
22962    this._addShiftTarget( cornerX, cornerY, boundsSize );
22963
22964    if ( segment ) {
22965      // add targets for each column on bottom / row on right
22966      var segSpan = Math.round( rect[ measure ] / segment );
22967      for ( var i=1; i < segSpan; i++ ) {
22968        var segX = isHorizontal ? cornerX : rect.x + segment * i;
22969        var segY = isHorizontal ? rect.y + segment * i : cornerY;
22970        this._addShiftTarget( segX, segY, boundsSize );
22971      }
22972    }
22973  }, this );
22974
22975};
22976
22977proto._addShiftTarget = function( x, y, boundsSize ) {
22978  var checkCoord = this._getOption('horizontal') ? y : x;
22979  if ( checkCoord !== 0 && checkCoord > boundsSize ) {
22980    return;
22981  }
22982  // create string for a key, easier to keep track of what targets
22983  var key = x + ',' + y;
22984  var hasKey = this.shiftTargetKeys.indexOf( key ) != -1;
22985  if ( hasKey ) {
22986    return;
22987  }
22988  this.shiftTargetKeys.push( key );
22989  this.shiftTargets.push({ x: x, y: y });
22990};
22991
22992// -------------------------- drop -------------------------- //
22993
22994proto.shift = function( item, x, y ) {
22995  var shiftPosition;
22996  var minDistance = Infinity;
22997  var position = { x: x, y: y };
22998  this.shiftTargets.forEach( function( target ) {
22999    var distance = getDistance( target, position );
23000    if ( distance < minDistance ) {
23001      shiftPosition = target;
23002      minDistance = distance;
23003    }
23004  });
23005  item.rect.x = shiftPosition.x;
23006  item.rect.y = shiftPosition.y;
23007};
23008
23009function getDistance( a, b ) {
23010  var dx = b.x - a.x;
23011  var dy = b.y - a.y;
23012  return Math.sqrt( dx * dx + dy * dy );
23013}
23014
23015// -------------------------- drag move -------------------------- //
23016
23017var DRAG_THROTTLE_TIME = 120;
23018
23019/**
23020 * handle an item drag move event
23021 * @param {Element} elem
23022 * @param {Number} x - horizontal change in position
23023 * @param {Number} y - vertical change in position
23024 */
23025proto.itemDragMove = function( elem, x, y ) {
23026  var item = this.isEnabled && this.getItem( elem );
23027  if ( !item ) {
23028    return;
23029  }
23030
23031  x -= this.size.paddingLeft;
23032  y -= this.size.paddingTop;
23033
23034  var _this = this;
23035  function onDrag() {
23036    _this.shift( item, x, y );
23037    item.positionDropPlaceholder();
23038    _this.layout();
23039  }
23040
23041  // throttle
23042  var now = new Date();
23043  if ( this._itemDragTime && now - this._itemDragTime < DRAG_THROTTLE_TIME ) {
23044    clearTimeout( this.dragTimeout );
23045    this.dragTimeout = setTimeout( onDrag, DRAG_THROTTLE_TIME );
23046  } else {
23047    onDrag();
23048    this._itemDragTime = now;
23049  }
23050};
23051
23052// -------------------------- drag end -------------------------- //
23053
23054/**
23055 * handle an item drag end event
23056 * @param {Element} elem
23057 */
23058proto.itemDragEnd = function( elem ) {
23059  var item = this.isEnabled && this.getItem( elem );
23060  if ( !item ) {
23061    return;
23062  }
23063
23064  clearTimeout( this.dragTimeout );
23065  item.element.classList.add('is-positioning-post-drag');
23066
23067  var completeCount = 0;
23068  var _this = this;
23069  function onDragEndLayoutComplete() {
23070    completeCount++;
23071    if ( completeCount != 2 ) {
23072      return;
23073    }
23074    // reset drag item
23075    item.element.classList.remove('is-positioning-post-drag');
23076    item.hideDropPlaceholder();
23077    _this.dispatchEvent( 'dragItemPositioned', null, [ item ] );
23078  }
23079
23080  item.once( 'layout', onDragEndLayoutComplete );
23081  this.once( 'layoutComplete', onDragEndLayoutComplete );
23082  item.moveTo( item.rect.x, item.rect.y );
23083  this.layout();
23084  this.dragItemCount = Math.max( 0, this.dragItemCount - 1 );
23085  this.sortItemsByPosition();
23086  item.disablePlacing();
23087  this.unstamp( item.element );
23088};
23089
23090/**
23091 * binds Draggabilly events
23092 * @param {Draggabilly} draggie
23093 */
23094proto.bindDraggabillyEvents = function( draggie ) {
23095  this._bindDraggabillyEvents( draggie, 'on' );
23096};
23097
23098proto.unbindDraggabillyEvents = function( draggie ) {
23099  this._bindDraggabillyEvents( draggie, 'off' );
23100};
23101
23102proto._bindDraggabillyEvents = function( draggie, method ) {
23103  var handlers = this.handleDraggabilly;
23104  draggie[ method ]( 'dragStart', handlers.dragStart );
23105  draggie[ method ]( 'dragMove', handlers.dragMove );
23106  draggie[ method ]( 'dragEnd', handlers.dragEnd );
23107};
23108
23109/**
23110 * binds jQuery UI Draggable events
23111 * @param {jQuery} $elems
23112 */
23113proto.bindUIDraggableEvents = function( $elems ) {
23114  this._bindUIDraggableEvents( $elems, 'on' );
23115};
23116
23117proto.unbindUIDraggableEvents = function( $elems ) {
23118  this._bindUIDraggableEvents( $elems, 'off' );
23119};
23120
23121proto._bindUIDraggableEvents = function( $elems, method ) {
23122  var handlers = this.handleUIDraggable;
23123  $elems
23124    [ method ]( 'dragstart', handlers.start )
23125    [ method ]( 'drag', handlers.drag )
23126    [ method ]( 'dragstop', handlers.stop );
23127};
23128
23129// ----- destroy ----- //
23130
23131var _destroy = proto.destroy;
23132proto.destroy = function() {
23133  _destroy.apply( this, arguments );
23134  // disable flag; prevent drag events from triggering. #72
23135  this.isEnabled = false;
23136};
23137
23138// -----  ----- //
23139
23140Packery.Rect = Rect;
23141Packery.Packer = Packer;
23142
23143return Packery;
23144
23145}));
23146
23147/*!
23148 * Packery layout mode v2.0.1
23149 * sub-classes Packery
23150 */
23151
23152/*jshint browser: true, strict: true, undef: true, unused: true */
23153
23154( function( window, factory ) {
23155
23156  // universal module definition
23157  if ( typeof define == 'function' && define.amd ) {
23158    // AMD
23159    define( [
23160        'isotope-layout/js/layout-mode',
23161        'packery/js/packery'
23162      ],
23163      factory );
23164  } else if ( typeof module == 'object' && module.exports ) {
23165    // CommonJS
23166    module.exports = factory(
23167      require('isotope-layout/js/layout-mode'),
23168      require('packery')
23169    );
23170  } else {
23171    // browser global
23172    factory(
23173      window.Isotope.LayoutMode,
23174      window.Packery
23175    );
23176  }
23177
23178}( window, function factor( LayoutMode, Packery ) {
23179
23180
23181  // create an Outlayer layout class
23182  var PackeryMode = LayoutMode.create('packery');
23183  var proto = PackeryMode.prototype;
23184
23185  var keepModeMethods = {
23186    _getElementOffset: true,
23187    _getMeasurement: true
23188  };
23189
23190  // inherit Packery prototype
23191  for ( var method in Packery.prototype ) {
23192    // do not inherit mode methods
23193    if ( !keepModeMethods[ method ] ) {
23194      proto[ method ] = Packery.prototype[ method ];
23195    }
23196  }
23197
23198  // set packer in _resetLayout
23199  var _resetLayout = proto._resetLayout;
23200  proto._resetLayout = function() {
23201    this.packer = this.packer || new Packery.Packer();
23202    this.shiftPacker = this.shiftPacker || new Packery.Packer();
23203    _resetLayout.apply( this, arguments );
23204  };
23205
23206  var _getItemLayoutPosition = proto._getItemLayoutPosition;
23207  proto._getItemLayoutPosition = function( item ) {
23208    // set packery rect
23209    item.rect = item.rect || new Packery.Rect();
23210    return _getItemLayoutPosition.call( this, item );
23211  };
23212
23213  // needsResizeLayout for vertical or horizontal
23214  var _needsResizeLayout = proto.needsResizeLayout;
23215  proto.needsResizeLayout = function() {
23216    if ( this._getOption('horizontal') ) {
23217      return this.needsVerticalResizeLayout();
23218    } else {
23219      return _needsResizeLayout.call( this );
23220    }
23221  };
23222
23223  // point to mode options for horizontal
23224  var _getOption = proto._getOption;
23225  proto._getOption = function( option ) {
23226    if ( option == 'horizontal' ) {
23227      return this.options.isHorizontal !== undefined ?
23228        this.options.isHorizontal : this.options.horizontal;
23229    }
23230    return _getOption.apply( this.isotope, arguments );
23231  };
23232
23233  return PackeryMode;
23234
23235}));
23236
23237/*!
23238 * cellsByRows layout mode for Isotope
23239 * v1.1.3
23240 * http://isotope.metafizzy.co/layout-modes/cellsbyrow.html
23241 */
23242
23243/*jshint browser: true, devel: false, strict: true, undef: true, unused: true */
23244
23245( function( window, factory ) {
23246  // universal module definition
23247  /* jshint strict: false */ /*globals define, module, require */
23248  if ( typeof define === 'function' && define.amd ) {
23249    // AMD
23250    define( [
23251        'isotope/js/layout-mode'
23252      ],
23253      factory );
23254  } else if ( typeof exports === 'object' ) {
23255    // CommonJS
23256    module.exports = factory(
23257      require('isotope-layout/js/layout-mode')
23258    );
23259  } else {
23260    // browser global
23261    factory(
23262      window.Isotope.LayoutMode
23263    );
23264  }
23265
23266}( window, function factory( LayoutMode ) {
23267  'use strict';
23268
23269  var CellsByRow = LayoutMode.create( 'cellsByRow' );
23270  var proto = CellsByRow.prototype;
23271
23272  proto._resetLayout = function() {
23273    // reset properties
23274    this.itemIndex = 0;
23275    // measurements
23276    this.getColumnWidth();
23277    this.getRowHeight();
23278    // set cols
23279    this.cols = Math.floor( this.isotope.size.innerWidth / this.columnWidth );
23280    this.cols = Math.max( this.cols, 1 );
23281  };
23282
23283  proto._getItemLayoutPosition = function( item ) {
23284    item.getSize();
23285    var col = this.itemIndex % this.cols;
23286    var row = Math.floor( this.itemIndex / this.cols );
23287    // center item within cell
23288    var x = ( col + 0.5 ) * this.columnWidth - item.size.outerWidth / 2;
23289    var y = ( row + 0.5 ) * this.rowHeight - item.size.outerHeight / 2;
23290    this.itemIndex++;
23291    return { x: x, y: y };
23292  };
23293
23294  proto._getContainerSize = function() {
23295    return {
23296      height: Math.ceil( this.itemIndex / this.cols ) * this.rowHeight
23297    };
23298  };
23299
23300  return CellsByRow;
23301
23302}));
23303/*global jQuery: true */
23304
23305/*!
23306   --------------------------------
23307   Infinite Scroll
23308   --------------------------------
23309   + https://github.com/paulirish/infinite-scroll
23310   + version 2.1.0
23311   + Copyright 2011/12 Paul Irish & Luke Shumard
23312   + Licensed under the MIT license
23313
23314   + Documentation: http://infinite-scroll.com/
23315*/
23316
23317// Uses AMD or browser globals to create a jQuery plugin.
23318(function (factory) {
23319	if (typeof define === 'function' && define.amd) {
23320		// AMD. Register as an anonymous module.
23321		define(['jquery'], factory);
23322	} else {
23323		// Browser globals
23324		factory(jQuery);
23325	}
23326}(function ($, undefined) {
23327	'use strict';
23328
23329	$.infinitescroll = function infscr(options, callback, element) {
23330		this.element = $(element);
23331
23332		// Flag the object in the event of a failed creation
23333		if (!this._create(options, callback)) {
23334			this.failed = true;
23335		}
23336	};
23337
23338	$.infinitescroll.defaults = {
23339		loading: {
23340			finished: undefined,
23341			finishedMsg: "<em>Congratulations, you've reached the end of the internet.</em>",
23342			img: 'data:image/gif;base64,R0lGODlh3AATAPQeAPDy+MnQ6LW/4N3h8MzT6rjC4sTM5r/I5NHX7N7j8c7U6tvg8OLl8uXo9Ojr9b3G5MfP6Ovu9tPZ7PT1+vX2+tbb7vf4+8/W69jd7rC73vn5/O/x+K243ai02////wAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQECgD/ACwAAAAA3AATAAAF/6AnjmRpnmiqrmzrvnAsz3Rt33iu73zv/8CgcEj0BAScpHLJbDqf0Kh0Sq1ar9isdioItAKGw+MAKYMFhbF63CW438f0mg1R2O8EuXj/aOPtaHx7fn96goR4hmuId4qDdX95c4+RBIGCB4yAjpmQhZN0YGYGXitdZBIVGAsLoq4BBKQDswm1CQRkcG6ytrYKubq8vbfAcMK9v7q7EMO1ycrHvsW6zcTKsczNz8HZw9vG3cjTsMIYqQkCLBwHCgsMDQ4RDAYIqfYSFxDxEfz88/X38Onr16+Bp4ADCco7eC8hQYMAEe57yNCew4IVBU7EGNDiRn8Z831cGLHhSIgdFf9chIeBg7oA7gjaWUWTVQAGE3LqBDCTlc9WOHfm7PkTqNCh54rePDqB6M+lR536hCpUqs2gVZM+xbrTqtGoWqdy1emValeXKzggYBBB5y1acFNZmEvXAoN2cGfJrTv3bl69Ffj2xZt3L1+/fw3XRVw4sGDGcR0fJhxZsF3KtBTThZxZ8mLMgC3fRatCbYMNFCzwLEqLgE4NsDWs/tvqdezZf13Hvk2A9Szdu2X3pg18N+68xXn7rh1c+PLksI/Dhe6cuO3ow3NfV92bdArTqC2Ebd3A8vjf5QWfH6Bg7Nz17c2fj69+fnq+8N2Lty+fuP78/eV2X13neIcCeBRwxorbZrA1ANoCDGrgoG8RTshahQ9iSKEEzUmYIYfNWViUhheCGJyIP5E4oom7WWjgCeBFAJNv1DVV01MAdJhhjdkplWNzO/5oXI846njjVEIqR2OS2B1pE5PVscajkxhMycqLJghQSwT40PgfAl4GqNSXYdZXJn5gSkmmmmJu1aZYb14V51do+pTOCmA40AqVCIhG5IJ9PvYnhIFOxmdqhpaI6GeHCtpooisuutmg+Eg62KOMKuqoTaXgicQWoIYq6qiklmoqFV0UoeqqrLbq6quwxirrrLTWauutJ4QAACH5BAUKABwALAcABADOAAsAAAX/IPd0D2dyRCoUp/k8gpHOKtseR9yiSmGbuBykler9XLAhkbDavXTL5k2oqFqNOxzUZPU5YYZd1XsD72rZpBjbeh52mSNnMSC8lwblKZGwi+0QfIJ8CncnCoCDgoVnBHmKfByGJimPkIwtiAeBkH6ZHJaKmCeVnKKTHIihg5KNq4uoqmEtcRUtEREMBggtEr4QDrjCuRC8h7/BwxENeicSF8DKy82pyNLMOxzWygzFmdvD2L3P0dze4+Xh1Arkyepi7dfFvvTtLQkZBC0T/FX3CRgCMOBHsJ+EHYQY7OinAGECgQsB+Lu3AOK+CewcWjwxQeJBihtNGHSoQOE+iQ3//4XkwBBhRZMcUS6YSXOAwIL8PGqEaSJCiYt9SNoCmnJPAgUVLChdaoFBURN8MAzl2PQphwQLfDFd6lTowglHve6rKpbjhK7/pG5VinZP1qkiz1rl4+tr2LRwWU64cFEihwEtZgbgR1UiHaMVvxpOSwBA37kzGz9e8G+B5MIEKLutOGEsAH2ATQwYfTmuX8aETWdGPZmiZcccNSzeTCA1Sw0bdiitC7LBWgu8jQr8HRzqgpK6gX88QbrB14z/kF+ELpwB8eVQj/JkqdylAudji/+ts3039vEEfK8Vz2dlvxZKG0CmbkKDBvllRd6fCzDvBLKBDSCeffhRJEFebFk1k/Mv9jVIoIJZSeBggwUaNeB+Qk34IE0cXlihcfRxkOAJFFhwGmKlmWDiakZhUJtnLBpnWWcnKaAZcxI0piFGGLBm1mc90kajSCveeBVWKeYEoU2wqeaQi0PetoE+rr14EpVC7oAbAUHqhYExbn2XHHsVqbcVew9tx8+XJKk5AZsqqdlddGpqAKdbAYBn1pcczmSTdWvdmZ17c1b3FZ99vnTdCRFM8OEcAhLwm1NdXnWcBBSMRWmfkWZqVlsmLIiAp/o1gGV2vpS4lalGYsUOqXrddcKCmK61aZ8SjEpUpVFVoCpTj4r661Km7kBHjrDyc1RAIQAAIfkEBQoAGwAsBwAEAM4ACwAABf/gtmUCd4goQQgFKj6PYKi0yrrbc8i4ohQt12EHcal+MNSQiCP8gigdz7iCioaCIvUmZLp8QBzW0EN2vSlCuDtFKaq4RyHzQLEKZNdiQDhRDVooCwkbfm59EAmKi4SGIm+AjIsKjhsqB4mSjT2IOIOUnICeCaB/mZKFNTSRmqVpmJqklSqskq6PfYYCDwYHDC4REQwGCBLGxxIQDsHMwhAIX8bKzcENgSLGF9PU1j3Sy9zX2NrgzQziChLk1BHWxcjf7N046tvN82715czn9Pryz6Ilc4ACj4EBOCZM8KEnAYYADBRKnACAYUMFv1wotIhCEcaJCisqwJFgAUSQGyX/kCSVUUTIdKMwJlyo0oXHlhskwrTJciZHEXsgaqS4s6PJiCAr1uzYU8kBBSgnWFqpoMJMUjGtDmUwkmfVmVypakWhEKvXsS4nhLW5wNjVroJIoc05wSzTr0PtiigpYe4EC2vj4iWrFu5euWIMRBhacaVJhYQBEFjA9jHjyQ0xEABwGceGAZYjY0YBOrRLCxUp29QM+bRkx5s7ZyYgVbTqwwti2ybJ+vLtDYpycyZbYOlptxdx0kV+V7lC5iJAyyRrwYKxAdiz82ng0/jnAdMJFz0cPi104Ec1Vj9/M6F173vKL/feXv156dw11tlqeMMnv4V5Ap53GmjQQH97nFfg+IFiucfgRX5Z8KAgbUlQ4IULIlghhhdOSB6AgX0IVn8eReghen3NRIBsRgnH4l4LuEidZBjwRpt6NM5WGwoW0KSjCwX6yJSMab2GwwAPDXfaBCtWpluRTQqC5JM5oUZAjUNS+VeOLWpJEQ7VYQANW0INJSZVDFSnZphjSikfmzE5N4EEbQI1QJmnWXCmHulRp2edwDXF43txukenJwvI9xyg9Q26Z3MzGUcBYFEChZh6DVTq34AU8Iflh51Sd+CnKFYQ6mmZkhqfBKfSxZWqA9DZanWjxmhrWwi0qtCrt/43K6WqVjjpmhIqgEGvculaGKklKstAACEAACH5BAUKABwALAcABADOAAsAAAX/ICdyQmaMYyAUqPgIBiHPxNpy79kqRXH8wAPsRmDdXpAWgWdEIYm2llCHqjVHU+jjJkwqBTecwItShMXkEfNWSh8e1NGAcLgpDGlRgk7EJ/6Ae3VKfoF/fDuFhohVeDeCfXkcCQqDVQcQhn+VNDOYmpSWaoqBlUSfmowjEA+iEAEGDRGztAwGCDcXEA60tXEiCrq8vREMEBLIyRLCxMWSH
23342MzExnbRvQ2Sy7vN0zvVtNfU2tLY3rPgLdnDvca4VQS/Cpk3ABwSLQkYAQwT/P309vcI7OvXr94jBQMJ/nskkGA/BQBRLNDncAIAiDcG6LsxAWOLiQzmeURBKWSLCQbv/1F0eDGinJUKR47YY1IEgQASKk7Yc7ACRwZm7mHweRJoz59BJUogisKCUaFMR0x4SlJBVBFTk8pZivTR0K73rN5wqlXEAq5Fy3IYgHbEzQ0nLy4QSoCjXLoom96VOJEeCosK5n4kkFfqXjl94wa+l1gvAcGICbewAOAxY8l/Ky/QhAGz4cUkGxu2HNozhwMGBnCUqUdBg9UuW9eUynqSwLHIBujePef1ZGQZXcM+OFuEBeBhi3OYgLyqcuaxbT9vLkf4SeqyWxSQpKGB2gQpm1KdWbu72rPRzR9Ne2Nu9Kzr/1Jqj0yD/fvqP4aXOt5sW/5qsXXVcv1Nsp8IBUAmgswGF3llGgeU1YVXXKTN1FlhWFXW3gIE+DVChApysACHHo7Q4A35lLichh+ROBmLKAzgYmYEYDAhCgxKGOOMn4WR4kkDaoBBOxJtdNKQxFmg5JIWIBnQc07GaORfUY4AEkdV6jHlCEISSZ5yTXpp1pbGZbkWmcuZmQCaE6iJ0FhjMaDjTMsgZaNEHFRAQVp3bqXnZED1qYcECOz5V6BhSWCoVJQIKuKQi2KFKEkEFAqoAo7uYSmO3jk61wUUMKmknJ4SGimBmAa0qVQBhAAAIfkEBQoAGwAsBwAEAM4ACwAABf/gJm5FmRlEqhJC+bywgK5pO4rHI0D3pii22+Mg6/0Ej96weCMAk7cDkXf7lZTTnrMl7eaYoy10JN0ZFdco0XAuvKI6qkgVFJXYNwjkIBcNBgR8TQoGfRsJCRuCYYQQiI+ICosiCoGOkIiKfSl8mJkHZ4U9kZMbKaI3pKGXmJKrngmug4WwkhA0lrCBWgYFCCMQFwoQDRHGxwwGCBLMzRLEx8iGzMMO0cYNeCMKzBDW19lnF9DXDIY/48Xg093f0Q3s1dcR8OLe8+Y91OTv5wrj7o7B+7VNQqABIoRVCMBggsOHE36kSoCBIcSH3EbFangxogJYFi8CkJhqQciLJEf/LDDJEeJIBT0GsOwYUYJGBS0fjpQAMidGmyVP6sx4Y6VQhzs9VUwkwqaCCh0tmKoFtSMDmBOf9phg4SrVrROuasRQAaxXpVUhdsU6IsECZlvX3kwLUWzRt0BHOLTbNlbZG3vZinArge5Dvn7wbqtQkSYAAgtKmnSsYKVKo2AfW048uaPmG386i4Q8EQMBAIAnfB7xBxBqvapJ9zX9WgRS2YMpnvYMGdPK3aMjt/3dUcNI4blpj7iwkMFWDXDvSmgAlijrt9RTR78+PS6z1uAJZIe93Q8g5zcsWCi/4Y+C8bah5zUv3vv89uft30QP23punGCx5954oBBwnwYaNCDY/wYrsYeggnM9B2Fpf8GG2CEUVWhbWAtGouEGDy7Y4IEJVrbSiXghqGKIo7z1IVcXIkKWWR361QOLWWnIhwERpLaaCCee5iMBGJQmJGyPFTnbkfHVZGRtIGrg5HALEJAZbu39BuUEUmq1JJQIPtZilY5hGeSWsSk52G9XqsmgljdIcABytq13HyIM6RcUA+r1qZ4EBF3WHWB29tBgAzRhEGhig8KmqKFv8SeCeo+mgsF7YFXa1qWSbkDpom/mqR1PmHCqJ3fwNRVXjC7S6CZhFVCQ2lWvZiirhQq42SACt25IK2hv8TprriUV1usGgeka7LFcNmCldMLi6qZMgFLgpw16Cipb7bC1knXsBiEAACH5BAUKABsALAcABADOAAsAAAX/4FZsJPkUmUGsLCEUTywXglFuSg7fW1xAvNWLF6sFFcPb42C8EZCj24EJdCp2yoegWsolS0Uu6fmamg8n8YYcLU2bXSiRaXMGvqV6/KAeJAh8VgZqCX+BexCFioWAYgqNi4qAR4ORhRuHY408jAeUhAmYYiuVlpiflqGZa5CWkzc5fKmbbhIpsAoQDRG8vQwQCBLCwxK6vb5qwhfGxxENahvCEA7NzskSy7vNzzzK09W/PNHF1NvX2dXcN8K55cfh69Luveol3vO8zwi4Yhj+AQwmCBw4IYclDAAJDlQggVOChAoLKkgFkSCAHDwWLKhIEOONARsDKryogFPIiAUb/95gJNIiw4wnI778GFPhzBKFOAq8qLJEhQpiNArjMcHCmlTCUDIouTKBhApELSxFWiGiVKY4E2CAekPgUphDu0742nRrVLJZnyrFSqKQ2ohoSYAMW6IoDpNJ4bLdILTnAj8KUF7UeENjAKuDyxIgOuGiOI0EBBMgLNew5AUrDTMGsFixwBIaNCQuAXJB57qNJ2OWm2Aj4skwCQCIyNkhhtMkdsIuodE0AN4LJDRgfLPtn5YDLdBlraAByuUbBgxQwICxMOnYpVOPej074OFdlfc0TqC62OIbcppHjV4o+LrieWhfT8JC/I/T6W8oCl29vQ0XjLdBaA3s1RcPBO7lFvpX8BVoG4O5jTXRQRDuJ6FDTzEWF1/BCZhgbyAKE9qICYLloQYOFtahVRsWYlZ4KQJHlwHS/IYaZ6sZd9tmu5HQm2xi1UaTbzxYwJk/wBF5g5EEYOBZeEfGZmNdFyFZmZIR4jikbLThlh5kUUVJGmRT7sekkziRWUIACABk3T4qCsedgO4xhgGcY7q5pHJ4klBBTQRJ0CeHcoYHHUh6wgfdn9uJdSdMiebGJ0zUPTcoS286FCkrZxnYoYYKWLkBowhQoBeaOlZAgVhLidrXqg2G
23342iqpQpZ4apwSwRtjqrB3muoF9BboaXKmshlqWqsWiGt2wphJkQbAU5hoCACH5BAUKABsALAcABADOAAsAAAX/oGFw2WZuT5oZROsSQnGaKjRvilI893MItlNOJ5v5gDcFrHhKIWcEYu/xFEqNv6B1N62aclysF7fsZYe5aOx2yL5aAUGSaT1oTYMBwQ5VGCAJgYIJCnx1gIOBhXdwiIl7d0p2iYGQUAQBjoOFSQR/lIQHnZ+Ue6OagqYzSqSJi5eTpTxGcjcSChANEbu8DBAIEsHBChe5vL13G7fFuscRDcnKuM3H0La3EA7Oz8kKEsXazr7Cw9/Gztar5uHHvte47MjktznZ2w0G1+D3BgirAqJmJMAQgMGEgwgn5Ei0gKDBhBMALGRYEOJBb5QcWlQo4cbAihZz3GgIMqFEBSM1/4ZEOWPAgpIIJXYU+PIhRG8ja1qU6VHlzZknJNQ6UanCjQkWCIGSUGEjAwVLjc44+DTqUQtPPS5gejUrTa5TJ3g9sWCr1BNUWZI161StiQUDmLYdGfesibQ3XMq1OPYthrwuA2yU2LBs2cBHIypYQPPlYAKFD5cVvNPtW8eVGbdcQADATsiNO4cFAPkvHpedPzc8kUcPgNGgZ5RNDZG05reoE9s2vSEP79MEGiQGy1qP8LA4ZcdtsJE48ONoLTBtTV0B9LsTnPceoIDBDQvS7W7vfjVY3q3eZ4A339J4eaAmKqU/sV58HvJh2RcnIBsDUw0ABqhBA5aV5V9XUFGiHfVeAiWwoFgJJrIXRH1tEMiDFV4oHoAEGlaWhgIGSGBO2nFomYY3mKjVglidaNYJGJDkWW2xxTfbjCbVaOGNqoX2GloR8ZeTaECS9pthRGJH2g0b3Agbk6hNANtteHD2GJUucfajCQBy5OOTQ25ZgUPvaVVQmbKh9510/qQpwXx3SQdfk8tZJOd5b6JJFplT3ZnmmX3qd5l1eg5q00HrtUkUn0AKaiGjClSAgKLYZcgWXwocGRcCFGCKwSB6ceqphwmYRUFYT/1WKlOdUpipmxW0mlCqHjYkAaeoZlqrqZ4qd+upQKaapn/AmgAegZ8KUtYtFAQQAgAh+QQFCgAbACwHAAQAzgALAAAF/+C2PUcmiCiZGUTrEkKBis8jQEquKwU5HyXIbEPgyX7BYa5wTNmEMwWsSXsqFbEh8DYs9mrgGjdK6GkPY5GOeU6ryz7UFopSQEzygOGhJBjoIgMDBAcBM0V/CYqLCQqFOwobiYyKjn2TlI6GKC2YjJZknouaZAcQlJUHl6eooJwKooobqoewrJSEmyKdt59NhRKFMxLEEA4RyMkMEAjDEhfGycqAG8TQx9IRDRDE3d3R2ctD1RLg0ttKEnbY5wZD3+zJ6M7X2RHi9Oby7u/r9g38UFjTh2xZJBEBMDAboogAgwkQI07IMUORwocSJwCgWDFBAIwZOaJIsOBjRogKJP8wTODw5ESVHVtm3AhzpEeQElOuNDlTZ0ycEUWKWFASqEahGwYUPbnxoAgEdlYSqDBkgoUNClAlIHbSAoOsqCRQnQHxq1axVb06FWFxLIqyaze0Tft1JVqyE+pWXMD1pF6bYl3+HTqAWNW8cRUFzmih0ZAAB2oGKukSAAGGRHWJgLiR6AylBLpuHKKUMlMCngMpDSAa9QIUggZVVvDaJobLeC3XZpvgNgCmtPcuwP3WgmXSq4do0DC6o2/guzcseECtUoO0hmcsGKDgOt7ssBd07wqesAIGZC1YIBa7PQHvb1+SFo+++HrJSQfB33xfav3i5eX3Hnb4CTJgegEq8tH/YQEOcIJzbm2G2EoYRLgBXFpVmFYDcREV4HIcnmUhiGBRouEMJGJGzHIspqgdXxK0yCKHRNXoIX4uorCdTyjkyNtdPWrA4Up82EbAbzMRxxZRR54WXVLDIRmRcag5d2R6ugl3ZXzNhTecchpMhIGVAKAYpgJjjsSklBEd99maZoo535ZvdamjBEpusJyctg3h4X8XqodBMx0tiNeg/oGJaKGABpogS40KSqiaEgBqlQWLUtqoVQnytekEjzo0hHqhRorppOZt2p923M2AAV+oBtpAnnPNoB6HaU6mAAIU+IXmi3j2mtFXuUoHKwXpzVrsjcgGOauKEjQrwq157hitGq2NoWmjh7z6Wmxb0m5w66+2VRAuXN/yFUAIACH5BAUKABsALAcABADOAAsAAAX/4CZuRiaM45MZqBgIRbs9AqTcuFLE7VHLOh7KB5ERdjJaEaU4ClO/lgKWjKKcMiJQ8KgumcieVdQMD8cbBeuAkkC6LYLhOxoQ2PF5Ys9PKPBMen17f0CCg4VSh32JV4t8jSNqEIOEgJKPlkYBlJWRInKdiJdkmQlvKAsLBxdABA4RsbIMBggtEhcQsLKxDBC2TAS6vLENdJLDxMZAubu8vjIbzcQRtMzJz79S08oQEt/guNiyy7fcvMbh4OezdAvGrakLAQwyABsELQkY9BP+//ckyPDD4J9BfAMh1GsBoImMeQUN+lMgUJ9CiRMa5msxoB9Gh/o8GmxYMZXIgxtR/yQ46S/gQAURR0pDwYDfywoyLPip5AdnCwsMFPBU4BPFhKBDi444quCmDKZOfwZ9KEGpCKgcN1jdALSpPqIYsabS+nSqvqplvYqQYAeDPgwKwjaMtiDl0oaqUAyo+3TuWwUAMPpVCfee0cEjVBGQq2ABx7oTWmQk4FglZMGN9fGVDMCuiH2AOVOu/PmyxM630gwM0CCn6q8LjVJ8GXvpa5Uwn95OTC/nNxkda1/dLSK475IjCD6dHbK1ZOa4hXP9DXs5chJ00UpVm5xo2qRpoxptwF2E4/IbJpB/SDz9+q9b1aNfQH08+p4a8uvX8B53fLP+ycAfemjsRUBgp1H20K+BghHgVgt1GXZXZpZ5lt4ECjxYR4ScUWiShEtZqBiIInRGWnERNnjiBglw+JyGnxUmGowsyiiZg189lNtPGACjV2+S9UjbU0JWF6SPvEk3QZEqsZYTk3UAaRSUnznJI5LmESCdBVSyaOWUWLK4I5gDUYVeV1T9l+FZClCAUVA09uSmRHBCKAECFEhW51ht6rnmWBXkaR+NjuHpJ40D3DmnQXt2F+ihZxlqVKOfQRACACH5BAUKABwALAcABADOAAsAAAX/ICdyUCkUo/g8mUG8MCGkKgspeC6j6XEIEBpBUeCNfECaglBcOVfJFK7YQwZHQ6JRZBUqTrSuVEuD3nI45pYjFuWKvjjSkCoRaBUMWxkwBGgJCXspQ36Bh4EEB0oKhoiBgyNLjo8Ki4QElIiWfJqHnISNEI+Ql5J9o6SgkqKkgqYihamPkW6oNBgSfiMMDQkGCBLCwxIQDhHIyQwQCGMKxsnKVyPCF9DREQ3MxMPX0cu4wt7J2uHWx9jlKd3o39MiuefYEcvNkuLt5O8c1ePI2tyELXGQwoGDAQf+iEC2xByDCRAjTlAgIUWCBRgCPJQ4AQBFXAs0coT40WLIjRxL/47AcHLkxIomRXL0CHPERZkpa4q4iVKiyp0tR/7kwHMkTUBBJR5dOCEBAVcKKtCAyOHpowXCpk7goABqBZdcvWploACpBKkpIJI1q5OD2rIWE0R1uTZu1LFwbWL9OlKuWb4c6+o9i3dEgw0RCGDUG9KlRw56gDY2qmCByZBaASi+TACA0TucAaTteCcy0ZuOK3N2vJlx58+LRQyY3Xm0ZsgjZg+oPQLi7dUcNXi0LOJw1pgNtB7XG6CBy+U75SYfPTSQAgZTNUDnQHt67wnbZyvwLgKiMN3oCZB3C76tdewpLFgIP2C88rbi4Y+QT3+8S5USMICZXWj1pkEDeUU3lOYGB3alSoEiMIjgX4WlgNF2EibIwQIXauWXSRg2SAOHIU5IIIMoZkhhWiJaiFVbKo6AQEgQXrTAazO1JhkBrBG3Y2Y6EsUhaGn95hprSN0oWpFE7rhkeaQBchGOEWnwEmc0uKWZj0LeuNV3W4Y2lZHFlQCSRjTIl8uZ+kG5HU/3sRlnTG2ytyadytnD3HrmuRcSn+0h1dycexIK1KCjYaCnjCCVqOFFJTZ5GkUUjESWaUIKU2lgCmAKKQIUjHapXRKE+t2og1VgankNYnohqKJ2CmKplso6GKz7WYCgqxeuyoF8u9IQAgA7',
23343			msg: null,
23344			msgText: '<em>Loading the next set of posts...</em>',
23345			selector: null,
23346			speed: 'fast',
23347			start: undefined
23348		},
23349		state: {
23350			isDuringAjax: false,
23351			isInvalidPage: false,
23352			isDestroyed: false,
23353			isDone: false, // For when it goes all the way through the archive.
23354			isPaused: false,
23355			isBeyondMaxPage: false,
23356			currPage: 1
23357		},
23358		debug: false,
23359		behavior: undefined,
23360		binder: $(window), // used to cache the selector
23361		nextSelector: 'div.navigation a:first',
23362		navSelector: 'div.navigation',
23363		contentSelector: null, // rename to pageFragment
23364		extraScrollPx: 150,
23365		itemSelector: 'div.post',
23366		animate: false,
23367		pathParse: undefined,
23368		dataType: 'html',
23369		appendCallback: true,
23370		bufferPx: 40,
23371		errorCallback: function () { },
23372		infid: 0, //Instance ID
23373		pixelsFromNavToBottom: undefined,
23374		path: undefined, // Either parts of a URL as an array (e.g. ["/page/", "/"] or a function that takes in the page number and returns a URL
23375		prefill: false, // When the document is smaller than the window, load data until the document is larger or links are exhausted
23376		maxPage: undefined // to manually control maximum page (when maxPage is undefined, maximum page limitation is not work)
23377	};
23378
23379	$.infinitescroll.prototype = {
23380
23381		/*
23382			----------------------------
23383			Private methods
23384			----------------------------
23385			*/
23386
23387		// Bind or unbind from scroll
23388		_binding: function infscr_binding(binding) {
23389
23390			var instance = this,
23391				opts = instance.options;
23392
23393			opts.v = '2.0b2.120520';
23394
23395			// if behavior is defined and this function is extended, call that instead of default
23396			if (!!opts.behavior && this['_binding_' + opts.behavior] !== undefined) {
23397				this['_binding_' + opts.behavior].call(this);
23398				return;
23399			}
23400
23401			if (binding !== 'bind' && binding !== 'unbind') {
23402				this._debug('Binding value  ' + binding + ' not valid');
23403				return false;
23404			}
23405
23406			if (binding === 'unbind') {
23407				(this.options.binder).unbind('smartscroll.infscr.' + instance.options.infid);
23408			} else {
23409				(this.options.binder)[binding]('smartscroll.infscr.' + instance.options.infid, function () {
23410					instance.scroll();
23411				});
23412			}
23413
23414			this._debug('Binding', binding);
23415		},
23416
23417		// Fundamental aspects of the plugin are initialized
23418		_create: function infscr_create(options, callback) {
23419
23420			// Add custom options to defaults
23421			var opts = $.extend(true, {}, $.infinitescroll.defaults, options);
23422			this.options = opts;
23423			var $window = $(window);
23424			var instance = this;
23425
23426			// Validate selectors
23427			if (!instance._validate(options)) {
23428				return false;
23429			}
23430
23431			// Validate page fragment path
23432			var path = $(opts.nextSelector).attr('href');
23433			if (!path) {
23434				this._debug('Navigation selector not found');
23435				return false;
23436			}
23437
23438			// Set the path to be a relative URL from root.
23439			opts.path = opts.path || this._determinepath(path);
23440
23441			// contentSelector is 'page fragment' option for .load() / .ajax() calls
23442			opts.contentSelector = opts.contentSelector || this.element;
23443
23444			// loading.selector - if we want to place the load message in a specific selector, defaulted to the contentSelector
23445			opts.loading.selector = opts.loading.selector || opts.contentSelector;
23446
23447			// Define loading.msg
23448			opts.loading.msg = opts.loading.msg || $('<div id="infscr-loading"><img alt="Loading..." src="' + opts.loading.img + '" /><div>' + opts.loading.msgText + '</div></div>');
23449
23450			// Preload loading.img
23451			(new Image()).src = opts.loading.img;
23452
23453			// distance from nav links to bottom
23454			// computed as: height of the document + top offset of container - top offset of nav link
23455			if (opts.pixelsFromNavToBottom === undefined) {
23456				var $nav = $(opts.navSelector),
23457					$content = $(opts.contentSelector),
23458					triggerTop = $nav.is(':visible') ? $nav.offset().top : $content.offset().top + $content.outerHeight();
23459
23460				opts.pixelsFromNavToBottom = $(document).height() - triggerTop;
23461				this._debug('pixelsFromNavToBottom: ' + opts.pixelsFromNavToBottom);
23462			}
23463
23464			var self = this;
23465
23466			// determine loading.start actions
23467			opts.loading.start = opts.loading.start || function () {
23468				$(opts.navSelector).hide();
23469				opts.loading.msg
23470					.appendTo(opts.loading.selector)
23471					.show(opts.loading.speed, $.proxy(function () {
23472						this.beginAjax(opts);
23473					}, self));
23474			};
23475
23476			// determine loading.finished actions
23477			opts.loading.finished = opts.loading.finished || function () {
23478				if (!opts.state.isBeyondMaxPage)
23479					opts.loading.msg.fadeOut(opts.loading.speed);
23480			};
23481
23482			// callback loading
23483			opts.callback = function (instance, data, url) {
23484				if (!!opts.behavior && instance['_callback_' + opts.behavior] !== undefined) {
23485					instance['_callback_' + opts.behavior].call($(opts.contentSelector)[0], data, url);
23486				}
23487
23488				if (callback) {
23489					callback.call($(opts.contentSelector)[0], data, opts, url);
23490				}
23491
23492				if (opts.prefill) {
23493					$window.bind('resize.infinite-scroll', instance._prefill);
23494				}
23495			};
23496
23497			if (options.debug) {
23498				// Tell IE9 to use its built-in console
23499				if (Function.prototype.bind && (typeof console === 'object' || typeof console === 'function') && typeof console.log === 'object') {
23500					['log', 'info', 'warn', 'error', 'assert', 'dir', 'clear', 'profile', 'profileEnd']
23501						.forEach(function (method) {
23502							console[method] = this.call(console[method], console);
23503						}, Function.prototype.bind);
23504				}
23505			}
23506
23507			this._setup();
23508
23509			// Setups the prefill method for use
23510			if (opts.prefill) {
23511				this._prefill();
23512			}
23513
23514			// Return true to indicate successful creation
23515			return true;
23516		},
23517
23518		_prefill: function infscr_prefill() {
23519			var instance = this;
23520			var $window = $(window);
23521
23522			function needsPrefill() {
23523				return ($(instance.options.contentSelector).height() <= $window.height());
23524			}
23525
23526			this._prefill = function () {
23527				if (needsPrefill()) {
23528					instance.scroll();
23529				}
23530
23531				$window.bind('resize.infinite-scroll', function () {
23532					if (needsPrefill()) {
23533						$window.unbind('resize.infinite-scroll');
23534						instance.scroll();
23535					}
23536				});
23537			};
23538
23539			// Call self after setting up the new function
23540			this._prefill();
23541		},
23542
23543		// Console log wrapper
23544		_debug: function infscr_debug() {
23545			if (true !== this.options.debug) {
23546				return;
23547			}
23548
23549			if (typeof console !== 'undefined' && typeof console.log === 'function') {
23550				// Modern browsers
23551				// Single argument, which is a string
23552				if ((Array.prototype.slice.call(arguments)).length === 1 && typeof Array.prototype.slice.call(arguments)[0] === 'string') {
23553					console.log((Array.prototype.slice.call(arguments)).toString());
23554				} else {
23555					console.log(Array.prototype.slice.call(arguments));
23556				}
23557			} else if (!Function.prototype.bind && typeof console !== 'undefined' && typeof console.log === 'object') {
23558				// IE8
23559				Function.prototype.call.call(console.log, console, Array.prototype.slice.call(arguments));
23560			}
23561		},
23562
23563		// find the number to increment in the path.
23564		_determinepath: function infscr_determinepath(path) {
23565
23566			var opts = this.options;
23567
23568			// if behavior is defined and this function is extended, call that instead of default
23569			if (!!opts.behavior && this['_determinepath_' + opts.behavior] !== undefined) {
23570				return this['_determinepath_' + opts.behavior].call(this, path);
23571			}
23572
23573			var url = new URL(path);
23574			var pathname = url.pathname;
23575			var hasNumber = /\d/.test(pathname);
23576
23577			if (!!opts.pathParse) {
23578				this._debug('pathParse manual');
23579				return opts.pathParse(path, this.options.state.currPage + 1);
23580            } else if (hasNumber && path.match(/(\?|\&)(upage=)(\d+)/)) {
23581				var parts = path.split(/(\?|\&)(upage=)(\d+)/);
23582				return [parts[0] + parts[1] + parts[2], parts[4]];
23583            } else if (path.match(/^(.*?)\b2\b(.*?$)/)) {
23584				path = path.match(/^(.*?)\b2\b(.*?$)/).slice(1);
23585
23586                // if there is any 2 in the url at all.
23587            } else if (path.match(/^(.*?)2(.*?$)/)) {
23588                // page= is used in django:
23589                // http://www.infinite-scroll.com/changelog/comment-page-1/#comment-127
23590                if (path.match(/^(.*?page=)2(\/.*|$)/)) {
23591                    path = path.match(/^(.*?page=)2(\/.*|$)/).slice(1);
23592                    return path;
23593                }
23594
23595                path = path.match(/^(.*?)2(.*?$)/).slice(1);
23596
23597            } else {
23598                // page= is used in drupal too but second page is page=1 not page=2:
23599                // thx Jerod Fritz, vladikoff
23600                if (path.match(/^(.*?page=)1(\/.*|$)/)) {
23601                    path = path.match(/^(.*?page=)1(\/.*|$)/).slice(1);
23602                    return path;
23603                } else {
23604                    this._debug("Sorry, we couldn't parse your Next (Previous Posts) URL. Verify your the css selector points to the correct A tag. If you still get this error: yell, scream, and kindly ask for help at infinite-scroll.com.");
23605                    // Get rid of isInvalidPage to allow permalink to state
23606                    opts.state.isInvalidPage = true;  //prevent it from running on this page.
23607                }
23608            }
23609            this._debug('determinePath', path);
23610            return path;
23611
23612        },
23613
23614        // Custom error
23615        _error: function infscr_error(xhr) {
23616
23617            var opts = this.options;
23618
23619            // if behavior is defined and this function is extended, call that instead of default
23620            if (!!opts.behavior && this['_error_'+opts.behavior] !== undefined) {
23621                this['_error_'+opts.behavior].call(this,xhr);
23622                return;
23623            }
23624
23625            if (xhr !== 'destroy' && xhr !== 'end') {
23626                xhr = 'unknown';
23627            }
23628
23629            this._debug('Error', xhr);
23630
23631            if (xhr === 'end' || opts.state.isBeyondMaxPage) {
23632                this._showdonemsg();
23633            }
23634
23635            opts.state.isDone = true;
23636            opts.state.currPage = 1; // if you need to go back to this instance
23637            opts.state.isPaused = false;
23638            opts.state.isBeyondMaxPage = false;
23639            this._binding('unbind');
23640
23641        },
23642
23643        // Load Callback
23644        _loadcallback: function infscr_loadcallback(box, data, url) {
23645            var opts = this.options,
23646            callback = this.options.callback, // GLOBAL OBJECT FOR CALLBACK
23647            result = (opts.state.isDone) ? 'done' : (!opts.appendCallback) ? 'no-append' : 'append',
23648            frag;
23649
23650            // if behavior is defined and this function is extended, call that instead of default
23651            if (!!opts.behavior && this['_loadcallback_'+opts.behavior] !== undefined) {
23652                this['_loadcallback_'+opts.behavior].call(this,box,data);
23653                return;
23654            }
23655
23656            switch (result) {
23657                case 'done':
23658                    this._showdonemsg();
23659                    return false;
23660
23661                case 'no-append':
23662                    if (opts.dataType === 'html') {
23663                        data = '<div>' + data + '</div>';
23664                        data = $(data).find(opts.itemSelector);
23665                    }
23666
23667                    // if it didn't return anything
23668                    if (data.length === 0) {
23669                        return this._error('end');
23670                    }
23671
23672                    break;
23673
23674                case 'append':
23675                    var children = box.children();
23676                    // if it didn't return anything
23677                    if (children.length === 0) {
23678                        return this._error('end');
23679                    }
23680
23681                    // use a documentFragment because it works when content is going into a table or UL
23682                    frag = document.createDocumentFragment();
23683                    while (box[0].firstChild) {
23684                        frag.appendChild(box[0].firstChild);
23685                    }
23686
23687                    this._debug('contentSelector', $(opts.contentSelector)[0]);
23688                    $(opts.contentSelector)[0].appendChild(frag);
23689                    // previously, we would pass in the new DOM element as context for the callback
23690                    // however we're now using a documentfragment, which doesn't have parents or children,
23691                    // so the context is the contentContainer guy, and we pass in an array
23692                    // of the elements collected as the first argument.
23693
23694                    data = children.get();
23695                    break;
23696            }
23697
23698            // loadingEnd function
23699            opts.loading.finished.call($(opts.contentSelector)[0],opts);
23700
23701            // smooth scroll to ease in the new content
23702            if (opts.animate) {
23703                var scrollTo = $(window).scrollTop() + $(opts.loading.msg).height() + opts.extraScrollPx + 'px';
23704                $('html,body').animate({ scrollTop: scrollTo }, 800, function () { opts.state.isDuringAjax = false; });
23705            }
23706
23707            if (!opts.animate) {
23708                // once the call is done, we can allow it again.
23709                opts.state.isDuringAjax = false;
23710            }
23711
23712            callback(this, data, url);
23713
23714            if (opts.prefill) {
23715                this._prefill();
23716            }
23717        },
23718
23719        _nearbottom: function infscr_nearbottom() {
23720
23721            var opts = this.options,
23722            pixelsFromWindowBottomToBottom = 0 + $(document).height() - (opts.binder.scrollTop()) - $(window).height();
23723
23724            // if behavior is defined and this function is extended, call that instead of default
23725            if (!!opts.behavior && this['_nearbottom_'+opts.behavior] !== undefined) {
23726                return this['_nearbottom_'+opts.behavior].call(this);
23727            }
23728
23729            this._debug('math:', pixelsFromWindowBottomToBottom, opts.pixelsFromNavToBottom);
23730
23731            // if distance remaining in the scroll (including buffer) is less than the orignal nav to bottom....
23732            return (pixelsFromWindowBottomToBottom - opts.bufferPx < opts.pixelsFromNavToBottom);
23733
23734        },
23735
23736        // Pause / temporarily disable plugin from firing
23737        _pausing: function infscr_pausing(pause) {
23738
23739            var opts = this.options;
23740
23741            // if behavior is defined and this function is extended, call that instead of default
23742            if (!!opts.behavior && this['_pausing_'+opts.behavior] !== undefined) {
23743                this['_pausing_'+opts.behavior].call(this,pause);
23744                return;
23745            }
23746
23747            // If pause is not 'pause' or 'resume', toggle it's value
23748            if (pause !== 'pause' && pause !== 'resume' && pause !== null) {
23749                this._debug('Invalid argument. Toggling pause value instead');
23750            }
23751
23752            pause = (pause && (pause === 'pause' || pause === 'resume')) ? pause : 'toggle';
23753
23754            switch (pause) {
23755                case 'pause':
23756                    opts.state.isPaused = true;
23757                break;
23758
23759                case 'resume':
23760                    opts.state.isPaused = false;
23761                break;
23762
23763                case 'toggle':
23764                    opts.state.isPaused = !opts.state.isPaused;
23765                break;
23766            }
23767
23768            this._debug('Paused', opts.state.isPaused);
23769            return false;
23770
23771        },
23772
23773        // Behavior is determined
23774        // If the behavior option is undefined, it will set to default and bind to scroll
23775        _setup: function infscr_setup() {
23776
23777            var opts = this.options;
23778
23779            // if behavior is defined and this function is extended, call that instead of default
23780            if (!!opts.behavior && this['_setup_'+opts.behavior] !== undefined) {
23781                this['_setup_'+opts.behavior].call(this);
23782                return;
23783            }
23784
23785            this._binding('bind');
23786
23787            return false;
23788
23789        },
23790
23791        // Show done message
23792        _showdonemsg: function infscr_showdonemsg() {
23793
23794            var opts = this.options;
23795
23796            // if behavior is defined and this function is extended, call that instead of default
23797            if (!!opts.behavior && this['_showdonemsg_'+opts.behavior] !== undefined) {
23798                this['_showdonemsg_'+opts.behavior].call(this);
23799                return;
23800            }
23801
23802            opts.loading.msg
23803            .find('img')
23804            .hide()
23805            .parent()
23806            .find('div').html(opts.loading.finishedMsg).animate({ opacity: 1 }, 2000, function () {
23807                $(this).parent().fadeOut(opts.loading.speed);
23808            });
23809
23810            // user provided callback when done
23811            opts.errorCallback.call($(opts.contentSelector)[0],'done');
23812        },
23813
23814        // grab each selector option and see if any fail
23815        _validate: function infscr_validate(opts) {
23816            for (var key in opts) {
23817                if (key.indexOf && key.indexOf('Selector') > -1 && $(opts[key]).length === 0) {
23818                    this._debug('Your ' + key + ' found no elements.');
23819                    return false;
23820                }
23821            }
23822
23823            return true;
23824        },
23825
23826        /*
23827            ----------------------------
23828            Public methods
23829            ----------------------------
23830            */
23831
23832        // Bind to scroll
23833        bind: function infscr_bind() {
23834            this._binding('bind');
23835        },
23836
23837        // Destroy current instance of plugin
23838        destroy: function infscr_destroy() {
23839            this.options.state.isDestroyed = true;
23840            this.options.loading.finished();
23841            return this._error('destroy');
23842        },
23843
23844        // Set pause value to false
23845        pause: function infscr_pause() {
23846            this._pausing('pause');
23847        },
23848
23849        // Set pause value to false
23850        resume: function infscr_resume() {
23851            this._pausing('resume');
23852        },
23853
23854        beginAjax: function infscr_ajax(opts) {
23855            var instance = this,
23856                path = opts.path,
23857                box, desturl, method, condition;
23858
23859			// increment the URL bit. e.g. /page/3/
23860            opts.state.currPage++;
23861
23862            // Manually control maximum page
23863            if ( opts.maxPage !== undefined && opts.state.currPage > opts.maxPage ){
23864                opts.state.isBeyondMaxPage = true;
23865                this.destroy();
23866                return;
23867            }
23868
23869            // if we're dealing with a table we can't use DIVs
23870            box = $(opts.contentSelector).is('table, tbody') ? $('<tbody/>') : $('<div/>');
23871
23872			desturl = (typeof path === 'function') ? path(opts.state.currPage) : path.join(opts.state.currPage);
23873
23874            instance._debug('heading into ajax', desturl);
23875
23876            method = (opts.dataType === 'html' || opts.dataType === 'json' ) ? opts.dataType : 'html+callback';
23877            if (opts.appendCallback && opts.dataType === 'html') {
23878                method += '+callback';
23879            }
23880
23881            switch (method) {
23882                case 'html+callback':
23883                    instance._debug('Using HTML via .load() method');
23884                    box.load(desturl + ' ' + opts.itemSelector, undefined, function infscr_ajax_callback(responseText) {
23885                        instance._loadcallback(box, responseText, desturl);
23886                    });
23887
23888                    break;
23889
23890                case 'html':
23891                    instance._debug('Using ' + (method.toUpperCase()) + ' via $.ajax() method');
23892                    $.ajax({
23893                        // params
23894                        url: desturl,
23895                        dataType: opts.dataType,
23896                        complete: function infscr_ajax_callback(jqXHR, textStatus) {
23897                            condition = (typeof (jqXHR.isResolved) !== 'undefined') ? (jqXHR.isResolved()) : (textStatus === 'success' || textStatus === 'notmodified');
23898                            if (condition) {
23899                                instance._loadcallback(box, jqXHR.responseText, desturl);
23900                            } else {
23901                                instance._error('end');
23902                            }
23903                        }
23904                    });
23905
23906                    break;
23907                case 'json':
23908                    instance._debug('Using ' + (method.toUpperCase()) + ' via $.ajax() method');
23909                    $.ajax({
23910                        dataType: 'json',
23911                        type: 'GET',
23912                        url: desturl,
23913                        success: function (data, textStatus, jqXHR) {
23914                            condition = (typeof (jqXHR.isResolved) !== 'undefined') ? (jqXHR.isResolved()) : (textStatus === 'success' || textStatus === 'notmodified');
23915                            if (opts.appendCallback) {
23916                                // if appendCallback is true, you must defined template in options.
23917                                // note that data passed into _loadcallback is already an html (after processed in opts.template(data)).
23918                                if (opts.template !== undefined) {
23919                                    var theData = opts.template(data);
23920                                    box.append(theData);
23921                                    if (condition) {
23922                                        instance._loadcallback(box, theData);
23923                                    } else {
23924                                        instance._error('end');
23925                                    }
23926                                } else {
23927                                    instance._debug('template must be defined.');
23928                                    instance._error('end');
23929                                }
23930                            } else {
23931                                // if appendCallback is false, we will pass in the JSON object. you should handle it yourself in your callback.
23932                                if (condition) {
23933                                    instance._loadcallback(box, data, desturl);
23934                                } else {
23935                                    instance._error('end');
23936                                }
23937                            }
23938                        },
23939                        error: function() {
23940                            instance._debug('JSON ajax request failed.');
23941                            instance._error('end');
23942                        }
23943                    });
23944
23945                    break;
23946            }
23947        },
23948
23949        // Retrieve next set of content items
23950        retrieve: function infscr_retrieve(pageNum) {
23951            pageNum = pageNum || null;
23952
23953            var instance = this,
23954            opts = instance.options;
23955
23956            // if behavior is defined and this function is extended, call that instead of default
23957            if (!!opts.behavior && this['retrieve_'+opts.behavior] !== undefined) {
23958                this['retrieve_'+opts.behavior].call(this,pageNum);
23959                return;
23960            }
23961
23962            // for manual triggers, if destroyed, get out of here
23963            if (opts.state.isDestroyed) {
23964                this._debug('Instance is destroyed');
23965                return false;
23966            }
23967
23968            // we dont want to fire the ajax multiple times
23969            opts.state.isDuringAjax = true;
23970
23971            opts.loading.start.call($(opts.contentSelector)[0],opts);
23972        },
23973
23974        // Check to see next page is needed
23975        scroll: function infscr_scroll() {
23976
23977            var opts = this.options,
23978            state = opts.state;
23979
23980            // if behavior is defined and this function is extended, call that instead of default
23981            if (!!opts.behavior && this['scroll_'+opts.behavior] !== undefined) {
23982                this['scroll_'+opts.behavior].call(this);
23983                return;
23984            }
23985
23986            if (state.isDuringAjax || state.isInvalidPage || state.isDone || state.isDestroyed || state.isPaused) {
23987                return;
23988            }
23989
23990            if (!this._nearbottom()) {
23991                return;
23992            }
23993
23994            this.retrieve();
23995
23996        },
23997
23998        // Toggle pause value
23999        toggle: function infscr_toggle() {
24000            this._pausing();
24001        },
24002
24003        // Unbind from scroll
24004        unbind: function infscr_unbind() {
24005            this._binding('unbind');
24006        },
24007
24008        // update options
24009        update: function infscr_options(key) {
24010            if ($.isPlainObject(key)) {
24011                this.options = $.extend(true,this.options,key);
24012            }
24013        }
24014    };
24015
24016
24017    /*
24018        ----------------------------
24019        Infinite Scroll function
24020        ----------------------------
24021
24022        Borrowed logic from the following...
24023
24024        jQuery UI
24025        - https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.widget.js
24026
24027        jCarousel
24028        - https://github.com/jsor/jcarousel/blob/master/lib/jquery.jcarousel.js
24029
24030        Masonry
24031        - https://github.com/desandro/masonry/blob/master/jquery.masonry.js
24032
24033*/
24034
24035    $.fn.infinitescroll = function infscr_init(options, callback) {
24036
24037
24038        var thisCall = typeof options;
24039
24040        switch (thisCall) {
24041
24042            // method
24043            case 'string':
24044                var args = Array.prototype.slice.call(arguments, 1);
24045
24046                this.each(function () {
24047                    var instance = $.data(this, 'infinitescroll');
24048
24049                    if (!instance) {
24050                        // not setup yet
24051                        // return $.error('Method ' + options + ' cannot be called until Infinite Scroll is setup');
24052                        return false;
24053                    }
24054
24055                    if (!$.isFunction(instance[options]) || options.charAt(0) === '_') {
24056                        // return $.error('No such method ' + options + ' for Infinite Scroll');
24057                        return false;
24058                    }
24059
24060                    // no errors!
24061                    instance[options].apply(instance, args);
24062                });
24063
24064            break;
24065
24066            // creation
24067            case 'object':
24068
24069                this.each(function () {
24070
24071                var instance = $.data(this, 'infinitescroll');
24072
24073                if (instance) {
24074
24075                    // update options of current instance
24076                    instance.update(options);
24077
24078                } else {
24079
24080                    // initialize new instance
24081                    instance = new $.infinitescroll(options, callback, this);
24082
24083                    // don't attach if instantiation failed
24084                    if (!instance.failed) {
24085                        $.data(this, 'infinitescroll', instance);
24086                    }
24087
24088                }
24089
24090            });
24091
24092            break;
24093
24094        }
24095
24096        return this;
24097    };
24098
24099
24100
24101    /*
24102     * smartscroll: debounced scroll event for jQuery *
24103     * https://github.com/lukeshumard/smartscroll
24104     * Based on smartresize by @louis_remi: https://github.com/lrbabe/jquery.smartresize.js *
24105     * Copyright 2011 Louis-Remi & Luke Shumard * Licensed under the MIT license. *
24106     */
24107
24108    var event = $.event,
24109    scrollTimeout;
24110
24111    event.special.smartscroll = {
24112        setup: function () {
24113            $(this).bind('scroll', event.special.smartscroll.handler);
24114        },
24115        teardown: function () {
24116            $(this).unbind('scroll', event.special.smartscroll.handler);
24117        },
24118        handler: function (event, execAsap) {
24119            // Save the context
24120            var context = this,
24121            args = arguments;
24122
24123            // set correct event type
24124            event.type = 'smartscroll';
24125
24126            if (scrollTimeout) { clearTimeout(scrollTimeout); }
24127            scrollTimeout = setTimeout(function () {
24128                $(context).trigger('smartscroll', args);
24129            }, execAsap === 'execAsap' ? 0 : 100);
24130        }
24131    };
24132
24133    $.fn.smartscroll = function (fn) {
24134        return fn ? this.bind('smartscroll', fn) : this.trigger('smartscroll', ['execAsap']);
24135    };
24136
24137}));
24138
24139/*!
24140Waypoints - 4.0.1
24141Copyright © 2011-2016 Caleb Troughton
24142Licensed under the MIT license.
24143https://github.com/imakewebthings/waypoints/blob/master/licenses.txt
24144*/
24145(function() {
24146  'use strict'
24147
24148  var keyCounter = 0
24149  var allWaypoints = {}
24150
24151  /* http://imakewebthings.com/waypoints/api/waypoint */
24152  function Waypoint(options) {
24153    if (!options) {
24154      throw new Error('No options passed to Waypoint constructor')
24155    }
24156    if (!options.element) {
24157      throw new Error('No element option passed to Waypoint constructor')
24158    }
24159    if (!options.handler) {
24160      throw new Error('No handler option passed to Waypoint constructor')
24161    }
24162
24163    this.key = 'waypoint-' + keyCounter
24164    this.options = Waypoint.Adapter.extend({}, Waypoint.defaults, options)
24165    this.element = this.options.element
24166    this.adapter = new Waypoint.Adapter(this.element)
24167    this.callback = options.handler
24168    this.axis = this.options.horizontal ? 'horizontal' : 'vertical'
24169    this.enabled = this.options.enabled
24170    this.triggerPoint = null
24171    this.group = Waypoint.Group.findOrCreate({
24172      name: this.options.group,
24173      axis: this.axis
24174    })
24175    this.context = Waypoint.Context.findOrCreateByElement(this.options.context)
24176
24177    if (Waypoint.offsetAliases[this.options.offset]) {
24178      this.options.offset = Waypoint.offsetAliases[this.options.offset]
24179    }
24180    this.group.add(this)
24181    this.context.add(this)
24182    allWaypoints[this.key] = this
24183    keyCounter += 1
24184  }
24185
24186  /* Private */
24187  Waypoint.prototype.queueTrigger = function(direction) {
24188    this.group.queueTrigger(this, direction)
24189  }
24190
24191  /* Private */
24192  Waypoint.prototype.trigger = function(args) {
24193    if (!this.enabled) {
24194      return
24195    }
24196    if (this.callback) {
24197      this.callback.apply(this, args)
24198    }
24199  }
24200
24201  /* Public */
24202  /* http://imakewebthings.com/waypoints/api/destroy */
24203  Waypoint.prototype.destroy = function() {
24204    this.context.remove(this)
24205    this.group.remove(this)
24206    delete allWaypoints[this.key]
24207  }
24208
24209  /* Public */
24210  /* http://imakewebthings.com/waypoints/api/disable */
24211  Waypoint.prototype.disable = function() {
24212    this.enabled = false
24213    return this
24214  }
24215
24216  /* Public */
24217  /* http://imakewebthings.com/waypoints/api/enable */
24218  Waypoint.prototype.enable = function() {
24219    this.context.refresh()
24220    this.enabled = true
24221    return this
24222  }
24223
24224  /* Public */
24225  /* http://imakewebthings.com/waypoints/api/next */
24226  Waypoint.prototype.next = function() {
24227    return this.group.next(this)
24228  }
24229
24230  /* Public */
24231  /* http://imakewebthings.com/waypoints/api/previous */
24232  Waypoint.prototype.previous = function() {
24233    return this.group.previous(this)
24234  }
24235
24236  /* Private */
24237  Waypoint.invokeAll = function(method) {
24238    var allWaypointsArray = []
24239    for (var waypointKey in allWaypoints) {
24240      allWaypointsArray.push(allWaypoints[waypointKey])
24241    }
24242    for (var i = 0, end = allWaypointsArray.length; i < end; i++) {
24243      allWaypointsArray[i][method]()
24244    }
24245  }
24246
24247  /* Public */
24248  /* http://imakewebthings.com/waypoints/api/destroy-all */
24249  Waypoint.destroyAll = function() {
24250    Waypoint.invokeAll('destroy')
24251  }
24252
24253  /* Public */
24254  /* http://imakewebthings.com/waypoints/api/disable-all */
24255  Waypoint.disableAll = function() {
24256    Waypoint.invokeAll('disable')
24257  }
24258
24259  /* Public */
24260  /* http://imakewebthings.com/waypoints/api/enable-all */
24261  Waypoint.enableAll = function() {
24262    Waypoint.Context.refreshAll()
24263    for (var waypointKey in allWaypoints) {
24264      allWaypoints[waypointKey].enabled = true
24265    }
24266    return this
24267  }
24268
24269  /* Public */
24270  /* http://imakewebthings.com/waypoints/api/refresh-all */
24271  Waypoint.refreshAll = function() {
24272    Waypoint.Context.refreshAll()
24273  }
24274
24275  /* Public */
24276  /* http://imakewebthings.com/waypoints/api/viewport-height */
24277  Waypoint.viewportHeight = function() {
24278    return window.innerHeight || document.documentElement.clientHeight
24279  }
24280
24281  /* Public */
24282  /* http://imakewebthings.com/waypoints/api/viewport-width */
24283  Waypoint.viewportWidth = function() {
24284    return document.documentElement.clientWidth
24285  }
24286
24287  Waypoint.adapters = []
24288
24289  Waypoint.defaults = {
24290    context: window,
24291    continuous: true,
24292    enabled: true,
24293    group: 'default',
24294    horizontal: false,
24295    offset: 0
24296  }
24297
24298  Waypoint.offsetAliases = {
24299    'bottom-in-view': function() {
24300      return this.context.innerHeight() - this.adapter.outerHeight()
24301    },
24302    'right-in-view': function() {
24303      return this.context.innerWidth() - this.adapter.outerWidth()
24304    }
24305  }
24306
24307  window.Waypoint = Waypoint
24308}())
24309;(function() {
24310  'use strict'
24311
24312  function requestAnimationFrameShim(callback) {
24313    window.setTimeout(callback, 1000 / 60)
24314  }
24315
24316  var keyCounter = 0
24317  var contexts = {}
24318  var Waypoint = window.Waypoint
24319  var oldWindowLoad = window.onload
24320
24321  /* http://imakewebthings.com/waypoints/api/context */
24322  function Context(element) {
24323    this.element = element
24324    this.Adapter = Waypoint.Adapter
24325    this.adapter = new this.Adapter(element)
24326    this.key = 'waypoint-context-' + keyCounter
24327    this.didScroll = false
24328    this.didResize = false
24329    this.oldScroll = {
24330      x: this.adapter.scrollLeft(),
24331      y: this.adapter.scrollTop()
24332    }
24333    this.waypoints = {
24334      vertical: {},
24335      horizontal: {}
24336    }
24337
24338    element.waypointContextKey = this.key
24339    contexts[element.waypointContextKey] = this
24340    keyCounter += 1
24341    if (!Waypoint.windowContext) {
24342      Waypoint.windowContext = true
24343      Waypoint.windowContext = new Context(window)
24344    }
24345
24346    this.createThrottledScrollHandler()
24347    this.createThrottledResizeHandler()
24348  }
24349
24350  /* Private */
24351  Context.prototype.add = function(waypoint) {
24352    var axis = waypoint.options.horizontal ? 'horizontal' : 'vertical'
24353    this.waypoints[axis][waypoint.key] = waypoint
24354    this.refresh()
24355  }
24356
24357  /* Private */
24358  Context.prototype.checkEmpty = function() {
24359    var horizontalEmpty = this.Adapter.isEmptyObject(this.waypoints.horizontal)
24360    var verticalEmpty = this.Adapter.isEmptyObject(this.waypoints.vertical)
24361    var isWindow = this.element == this.element.window
24362    if (horizontalEmpty && verticalEmpty && !isWindow) {
24363      this.adapter.off('.waypoints')
24364      delete contexts[this.key]
24365    }
24366  }
24367
24368  /* Private */
24369  Context.prototype.createThrottledResizeHandler = function() {
24370    var self = this
24371
24372    function resizeHandler() {
24373      self.handleResize()
24374      self.didResize = false
24375    }
24376
24377    this.adapter.on('resize.waypoints', function() {
24378      if (!self.didResize) {
24379        self.didResize = true
24380        Waypoint.requestAnimationFrame(resizeHandler)
24381      }
24382    })
24383  }
24384
24385  /* Private */
24386  Context.prototype.createThrottledScrollHandler = function() {
24387    var self = this
24388    function scrollHandler() {
24389      self.handleScroll()
24390      self.didScroll = false
24391    }
24392
24393    this.adapter.on('scroll.waypoints', function() {
24394      if (!self.didScroll || Waypoint.isTouch) {
24395        self.didScroll = true
24396        Waypoint.requestAnimationFrame(scrollHandler)
24397      }
24398    })
24399  }
24400
24401  /* Private */
24402  Context.prototype.handleResize = function() {
24403    Waypoint.Context.refreshAll()
24404  }
24405
24406  /* Private */
24407  Context.prototype.handleScroll = function() {
24408    var triggeredGroups = {}
24409    var axes = {
24410      horizontal: {
24411        newScroll: this.adapter.scrollLeft(),
24412        oldScroll: this.oldScroll.x,
24413        forward: 'right',
24414        backward: 'left'
24415      },
24416      vertical: {
24417        newScroll: this.adapter.scrollTop(),
24418        oldScroll: this.oldScroll.y,
24419        forward: 'down',
24420        backward: 'up'
24421      }
24422    }
24423
24424    for (var axisKey in axes) {
24425      var axis = axes[axisKey]
24426      var isForward = axis.newScroll > axis.oldScroll
24427      var direction = isForward ? axis.forward : axis.backward
24428
24429      for (var waypointKey in this.waypoints[axisKey]) {
24430        var waypoint = this.waypoints[axisKey][waypointKey]
24431        if (waypoint.triggerPoint === null) {
24432          continue
24433        }
24434        var wasBeforeTriggerPoint = axis.oldScroll < waypoint.triggerPoint
24435        var nowAfterTriggerPoint = axis.newScroll >= waypoint.triggerPoint
24436        var crossedForward = wasBeforeTriggerPoint && nowAfterTriggerPoint
24437        var crossedBackward = !wasBeforeTriggerPoint && !nowAfterTriggerPoint
24438        if (crossedForward || crossedBackward) {
24439          waypoint.queueTrigger(direction)
24440          triggeredGroups[waypoint.group.id] = waypoint.group
24441        }
24442      }
24443    }
24444
24445    for (var groupKey in triggeredGroups) {
24446      triggeredGroups[groupKey].flushTriggers()
24447    }
24448
24449    this.oldScroll = {
24450      x: axes.horizontal.newScroll,
24451      y: axes.vertical.newScroll
24452    }
24453  }
24454
24455  /* Private */
24456  Context.prototype.innerHeight = function() {
24457    /*eslint-disable eqeqeq */
24458    if (this.element == this.element.window) {
24459      return Waypoint.viewportHeight()
24460    }
24461    /*eslint-enable eqeqeq */
24462    return this.adapter.innerHeight()
24463  }
24464
24465  /* Private */
24466  Context.prototype.remove = function(waypoint) {
24467    delete this.waypoints[waypoint.axis][waypoint.key]
24468    this.checkEmpty()
24469  }
24470
24471  /* Private */
24472  Context.prototype.innerWidth = function() {
24473    /*eslint-disable eqeqeq */
24474    if (this.element == this.element.window) {
24475      return Waypoint.viewportWidth()
24476    }
24477    /*eslint-enable eqeqeq */
24478    return this.adapter.innerWidth()
24479  }
24480
24481  /* Public */
24482  /* http://imakewebthings.com/waypoints/api/context-destroy */
24483  Context.prototype.destroy = function() {
24484    var allWaypoints = []
24485    for (var axis in this.waypoints) {
24486      for (var waypointKey in this.waypoints[axis]) {
24487        allWaypoints.push(this.waypoints[axis][waypointKey])
24488      }
24489    }
24490    for (var i = 0, end = allWaypoints.length; i < end; i++) {
24491      allWaypoints[i].destroy()
24492    }
24493  }
24494
24495  /* Public */
24496  /* http://imakewebthings.com/waypoints/api/context-refresh */
24497  Context.prototype.refresh = function() {
24498    /*eslint-disable eqeqeq */
24499    var isWindow = this.element == this.element.window
24500    /*eslint-enable eqeqeq */
24501    var contextOffset = isWindow ? undefined : this.adapter.offset()
24502    var triggeredGroups = {}
24503    var axes
24504
24505    this.handleScroll()
24506    axes = {
24507      horizontal: {
24508        contextOffset: isWindow ? 0 : contextOffset.left,
24509        contextScroll: isWindow ? 0 : this.oldScroll.x,
24510        contextDimension: this.innerWidth(),
24511        oldScroll: this.oldScroll.x,
24512        forward: 'right',
24513        backward: 'left',
24514        offsetProp: 'left'
24515      },
24516      vertical: {
24517        contextOffset: isWindow ? 0 : contextOffset.top,
24518        contextScroll: isWindow ? 0 : this.oldScroll.y,
24519        contextDimension: this.innerHeight(),
24520        oldScroll: this.oldScroll.y,
24521        forward: 'down',
24522        backward: 'up',
24523        offsetProp: 'top'
24524      }
24525    }
24526
24527    for (var axisKey in axes) {
24528      var axis = axes[axisKey]
24529      for (var waypointKey in this.waypoints[axisKey]) {
24530        var waypoint = this.waypoints[axisKey][waypointKey]
24531        var adjustment = waypoint.options.offset
24532        var oldTriggerPoint = waypoint.triggerPoint
24533        var elementOffset = 0
24534        var freshWaypoint = oldTriggerPoint == null
24535        var contextModifier, wasBeforeScroll, nowAfterScroll
24536        var triggeredBackward, triggeredForward
24537
24538        if (waypoint.element !== waypoint.element.window) {
24539          elementOffset = waypoint.adapter.offset()[axis.offsetProp]
24540        }
24541
24542        if (typeof adjustment === 'function') {
24543          adjustment = adjustment.apply(waypoint)
24544        }
24545        else if (typeof adjustment === 'string') {
24546          adjustment = parseFloat(adjustment)
24547          if (waypoint.options.offset.indexOf('%') > - 1) {
24548            adjustment = Math.ceil(axis.contextDimension * adjustment / 100)
24549          }
24550        }
24551
24552        contextModifier = axis.contextScroll - axis.contextOffset
24553        waypoint.triggerPoint = Math.floor(elementOffset + contextModifier - adjustment)
24554        wasBeforeScroll = oldTriggerPoint < axis.oldScroll
24555        nowAfterScroll = waypoint.triggerPoint >= axis.oldScroll
24556        triggeredBackward = wasBeforeScroll && nowAfterScroll
24557        triggeredForward = !wasBeforeScroll && !nowAfterScroll
24558
24559        if (!freshWaypoint && triggeredBackward) {
24560          waypoint.queueTrigger(axis.backward)
24561          triggeredGroups[waypoint.group.id] = waypoint.group
24562        }
24563        else if (!freshWaypoint && triggeredForward) {
24564          waypoint.queueTrigger(axis.forward)
24565          triggeredGroups[waypoint.group.id] = waypoint.group
24566        }
24567        else if (freshWaypoint && axis.oldScroll >= waypoint.triggerPoint) {
24568          waypoint.queueTrigger(axis.forward)
24569          triggeredGroups[waypoint.group.id] = waypoint.group
24570        }
24571      }
24572    }
24573
24574    Waypoint.requestAnimationFrame(function() {
24575      for (var groupKey in triggeredGroups) {
24576        triggeredGroups[groupKey].flushTriggers()
24577      }
24578    })
24579
24580    return this
24581  }
24582
24583  /* Private */
24584  Context.findOrCreateByElement = function(element) {
24585    return Context.findByElement(element) || new Context(element)
24586  }
24587
24588  /* Private */
24589  Context.refreshAll = function() {
24590    for (var contextId in contexts) {
24591      contexts[contextId].refresh()
24592    }
24593  }
24594
24595  /* Public */
24596  /* http://imakewebthings.com/waypoints/api/context-find-by-element */
24597  Context.findByElement = function(element) {
24598    return contexts[element.waypointContextKey]
24599  }
24600
24601  window.onload = function() {
24602    if (oldWindowLoad) {
24603      oldWindowLoad()
24604    }
24605    Context.refreshAll()
24606  }
24607
24608
24609  Waypoint.requestAnimationFrame = function(callback) {
24610    var requestFn = window.requestAnimationFrame ||
24611      window.mozRequestAnimationFrame ||
24612      window.webkitRequestAnimationFrame ||
24613      requestAnimationFrameShim
24614    requestFn.call(window, callback)
24615  }
24616  Waypoint.Context = Context
24617}())
24618;(function() {
24619  'use strict'
24620
24621  function byTriggerPoint(a, b) {
24622    return a.triggerPoint - b.triggerPoint
24623  }
24624
24625  function byReverseTriggerPoint(a, b) {
24626    return b.triggerPoint - a.triggerPoint
24627  }
24628
24629  var groups = {
24630    vertical: {},
24631    horizontal: {}
24632  }
24633  var Waypoint = window.Waypoint
24634
24635  /* http://imakewebthings.com/waypoints/api/group */
24636  function Group(options) {
24637    this.name = options.name
24638    this.axis = options.axis
24639    this.id = this.name + '-' + this.axis
24640    this.waypoints = []
24641    this.clearTriggerQueues()
24642    groups[this.axis][this.name] = this
24643  }
24644
24645  /* Private */
24646  Group.prototype.add = function(waypoint) {
24647    this.waypoints.push(waypoint)
24648  }
24649
24650  /* Private */
24651  Group.prototype.clearTriggerQueues = function() {
24652    this.triggerQueues = {
24653      up: [],
24654      down: [],
24655      left: [],
24656      right: []
24657    }
24658  }
24659
24660  /* Private */
24661  Group.prototype.flushTriggers = function() {
24662    for (var direction in this.triggerQueues) {
24663      var waypoints = this.triggerQueues[direction]
24664      var reverse = direction === 'up' || direction === 'left'
24665      waypoints.sort(reverse ? byReverseTriggerPoint : byTriggerPoint)
24666      for (var i = 0, end = waypoints.length; i < end; i += 1) {
24667        var waypoint = waypoints[i]
24668        if (waypoint.options.continuous || i === waypoints.length - 1) {
24669          waypoint.trigger([direction])
24670        }
24671      }
24672    }
24673    this.clearTriggerQueues()
24674  }
24675
24676  /* Private */
24677  Group.prototype.next = function(waypoint) {
24678    this.waypoints.sort(byTriggerPoint)
24679    var index = Waypoint.Adapter.inArray(waypoint, this.waypoints)
24680    var isLast = index === this.waypoints.length - 1
24681    return isLast ? null : this.waypoints[index + 1]
24682  }
24683
24684  /* Private */
24685  Group.prototype.previous = function(waypoint) {
24686    this.waypoints.sort(byTriggerPoint)
24687    var index = Waypoint.Adapter.inArray(waypoint, this.waypoints)
24688    return index ? this.waypoints[index - 1] : null
24689  }
24690
24691  /* Private */
24692  Group.prototype.queueTrigger = function(waypoint, direction) {
24693    this.triggerQueues[direction].push(waypoint)
24694  }
24695
24696  /* Private */
24697  Group.prototype.remove = function(waypoint) {
24698    var index = Waypoint.Adapter.inArray(waypoint, this.waypoints)
24699    if (index > -1) {
24700      this.waypoints.splice(index, 1)
24701    }
24702  }
24703
24704  /* Public */
24705  /* http://imakewebthings.com/waypoints/api/first */
24706  Group.prototype.first = function() {
24707    return this.waypoints[0]
24708  }
24709
24710  /* Public */
24711  /* http://imakewebthings.com/waypoints/api/last */
24712  Group.prototype.last = function() {
24713    return this.waypoints[this.waypoints.length - 1]
24714  }
24715
24716  /* Private */
24717  Group.findOrCreate = function(options) {
24718    return groups[options.axis][options.name] || new Group(options)
24719  }
24720
24721  Waypoint.Group = Group
24722}())
24723;(function() {
24724  'use strict'
24725
24726  var $ = window.jQuery
24727  var Waypoint = window.Waypoint
24728
24729  function JQueryAdapter(element) {
24730    this.$element = $(element)
24731  }
24732
24733  $.each([
24734    'innerHeight',
24735    'innerWidth',
24736    'off',
24737    'offset',
24738    'on',
24739    'outerHeight',
24740    'outerWidth',
24741    'scrollLeft',
24742    'scrollTop'
24743  ], function(i, method) {
24744    JQueryAdapter.prototype[method] = function() {
24745      var args = Array.prototype.slice.call(arguments)
24746      return this.$element[method].apply(this.$element, args)
24747    }
24748  })
24749
24750  $.each([
24751    'extend',
24752    'inArray',
24753    'isEmptyObject'
24754  ], function(i, method) {
24755    JQueryAdapter[method] = $[method]
24756  })
24757
24758  Waypoint.adapters.push({
24759    name: 'jquery',
24760    Adapter: JQueryAdapter
24761  })
24762  Waypoint.Adapter = JQueryAdapter
24763}())
24764;(function() {
24765  'use strict'
24766
24767  var Waypoint = window.Waypoint
24768
24769  function createExtension(framework) {
24770    return function() {
24771      var waypoints = []
24772      var overrides = arguments[0]
24773
24774      if (framework.isFunction(arguments[0])) {
24775        overrides = framework.extend({}, arguments[1])
24776        overrides.handler = arguments[0]
24777      }
24778
24779      this.each(function() {
24780        var options = framework.extend({}, overrides, {
24781          element: this
24782        })
24783        if (typeof options.context === 'string') {
24784          options.context = framework(this).closest(options.context)[0]
24785        }
24786        waypoints.push(new Waypoint(options))
24787      })
24788
24789      return waypoints
24790    }
24791  }
24792
24793  if (window.jQuery) {
24794    window.jQuery.fn.waypoint = createExtension(window.jQuery)
24795  }
24796  if (window.Zepto) {
24797    window.Zepto.fn.waypoint = createExtension(window.Zepto)
24798  }
24799}())
24800;
24801/*!
24802Waypoints Inview Shortcut - 4.0.1
24803Copyright © 2011-2016 Caleb Troughton
24804Licensed under the MIT license.
24805https://github.com/imakewebthings/waypoints/blob/master/licenses.txt
24806*/
24807(function() {
24808  'use strict'
24809
24810  function noop() {}
24811
24812  var Waypoint = window.Waypoint
24813
24814  /* http://imakewebthings.com/waypoints/shortcuts/inview */
24815  function Inview(options) {
24816    this.options = Waypoint.Adapter.extend({}, Inview.defaults, options)
24817    this.axis = this.options.horizontal ? 'horizontal' : 'vertical'
24818    this.waypoints = []
24819    this.element = this.options.element
24820    this.createWaypoints()
24821  }
24822
24823  /* Private */
24824  Inview.prototype.createWaypoints = function() {
24825    var configs = {
24826      vertical: [{
24827        down: 'enter',
24828        up: 'exited',
24829        offset: '100%'
24830      }, {
24831        down: 'entered',
24832        up: 'exit',
24833        offset: 'bottom-in-view'
24834      }, {
24835        down: 'exit',
24836        up: 'entered',
24837        offset: 0
24838      }, {
24839        down: 'exited',
24840        up: 'enter',
24841        offset: function() {
24842          return -this.adapter.outerHeight()
24843        }
24844      }],
24845      horizontal: [{
24846        right: 'enter',
24847        left: 'exited',
24848        offset: '100%'
24849      }, {
24850        right: 'entered',
24851        left: 'exit',
24852        offset: 'right-in-view'
24853      }, {
24854        right: 'exit',
24855        left: 'entered',
24856        offset: 0
24857      }, {
24858        right: 'exited',
24859        left: 'enter',
24860        offset: function() {
24861          return -this.adapter.outerWidth()
24862        }
24863      }]
24864    }
24865
24866    for (var i = 0, end = configs[this.axis].length; i < end; i++) {
24867      var config = configs[this.axis][i]
24868      this.createWaypoint(config)
24869    }
24870  }
24871
24872  /* Private */
24873  Inview.prototype.createWaypoint = function(config) {
24874    var self = this
24875    this.waypoints.push(new Waypoint({
24876      context: this.options.context,
24877      element: this.options.element,
24878      enabled: this.options.enabled,
24879      handler: (function(config) {
24880        return function(direction) {
24881          self.options[config[direction]].call(self, direction)
24882        }
24883      }(config)),
24884      offset: config.offset,
24885      horizontal: this.options.horizontal
24886    }))
24887  }
24888
24889  /* Public */
24890  Inview.prototype.destroy = function() {
24891    for (var i = 0, end = this.waypoints.length; i < end; i++) {
24892      this.waypoints[i].destroy()
24893    }
24894    this.waypoints = []
24895  }
24896
24897  Inview.prototype.disable = function() {
24898    for (var i = 0, end = this.waypoints.length; i < end; i++) {
24899      this.waypoints[i].disable()
24900    }
24901  }
24902
24903  Inview.prototype.enable = function() {
24904    for (var i = 0, end = this.waypoints.length; i < end; i++) {
24905      this.waypoints[i].enable()
24906    }
24907  }
24908
24909  Inview.defaults = {
24910    context: window,
24911    enabled: true,
24912    enter: noop,
24913    entered: noop,
24914    exit: noop,
24915    exited: noop
24916  }
24917
24918  Waypoint.Inview = Inview
24919}())
24920;
24921
24922/*
24923 * SmartMenus jQuery v0.9.6
24924 * http://www.smartmenus.org/
24925 *
24926 * Copyright 2014 Vasil Dinkov, Vadikom Web Ltd.
24927 * http://vadikom.com/
24928 *
24929 * Released under the MIT license:
24930 * http://www.opensource.org/licenses/MIT
24931 */
24932
24933(function($) {
24934
24935	var menuTrees = [],
24936		IE = !!window.createPopup, // we need to detect it, unfortunately
24937		IElt9 = IE && !document.defaultView,
24938		IElt8 = IE && !document.querySelector,
24939		IE6 = IE && typeof document.documentElement.currentStyle.minWidth == 'undefined',
24940		mouse = false, // optimize for touch by default - we will detect for mouse input
24941		mouseDetectionEnabled = false;
24942
24943	// Handle detection for mouse input (i.e. desktop browsers, tablets with a mouse, etc.)
24944	function initMouseDetection(disable) {
24945		if (!mouseDetectionEnabled && !disable) {
24946			// if we get two consecutive mousemoves within 2 pixels from each other and within 300ms, we assume a real mouse/cursor is present
24947			// in practice, this seems like impossible to trick unintentianally with a real mouse and a pretty safe detection on touch devices (even with older browsers that do not support touch events)
24948			var firstTime = true,
24949				lastMove = null;
24950			$(document).bind({
24951				'mousemove.smartmenus_mouse': function(e) {
24952					var thisMove = { x: e.pageX, y: e.pageY, timeStamp: new Date().getTime() };
24953					if (lastMove) {
24954						var deltaX = Math.abs(lastMove.x - thisMove.x),
24955							deltaY = Math.abs(lastMove.y - thisMove.y);
24956	 					if ((deltaX > 0 || deltaY > 0) && deltaX <= 2 && deltaY <= 2 && thisMove.timeStamp - lastMove.timeStamp <= 300) {
24957							mouse = true;
24958							// if this is the first check after page load, check if we are not over some item by chance and call the mouseenter handler if yes
24959							if (firstTime) {
24960								var $a = $(e.target).closest('a');
24961								if ($a.is('a')) {
24962									$.each(menuTrees, function() {
24963										if ($.contains(this.$root[0], $a[0])) {
24964											this.itemEnter({ currentTarget: $a[0] });
24965											return false;
24966										}
24967									});
24968								}
24969								firstTime = false;
24970							}
24971						}
24972					}
24973					lastMove = thisMove;
24974				},
24975				'touchstart.smartmenus_mouse pointerover.smartmenus_mouse MSPointerOver.smartmenus_mouse': function(e) {
24976					if (!/^(4|mouse|pen)$/.test(e.originalEvent.pointerType)) {
24977						mouse = false;
24978					}
24979				}
24980			});
24981			mouseDetectionEnabled = true;
24982		} else if (mouseDetectionEnabled && disable) {
24983			$(document).unbind('.smartmenus_mouse');
24984			mouseDetectionEnabled = false;
24985		}
24986	};
24987
24988	$.SmartMenus = function(elm, options) {
24989		this.$root = $(elm);
24990		this.opts = options;
24991		this.rootId = ''; // internal
24992		this.$subArrow = null;
24993		this.subMenus = []; // all sub menus in the tree (UL elms) in no particular order (only real - e.g. UL's in mega sub menus won't be counted)
24994		this.activatedItems = []; // stores last activated A's for each level
24995		this.visibleSubMenus = []; // stores visible sub menus UL's
24996		this.showTimeout = 0;
24997		this.hideTimeout = 0;
24998		this.scrollTimeout = 0;
24999		this.clickActivated = false;
25000		this.zIndexInc = 0;
25001		this.$firstLink = null; // we'll use these for some tests
25002		this.$firstSub = null; // at runtime so we'll cache them
25003		this.disabled = false;
25004		this.$disableOverlay = null;
25005		this.lastLevel = 0;
25006		this.init();
25007	};
25008
25009	$.extend($.SmartMenus, {
25010		hideAll: function() {
25011			$.each(menuTrees, function() {
25012				this.menuHideAll();
25013			});
25014		},
25015		destroy: function() {
25016			while (menuTrees.length) {
25017				menuTrees[0].destroy();
25018			}
25019			initMouseDetection(true);
25020		},
25021		prototype: {
25022			init: function(refresh) {
25023				var self = this;
25024
25025				if (!refresh) {
25026					menuTrees.push(this);
25027
25028					this.rootId = (new Date().getTime() + Math.random() + '').replace(/\D/g, '');
25029
25030					if (this.$root.hasClass('sm-rtl')) {
25031						this.opts.rightToLeftSubMenus = true;
25032					}
25033
25034					// init root (main menu)
25035					this.$root
25036						.data('smartmenus', this)
25037						.attr('data-smartmenus-id', this.rootId)
25038						.dataSM('level', 1)
25039						.bind({
25040							// 'mouseover.smartmenus focusin.smartmenus': $.proxy(this.rootOver, this),
25041							// 'mouseout.smartmenus focusout.smartmenus': $.proxy(this.rootOut, this)
25042							'mouseover.smartmenus': $.proxy(this.rootOver, this),
25043							'mouseout.smartmenus': $.proxy(this.rootOut, this)
25044						})
25045						.delegate('a, div.logo-container', {
25046							'mouseenter.smartmenus': $.proxy(this.itemEnter, this),
25047							'mouseleave.smartmenus': $.proxy(this.itemLeave, this),
25048							'mousedown.smartmenus': $.proxy(this.itemDown, this),
25049							'focus.smartmenus': $.proxy(this.itemFocus, this),
25050							'blur.smartmenus': $.proxy(this.itemBlur, this),
25051							'click.smartmenus': $.proxy(this.itemClick, this),
25052							'touchend.smartmenus': $.proxy(this.itemTouchEnd, this)
25053						});
25054
25055					var eNamespace = '.smartmenus' + this.rootId;
25056					// hide menus on tap or click outside the root UL
25057					if (this.opts.hideOnClick) {
25058							$(document).on('touchstart' + eNamespace, $.proxy(this.docTouchStart, this))
25059								.on('touchmove' + eNamespace, $.proxy(this.docTouchMove, this))
25060								.on('touchend' + eNamespace, $.proxy(this.docTouchEnd, this))
25061								// for Opera Mobile < 11.5, webOS browser, etc. we'll check click too
25062								.on('click' + eNamespace, $.proxy(this.docClick, this));
25063					}
25064					// hide sub menus on resize
25065					$(window).on('resize' + eNamespace + ' orientationchange' + eNamespace, $.proxy(this.winResize, this));
25066					var $vmenu = $('body.vmenu .vmenu-container');
25067					if ( ! $vmenu.length && UNCODE.wwidth > UNCODE.mediaQuery ) {
25068						$(window).on('scroll' + eNamespace + ' orientationchange' + eNamespace, $.proxy(this.winResize, this));
25069					}
25070
25071					if (this.opts.subIndicators) {
25072						this.$subArrow = $('<span/>').addClass('sub-arrow');
25073						if (this.opts.subIndicatorsText) {
25074							this.$subArrow.html(this.opts.subIndicatorsText);
25075						}
25076					}
25077
25078					// make sure mouse detection is enabled
25079					initMouseDetection();
25080				}
25081
25082				// init sub menus
25083				this.$firstSub = this.$root.find('ul:not(.nav-tabs):not(.unmenu-block):not(.unmenu-block *)').each(function() { self.menuInit($(this)); }).eq(0);
25084
25085				this.$firstLink = this.$root.find('a').eq(0);
25086
25087				// find current item
25088				if (this.opts.markCurrentItem) {
25089					var reDefaultDoc = /(index|default)\.[^#\?\/]*/i,
25090						reHash = /#.*/,
25091						locHref = window.location.href.replace(reDefaultDoc, ''),
25092						locHrefNoHash = locHref.replace(reHash, '');
25093					this.$root.find('a').each(function() {
25094						var href = this.href.replace(reDefaultDoc, ''),
25095							$this = $(this);
25096						if (href == locHref || href == locHrefNoHash) {
25097							$this.addClass('current');
25098							if (self.opts.markCurrentTree) {
25099								$this.parents('li').each(function() {
25100									var $this = $(this);
25101									if ($this.dataSM('sub')) {
25102										$this.children('a').addClass('current');
25103									}
25104								});
25105							}
25106						}
25107					});
25108				}
25109			},
25110			destroy: function() {
25111				this.menuHideAll();
25112				this.$root
25113					.removeData('smartmenus')
25114					.removeAttr('data-smartmenus-id')
25115					.removeDataSM('level')
25116					.unbind('.smartmenus')
25117					.undelegate('.smartmenus');
25118				var eNamespace = '.smartmenus' + this.rootId;
25119				$(document).unbind(eNamespace);
25120				$(window).unbind(eNamespace);
25121				if (this.opts.subIndicators) {
25122					this.$subArrow = null;
25123				}
25124				var self = this;
25125				$.each(this.subMenus, function() {
25126					if (this.hasClass('mega-menu')) {
25127						this.find('ul:not(.nav-tabs):not(.unmenu-block):not(.unmenu-block *)').removeDataSM('in-mega');
25128					}
25129					if (this.dataSM('shown-before')) {
25130						if (IElt8) {
25131							this.children().css({ styleFloat: '', width: '' });
25132						}
25133						if (self.opts.subMenusMinWidth || self.opts.subMenusMaxWidth) {
25134							if (!IE6) {
25135								this.css({ width: '', minWidth: '', maxWidth: '' }).removeClass('sm-nowrap');
25136							} else {
25137								this.css({ width: '', overflowX: '', overflowY: '' }).children().children('a').css('white-space', '');
25138							}
25139						}
25140						if (this.dataSM('scroll-arrows')) {
25141							this.dataSM('scroll-arrows').remove();
25142						}
25143						this.css({ zIndex: '', top: '', left: '', marginLeft: '', marginTop: '', display: '' });
25144					}
25145					if (self.opts.subIndicators) {
25146						this.dataSM('parent-a').removeClass('has-submenu').children('span.sub-arrow').remove();
25147					}
25148					this.removeDataSM('shown-before')
25149						.removeDataSM('ie-shim')
25150						.removeDataSM('scroll-arrows')
25151						.removeDataSM('parent-a')
25152						.removeDataSM('level')
25153						.removeDataSM('beforefirstshowfired')
25154						.parent().removeDataSM('sub');
25155				});
25156				if (this.opts.markCurrentItem) {
25157					this.$root.find('a.current').removeClass('current');
25158				}
25159				this.$root = null;
25160				this.$firstLink = null;
25161				this.$firstSub = null;
25162				if (this.$disableOverlay) {
25163					this.$disableOverlay.remove();
25164					this.$disableOverlay = null;
25165				}
25166				menuTrees.splice($.inArray(this, menuTrees), 1);
25167			},
25168			disable: function(noOverlay) {
25169				if (!this.disabled) {
25170					this.menuHideAll();
25171					// display overlay over the menu to prevent interaction
25172					if (!noOverlay && !this.opts.isPopup && this.$root.is(':visible')) {
25173						var pos = this.$root.offset();
25174						this.$disableOverlay = $('<div class="sm-jquery-disable-overlay"/>').css({
25175							position: 'absolute',
25176							top: pos.top,
25177							left: pos.left,
25178							width: this.$root.outerWidth(),
25179							height: this.$root.outerHeight(),
25180							zIndex: this.getStartZIndex() + 1,
25181							opacity: 0
25182						}).appendTo(document.body);
25183					}
25184					this.disabled = true;
25185				}
25186			},
25187			docClick: function(e) {
25188				// hide on any click outside the menu or on a menu link
25189				if (this.visibleSubMenus.length && !$.contains(this.$root[0], e.target) || $(e.target).is('a:not([data-filter])')) {
25190					this.menuHideAll($(e.target));
25191				}
25192			},
25193			docTouchEnd: function(e) {
25194				if (!this.lastTouch) {
25195					return;
25196				}
25197				if (this.visibleSubMenus.length && (this.lastTouch.x2 === undefined || this.lastTouch.x1 == this.lastTouch.x2) && (this.lastTouch.y2 === undefined || this.lastTouch.y1 == this.lastTouch.y2) && (!this.lastTouch.target || !$.contains(this.$root[0], this.lastTouch.target))) {
25198					if (this.hideTimeout) {
25199						clearTimeout(this.hideTimeout);
25200						this.hideTimeout = 0;
25201					}
25202					// hide with a delay to prevent triggering accidental unwanted click on some page element
25203					var self = this;
25204					this.hideTimeout = setTimeout(function() { self.menuHideAll($(e.target)); }, 350);
25205				}
25206				this.lastTouch = null;
25207			},
25208			docTouchMove: function(e) {
25209				if (!this.lastTouch) {
25210					return;
25211				}
25212				var touchPoint = e.originalEvent.touches[0];
25213				this.lastTouch.x2 = touchPoint.pageX;
25214				this.lastTouch.y2 = touchPoint.pageY;
25215			},
25216			docTouchStart: function(e) {
25217				var touchPoint = e.originalEvent.touches[0];
25218				this.lastTouch = { x1: touchPoint.pageX, y1: touchPoint.pageY, target: touchPoint.target };
25219			},
25220			enable: function() {
25221				if (this.disabled) {
25222					if (this.$disableOverlay) {
25223						this.$disableOverlay.remove();
25224						this.$disableOverlay = null;
25225					}
25226					this.disabled = false;
25227				}
25228			},
25229			getHeight: function($elm) {
25230				return this.getOffset($elm, true);
25231			},
25232			// returns precise width/height float values in IE9+, FF4+, recent WebKit
25233			// http://vadikom.com/dailies/offsetwidth-offsetheight-useless-in-ie9-firefox4/
25234			getOffset: function($elm, height) {
25235				var old,
25236					$win = $(window),
25237					winW = $win.width();
25238				if ($elm.css('display') == 'none') {
25239					old = { position: $elm[0].style.position, visibility: $elm[0].style.visibility };
25240					$elm.css({ position: 'absolute', visibility: 'hidden' }).show();
25241					if ( 
25242						($('body').hasClass('menu-mobile-off-canvas') && winW < 960 && $elm.closest('.main-menu-container').length)
25243						||
25244						(( $('body').hasClass('vmenu-offcanvas-overlay') || $('body').hasClass('vmenu') ) && winW >= 960 && $elm.closest('.main-menu-container').length && !$elm.closest('.menu-horizontal-inner').length)
25245					) {
25246						$elm.closest('li').addClass('smartmenu-open-item');
25247					}
25248				}
25249				var defaultView = $elm[0].ownerDocument.defaultView,
25250					compStyle = defaultView && defaultView.getComputedStyle && defaultView.getComputedStyle($elm[0], null),
25251					val = compStyle && parseFloat(compStyle[height ? 'height' : 'width']);
25252				if (val) {
25253					val += parseFloat(compStyle[height ? 'paddingTop' : 'paddingLeft'])
25254	 					+ parseFloat(compStyle[height ? 'paddingBottom' : 'paddingRight'])
25255	 					+ parseInt(compStyle[height ? 'borderTopWidth' : 'borderLeftWidth'])
25256	 					+ parseInt(compStyle[height ? 'borderBottomWidth' : 'borderRightWidth']);
25257				} else {
25258					val = height ? $elm[0].offsetHeight : $elm[0].offsetWidth;
25259				}
25260				if (old) {
25261					$elm.hide().css(old);
25262				}
25263				return val;
25264			},
25265			getWidth: function($elm) {
25266				return this.getOffset($elm);
25267			},
25268			getStartZIndex: function() {
25269				var zIndex = parseInt(this.$root.css('z-index'));
25270				return !isNaN(zIndex) ? zIndex : 1;
25271			},
25272			handleEvents: function() {
25273				return !this.disabled && this.isCSSOn();
25274			},
25275			handleItemEvents: function($a) {
25276				return this.handleEvents() && !this.isLinkInMegaMenu($a);
25277			},
25278			isCollapsible: function() {
25279				return this.$firstSub.css('position') == 'static';
25280			},
25281			isCSSOn: function() {
25282				return this.$firstLink.css('display') == 'block' || this.$firstLink.css('display') == 'flex' || this.$firstLink.css('display') == 'inline-flex' || this.$firstLink.css('display') == 'table-cell' || this.$firstLink.css('display') == 'inline';
25283			},
25284			isFixed: function() {
25285				return this.$root.css('position') == 'fixed';
25286			},
25287			isLinkInMegaMenu: function($a) {
25288				return !$a.parent().parent().dataSM('level');
25289			},
25290			isTouchMode: function() {
25291				return !mouse || this.isCollapsible();
25292			},
25293			itemActivate: function($a, $show) {
25294				var $li = $a.parent(),
25295					$ul = $li.parent(),
25296					level = $ul.dataSM('level'),
25297					winh = $(window).height();
25298				// if for some reason the parent item is not activated (e.g. this is an API call to activate the item), activate all parent items first
25299				if (level > 1 && (!this.activatedItems[level - 2] || this.activatedItems[level - 2][0] != $ul.dataSM('parent-a')[0])) {
25300					var self = this;
25301					$($ul.parentsUntil('[data-smartmenus-id]', 'ul:not(.nav-tabs):not(.unmenu-block):not(.unmenu-block *)').get().reverse()).add($ul).each(function() {
25302						self.itemActivate($(this).dataSM('parent-a'));
25303					});
25304				}
25305				// hide any visible deeper level sub menus
25306				if (this.visibleSubMenus.length > level) {
25307					for (var i = this.visibleSubMenus.length - 1, l = !this.activatedItems[level - 1] || this.activatedItems[level - 1][0] != $a[0] ? level - 1 : level; i > l; i--) {
25308						this.lastLevel = level;
25309						if ( typeof $show === 'undefined' && this.isCollapsible() ) {
25310							this.menuHide(this.visibleSubMenus[i], $a);
25311							return;
25312						} else {
25313							this.menuHide(this.visibleSubMenus[i]);
25314						}
25315					}
25316				}
25317				// save new active item and sub menu for this level
25318				this.activatedItems[level - 1] = $a;
25319				this.visibleSubMenus[level - 1] = $ul;
25320				if (this.$root.triggerHandler('activate.smapi', $a[0]) === false) {
25321					return;
25322				}
25323				// show the sub menu if this item has one
25324				var $sub = $li.dataSM('sub');
25325				if ($sub && (this.isTouchMode() || (!this.opts.showOnClick || this.clickActivated))) {
25326				// if ($sub && (this.isTouchMode() || (!this.opts.showOnClick))) {
25327					var aRect = $a[0].getBoundingClientRect();
25328					if ( (aRect.y < 0 || aRect.y > winh) && this.isCollapsible() && (this.lastLevel === this.activatedItems.length) ) {
25329						setTimeout(function(){
25330							var currentScroll = $a.closest('.main-menu-container').scrollTop();
25331							$a.closest('.main-menu-container').scrollTop(currentScroll + aRect.y);
25332						}, 1);
25333					}
25334					this.menuShow($sub);
25335				}
25336			},
25337			itemBlur: function(e) {
25338				var $a = $(e.currentTarget);
25339				if (!this.handleItemEvents($a)) {
25340					return;
25341				}
25342				this.$root.triggerHandler('blur.smapi', $a[0]);
25343			},
25344			itemClick: function(e) {
25345				var $a = $(e.currentTarget);
25346
25347				if (!this.handleItemEvents($a)) {
25348					return;
25349				}
25350				$a.removeDataSM('mousedown');
25351				if (this.$root.triggerHandler('click.smapi', $a[0]) === false) {
25352					return false;
25353				}
25354				var $sub = $a.parent().dataSM('sub');
25355				if (this.isTouchMode()) {
25356					// undo fix: prevent the address bar on iPhone from sliding down when expanding a sub menu
25357					if ($a.dataSM('href')) {
25358						$a.attr('href', $a.dataSM('href')).removeDataSM('href');
25359					}
25360					// if the sub is not visible
25361					if ($sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) {
25362						// try to activate the item and show the sub
25363						this.itemActivate($a);
25364						// if "itemActivate" showed the sub, prevent the click so that the link is not loaded
25365						// if it couldn't show it, then the sub menus are disabled with an !important declaration (e.g. via mobile styles) so let the link get loaded
25366						if ($sub.is(':visible')) {
25367							return false;
25368						}
25369					}
25370				// } else if (this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 && $sub && !$sub.is(':visible')) {
25371				} else if (this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 && $sub) {
25372					this.clickActivated = true;
25373					this.menuShow($sub);
25374					return false;
25375				}
25376				if ($a.hasClass('disabled')) {
25377					return false;
25378				}
25379				if (this.$root.triggerHandler('select.smapi', $a[0]) === false) {
25380					return false;
25381				}
25382			},
25383			itemDown: function(e) {
25384				var $a = $(e.currentTarget);
25385				if (!this.handleItemEvents($a)) {
25386					return;
25387				}
25388				$a.dataSM('mousedown', true);
25389			},
25390			itemEnter: function(e) {
25391				// if ( this.opts.showOnClick ) {
25392				// 	return
25393				// }
25394				var $a = $(e.currentTarget);
25395				if (!this.handleItemEvents($a)) {
25396					return;
25397				}
25398				if (!this.isTouchMode()) {
25399					if (this.showTimeout) {
25400						clearTimeout(this.showTimeout);
25401						this.showTimeout = 0;
25402					}
25403					var self = this;
25404					this.showTimeout = setTimeout(function() { self.itemActivate($a); }, this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 ? 1 : this.opts.showTimeout);
25405				}
25406				this.$root.triggerHandler('mouseenter.smapi', $a[0]);
25407			},
25408			itemFocus: function(e) {
25409				var $a = $(e.currentTarget);
25410				if (!this.handleItemEvents($a)) {
25411					return;
25412				}
25413				// fix (the mousedown check): in some browsers a tap/click produces consecutive focus + click events so we don't need to activate the item on focus
25414				if ((!this.isTouchMode() || !$a.dataSM('mousedown')) && (!this.activatedItems.length || this.activatedItems[this.activatedItems.length - 1][0] != $a[0])) {
25415					this.itemActivate($a);
25416				}
25417				this.$root.triggerHandler('focus.smapi', $a[0]);
25418			},
25419			itemLeave: function(e) {
25420				// if ( this.opts.showOnClick ) {
25421				// 	return
25422				// }
25423				var $a = $(e.currentTarget);
25424				if (!this.handleItemEvents($a)) {
25425					return;
25426				}
25427				if (!this.isTouchMode()) {
25428					if ($a[0].blur) {
25429						$a[0].blur();
25430					}
25431					if (this.showTimeout) {
25432						clearTimeout(this.showTimeout);
25433						this.showTimeout = 0;
25434					}
25435				}
25436				$a.removeDataSM('mousedown');
25437				this.$root.triggerHandler('mouseleave.smapi', $a[0]);
25438			},
25439			itemTouchEnd: function(e) {
25440				var $a = $(e.currentTarget);
25441				if (!this.handleItemEvents($a)) {
25442					return;
25443				}
25444				// prevent the address bar on iPhone from sliding down when expanding a sub menu
25445				var $sub = $a.parent().dataSM('sub');
25446				if ($a.attr('href').charAt(0) !== '#' && $sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) {
25447					$a.dataSM('href', $a.attr('href'));
25448					$a.attr('href', '#');
25449				}
25450			},
25451			menuFixLayout: function($ul) {
25452				// fixes a menu that is being shown for the first time
25453				if (!$ul.dataSM('shown-before')) {
25454					$ul.hide().dataSM('shown-before', true);
25455					// fix the layout of the items in IE<8
25456					if (IElt8) {
25457						$ul.children().css({ styleFloat: 'left', width: '100%' });
25458					}
25459				}
25460			},
25461			menuHide: function($sub, $show) {
25462				if (this.$root.triggerHandler('beforehide.smapi', $sub[0]) === false) {
25463					return;
25464				}
25465				$sub.stop(true, true);
25466				if ($sub.is(':visible')) {
25467					var self = this;
25468					var complete = function() {
25469						// unset z-index
25470						if (IElt9) {
25471							$sub.parent().css('z-index', '');
25472						} else {
25473							$sub.css('z-index', '');
25474						}
25475						if ( typeof $show !== 'undefined' ) {
25476							self.itemActivate($show, true)
25477						}
25478					};
25479					// if sub is collapsible (mobile view)
25480					if (this.isCollapsible()) {
25481						if (this.opts.collapsibleHideFunction) {
25482							this.opts.collapsibleHideFunction.call(this, $sub, complete);
25483						} else {
25484							$sub.hide(this.opts.collapsibleHideDuration, complete);
25485						}
25486					} else {
25487						if (this.opts.hideFunction) {
25488							this.opts.hideFunction.call(this, $sub, complete);
25489						} else {
25490							$sub.hide(this.opts.hideDuration, complete);
25491						}
25492					}
25493					// remove IE iframe shim
25494					if ($sub.dataSM('ie-shim')) {
25495						$sub.dataSM('ie-shim').remove();
25496					}
25497					// deactivate scrolling if it is activated for this sub
25498					if ($sub.dataSM('scroll')) {
25499						$sub.unbind('.smartmenus_scroll').removeDataSM('scroll').dataSM('scroll-arrows').hide();
25500					}
25501					// unhighlight parent item
25502					$sub.dataSM('parent-a').removeClass('highlighted');
25503					var level = $sub.dataSM('level');
25504					this.activatedItems.splice(level - 1, 1);
25505					this.visibleSubMenus.splice(level - 1, 1);
25506					this.$root.triggerHandler('hide.smapi', $sub[0]);
25507				}
25508			},
25509			menuHideAll: function($item) {
25510				if ($item != undefined && $item.parent().hasClass('menu-item') && !$item.parent().hasClass('menu-item-has-children')) return;
25511				var $win = $(window),
25512					winW = $win.width();
25513				if (this.showTimeout) {
25514					clearTimeout(this.showTimeout);
25515					this.showTimeout = 0;
25516				}
25517				// hide all subs
25518				for (var i = this.visibleSubMenus.length - 1; i > 0; i--) {
25519					if ( this.visibleSubMenus[i].closest('.smartmenu-open-item').length ) {
25520						if ( $item != undefined && $item.closest('.smartmenu-open-item').length ) {
25521							this.menuHide(this.visibleSubMenus[i]);
25522							$(this.visibleSubMenus[i]).closest('.smartmenu-open-item').removeClass('smartmenu-open-item');
25523						} else {
25524							return;
25525						}
25526					} else {
25527						//if ( !this.visibleSubMenus[i].closest('.menu-accordion').length ) {
25528							this.menuHide(this.visibleSubMenus[i]);
25529						//}
25530					}
25531				}
25532				// hide root if it's popup
25533				if (this.opts.isPopup) {
25534					this.$root.stop(true, true);
25535					if (this.$root.is(':visible')) {
25536						if (this.opts.hideFunction) {
25537							this.opts.hideFunction.call(this, this.$root);
25538						} else {
25539							this.$root.hide(this.opts.hideDuration);
25540						}
25541						// remove IE iframe shim
25542						if (this.$root.dataSM('ie-shim')) {
25543							this.$root.dataSM('ie-shim').remove();
25544						}
25545					}
25546				}
25547				this.activatedItems = [];
25548				this.visibleSubMenus = [];
25549				this.clickActivated = false;
25550				// reset z-index increment
25551				this.zIndexInc = 0;
25552			},
25553			menuIframeShim: function($ul) {
25554				// create iframe shim for the menu
25555				if (IE && this.opts.overlapControlsInIE && !$ul.dataSM('ie-shim')) {
25556					$ul.dataSM('ie-shim', $('<iframe/>').attr({ src: 'javascript:0', tabindex: -9 })
25557						.css({ position: 'absolute', top: 'auto', left: '0', opacity: 0, border: '0' })
25558					);
25559				}
25560			},
25561			menuInit: function($ul) {
25562				if (!$ul.dataSM('in-mega')) {
25563					this.subMenus.push($ul);
25564					// mark UL's in mega drop downs (if any) so we can neglect them
25565					if ($ul.hasClass('mega-menu')) {
25566						$ul.find('ul:not(.nav-tabs):not(.unmenu-block):not(.unmenu-block *)').dataSM('in-mega', true);
25567					}
25568					// get level (much faster than, for example, using parentsUntil)
25569					var level = 2,
25570						par = $ul[0];
25571					while (par != null && par.parentNode != null && ( par = par.parentNode.parentNode) != this.$root[0]) {
25572						level++;
25573					}
25574					// cache stuff
25575					$ul.dataSM('parent-a', $ul.prevAll('a').eq(-1))
25576						.dataSM('level', level)
25577						.parent().dataSM('sub', $ul);
25578					// add sub indicator to parent item
25579					if (this.opts.subIndicators) {
25580						$ul.dataSM('parent-a').addClass('has-submenu')[this.opts.subIndicatorsPos](this.$subArrow.clone());
25581					}
25582				}
25583				if ( $('.vc_row[data-parent].has-bg', $ul).length && !$('.vc_row[data-parent]:not(.has-bg)', $ul).length ) {
25584					$ul.addClass('has-bg-items');
25585				}
25586			},
25587			menuPosition: function($sub) {
25588				var fixIE = $('html.ie').length;
25589				// if (fixIE) {
25590				// 	var $rowParent = $($sub).closest('.main-menu-container');
25591				// 	$rowParent.height($rowParent.height());
25592				// }
25593				var $a = $sub.dataSM('parent-a'),
25594					$li = $sub.parent(),
25595					$ul = $sub.parent().parent(),
25596					// $container = $ul.closest('.row-menu-inner').length ? ( $('body').hasClass('megamenu-side-to-side') ? ( $('body').hasClass('boxed-width') ? $ul.closest('.row-menu') : $(window) ) : $ul.closest('.row-menu-inner') ) : $ul.closest('.uncol'),
25597					$container = $ul.closest('.row-menu-inner').length ? ( $('body').hasClass('megamenu-side-to-side') ? $ul.closest('.row-menu') : $ul.closest('.row-menu-inner') ) : $ul.closest('.uncol'),
25598					level = $sub.dataSM('level'),
25599					subW = this.getWidth($sub),
25600					subH = this.getHeight($sub),
25601					itemOffset = $a.offset(),
25602					itemX = itemOffset.left,
25603					itemY = itemOffset.top,
25604					itemW = this.getWidth($a),
25605					itemH = this.getHeight($a),
25606					$win = $(window),
25607					winX = $win.scrollLeft(),
25608					winY = $win.scrollTop(),
25609					winW = $win.width(),
25610					winH = $win.height(),
25611					containerW = $container.width(),
25612					containerOffsetX = containerW + ((winW - containerW) / 2),
25613					horizontalParent = $ul.hasClass('sm') && !$ul.hasClass('sm-vertical'),
25614					subOffsetX = level == 2 ? this.opts.mainMenuSubOffsetX : this.opts.subMenusSubOffsetX,
25615					subOffsetY = level == 2 ? this.opts.mainMenuSubOffsetY : this.opts.subMenusSubOffsetY,
25616					x, y, leftPos;
25617
25618				if (horizontalParent) {
25619					x = this.opts.rightToLeftSubMenus ? itemW - subW - subOffsetX : subOffsetX;
25620					y = this.opts.bottomToTopSubMenus ? -subH - subOffsetY : itemH + subOffsetY;
25621				} else {
25622					x = this.opts.rightToLeftSubMenus ? subOffsetX - subW : subW - subOffsetX;
25623					y = this.opts.bottomToTopSubMenus ? itemH - subOffsetY - subH : subOffsetY;
25624				}
25625				if (this.opts.keepInViewport && !this.isCollapsible()) {
25626					if (this.isFixed()) {
25627						itemX -= winX;
25628						itemY -= winY;
25629						winX = winY = 0;
25630					}
25631					var absX = itemX + x,
25632						absY = itemY + y;
25633					if (this.opts.rightToLeftSubMenus && absX < winX) {
25634						x = horizontalParent ? winX - absX + x : itemW - subOffsetX;
25635					} else if (!this.opts.rightToLeftSubMenus && absX + subW > winX + containerOffsetX ) {
25636						x = horizontalParent ? winX + containerOffsetX - subW - absX + x : subOffsetX - subW;
25637					}
25638					if (!horizontalParent) {
25639						if (subH < winH && absY + subH > winY + winH) {
25640							y += winY + winH - subH - absY;
25641						} else if (subH >= winH || absY < winY) {
25642							y += winY - absY;
25643						}
25644					}
25645					// do we need scrolling?
25646					// 0.49 added for the sake of IE9/FF4+ where we might be dealing with float numbers for "subH"
25647					if (mouse && (horizontalParent && (absY + subH > winY + winH + 0.49 || absY < winY) || !horizontalParent && subH > winH + 0.49)) {
25648						var self = this;
25649						if (!$sub.dataSM('scroll-arrows')) {
25650							$sub.dataSM('scroll-arrows', $([$('<span class="scroll-up"><span class="scroll-up-arrow"></span></span>')[0], $('<span class="scroll-down"><span class="scroll-down-arrow"></span></span>')[0]])
25651								.bind({
25652									mouseenter: function() { self.menuScroll($sub, $(this).hasClass('scroll-up')); },
25653									mouseleave: function(e) {
25654										self.menuScrollStop($sub);
25655										self.menuScrollOut($sub, e);
25656									},
25657									'mousewheel DOMMouseScroll': function(e) { e.preventDefault(); }
25658								})
25659								.insertAfter($sub)
25660							);
25661						}
25662						// bind events to show/hide arrows on hover and save scrolling data for this sub
25663						var vportY = winY - (itemY + itemH);
25664						$sub.dataSM('scroll', {
25665								vportY: vportY,
25666								subH: subH,
25667								winH: winH,
25668								step: 1
25669							})
25670							.bind({
25671								'mouseover.smartmenus_scroll': function(e) { self.menuScrollOver($sub, e); },
25672								'mouseout.smartmenus_scroll': function(e) { self.menuScrollOut($sub, e); },
25673								'mousewheel.smartmenus_scroll DOMMouseScroll.smartmenus_scroll': function(e) { self.menuScrollMousewheel($sub, e); }
25674							})
25675							.dataSM('scroll-arrows').css({ top: 'auto', left: '0', marginLeft: x + (parseInt($sub.css('border-left-width')) || 0), width: this.getWidth($sub) - (parseInt($sub.css('border-left-width')) || 0) - (parseInt($sub.css('border-right-width')) || 0), zIndex: this.get
25675StartZIndex() + this.zIndexInc })
25676							.eq(0).css('margin-top', vportY).end()
25677							.eq(1).css('margin-top', vportY + winH - this.getHeight($sub.dataSM('scroll-arrows').eq(1))).end()
25678							.eq(horizontalParent && this.opts.bottomToTopSubMenus ? 0 : 1).show();
25679					}
25680				}
25681				if ( !$sub.closest('.menu-accordion').length ) {
25682					var rightPos = 'auto';
25683					if ( $sub.closest('.grid-filters').length ) {
25684						if ( $sub.closest('.text-right').length ) {
25685							leftPos = '0px';
25686							rightPos = 'auto';
25687						} else {
25688							leftPos = 'auto';
25689							rightPos = '0px';
25690						}
25691						x = 0;
25692					} else {
25693						if ( $sub.find('[data-parent="true"]:not(.limit-width):not(.row-parent-limit)').length && $sub.closest('.row-menu').is('.limit-width') && level === 2) {
25694							var parentContW = $sub.closest('.menu-container').width();
25695							$sub.css({ width: parentContW});
25696							$sub.addClass('need-focus');
25697							leftPos = -1 * (parseFloat($sub.closest('ul.menu-smart').offset().left) - parseFloat($sub.closest('.menu-container').offset().left));
25698							x = 0;
25699						} else if ( $sub.hasClass('mega-menu-inner') || $sub.find('[data-parent="true"]:not(.limit-width):not(.row-parent-limit)').length ) {
25700							$sub.css({ width: containerW});
25701							$sub.addClass('need-focus');
25702							leftPos = -1 * (parseFloat($sub.closest('ul.menu-smart').offset().left) - parseFloat($sub.closest('.row-menu').offset().left));
25703							if ( ! $('body').hasClass('megamenu-side-to-side') ) {
25704								leftPos += parseFloat($sub.closest('.row-menu-inner').css('paddingLeft'));
25705							}
25706							x = 0;
25707						} else {
25708							if ( $sub.is('.block-wrapper-parent') && !$sub.find('.col-custom-width').length && !$sub.find('.row-parent-limit').length && level === 2 ) {
25709								leftPos = ( $li.position().left - ( (UNCODE.wwidth - $sub.outerWidth() )/2) ) + 'px';
25710							} else {
25711								leftPos = (level > 2 ? $li.position().left - parseFloat($li.closest('ul:not(.nav-tabs):not(.unmenu-block):not(.unmenu-block *)').css('paddingLeft')) : $li.position().left ) + 'px';
25712							}
25713							x = (level > 2 && x >= 0) ? x + 1 : x - 1;
25714						}
25715					}
25716				}
25717
25718				// $sub.css({ top: (level > 2) ? $a[0].offsetTop : (fixIE ? itemH : '100%'), left: leftPos, right: rightPos, marginLeft: x, marginTop: (level > 2) ? 0 : y - itemH + ($sub.closest('.menu-borders').length ? 1 : 0) });
25719				$sub.css({ top: (level > 2) ? $a[0].offsetTop : (fixIE ? itemH : '100%'), left: leftPos, right: rightPos, marginLeft: x, marginTop: (level > 2) ? 0 : y - itemH + ($sub.closest('.menu-borders').length && !$sub.closest('.menu-borders.needs-after').length ? 1 : 0) });
25720				// IE iframe shim
25721				this.menuIframeShim($sub);
25722				if ($sub.dataSM('ie-shim')) {
25723					$sub.dataSM('ie-shim').css({ zIndex: $sub.css('z-index'), width: subW, height: subH, marginLeft: x, marginTop: y - itemH + ($sub.closest('.menu-mini').length ? 0 : 1) });
25724				}
25725			},
25726			menuScroll: function($sub, up, wheel) {
25727				var y = parseFloat($sub.css('margin-top')),
25728					scroll = $sub.dataSM('scroll'),
25729					navH = $('.navbar-main').outerHeight(),
25730					end = scroll.vportY + (up ? navH + 54 : scroll.winH - scroll.subH),
25731					step = wheel || !this.opts.scrollAccelerate ? this.opts.scrollStep : Math.floor($sub.dataSM('scroll').step);
25732				$sub.add($sub.dataSM('ie-shim')).css('margin-top', Math.abs(end - y) > step ? y + (up ? step : -step) : end);
25733				y = parseFloat($sub.css('margin-top'));
25734				// show opposite arrow if appropriate
25735				if (up && y + scroll.subH > scroll.vportY + scroll.winH || !up && y < scroll.vportY) {
25736					$sub.dataSM('scroll-arrows').eq(up ? 1 : 0).show();
25737				}
25738				// accelerate when not using mousewheel to scroll
25739				if (!wheel && this.opts.scrollAccelerate && $sub.dataSM('scroll').step < this.opts.scrollStep) {
25740					$sub.dataSM('scroll').step += 0.5;
25741				}
25742				// "y" and "end" might be float numbers in IE9/FF4+ so this weird way to check is used
25743				if (Math.abs(y - end) < 1) {
25744					$sub.dataSM('scroll-arrows').eq(up ? 0 : 1).hide();
25745					$sub.dataSM('scroll').step = 1;
25746				} else if (!wheel) {
25747					var self = this;
25748					this.scrollTimeout = setTimeout(function() { self.menuScroll($sub, up); }, this.opts.scrollInterval);
25749				}
25750			},
25751			menuScrollMousewheel: function($sub, e) {
25752				var $closestSub = $(e.target).closest('ul:not(.nav-tabs):not(.unmenu-block):not(.unmenu-block *)');
25753				while ($closestSub.dataSM('in-mega')) {
25754					$closestSub = $closestSub.parent().closest('ul:not(.nav-tabs):not(.unmenu-block):not(.unmenu-block *)');
25755				}
25756				if ($closestSub[0] == $sub[0]) {
25757					var up = (e.originalEvent.wheelDelta || -e.originalEvent.detail) > 0;
25758					if ($sub.dataSM('scroll-arrows').eq(up ? 0 : 1).is(':visible')) {
25759						this.menuScroll($sub, up, true);
25760					}
25761				}
25762				if ( ! $sub.hasClass('mega-menu-inner') && ! $sub.find('[data-parent="true"]:not(.limit-width):not(.row-parent-limit)') ) {
25763					e.preventDefault();
25764				}
25765			},
25766			menuScrollOut: function($sub, e) {
25767				var reClass = /^scroll-(up|down)/,
25768					$closestSub = $(e.relatedTarget).closest('ul:not(.nav-tabs):not(.unmenu-block):not(.unmenu-block *)');
25769				while ($closestSub.dataSM('in-mega')) {
25770					$closestSub = $closestSub.parent().closest('ul:not(.nav-tabs):not(.unmenu-block):not(.unmenu-block *)');
25771				}
25772				if (!reClass.test((e.relatedTarget || '').className) && ($sub[0] != e.relatedTarget && !$.contains($sub[0], e.relatedTarget) || $closestSub[0] != $sub[0])) {
25773					$sub.dataSM('scroll-arrows').css('visibility', 'hidden');
25774				}
25775			},
25776			menuScrollOver: function($sub, e) {
25777				var reClass = /^scroll-(up|down)/,
25778					$closestSub = $(e.target).closest('ul:not(.nav-tabs):not(.unmenu-block):not(.unmenu-block *)');
25779				while ($closestSub.dataSM('in-mega')) {
25780					$closestSub = $closestSub.parent().closest('ul:not(.nav-tabs):not(.unmenu-block):not(.unmenu-block *)');
25781				}
25782				if (!reClass.test(e.target.className) && $closestSub[0] == $sub[0]) {
25783					$sub.dataSM('scroll-arrows').css('visibility', 'visible');
25784				}
25785			},
25786			menuScrollStop: function($sub) {
25787				if (this.scrollTimeout) {
25788					clearTimeout(this.scrollTimeout);
25789					this.scrollTimeout = 0;
25790					$sub.dataSM('scroll').step = 1;
25791				}
25792			},
25793			menuShow: function($sub) {
25794				if (!$sub.dataSM('beforefirstshowfired')) {
25795					$sub.dataSM('beforefirstshowfired', true);
25796					if (this.$root.triggerHandler('beforefirstshow.smapi', $sub[0]) === false) {
25797						return;
25798					}
25799				}
25800				if ( this.isCollapsible() ) {
25801					this.$root.triggerHandler('beforecollapse.smapi', $sub[0]);
25802				}
25803				if (this.$root.triggerHandler('beforeshow.smapi', $sub[0]) === false) {
25804					return;
25805				}
25806				this.menuFixLayout($sub);
25807				$sub.stop(true, true);
25808				if (!$sub.is(':visible')) {
25809					$sub.css({
25810						'visibility': 'visible',
25811						'pointer-events': 'auto',
25812					});
25813					// set z-index - for IE < 9 set it to the parent LI
25814					var zIndex = this.getStartZIndex() + (++this.zIndexInc);
25815					if (IElt9) {
25816						$sub.parent().css('z-index', zIndex);
25817					} else {
25818						$sub.css('z-index', zIndex);
25819					}
25820					// highlight parent item
25821					if (this.opts.keepHighlighted || this.isCollapsible()) {
25822						if ($sub.dataSM('parent-a').attr('data-type') != 'title')
25823							$sub.dataSM('parent-a').addClass('highlighted');
25824					}
25825					// min/max-width fix - no way to rely purely on CSS as all UL's are nested
25826					if (this.opts.subMenusMinWidth || this.opts.subMenusMaxWidth) {
25827						if (!IElt8) {
25828							$sub.css({ width: ($sub.hasClass('mega-menu-inner') || $sub.find('[data-parent="true"]:not(.limit-width):not(.row-parent-limit)')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap');
25829							if (this.opts.subMenusMinWidth) {
25830							 	$sub.css('min-width', this.opts.subMenusMinWidth);
25831							}
25832							if (this.opts.subMenusMaxWidth) {
25833							 	var noMaxWidth = this.getWidth($sub);
25834							 	if ( ! $sub.hasClass('mega-menu-inner') && ! $sub.find('[data-parent="true"]:not(.limit-width):not(.row-parent-limit)') ) {
25835								 	$sub.css('max-width', this.opts.subMenusMaxWidth);
25836							 	}
25837								if (noMaxWidth > this.getWidth($sub)) {
25838									$sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth);
25839								}
25840							}
25841						// IE6,7
25842 						} else {
25843							$sub.children().css('styleFloat', 'none');
25844							if (IE6) {
25845								$sub.width(this.opts.subMenusMinWidth ? this.opts.subMenusMinWidth : 1)
25846									.children().children('a').css('white-space', 'nowrap');
25847							} else { // IE7
25848								$sub.css({ width: ($sub.hasClass('mega-menu-inner') || $sub.find('[data-parent="true"]:not(.limit-width):not(.row-parent-limit)')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap');
25849								if (this.opts.subMenusMinWidth) {
25850									$sub.css('min-width', this.opts.subMenusMinWidth);
25851								}
25852							}
25853							if (this.opts.subMenusMaxWidth) {
25854								var noMaxWidth = $sub.width();
25855								if (IE6) {
25856							 		var maxWidth = $sub.css({ width: this.opts.subMenusMaxWidth, overflowX: 'hidden', overflowY: 'hidden' }).width();
25857									if (noMaxWidth > maxWidth) {
25858										$sub.css({ width: maxWidth, overflowX: 'visible', overflowY: 'visible' }).children().children('a').css('white-space', '');
25859									} else {
25860										$sub.css({ width: noMaxWidth, overflowX: 'visible', overflowY: 'visible' });
25861									}
25862								} else { // IE7
25863								 	if ( ! $sub.hasClass('mega-menu-inner') && ! $sub.find('[data-parent="true"]:not(.limit-width):not(.row-parent-limit)') ) {
25864									 	$sub.css('max-width', this.opts.subMenusMaxWidth);
25865								 	}
25866									if (noMaxWidth > $sub.width()) {
25867										$sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth);
25868									} else {
25869										$sub.width(noMaxWidth);
25870									}
25871								}
25872							} else {
25873							 	$sub.width($sub.width());
25874							}
25875							$sub.children().css('styleFloat', 'left');
25876						}
25877					}
25878					if ( ( ( ($sub.hasClass('mega-menu-inner') || $sub.find('[data-parent="true"]:not(.limit-width):not(.row-parent-limit)')) && $('body').hasClass('scrollable-megamenu') ) ) && UNCODE.wwidth > UNCODE.mediaQuery ) {
25879						var $nav = $('.navbar-main'),
25880							navH = 0,
25881							navTop = 0,
25882							$vmenu = $('body.vmenu .vmenu-container, body.menu-overlay .vmenu-container, body.menu-offcanvas .vmenu-container');
25883						if ( $nav.length && typeof $nav[0] !== 'undefined' ) {
25884							var navRect = $nav[0].getBoundingClientRect();
25885							navH = navRect.height;
25886							navTop = navRect.top;
25887						}
25888						if ( ! $vmenu.length ) {
25889							$sub.css({ maxHeight: UNCODE.wheight - navH });
25890							if ( $('.megamenu-block-wrapper', $sub).length ) {
25891								$sub.find('> li').addClass('has-scroll').css({ maxHeight: UNCODE.wheight - navH });
25892							}
25893						}
25894					}
25895					this.menuPosition($sub);
25896					// insert IE iframe shim
25897					if ($sub.dataSM('ie-shim')) {
25898						$sub.dataSM('ie-shim').insertBefore($sub);
25899					}
25900					var complete = function() {
25901						// fix: "overflow: hidden;" is not reset on animation complete in jQuery < 1.9.0 in Chrome when global "box-sizing: border-box;" is used
25902						$sub.css('overflow', '');
25903					};
25904					// if sub is collapsible (mobile view)
25905					if (this.isCollapsible()) {
25906						if (this.opts.collapsibleShowFunction) {
25907							this.opts.collapsibleShowFunction.call(this, $sub, complete);
25908						} else {
25909							$sub.show(this.opts.collapsibleShowDuration, complete);
25910						}
25911					} else {
25912						if (this.opts.showFunction) {
25913							this.opts.showFunction.call(this, $sub, complete);
25914						} else {
25915							$sub.show(this.opts.showDuration, complete);
25916						}
25917					}
25918					// save new sub menu for this level
25919					this.visibleSubMenus[$sub.dataSM('level') - 1] = $sub;
25920					this.$root.triggerHandler('show.smapi', $sub[0]);
25921				}
25922			},
25923			popupHide: function(noHideTimeout) {
25924				if (this.hideTimeout) {
25925					clearTimeout(this.hideTimeout);
25926					this.hideTimeout = 0;
25927				}
25928				var self = this;
25929				this.hideTimeout = setTimeout(function() {
25930					self.menuHideAll();
25931				}, noHideTimeout ? 1 : this.opts.hideTimeout);
25932			},
25933			popupShow: function(left, top) {
25934				if (!this.opts.isPopup) {
25935					alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.');
25936					return;
25937				}
25938				if (this.hideTimeout) {
25939					clearTimeout(this.hideTimeout);
25940					this.hideTimeout = 0;
25941				}
25942				this.menuFixLayout(this.$root);
25943				this.$root.stop(true, true);
25944				if (!this.$root.is(':visible')) {
25945					this.$root.css({ left: left, top: top });
25946					// IE iframe shim
25947					this.menuIframeShim(this.$root);
25948					if (this.$root.dataSM('ie-shim')) {
25949						this.$root.dataSM('ie-shim').css({ zIndex: this.$root.css('z-index'), width: this.getWidth(this.$root), height: this.getHeight(this.$root), left
25949: left, top: top }).insertBefore(this.$root);
25950					}
25951					// show menu
25952					if (this.opts.showFunction) {
25953						this.opts.showFunction.call(this, this.$root);
25954					} else {
25955						this.$root.show(this.opts.showDuration);
25956					}
25957					this.visibleSubMenus[0] = this.$root;
25958				}
25959			},
25960			refresh: function() {
25961				this.menuHideAll();
25962				this.$root.find('ul:not(.nav-tabs):not(.unmenu-block):not(.unmenu-block *)').each(function() {
25963						var $this = $(this);
25964						if ($this.dataSM('scroll-arrows')) {
25965							$this.dataSM('scroll-arrows').remove();
25966						}
25967					})
25968					.removeDataSM('in-mega')
25969					.removeDataSM('shown-before')
25970					.removeDataSM('ie-shim')
25971					.removeDataSM('scroll-arrows')
25972					.removeDataSM('parent-a')
25973					.removeDataSM('level')
25974					.removeDataSM('beforefirstshowfired');
25975				this.$root.find('a.has-submenu').removeClass('has-submenu')
25976					.parent().removeDataSM('sub');
25977				if (this.opts.subIndicators) {
25978					this.$root.find('span.sub-arrow').remove();
25979				}
25980				if (this.opts.markCurrentItem) {
25981					this.$root.find('a.current').removeClass('current');
25982				}
25983				this.subMenus = [];
25984				this.init(true);
25985			},
25986			rootOut: function(e) {
25987				if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) {
25988					return;
25989				}
25990				if (this.hideTimeout) {
25991					clearTimeout(this.hideTimeout);
25992					this.hideTimeout = 0;
25993				}
25994				if (!this.opts.showOnClick || !this.opts.hideOnClick) {
25995					var self = this;
25996					this.hideTimeout = setTimeout(function() { self.menuHideAll(); }, this.opts.hideTimeout);
25997				}
25998			},
25999			rootOver: function(e) {
26000				if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) {
26001					return;
26002				}
26003				if (this.hideTimeout) {
26004					clearTimeout(this.hideTimeout);
26005					this.hideTimeout = 0;
26006				}
26007			},
26008			winResize: function(e) {
26009				if (!this.handleEvents()) {
26010					// we still need to resize the disable overlay if it's visible
26011					if (this.$disableOverlay) {
26012						var pos = this.$root.offset();
26013	 					this.$disableOverlay.css({
26014							top: pos.top,
26015							left: pos.left,
26016							width: this.$root.outerWidth(),
26017							height: this.$root.outerHeight()
26018						});
26019					}
26020					return;
26021				}
26022				// hide sub menus on resize - on mobile do it only on orientation change
26023				if (!this.isCollapsible() && (!('onorientationchange' in window) || e.type == 'orientationchange')) {
26024					if (this.activatedItems.length) {
26025						this.activatedItems[this.activatedItems.length - 1][0].blur();
26026					}
26027					this.menuHideAll();
26028				}
26029			}
26030		}
26031	});
26032
26033	$.fn.dataSM = function(key, val) {
26034		if (val) {
26035			return this.data(key + '_smartmenus', val);
26036		}
26037		return this.data(key + '_smartmenus');
26038	}
26039
26040	$.fn.removeDataSM = function(key) {
26041		return this.removeData(key + '_smartmenus');
26042	}
26043
26044	$.fn.smartmenus = function(options) {
26045		if (typeof options == 'string') {
26046			var args = arguments,
26047				method = options;
26048			Array.prototype.shift.call(args);
26049			return this.each(function() {
26050				var smartmenus = $(this).data('smartmenus');
26051				if (smartmenus && smartmenus[method]) {
26052					smartmenus[method].apply(smartmenus, args);
26053				}
26054			});
26055		}
26056		var opts = $.extend({}, $.fn.smartmenus.defaults, options);
26057		return this.each(function() {
26058			new $.SmartMenus(this, opts);
26059		});
26060	}
26061
26062	// default settings
26063	$.fn.smartmenus.defaults = {
26064		isPopup:		false,		// is this a popup menu (can be shown via the popupShow/popupHide methods) or a permanent menu bar
26065		mainMenuSubOffsetX:	0,		// pixels offset from default position
26066		mainMenuSubOffsetY:	0,		// pixels offset from default position
26067		subMenusSubOffsetX:	0,		// pixels offset from default position
26068		subMenusSubOffsetY:	0,		// pixels offset from default position
26069		subMenusMinWidth:	false, //'10em',		// min-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored
26070		subMenusMaxWidth:	false, //'20em',		// max-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored
26071		subIndicators: 		true,		// create sub menu indicators - creates a SPAN and inserts it in the A
26072		subIndicatorsPos: 	'prepend',	// position of the SPAN relative to the menu item content ('prepend', 'append')
26073		subIndicatorsText:	'+',		// [optionally] add text in the SPAN (e.g. '+') (you may want to check the CSS for the sub indicators too)
26074		scrollStep: 		30,		// pixels step when scrolling long sub menus that do not fit in the viewport height
26075		scrollInterval:		30,		// interval between each scrolling step
26076		scrollAccelerate:	true,		// accelerate scrolling or use a fixed step
26077		showTimeout:		250,		// timeout before showing the sub menus
26078		hideTimeout:		500,		// timeout before hiding the sub menus
26079		showDuration:		0,		// duration for show animation - set to 0 for no animation - matters only if showFunction:null
26080		showFunction:		null,		// custom function to use when showing a sub menu (the default is the jQuery 'show')
26081							// don't forget to call complete() at the end of whatever you do
26082							// e.g.: function($ul, complete) { $ul.fadeIn(250, complete); }
26083		hideDuration:		0,		// duration for hide animation - set to 0 for no animation - matters only if hideFunction:null
26084		hideFunction:		function($ul, complete) { $ul.fadeOut(200, complete); },	// custom function to use when hiding a sub menu (the default is the jQuery 'hide')
26085							// don't forget to call complete() at the end of whatever you do
26086							// e.g.: function($ul, complete) { $ul.fadeOut(250, complete); }
26087		collapsibleShowDuration:0,		// duration for show animation for collapsible sub menus - matters only if collapsibleShowFunction:null
26088		collapsibleShowFunction:function($ul, complete) { $ul.slideDown(200, complete); },	// custom function to use when showing a collapsible sub menu
26089							// (i.e. when mobile styles are used to make the sub menus collapsible)
26090		collapsibleHideDuration:0,		// duration for hide animation for collapsible sub menus - matters only if collapsibleHideFunction:null
26091		collapsibleHideFunction:function($ul, complete) { $ul.slideUp(200, complete); },	// custom function to use when hiding a collapsible sub menu
26092							// (i.e. when mobile styles are used to make the sub menus collapsible)
26093		showOnClick:		false,		// show the first-level sub menus onclick instead of onmouseover (matters only for mouse input)
26094		hideOnClick:		true,		// hide the sub menus on click/tap anywhere on the page
26095		keepInViewport:		true,		// reposition the sub menus if needed to make sure they always appear inside the viewport
26096		keepHighlighted:	true,		// keep all ancestor items of the current sub menu highlighted (adds the 'highlighted' class to the A's)
26097		markCurrentItem:	false,		// automatically add the 'current' class to the A element of the item linking to the current URL
26098		markCurrentTree:	true,		// add the 'current' class also to the A elements of all ancestor items of the current item
26099		rightToLeftSubMenus:	false,		// right to left display of the sub menus (check the CSS for the sub indicators' position)
26100		bottomToTopSubMenus:	false,		// bottom to top display of the sub menus
26101		overlapControlsInIE:	true		// make sure sub menus appear on top of special OS controls in IE (i.e. SELECT, OBJECT, EMBED, etc.)
26102	};
26103
26104})(jQuery);
26105/*
26106 * jQuery Easing v1.4.1 - http://gsgd.co.uk/sandbox/jquery/easing/
26107 * Open source under the BSD License.
26108 * Copyright © 2008 George McGinley Smith
26109 * All rights reserved.
26110 * https://raw.github.com/gdsmith/jquery.easing/master/LICENSE
26111*/
26112
26113/* globals jQuery, define, module, require */
26114(function (factory) {
26115	if (typeof define === "function" && define.amd) {
26116		define(['jquery'], function ($) {
26117			return factory($);
26118		});
26119	} else if (typeof module === "object" && typeof module.exports === "object") {
26120		module.exports = factory(require('jquery'));
26121	} else {
26122		factory(jQuery);
26123	}
26124})(function($){
26125
26126	// Preserve the original jQuery "swing" easing as "jswing"
26127	if (typeof $.easing !== 'undefined') {
26128		$.easing['jswing'] = $.easing['swing'];
26129	}
26130
26131	var pow = Math.pow,
26132		sqrt = Math.sqrt,
26133		sin = Math.sin,
26134		cos = Math.cos,
26135		PI = Math.PI,
26136		c1 = 1.70158,
26137		c2 = c1 * 1.525,
26138		c3 = c1 + 1,
26139		c4 = ( 2 * PI ) / 3,
26140		c5 = ( 2 * PI ) / 4.5;
26141
26142	// x is the fraction of animation progress, in the range 0..1
26143	function bounceOut(x) {
26144		var n1 = 7.5625,
26145			d1 = 2.75;
26146		if ( x < 1/d1 ) {
26147			return n1*x*x;
26148		} else if ( x < 2/d1 ) {
26149			return n1*(x-=(1.5/d1))*x + .75;
26150		} else if ( x < 2.5/d1 ) {
26151			return n1*(x-=(2.25/d1))*x + .9375;
26152		} else {
26153			return n1*(x-=(2.625/d1))*x + .984375;
26154		}
26155	}
26156
26157	$.extend( $.easing, {
26158		def: 'easeOutQuad',
26159		swing: function (x) {
26160			return $.easing[$.easing.def](x);
26161		},
26162		easeInQuad: function (x) {
26163			return x * x;
26164		},
26165		easeOutQuad: function (x) {
26166			return 1 - ( 1 - x ) * ( 1 - x );
26167		},
26168		easeInOutQuad: function (x) {
26169			return x < 0.5 ?
26170				2 * x * x :
26171				1 - pow( -2 * x + 2, 2 ) / 2;
26172		},
26173		easeInCubic: function (x) {
26174			return x * x * x;
26175		},
26176		easeOutCubic: function (x) {
26177			return 1 - pow( 1 - x, 3 );
26178		},
26179		easeInOutCubic: function (x) {
26180			return x < 0.5 ?
26181				4 * x * x * x :
26182				1 - pow( -2 * x + 2, 3 ) / 2;
26183		},
26184		easeInQuart: function (x) {
26185			return x * x * x * x;
26186		},
26187		easeOutQuart: function (x) {
26188			return 1 - pow( 1 - x, 4 );
26189		},
26190		easeInOutQuart: function (x) {
26191			return x < 0.5 ?
26192				8 * x * x * x * x :
26193				1 - pow( -2 * x + 2, 4 ) / 2;
26194		},
26195		easeInQuint: function (x) {
26196			return x * x * x * x * x;
26197		},
26198		easeOutQuint: function (x) {
26199			return 1 - pow( 1 - x, 5 );
26200		},
26201		easeInOutQuint: function (x) {
26202			return x < 0.5 ?
26203				16 * x * x * x * x * x :
26204				1 - pow( -2 * x + 2, 5 ) / 2;
26205		},
26206		easeInSine: function (x) {
26207			return 1 - cos( x * PI/2 );
26208		},
26209		easeOutSine: function (x) {
26210			return sin( x * PI/2 );
26211		},
26212		easeInOutSine: function (x) {
26213			return -( cos( PI * x ) - 1 ) / 2;
26214		},
26215		easeInExpo: function (x) {
26216			return x === 0 ? 0 : pow( 2, 10 * x - 10 );
26217		},
26218		easeOutExpo: function (x) {
26219			return x === 1 ? 1 : 1 - pow( 2, -10 * x );
26220		},
26221		easeInOutExpo: function (x) {
26222			return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ?
26223				pow( 2, 20 * x - 10 ) / 2 :
26224				( 2 - pow( 2, -20 * x + 10 ) ) / 2;
26225		},
26226		easeInCirc: function (x) {
26227			return 1 - sqrt( 1 - pow( x, 2 ) );
26228		},
26229		easeOutCirc: function (x) {
26230			return sqrt( 1 - pow( x - 1, 2 ) );
26231		},
26232		easeInOutCirc: function (x) {
26233			return x < 0.5 ?
26234				( 1 - sqrt( 1 - pow( 2 * x, 2 ) ) ) / 2 :
26235				( sqrt( 1 - pow( -2 * x + 2, 2 ) ) + 1 ) / 2;
26236		},
26237		easeInElastic: function (x) {
26238			return x === 0 ? 0 : x === 1 ? 1 :
26239				-pow( 2, 10 * x - 10 ) * sin( ( x * 10 - 10.75 ) * c4 );
26240		},
26241		easeOutElastic: function (x) {
26242			return x === 0 ? 0 : x === 1 ? 1 :
26243				pow( 2, -10 * x ) * sin( ( x * 10 - 0.75 ) * c4 ) + 1;
26244		},
26245		easeInOutElastic: function (x) {
26246			return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ?
26247				-( pow( 2, 20 * x - 10 ) * sin( ( 20 * x - 11.125 ) * c5 )) / 2 :
26248				pow( 2, -20 * x + 10 ) * sin( ( 20 * x - 11.125 ) * c5 ) / 2 + 1;
26249		},
26250		easeInBack: function (x) {
26251			return c3 * x * x * x - c1 * x * x;
26252		},
26253		easeOutBack: function (x) {
26254			return 1 + c3 * pow( x - 1, 3 ) + c1 * pow( x - 1, 2 );
26255		},
26256		easeInOutBack: function (x) {
26257			return x < 0.5 ?
26258				( pow( 2 * x, 2 ) * ( ( c2 + 1 ) * 2 * x - c2 ) ) / 2 :
26259				( pow( 2 * x - 2, 2 ) *( ( c2 + 1 ) * ( x * 2 - 2 ) + c2 ) + 2 ) / 2;
26260		},
26261		easeInBounce: function (x) {
26262			return 1 - bounceOut( 1 - x );
26263		},
26264		easeOutBounce: bounceOut,
26265		easeInOutBounce: function (x) {
26266			return x < 0.5 ?
26267				( 1 - bounceOut( 1 - 2 * x ) ) / 2 :
26268				( 1 + bounceOut( 2 * x - 1 ) ) / 2;
26269		}
26270	});
26271	return $;
26272});
26273
26274/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net)
26275 * Licensed under the MIT License (LICENSE.txt).
26276 *
26277 * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
26278 * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
26279 * Thanks to: Seamus Leahy for adding deltaX and deltaY
26280 *
26281 * Version: 3.0.6
26282 *
26283 * Requires: 1.2.2+
26284 */
26285(function($) {
26286    var types = ['DOMMouseScroll', 'mousewheel'];
26287    if ($.event.fixHooks) {
26288        for (var i = types.length; i;) {
26289            $.event.fixHooks[types[--i]] = $.event.mouseHooks;
26290        }
26291    }
26292    $.event.special.mousewheel = {
26293        setup: function() {
26294            if (this.addEventListener) {
26295                for (var i = types.length; i;) {
26296                    this.addEventListener(types[--i], handler, false);
26297                }
26298            } else {
26299                this.onmousewheel = handler;
26300            }
26301        },
26302        teardown: function() {
26303            if (this.removeEventListener) {
26304                for (var i = types.length; i;) {
26305                    this.removeEventListener(types[--i], handler, false);
26306                }
26307            } else {
26308                this.onmousewheel = null;
26309            }
26310        }
26311    };
26312    $.fn.extend({
26313        mousewheel: function(fn) {
26314            return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");
26315        },
26316        unmousewheel: function(fn) {
26317            return this.unbind("mousewheel", fn);
26318        }
26319    });
26320
26321    function handler(event) {
26322        var orgEvent = event || window.event,
26323            args = [].slice.call(arguments, 1),
26324            delta = 0,
26325            returnValue = true,
26326            deltaX = 0,
26327            deltaY = 0;
26328        event = $.event.fix(orgEvent);
26329        event.type = "mousewheel";
26330        // Old school scrollwheel delta
26331        if (orgEvent.wheelDelta) {
26332            delta = orgEvent.wheelDelta / 120;
26333        }
26334        if (orgEvent.detail) {
26335            delta = -orgEvent.detail / 3;
26336        }
26337        // New school multidimensional scroll (touchpads) deltas
26338        deltaY = delta;
26339        // Gecko
26340        if (orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS) {
26341            deltaY = 0;
26342            deltaX = -1 * delta;
26343        }
26344        // Webkit
26345        if (orgEvent.wheelDeltaY !== undefined) {
26346            deltaY = orgEvent.wheelDeltaY / 120;
26347        }
26348        if (orgEvent.wheelDeltaX !== undefined) {
26349            deltaX = -1 * orgEvent.wheelDeltaX / 120;
26350        }
26351        // Add event and delta to the front of the arguments
26352        args.unshift(event, delta, deltaX, deltaY);
26353        return ($.event.dispatch || $.event.handle).apply(this, args);
26354    }
26355})(jQuery);
26356/**
26357 * jQuery iLightBox - Revolutionary Lightbox Plugin
26358 * http://www.ilightbox.net/
26359 *
26360 * @version: 2.2.4 - October 14, 2017
26361 *
26362 * @author: iProDev (Hemn Chawroka)
26363 *          http://www.iprodev.com/
26364 *
26365 */
26366(function($, window, undefined) {
26367
26368	var extensions = {
26369			flash: ['swf'],
26370			image: ['bmp', 'gif', 'jpeg', 'jpg', 'png', 'tiff', 'tif', 'jfif', 'jpe', 'webp'],
26371			iframe: ['asp', 'aspx', 'cgi', 'cfm', 'htm', 'html', 'jsp', 'php', 'pl', 'php3', 'php4', 'php5', 'phtml', 'rb', 'rhtml', 'shtml', 'txt'],
26372			video: ['avi', 'mov', 'mpg', 'mpeg', 'movie', 'mp4', 'webm', 'ogv', 'ogg', '3gp', 'm4v']
26373		},
26374
26375		// Global DOM elements
26376		$win = $(window),
26377		$doc = $(document),
26378
26379		// Support indicators
26380		browser,
26381		transform,
26382		gpuAcceleration,
26383		fullScreenApi = '',
26384		userAgent = navigator.userAgent || navigator.vendor || window.opera,
26385        supportTouch = "ontouchstart" in window || navigator.msMaxTouchPoints || (navigator.maxTouchPoints && navigator.userAgent.indexOf('Windows') > -1),
26386        ishybrid = navigator.maxTouchPoints && navigator.userAgent.indexOf('Windows') > -1,
26387        isMobile = /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(userAgent) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(userAgent.substr(0, 4)),
26388
26389		// Events
26390		clickEvent = ishybrid ? "itap.iLightBox click.iLightBox" : supportTouch ? "itap.iLightBox" : "click.iLightBox",
26391		touchStartEvent = ishybrid ? "touchstart.iLightBox mousedown.iLightBox" : supportTouch ? "touchstart.iLightBox" : "mousedown.iLightBox",
26392		touchStopEvent = ishybrid ? "touchend.iLightBox mouseup.iLightBox" : supportTouch ? "touchend.iLightBox" : "mouseup.iLightBox",
26393		touchMoveEvent = ishybrid ? "touchmove.iLightBox mousemove.iLightBox" : supportTouch ? "touchmove.iLightBox" : "mousemove.iLightBox",
26394
26395		// Math shorthands
26396		abs = Math.abs,
26397		sqrt = Math.sqrt,
26398		round = Math.round,
26399		max = Math.max,
26400		min = Math.min,
26401		floor = Math.floor,
26402		random = Math.random,
26403
26404		pluginspages = {
26405			quicktime: 'http://www.apple.com/quicktime/download',
26406			flash: 'http://www.adobe.com/go/getflash'
26407		},
26408
26409		iLightBox = function(el, options, items, instant) {
26410			var iL = this;
26411
26412			iL.options = options,
26413				iL.selector = options.selector || el,
26414				iL.context = document,
26415				iL.instant = instant;
26416
26417			if (items.length < 1) iL.attachItems();
26418			else iL.items = items;
26419
26420			iL.vars = {
26421				total: iL.items.length,
26422				start: 0,
26423				current: null,
26424				next: null,
26425				prev: null,
26426				BODY: $('body'),
26427				loadRequests: 0,
26428				overlay: $('<div class="ilightbox-overlay"></div>'),
26429				loader: $('<div class="ilightbox-loader"><div></div></div>'),
26430				toolbar: $('<div class="ilightbox-toolbar"></div>'),
26431				innerToolbar: $('<div class="ilightbox-inner-toolbar"></div>'),
26432				title: $('<div class="ilightbox-title"></div>'),
26433				closeButton: $('<a class="ilightbox-close" title="' + iL.options.text.close + '"></a>'),
26434				fullScreenButton: $('<a class="ilightbox-fullscreen" title="' + iL.options.text.enterFullscreen + '"></a>'),
26435				innerPlayButton: $('<a class="ilightbox-play" title="' + iL.options.text.slideShow + '"></a>'),
26436				innerNextButton: $('<a class="ilightbox-next-button" title="' + iL.options.text.next + '"></a>'),
26437				innerPrevButton: $('<a class="ilightbox-prev-button" title="' + iL.options.text.previous + '"></a>'),
26438				holder: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + '" ondragstart="return false;"><div class="ilightbox-container"></div></div>'),
26439				nextPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-next" ondragstart="return false;"><div class="ilightbox-container"></div></div>'),
26440				prevPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-prev" ondragstart="return false;"><div class="ilightbox-container"></div></div>'),
26441				nextButton: $('<a class="ilightbox-button ilightbox-next-button" ondragstart="return false;" title="' + iL.options.text.next + '"><span></span></a>'),
26442				prevButton: $('<a class="ilightbox-button ilightbox-prev-button" ondragstart="return false;" title="' + iL.options.text.previous + '"><span></span></a>'),
26443				thumbnails: $('<div class="ilightbox-thumbnails" ondragstart="return false;"><div class="ilightbox-thumbnails-container"><a class="ilightbox-thumbnails-dragger"></a><div class="ilightbox-thumbnails-grid"></div></div></div>'),
26444				thumbs: false,
26445				nextLock: false,
26446				prevLock: false,
26447				hashLock: false,
26448				isMobile: false,
26449				mobileMaxWidth: 980,
26450				isInFullScreen: false,
26451				isSwipe: false,
26452				mouseID: 0,
26453				cycleID: 0,
26454				isPaused: 0,
26455				captionHeight: 39,
26456			};
26457
26458			// Hideable elements with mousemove event
26459			iL.vars.hideableElements = iL.vars.nextButton.add(iL.vars.prevButton);
26460
26461			iL.normalizeItems();
26462
26463			//Check necessary plugins
26464			iL.availPlugins();
26465
26466			//Set startFrom
26467			iL.options.startFrom = (iL.options.startFrom > 0 && iL.options.startFrom >= iL.vars.total) ? iL.vars.total - 1 : iL.options.startFrom;
26468
26469			//If randomStart
26470			iL.options.startFrom = (iL.options.randomStart) ? floor(random() * iL.vars.total) : iL.options.startFrom;
26471			iL.vars.start = iL.options.startFrom;
26472
26473			if (instant) iL.instantCall();
26474			else iL.patchItemsEvents();
26475
26476			if (iL.options.linkId) {
26477				iL.hashChangeHandler();
26478				$win.iLightBoxHashChange(function() {
26479					iL.hashChangeHandler();
26480				});
26481			}
26482
26483			if (supportTouch) {
26484				var RegExp = /(click|mouseenter|mouseleave|mouseover|mouseout)/ig,
26485					replace = "itap";
26486				iL.options.caption.show = iL.options.caption.show.replace(RegExp, replace),
26487					iL.options.caption.hide = iL.options.caption.hide.replace(RegExp, replace),
26488					iL.options.social.show = iL.options.social.show.replace(RegExp, replace),
26489					iL.options.social.hide = iL.options.social.hide.replace(RegExp, replace);
26490			}
26491
26492			if (iL.options.controls.arrows || $(window).width() < UNCODE.mediaQuery) {
26493				$.extend(iL.options.styles, {
26494					nextOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4,
26495					prevOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4,
26496					nextOpacity: 0,
26497					prevOpacity: 0
26498				});
26499			}
26500		};
26501
26502	//iLightBox helpers
26503	iLightBox.prototype = {
26504		showLoader: function() {
26505			var iL = this;
26506			iL.vars.loadRequests += 1;
26507			if (iL.options.path.toLowerCase() == "horizontal") iL.vars.loader.addClass('ilightbox-show').stop().animate({
26508				//top: '-30px'
26509				opacity: '1'
26510			}, iL.options.show.speed, 'easeOutCirc');
26511			else iL.vars.loader.addClass('ilightbox-show').stop().animate({
26512				//left: '-30px'
26513				opacity: '1'
26514			}, iL.options.show.speed, 'easeOutCirc');
26515		},
26516
26517		hideLoader: function() {
26518			var iL = this;
26519			iL.vars.loadRequests -= 1;
26520			iL.vars.loadRequests = (iL.vars.loadRequests < 0) ? 0 : iL.vars.loadRequests;
26521			if (iL.options.path.toLowerCase() == "horizontal") {
26522				if (iL.vars.loadRequests <= 0) iL.vars.loader.removeClass('ilightbox-show').stop().animate({
26523					//top: '-192px'
26524					opacity: '0'
26525				}, iL.options.show.speed, 'easeInCirc');
26526			} else {
26527				if (iL.vars.loadRequests <= 0) iL.vars.loader.removeClass('ilightbox-show').stop().animate({
26528					//left: '-192px'
26529					opacity: '0'
26530				}, iL.options.show.speed, 'easeInCirc');
26531			}
26532		},
26533
26534		createUI: function() {
26535			var iL = this;
26536
26537			iL.ui = {
26538				currentElement: iL.vars.holder,
26539				nextElement: iL.vars.nextPhoto,
26540				prevElement: iL.vars.prevPhoto,
26541				currentItem: iL.vars.current,
26542				nextItem: iL.vars.next,
26543				prevItem: iL.vars.prev,
26544				hide: function() {
26545					iL.closeAction();
26546				},
26547				refresh: function() {
26548					(arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto();
26549				},
26550				fullscreen: function() {
26551					iL.fullScreenAction();
26552				}
26553			};
26554		},
26555
26556		attachItems: function() {
26557			var iL = this,
26558				itemsObject = new Array(),
26559				items = new Array();
26560
26561			$(iL.selector, iL.context).each(function() {
26562				var t = $(this),
26563					URL = t.attr(iL.options.attr) || null,
26564					options = t.data("options") && eval("({" + t.data("options") + "})") || {},
26565					caption = t.data('caption'),
26566					title = t.data('title'),
26567					type = t.data('type') || getTypeByExtension(URL),
26568					clone = t.data('lbox-clone') || false;
26569
26570				//Uncode addition ##START##
26571				if (type === false) {
26572					return;
26573				}
26574				//Uncode addition ##END##
26575
26576				if (t.data('lbox-clone') != undefined) return;
26577
26578				//Uncode addition ##START##
26579				if ( typeof t.attr('data-album') != 'undefined' && t.attr('data-album') != '' ) {
26580					var ALBUM_URLS = JSON.parse(t.attr('data-album')),
26581						URL_i,
26582						URLS_LENGHT = ALBUM_URLS.length;
26583
26584					for (URL_i = 0; URL_i < URLS_LENGHT; URL_i++) {
26585						if ( typeof ALBUM_URLS[URL_i].url !== 'undefined' && ALBUM_URLS[URL_i].url != '' ) {
26586							var item_opts = 'width:' + ALBUM_URLS[URL_i].width + ',height:' + ALBUM_URLS[URL_i].height + ',thumbnail: \'' + ALBUM_URLS[URL_i].thumbnail + '\'';
26587							item_opts = item_opts && eval("({" + item_opts + "})") || {},
26588							items.push({
26589								URL: ALBUM_URLS[URL_i].url,
26590								caption: ALBUM_URLS[URL_i].caption,
26591								title: ALBUM_URLS[URL_i].title,
26592								type: getTypeByExtension(ALBUM_URLS[URL_i].url),
26593								options: item_opts,
26594								clone: clone
26595							});
26596							var newT = t;
26597							newT.attr('href',ALBUM_URLS[URL_i].url);
26598							if (!iL.instant) itemsObject.push(newT);
26599						}
26600					}
26601				} else {
26602				//Uncode addition ##END##
26603					items.push({
26604						URL: URL,
26605						caption: caption,
26606						title: title,
26607						type: type,
26608						options: options,
26609						clone: clone
26610					});
26611				}
26612
26613
26614				if (iL.vars != undefined) iL.vars.total = items.length;
26615
26616				if (!iL.instant) itemsObject.push(t);
26617			});
26618
26619			iL.items = items,
26620				iL.itemsObject = itemsObject;
26621
26622		},
26623
26624		normalizeItems: function() {
26625			var iL = this,
26626				newItems = new Array();
26627
26628			$.each(iL.items, function(key, val) {
26629
26630				if (typeof val == "string") val = {
26631					url: val
26632				};
26633
26634				var URL = val.url || val.URL || null,
26635					options = val.options || {},
26636					caption = val.caption || null,
26637					title = val.title || null,
26638					type = (val.type) ? val.type.toLowerCase() : getTypeByExtension(URL),
26639					ext = (typeof URL != 'object') ? getExtension(URL) : '';
26640
26641				options.thumbnail = options.thumbnail || ((type == "image") ? URL : null),
26642				options.videoType = options.videoType || null,
26643				options.skin = options.skin || iL.options.skin,
26644				options.width = options.width || null,
26645				options.height = options.height || null,
26646				options.mousewheel = (typeof options.mousewheel != 'undefined') ? options.mousewheel : true,
26647				options.swipe = (typeof options.swipe != 'undefined') ? options.swipe : true,
26648				options.social = (typeof options.social != 'undefined') ? options.social : iL.options.social.buttons && $.extend({}, {}, iL.options.social.buttons);
26649
26650				if (type == "video") {
26651					options.html5video = (typeof options.html5video != 'undefined') ? options.html5video : {};
26652
26653					options.html5video.webm = options.html5video.webm || options.html5video.WEBM || null;
26654					options.html5video.controls = (typeof options.html5video.controls != 'undefined') ? options.html5video.controls : "controls";
26655					options.html5video.preload = options.html5video.preload || "metadata";
26656					options.html5video.autoplay = (typeof options.html5video.autoplay != 'undefined') ? options.html5video.autoplay : false;
26657					//UNCODE addition
26658					options.html5video.loop = (typeof options.html5video.loop != 'undefined') ? options.html5video.loop : false;
26659				}
26660
26661				if (!options.width || !options.height) {
26662					if (type == "video") options.width = 1280, options.height = 720;
26663					else if (type == "iframe") options.width = '100%', options.height = '90%';
26664					else if (type == "flash") options.width = 1280, options.height = 720;
26665				}
26666
26667				delete val.url;
26668				val.index = key;
26669				val.URL = URL;
26670				val.caption = caption;
26671				val.title = title;
26672				val.type = type;
26673				val.options = options;
26674				val.ext = ext;
26675
26676				newItems.push(val);
26677			});
26678
26679			iL.items = newItems;
26680		},
26681
26682		instantCall: function() {
26683			var iL = this,
26684				key = iL.vars.start;
26685
26686			iL.vars.current = key;
26687			iL.vars.next = (iL.items[key + 1]) ? key + 1 : null;
26688			iL.vars.prev = (iL.items[key - 1]) ? key - 1 : null;
26689
26690			iL.addContents();
26691			iL.patchEvents();
26692		},
26693
26694		addContents: function() {
26695			var iL = this,
26696				vars = iL.vars,
26697				opts = iL.options,
26698				viewport = getViewport(),
26699				path = opts.path.toLowerCase(),
26700				recognizingItems = vars.total > 0 && iL.items.filter(function(e, i, arr) {
26701					return ['image', 'flash', 'video'].indexOf(e.type) === -1 && typeof e.recognized === 'undefined' && (opts.smartRecognition || e.options.smartRecognition);
26702				}),
26703				needRecognition = recognizingItems.length > 0;
26704
26705			if (opts.mobileOptimizer && !opts.innerToolbar)
26706				vars.isMobile = viewport.width <= vars.mobileMaxWidth;
26707
26708			vars.overlay.addClass(opts.skin).hide().css('opacity', opts.overlay.opacity);
26709
26710			if (opts.linkId)
26711				vars.overlay[0].setAttribute('linkid', opts.linkId);
26712
26713			//Add Toolbar Buttons
26714			if (opts.controls.toolbar) {
26715				vars.toolbar.addClass(opts.skin).append(vars.closeButton);
26716				if (opts.controls.fullscreen)
26717					vars.toolbar.append(vars.fullScreenButton);
26718				if (opts.controls.slideshow)
26719					vars.toolbar.append(vars.innerPlayButton);
26720				if (vars.total > 1)
26721					vars.toolbar.append(vars.innerPrevButton).append(vars.innerNextButton);
26722			}
26723
26724			//Append elements to body
26725			vars.BODY.addClass('ilightbox-noscroll').append(vars.overlay).append(vars.loader).append(vars.holder).append(vars.nextPhoto).append(vars.prevPhoto);
26726
26727			if (!opts.innerToolbar)
26728				vars.BODY.append(vars.toolbar);
26729			if (opts.controls.arrows)
26730				vars.BODY.append(vars.nextButton).append(vars.prevButton);
26731
26732			if (opts.controls.thumbnail && vars.total > 1) {
26733				vars.BODY.append(vars.thumbnails);
26734				vars.thumbnails.addClass(opts.skin).addClass('ilightbox-' + path);
26735				$('div.ilightbox-thumbnails-grid', vars.thumbnails).empty();
26736				vars.thumbs = true;
26737			}
26738
26739			//Configure loader and arrows
26740			var loaderCss = (opts.path.toLowerCase() == "horizontal") ? {
26741				left: parseInt((viewport.width / 2) - (vars.loader.outerWidth() / 2))
26742			} : {
26743				top: parseInt((viewport.height / 2) - (vars.loader.outerHeight() / 2))
26744			};
26745			vars.loader.addClass(opts.skin).css(loaderCss);
26746			vars.nextButton.add(vars.prevButton).addClass(opts.skin);
26747			if (path == "horizontal")
26748				vars.loader.add(vars.nextButton).add(vars.prevButton).addClass('horizontal');
26749
26750			// Configure arrow buttons
26751			vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile');
26752
26753			if (!opts.infinite) {
26754				vars.prevButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
26755
26756				if (vars.current == 0)
26757					vars.prevButton.add(vars.innerPrevButton).addClass('disabled');
26758				if (vars.current >= vars.total - 1)
26759					vars.nextButton.add(vars.innerNextButton).addClass('disabled');
26760			}
26761
26762			if (opts.show.effect) {
26763				vars.overlay.stop().fadeIn(opts.show.speed);
26764				vars.toolbar.stop().fadeIn(opts.show.speed);
26765			} else {
26766				vars.overlay.show();
26767				vars.toolbar.show();
26768			}
26769
26770			var length = recognizingItems.length;
26771			if (needRecognition) {
26772				iL.showLoader();
26773
26774				$.each(recognizingItems, function(key, val) {
26775					var resultFnc = function(result) {
26776							var key = -1,
26777								filter = iL.items.filter(function(e, i, arr) {
26778									if (e.URL == result.url)
26779										key = i;
26780
26781									return e.URL == result.url;
26782								}),
26783								self = iL.items[key];
26784
26785							if (result)
26786								$.extend(true, self, {
26787									URL: result.source,
26788									type: result.type,
26789									recognized: true,
26790									options: {
26791										html5video: result.html5video,
26792										width: (result.type == "image") ? 0 : (result.width || self.width),
26793										height: (result.type == "image") ? 0 : (result.height || self.height),
26794										thumbnail: self.options.thumbnail || result.thumbnail
26795									}
26796								});
26797
26798							length--;
26799
26800							if (length == 0) {
26801								iL.hideLoader();
26802
26803								vars.dontGenerateThumbs = false;
26804								iL.generateThumbnails();
26805
26806								if (opts.show.effect)
26807									setTimeout(function() {
26808										iL.generateBoxes();
26809									}, opts.show.speed);
26810								else
26811									iL.generateBoxes();
26812							}
26813						};
26814
26815					iL.ogpRecognition(this, resultFnc);
26816				});
26817			}
26818			else {
26819				if (opts.show.effect)
26820					setTimeout(function() {
26821						iL.generateBoxes();
26822					}, opts.show.speed);
26823				else
26824					iL.generateBoxes();
26825			}
26826
26827			iL.createUI();
26828
26829			window.iLightBox = {
26830				close: function() {
26831					iL.closeAction();
26832				},
26833				fullscreen: function() {
26834					iL.fullScreenAction();
26835				},
26836				moveNext: function() {
26837					iL.moveTo('next');
26838				},
26839				movePrev: function() {
26840					iL.moveTo('prev');
26841				},
26842				goTo: function(index) {
26843					iL.goTo(index);
26844				},
26845				refresh: function() {
26846					iL.refresh();
26847				},
26848				reposition: function() {
26849					(arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto();
26850				},
26851				setOption: function(options) {
26852					iL.setOption(options);
26853				},
26854				destroy: function() {
26855					iL.closeAction();
26856					iL.dispatchItemsEvents();
26857				}
26858			};
26859
26860			if (opts.linkId) {
26861				vars.hashLock = true;
26862				window.location.hash = opts.linkId + '/' + vars.current;
26863				setTimeout(function() {
26864					vars.hashLock = false;
26865				}, 55);
26866			}
26867
26868			if (!opts.slideshow.startPaused) {
26869				iL.resume();
26870				vars.innerPlayButton.removeClass('ilightbox-play').addClass('ilightbox-pause');
26871			}
26872
26873			//Trigger the onOpen callback
26874			if (typeof iL.options.callback.onOpen == 'function') iL.options.callback.onOpen.call(iL);
26875		},
26876
26877		loadContent: function(obj, opt, speed) {
26878			var iL = this,
26879				holder, item;
26880
26881			iL.createUI();
26882
26883			obj.speed = speed || iL.options.effects.loadedFadeSpeed;
26884
26885			if (opt == 'current') {
26886				if (!obj.options.mousewheel) iL.vars.lockWheel = true;
26887				else iL.vars.lockWheel = false;
26888
26889				if (!obj.options.swipe) iL.vars.lockSwipe = true;
26890				else iL.vars.lockSwipe = false;
26891			}
26892
26893			switch (opt) {
26894				case 'current':
26895					holder = iL.vars.holder, item = iL.vars.current;
26896					break;
26897				case 'next':
26898					holder = iL.vars.nextPhoto, item = iL.vars.next;
26899					break;
26900				case 'prev':
26901					holder = iL.vars.prevPhoto, item = iL.vars.prev;
26902					break;
26903			}
26904
26905			holder.removeAttr('style class').addClass('ilightbox-holder' + (supportTouch ? ' supportTouch' : '')).addClass(obj.options.skin);
26906			$('div.ilightbox-inner-toolbar', holder).remove();
26907
26908			if (obj.title || iL.options.innerToolbar) {
26909				var innerToolbar = iL.vars.innerToolbar.clone();
26910				if (obj.title && iL.options.show.title) {
26911					var title = iL.vars.title.clone();
26912					title.empty().html(obj.title);
26913					innerToolbar.append(title);
26914				}
26915				if (iL.options.innerToolbar) {
26916					innerToolbar.append((iL.vars.total > 1) ? iL.vars.toolbar.clone() : iL.vars.toolbar);
26917				}
26918				holder.prepend(innerToolbar);
26919			}
26920
26921			//console.warn('loadContent', arguments);
26922
26923			iL.loadSwitcher(obj, holder, item, opt);
26924		},
26925
26926		loadSwitcher: function(obj, holder, item, opt) {
26927			var iL = this,
26928				opts = iL.options,
26929				api = {
26930					element: holder,
26931					position: item
26932				};
26933
26934			switch (obj.type) {
26935				case 'image':
26936					//Trigger the onBeforeLoad callback
26937					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
26938					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
26939
26940					iL.loadImage(obj.URL, function(img) {
26941						//Trigger the onAfterLoad callback
26942						if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
26943						if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
26944
26945						var width = (img) ? img.width : 400,
26946							height = (img) ? img.height : 200;
26947
26948						holder.data({
26949							naturalWidth: width,
26950							naturalHeight: height
26951						});
26952
26953						$('div.ilightbox-container', holder).empty().append((img) ? '<img src="' + obj.URL + '" class="ilightbox-image" />' : '<span class="ilightbox-alert">' + opts.errors.loadImage + '</span>');
26954
26955						//Trigger the onRender callback
26956						if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
26957						if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
26958
26959						iL.configureHolder(obj, opt, holder);
26960					});
26961
26962					break;
26963
26964				case 'video':
26965					holder.data({
26966						naturalWidth: obj.options.width,
26967						naturalHeight: obj.options.height
26968					});
26969
26970					if (opt === 'current') {
26971						iL.addContent(holder, obj);
26972
26973						//Trigger the onRender callback
26974						if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
26975						if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
26976					} else {
26977						$('div.ilightbox-container', holder).empty();
26978					}
26979
26980					iL.configureHolder(obj, opt, holder);
26981
26982					break;
26983
26984				case 'iframe':
26985					//iL.showLoader();
26986					holder.data({
26987						naturalWidth: obj.options.width,
26988						naturalHeight: obj.options.height
26989					});
26990
26991					iL.configureHolder(obj, opt, holder);
26992
26993					if (opt === 'current') {
26994						var el = iL.addContent(holder, obj);
26995
26996						//Trigger the onRender callback
26997						if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
26998						if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
26999
27000						//Trigger the onBeforeLoad callback
27001						if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
27002						if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
27003
27004						el.bind('load', function() {
27005							//Trigger the onAfterLoad callback
27006							if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
27007							if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
27008
27009							//iL.hideLoader();
27010							el.unbind('load');
27011						});
27012					} else {
27013						$('div.ilightbox-container', holder).empty();
27014					}
27015
27016					break;
27017
27018				case 'inline':
27019					var el = $(obj.URL),
27020						content = iL.addContent(holder, obj),
27021						images = findImageInElement(holder);
27022
27023					holder.data({
27024						naturalWidth: (iL.items[item].options.width || el.outerWidth()),
27025						naturalHeight: (iL.items[item].options.height || el.outerHeight())
27026					});
27027					content.children().eq(0).show();
27028
27029					//Trigger the onRender callback
27030					if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
27031					if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
27032
27033					//Trigger the onBeforeLoad callback
27034					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
27035					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
27036
27037					iL.loadImage(images, function() {
27038						//Trigger the onAfterLoad callback
27039						if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
27040						if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
27041
27042						iL.configureHolder(obj, opt, holder);
27043					});
27044
27045					break;
27046
27047				case 'flash':
27048					var el = iL.addContent(holder, obj);
27049
27050					holder.data({
27051						naturalWidth: (iL.items[item].options.width || el.outerWidth()),
27052						naturalHeight: (iL.items[item].options.height || el.outerHeight())
27053					});
27054
27055					//Trigger the onRender callback
27056					if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
27057					if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
27058
27059					iL.configureHolder(obj, opt, holder);
27060
27061					break;
27062
27063				case 'ajax':
27064					var ajax = obj.options.ajax || {};
27065					//Trigger the onBeforeLoad callback
27066					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
27067					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
27068
27069					iL.showLoader();
27070					$.ajax({
27071						url: obj.URL || opts.ajaxSetup.url,
27072						data: ajax.data || null,
27073						dataType: ajax.dataType || "html",
27074						type: ajax.type || opts.ajaxSetup.type,
27075						cache: ajax.cache || opts.ajaxSetup.cache,
27076						crossDomain: ajax.crossDomain || opts.ajaxSetup.crossDomain,
27077						global: ajax.global || opts.ajaxSetup.global,
27078						ifModified: ajax.ifModified || opts.ajaxSetup.ifModified,
27079						username: ajax.username || opts.ajaxSetup.username,
27080						password: ajax.password || opts.ajaxSetup.password,
27081						beforeSend: ajax.beforeSend || opts.ajaxSetup.beforeSend,
27082						complete: ajax.complete || opts.ajaxSetup.complete,
27083						success: function(data, textStatus, jqXHR) {
27084							iL.hideLoader();
27085
27086							var el = $(data),
27087								container = $('div.ilightbox-container', holder),
27088								elWidth = iL.items[item].options.width || parseInt(el[0].getAttribute('width')),
27089								elHeight = iL.items[item].options.height || parseInt(el[0].getAttribute('height')),
27090								css = (el[0].getAttribute('width') && el[0].getAttribute('height')) ? {
27091									'overflow': 'hidden'
27092								} : {};
27093
27094							container.empty().append($('<div class="ilightbox-wrapper"></div>').css(css).html(el));
27095							holder.show().data({
27096								naturalWidth: (elWidth || container.outerWidth()),
27097								naturalHeight: (elHeight || container.outerHeight())
27098							}).hide();
27099
27100							//Trigger the onRender callback
27101							if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
27102							if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
27103
27104							var images = findImageInElement(holder);
27105							iL.loadImage(images, function() {
27106								//Trigger the onAfterLoad callback
27107								if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
27108								if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
27109
27110								iL.configureHolder(obj, opt, holder);
27111							});
27112
27113							opts.ajaxSetup.success(data, textStatus, jqXHR);
27114							if (typeof ajax.success == 'function') ajax.success(data, textStatus, jqXHR);
27115						},
27116						error: function(jqXHR, textStatus, errorThrown) {
27117							//Trigger the onAfterLoad callback
27118							if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
27119							if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
27120
27121							iL.hideLoader();
27122							$('div.ilightbox-container', holder).empty().append('<span class="ilightbox-alert">' + opts.errors.loadContents + '</span>');
27123							iL.configureHolder(obj, opt, holder);
27124
27125							opts.ajaxSetup.error(jqXHR, textStatus, errorThrown);
27126							if (typeof ajax.error == 'function') ajax.error(jqXHR, textStatus, errorThrown);
27127						}
27128					});
27129
27130					break;
27131
27132				case 'html':
27133					var object = obj.URL,
27134						el
27135					container = $('div.ilightbox-container', holder);
27136
27137					if (object[0].nodeName) el = object.clone();
27138					else {
27139						var dom = $(object);
27140						if (dom.selector) el = $('<div>' + dom + '</div>');
27141						else el = dom;
27142					}
27143
27144					var elWidth = iL.items[item].options.width || parseInt(el.attr('width')),
27145						elHeight = iL.items[item].options.height || parseInt(el.attr('height'));
27146
27147					iL.addContent(holder, obj);
27148
27149					el.appendTo(document.documentElement).hide();
27150
27151					//Trigger the onRender callback
27152					if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
27153					if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
27154
27155					var images = findImageInElement(holder);
27156
27157					//Trigger the onBeforeLoad callback
27158					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
27159					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
27160
27161					iL.loadImage(images, function() {
27162						//Trigger the onAfterLoad callback
27163						if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
27164						if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
27165
27166						holder.show().data({
27167							naturalWidth: (elWidth || container.outerWidth()),
27168							naturalHeight: (elHeight || container.outerHeight())
27169						}).hide();
27170						el.remove();
27171
27172						iL.configureHolder(obj, opt, holder);
27173					});
27174
27175					break;
27176			}
27177		},
27178
27179		configureHolder: function(obj, opt, holder) {
27180			var iL = this,
27181				vars = iL.vars,
27182				opts = iL.options;
27183
27184			if (opt != "current")(opt == "next") ? holder.addClass('ilightbox-next') : holder.addClass('ilightbox-prev');
27185
27186			if (opt == "current")
27187				var item = vars.current;
27188			else if (opt == "next")
27189				var opacity = opts.styles.nextOpacity,
27190					item = vars.next;
27191			else
27192				var opacity = opts.styles.prevOpacity,
27193					item = vars.prev;
27194
27195			var api = {
27196				element: holder,
27197				position: item
27198			};
27199
27200			iL.items[item].options.width = iL.items[item].options.width || 0,
27201			iL.items[item].options.height = iL.items[item].options.height || 0;
27202
27203			if (opt == "current") {
27204				if (opts.show.effect) holder.css(transform, gpuAcceleration).fadeIn(obj.speed, function() {
27205					holder.css(transform, '');
27206					if (obj.caption) {
27207						iL.setCaption(obj, holder);
27208						var caption = $('div.ilightbox-caption', holder),
27209							percent = parseInt((caption.outerHeight() / holder.outerHeight()) * 100);
27210						if (opts.caption.start & percent <= 50) caption.fadeIn(opts.effects.fade
27210Speed);
27211					}
27212
27213					var social = obj.options.social;
27214					if (social) {
27215						iL.setSocial(social, obj.URL, holder);
27216						if (opts.social.start) $('div.ilightbox-social', holder).fadeIn(opts.effects.fadeSpeed);
27217					}
27218
27219					//Generate thumbnails
27220					iL.generateThumbnails();
27221
27222					//Trigger the onShow callback
27223					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
27224					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
27225				});
27226				else {
27227					holder.show();
27228
27229					//Generate thumbnails
27230					iL.generateThumbnails();
27231
27232					//Trigger the onShow callback
27233					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
27234					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
27235				}
27236			} else {
27237				if (opts.show.effect) holder.fadeTo(obj.speed, opacity, function() {
27238					if (opt == "next") vars.nextLock = false;
27239					else vars.prevLock = false;
27240
27241					//Generate thumbnails
27242					iL.generateThumbnails();
27243
27244					//Trigger the onShow callback
27245					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
27246					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
27247				});
27248				else {
27249					holder.css({
27250						opacity: opacity
27251					}).show();
27252					if (opt == "next") vars.nextLock = false;
27253					else vars.prevLock = false;
27254
27255					//Generate thumbnails
27256					iL.generateThumbnails();
27257
27258					//Trigger the onShow callback
27259					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
27260					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
27261				}
27262			}
27263
27264			setTimeout(function() {
27265				iL.repositionPhoto();
27266			}, 0);
27267		},
27268
27269		generateBoxes: function() {
27270			var iL = this,
27271				vars = iL.vars,
27272				opts = iL.options;
27273
27274			if (opts.infinite && vars.total >= 3) {
27275				if (vars.current == vars.total - 1) vars.next = 0;
27276				if (vars.current == 0) vars.prev = vars.total - 1;
27277			} else opts.infinite = false;
27278
27279			//UNCODE addition
27280			if ( typeof iL.items[vars.current] == 'undefined' )
27281				vars.current = 0;
27282
27283			iL.loadContent(iL.items[vars.current], 'current', opts.show.speed);
27284
27285			if (iL.items[vars.next]) iL.loadContent(iL.items[vars.next], 'next', opts.show.speed);
27286			if (iL.items[vars.prev]) iL.loadContent(iL.items[vars.prev], 'prev', opts.show.speed);
27287		},
27288
27289		generateThumbnails: function() {
27290			var iL = this,
27291				vars = iL.vars,
27292				opts = iL.options,
27293				timeOut = null;
27294
27295			if (vars.thumbs && !iL.vars.dontGenerateThumbs) {
27296				var thumbnails = vars.thumbnails,
27297					container = $('div.ilightbox-thumbnails-container', thumbnails),
27298					grid = $('div.ilightbox-thumbnails-grid', container),
27299					i = 0;
27300
27301				grid.removeAttr('style').empty();
27302
27303				$.each(iL.items, function(key, val) {
27304					var isActive = (vars.current == key) ? 'ilightbox-active' : '',
27305						opacity = (vars.current == key) ? opts.thumbnails.activeOpacity : opts.thumbnails.normalOpacity,
27306						thumb = val.options.thumbnail,
27307						thumbnail = $('<div class="ilightbox-thumbnail"></div>'),
27308						icon = $('<div class="ilightbox-thumbnail-icon"></div>');
27309
27310					thumbnail.css({
27311						opacity: 0
27312					}).addClass(isActive);
27313
27314					if ((val.type == "video" || val.type == "flash") && typeof val.options.icon == 'undefined') {
27315						icon.addClass('ilightbox-thumbnail-video');
27316						thumbnail.append(icon);
27317					} else if (val.options.icon) {
27318						icon.addClass('ilightbox-thumbnail-' + val.options.icon);
27319						thumbnail.append(icon);
27320					}
27321
27322					if (thumb) iL.loadImage(thumb, function(img) {
27323						i++;
27324						if (img) thumbnail.data({
27325							naturalWidth: img.width,
27326							naturalHeight: img.height
27327						}).append('<img src="' + thumb + '" border="0" />');
27328						else thumbnail.data({
27329							naturalWidth: opts.thumbnails.maxWidth,
27330							naturalHeight: opts.thumbnails.maxHeight
27331						});
27332
27333						clearTimeout(timeOut);
27334						timeOut = setTimeout(function() {
27335							iL.positionThumbnails(thumbnails, container, grid);
27336						}, 20);
27337						setTimeout(function() {
27338							thumbnail.fadeTo(opts.effects.loadedFadeSpeed, opacity);
27339						}, i * 20);
27340					});
27341
27342					grid.append(thumbnail);
27343				});
27344				iL.vars.dontGenerateThumbs = true;
27345			}
27346		},
27347
27348		positionThumbnails: function(thumbnails, container, grid) {
27349			var iL = this,
27350				vars = iL.vars,
27351				opts = iL.options,
27352				viewport = getViewport(),
27353				path = opts.path.toLowerCase();
27354
27355			if (!thumbnails) thumbnails = vars.thumbnails;
27356			if (!container) container = $('div.ilightbox-thumbnails-container', thumbnails);
27357			if (!grid) grid = $('div.ilightbox-thumbnails-grid', container);
27358
27359			var thumbs = $('.ilightbox-thumbnail', grid),
27360				widthAvail = (path == 'horizontal') ? viewport.width - opts.styles.pageOffsetX : thumbs.eq(0).outerWidth() - opts.styles.pageOffsetX,
27361				heightAvail = (path == 'horizontal') ? thumbs.eq(0).outerHeight() - opts.styles.pageOffsetY : viewport.height - opts.styles.pageOffsetY,
27362				gridWidth = (path == 'horizontal') ? 0 : widthAvail,
27363				gridHeight = (path == 'horizontal') ? heightAvail : 0,
27364				active = $('.ilightbox-active', grid),
27365				gridCss = {},
27366				css = {};
27367
27368			if (arguments.length < 3) {
27369				thumbs.css({
27370					opacity: opts.thumbnails.normalOpacity
27371				});
27372				active.css({
27373					opacity: opts.thumbnails.activeOpacity
27374				});
27375			}
27376
27377			thumbs.each(function(i) {
27378				var t = $(this),
27379					data = t.data(),
27380					width = (path == 'horizontal') ? 0 : opts.thumbnails.maxWidth;
27381				height = (path == 'horizontal') ? opts.thumbnails.maxHeight : 0;
27382				dims = iL.getNewDimenstions(width, height, data.naturalWidth, data.naturalHeight, true);
27383
27384				t.css({
27385					width: dims.width,
27386					height: dims.height
27387				});
27388				if (path == 'horizontal') t.css({
27389					'float': 'left'
27390				});
27391
27392				(path == 'horizontal') ? (
27393					gridWidth += t.outerWidth()
27394				) : (
27395					gridHeight += t.outerHeight()
27396				);
27397			});
27398
27399			gridCss = {
27400				width: gridWidth,
27401				height: gridHeight
27402			};
27403
27404			grid.css(gridCss);
27405
27406			gridCss = {};
27407
27408			var gridOffset = grid.offset(),
27409				activeOffset = (active.length) ? active.offset() : {
27410					top: parseInt(heightAvail / 2),
27411					left: parseInt(widthAvail / 2)
27412				};
27413
27414			gridOffset.top = (gridOffset.top - $doc.scrollTop()),
27415				gridOffset.left = (gridOffset.left - $doc.scrollLeft()),
27416				activeOffset.top = (activeOffset.top - gridOffset.top - $doc.scrollTop()),
27417				activeOffset.left = (activeOffset.left - gridOffset.left - $doc.scrollLeft());
27418
27419			(path == 'horizontal') ? (
27420				gridCss.top = 0,
27421				gridCss.left = parseInt((widthAvail / 2) - activeOffset.left - (active.outerWidth() / 2))
27422			) : (
27423				gridCss.top = parseInt(((heightAvail / 2) - activeOffset.top - (active.outerHeight() / 2))),
27424				gridCss.left = 0
27425			);
27426
27427			if (arguments.length < 3) grid.stop().animate(gridCss, opts.effects.repositionSpeed, 'easeOutCirc');
27428			else grid.css(gridCss);
27429		},
27430
27431		loadImage: function(image, callback) {
27432			if (!$.isArray(image)) image = [image];
27433
27434			var iL = this,
27435				length = image.length;
27436
27437			if (length > 0) {
27438				iL.showLoader();
27439				$.each(image, function(index, value) {
27440					var img = new Image();
27441					img.onload = function() {
27442						length -= 1;
27443						if (length == 0) {
27444							iL.hideLoader();
27445							callback(img);
27446						}
27447					};
27448					img.onerror = img.onabort = function() {
27449						length -= 1;
27450						if (length == 0) {
27451							iL.hideLoader();
27452							callback(false);
27453						}
27454					};
27455					img.src = image[index];
27456				});
27457			} else callback(false);
27458		},
27459
27460		patchItemsEvents: function() {
27461			var iL = this,
27462				vars = iL.vars,
27463				clickEvent = ishybrid ? "itap.iL click.iL" : supportTouch ? "itap.iL" : "click.iL",
27464				vEvent = ishybrid ? "click.iL itap.iL" : supportTouch ? "click.iL" : "itap.iL";
27465
27466			if (iL.context && iL.selector) {
27467				var $items = $(iL.selector, iL.context);
27468
27469				$(iL.context).on(clickEvent, iL.selector, function() {
27470					var $this = $(this),
27471						//UNCODE addition
27472						key = typeof $(this).data('lb-index') !== '' && $(this).closest('.owl-item').length ? $(this).data('lb-index') : $items.index($this);
27473					if (UNCODE.isMobile) {
27474						var isCarousel = $this.closest('.owl-carousel');
27475						if (isCarousel.length) {
27476							if (isCarousel.hasClass('owl-translating')) return false;
27477						}
27478					}
27479
27480					vars.current = key;
27481					vars.next = iL.items[key + 1] ? key + 1 : null;
27482					vars.prev = iL.items[key - 1] ? key - 1 : null;
27483
27484					//UNCODE addition
27485					if ( vars.BODY.hasClass('fp-slide-scrolling') )
27486						return false;
27487
27488					iL.addContents();
27489					iL.patchEvents();
27490
27491					return false;
27492				}).on(vEvent, iL.selector, function() {
27493					return false;
27494				});
27495			} else
27496				$.each(iL.itemsObject, function(key, val) {
27497					val.on(clickEvent, function() {
27498						vars.current = key;
27499						vars.next = iL.items[key + 1] ? key + 1 : null;
27500						vars.prev = iL.items[key - 1] ? key - 1 : null;
27501
27502						iL.addContents();
27503						iL.patchEvents();
27504
27505						return false;
27506					}).on(vEvent, function() {
27507						return false;
27508					});
27509				});
27510		},
27511
27512		dispatchItemsEvents: function() {
27513			var iL = this,
27514				vars = iL.vars,
27515				opts = iL.options;
27516
27517			if (iL.context && iL.selector)
27518				$(iL.context).off('.iL', iL.selector);
27519			else
27520				$.each(iL.itemsObject, function(key, val) {
27521					val.off('.iL');
27522				});
27523		},
27524
27525		refresh: function() {
27526			var iL = this;
27527
27528			iL.dispatchItemsEvents();
27529			iL.attachItems();
27530			iL.normalizeItems();
27531			iL.patchItemsEvents();
27532		},
27533
27534		patchEvents: function() {
27535			var iL = this,
27536				vars = iL.vars,
27537				opts = iL.options,
27538				path = opts.path.toLowerCase(),
27539				holders = $('.ilightbox-holder'),
27540				fullscreenEvent = fullScreenApi.fullScreenEventName + '.iLightBox',
27541				durationThreshold = 1000,
27542				horizontalDistanceThreshold =
27543				verticalDistanceThreshold = 100,
27544				buttonsArray = [vars.nextButton[0], vars.prevButton[0], vars.nextButton[0].firstChild, vars.prevButton[0].firstChild];
27545
27546			$win.bind('resize.iLightBox', function() {
27547				var viewport = getViewport();
27548
27549				if (opts.mobileOptimizer && !opts.innerToolbar) vars.isMobile = viewport.width <= vars.mobileMaxWidth;
27550				vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile');
27551
27552				iL.repositionPhoto(null);
27553				if (supportTouch) {
27554					clearTimeout(vars.setTime);
27555					vars.setTime = setTimeout(function() {
27556						var scrollTop = getScrollXY().y;
27557						window.scrollTo(0, scrollTop - 30);
27558						window.scrollTo(0, scrollTop + 30);
27559						window.scrollTo(0, scrollTop);
27560					}, 2000);
27561				}
27562				if (vars.thumbs) iL.positionThumbnails();
27563			}).bind('keydown.iLightBox', function(event) {
27564				if (opts.controls.keyboard) {
27565					switch (event.keyCode) {
27566						case 13:
27567							if (event.shiftKey && opts.keyboard.shift_enter) iL.fullScreenAction();
27568							break;
27569						case 27:
27570							if (opts.keyboard.esc) iL.closeAction();
27571							break;
27572						case 37:
27573							if (opts.keyboard.left && !vars.lockKey) iL.moveTo('prev');
27574							break;
27575						case 38:
27576							if (opts.keyboard.up && !vars.lockKey) iL.moveTo('prev');
27577							break;
27578						case 39:
27579							if (opts.keyboard.right && !vars.lockKey) iL.moveTo('next');
27580							break;
27581						case 40:
27582							if (opts.keyboard.down && !vars.lockKey) iL.moveTo('next');
27583							break;
27584					}
27585				}
27586			});
27587
27588			if (fullScreenApi.supportsFullScreen) $win.bind(fullscreenEvent, function() {
27589				iL.doFullscreen();
27590			});
27591
27592			var holderEventsArr = [opts.caption.show + '.iLightBox', opts.caption.hide + '.iLightBox', opts.social.show + '.iLightBox', opts.social.hide + '.iLightBox'].filter(function(e, i, arr) {
27593					return arr.lastIndexOf(e) === i;
27594				}),
27595				holderEvents = "";
27596
27597			$.each(holderEventsArr, function(key, val) {
27598				if (key != 0) holderEvents += ' ';
27599				holderEvents += val;
27600			});
27601
27602			$doc.on(clickEvent, '.ilightbox-overlay', function() {
27603				if (opts.overlay.blur) iL.closeAction();
27604			}).on(clickEvent, '.ilightbox-next, .ilightbox-next-button', function() {
27605				iL.moveTo('next');
27606			}).on(clickEvent, '.ilightbox-prev, .ilightbox-prev-button', function() {
27607				iL.moveTo('prev');
27608			}).on(clickEvent, '.ilightbox-thumbnail', function() {
27609				var t = $(this),
27610					thumbs = $('.ilightbox-thumbnail', vars.thumbnails),
27611					index = thumbs.index(t);
27612
27613				if (index != vars.current) iL.goTo(index);
27614			}).on(holderEvents, '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) {
27615				var caption = $('div.ilightbox-caption', vars.holder),
27616					social = $('div.ilightbox-social', vars.holder),
27617					fadeSpeed = opts.effects.fadeSpeed;
27618
27619				if (vars.nextLock || vars.prevLock) {
27620					if (e.type == opts.caption.show && !caption.is(':visible')) caption.fadeIn(fadeSpeed);
27621					else if (e.type == opts.caption.hide && caption.is(':visible')) caption.fadeOut(fadeSpeed);
27622
27623					if (e.type == opts.social.show && !social.is(':visible')) social.fadeIn(fadeSpeed);
27624					else if (e.type == opts.social.hide && social.is(':visible')) social.fadeOut(fadeSpeed);
27625				} else {
27626					if (e.type == opts.caption.show && !caption.is(':visible')) caption.stop().fadeIn(fadeSpeed);
27627					else if (e.type == opts.caption.hide && caption.is(':visible')) caption.stop().fadeOut(fadeSpeed);
27628
27629					if (e.type == opts.social.show && !social.is(':visible')) social.stop().fadeIn(fadeSpeed);
27630					else if (e.type == opts.social.hide && social.is(':visible')) social.stop().fadeOut(fadeSpeed);
27631				}
27632			}).on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-wrapper', function(e) {
27633				if (e.type == 'mouseenter') vars.lockWheel = true;
27634				else vars.lockWheel = false;
27635			}).on(clickEvent, '.ilightbox-toolbar a.ilightbox-close, .ilightbox-toolbar a.ilightbox-fullscreen, .ilightbox-toolbar a.ilightbox-play, .ilightbox-toolbar a.ilightbox-pause', function() {
27636				var t = $(this);
27637
27638				if (t.hasClass('ilightbox-fullscreen')) iL.fullScreenAction();
27639				else if (t.hasClass('ilightbox-play')) {
27640					iL.resume();
27641					t.addClass('ilightbox-pause').removeClass('ilightbox-play');
27642				} else if (t.hasClass('ilightbox-pause')) {
27643					iL.pause();
27644					t.addClass('ilightbox-play').removeClass('ilightbox-pause');
27645				} else iL.closeAction();
27646			}).on(touchMoveEvent, '.ilightbox-overlay, .ilightbox-thumbnails-container', function(e) {
27647				// prevent scrolling
27648				e.preventDefault();
27649			});
27650
27651			function mouseMoveHandler(e) {
27652				if (!vars.isMobile) {
27653					if (!vars.mouseID) {
27654						vars.hideableElements.show();
27655					}
27656
27657					vars.mouseID = clearTimeout(vars.mouseID);
27658
27659					if (buttonsArray.indexOf(e.target) === -1)
27660						vars.mouseID = setTimeout(function() {
27661							vars.hideableElements.hide();
27662							vars.mouseID = clearTimeout(vars.mouseID);
27663						}, 3000);
27664				}
27665			}
27666
27667			if (opts.controls.arrows && !supportTouch) $doc.on('mousemove.iLightBox', mouseMoveHandler);
27668
27669			if (opts.controls.slideshow && opts.slideshow.pauseOnHover) $doc.on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) {
27670				if (e.type == 'mouseenter' && vars.cycleID) iL.pause();
27671				else if (e.type == 'mouseleave' && vars.isPaused) iL.resume();
27672			});
27673
27674			var switchers = $('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails'),
27675				delay = false;
27676
27677			if (opts.controls.mousewheel) switchers.on('mousewheel.iLightBox', function(event, delta) {
27678				event.preventDefault();
27679				if (delay) return;
27680				delay = true;
27681				if (!vars.lockWheel) {
27682					event.preventDefault();
27683					if (delta < 0) {
27684						iL.moveTo('next');
27685					} else if (delta > 0) {
27686						iL.moveTo('prev');
27687					}
27688				}
27689				setTimeout(function(){
27690					delay = false;
27691				}, 2000);
27692			});
27693
27694			if (opts.controls.swipe) holders.on(touchStartEvent, function(event) {
27695				if (vars.nextLock || vars.prevLock || vars.total == 1 || vars.lockSwipe) return;
27696
27697				vars.BODY.addClass('ilightbox-closedhand');
27698
27699				var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event,
27700					scrollTop = $doc.scrollTop(),
27701					scrollLeft = $doc.scrollLeft(),
27702					offsets = [
27703						holders.eq(0).offset(),
27704						holders.eq(1).offset(),
27705						holders.eq(2).offset()
27706					],
27707					offSet = [{
27708						top: offsets[0].top - scrollTop,
27709						left: offsets[0].left - scrollLeft
27710					}, {
27711						top: offsets[1].top - scrollTop,
27712						left: offsets[1].left - scrollLeft
27713					}, {
27714						top: offsets[2].top - scrollTop,
27715						left: offsets[2].left - scrollLeft
27716					}],
27717					start = {
27718						time: (new Date()).getTime(),
27719						coords: [data.pageX - scrollLeft, data.pageY - scrollTop]
27720					},
27721					stop;
27722
27723				function moveEachHandler(i) {
27724					var t = $(this),
27725						offset = offSet[i],
27726						scroll = [(start.coords[0] - stop.coords[0]), (start.coords[1] - stop.coords[1])];
27727
27728					t[0].style[path == "horizontal" ? 'left' : 'top'] = (path == "horizontal" ? offset.left - scroll[0] : offset.top - scroll[1]) + 'px';
27729				}
27730
27731				function moveHandler(event) {
27732
27733					if (!start) return;
27734
27735					var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event;
27736
27737					stop = {
27738						time: (new Date()).getTime(),
27739						coords: [data.pageX - scrollLeft, data.pageY - scrollTop]
27740					};
27741
27742					holders.each(moveEachHandler);
27743
27744					// prevent scrolling
27745					event.preventDefault();
27746				}
27747
27748				function repositionHolders() {
27749					holders.each(function() {
27750						var t = $(this),
27751							offset = t.data('offset') || {
27752								top: t.offset().top - scrollTop,
27753								left: t.offset().left - scrollLeft
27754							},
27755							top = offset.top,
27756							left = offset.left;
27757
27758						t.css(transform, gpuAcceleration).stop().animate({
27759							top: top,
27760							left: left
27761						}, 500, 'easeOutCirc', function() {
27762							t.css(transform, '');
27763						});
27764					});
27765				}
27766
27767				holders.bind(touchMoveEvent, moveHandler);
27768				$doc.one(touchStopEvent, function(event) {
27769					holders.unbind(touchMoveEvent, moveHandler);
27770
27771					vars.BODY.removeClass('ilightbox-closedhand');
27772
27773					if (start && stop) {
27774						if (path == "horizontal" && stop.time - start.time < durationThreshold && abs(start.coords[0] - stop.coords[0]) > horizontalDistanceThreshold && abs(start.coords[1] - stop.coords[1]) < verticalDistanceThreshold) {
27775							if (start.coords[0] > stop.coords[0]) {
27776								if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders();
27777								else {
27778									vars.isSwipe = true;
27779									iL.moveTo('next');
27780								}
27781							} else {
27782								if (vars.current == 0 && !opts.infinite) repositionHolders();
27783								else {
27784									vars.isSwipe = true;
27785									iL.moveTo('prev');
27786								}
27787							}
27788						} else if (path == "vertical" && stop.time - start.time < durationThreshold && abs(start.coords[1] - stop.coords[1]) > horizontalDistanceThreshold && abs(start.coords[0] - stop.coords[0]) < verticalDistanceThreshold) {
27789							if (start.coords[1] > stop.coords[1]) {
27790								if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders();
27791								else {
27792									vars.isSwipe = true;
27793									iL.moveTo('next');
27794								}
27795							} else {
27796								if (vars.current == 0 && !opts.infinite) repositionHolders();
27797								else {
27798									vars.isSwipe = true;
27799									iL.moveTo('prev');
27800								}
27801							}
27802						} else repositionHolders();
27803					}
27804					start = stop = undefined;
27805				});
27806			});
27807
27808		},
27809
27810		goTo: function(index) {
27811			var iL = this,
27812				vars = iL.vars,
27813				opts = iL.options,
27814				diff = (index - vars.current);
27815
27816			if (opts.infinite) {
27817				if (index == vars.total - 1 && vars.current == 0) diff = -1;
27818				if (vars.current == vars.total - 1 && index == 0) diff = 1;
27819			}
27820
27821			if (diff == 1) iL.moveTo('next');
27822			else if (diff == -1) iL.moveTo('prev');
27823			else {
27824
27825				if (vars.nextLock || vars.prevLock) return false;
27826
27827				//Trigger the onBeforeChange callback
27828				if (typeof opts.callback.onBeforeChange == 'function') opts.callback.onBeforeChange.call(iL, iL.ui);
27829
27830				if (opts.linkId) {
27831					vars.hashLock = true;
27832					window.location.hash = opts.linkId + '/' + index;
27833				}
27834
27835				if (iL.items[index]) {
27836					if (!iL.items[index].options.mousewheel) vars.lockWheel = true;
27837					else iL.vars.lockWheel = false;
27838
27839					if (!iL.items[index].options.swipe) vars.lockSwipe = true;
27840					else vars.lockSwipe = false;
27841				}
27842
27843				$.each([vars.holder, vars.nextPhoto, vars.prevPhoto], function(key, val) {
27844					val.css(transform, gpuAcceleration).fadeOut(opts.effects.loadedFadeSpeed);
27845				});
27846
27847				vars.current = index;
27848				vars.next = index + 1;
27849				vars.prev = index - 1;
27850
27851				iL.createUI();
27852
27853				setTimeout(function() {
27854					iL.generateBoxes();
27855				}, opts.effects.loadedFadeSpeed + 50);
27856
27857				$('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(index).addClass('ilightbox-active');
27858				iL.positionThumbnails();
27859
27860				if (opts.linkId) setTimeout(function() {
27861					vars.hashLock = false;
27862				}, 55);
27863
27864				// Configure arrow buttons
27865				if (!opts.infinite) {
27866					vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
27867
27868					if (vars.current == 0) {
27869						vars.prevButton.add(vars.innerPrevButton).addClass('disabled');
27870					}
27871					if (vars.current >= vars.total - 1) {
27872						vars.nextButton.add(vars.innerNextButton).addClass('disabled');
27873					}
27874				}
27875
27876				// Reset next cycle timeout
27877				iL.resetCycle();
27878
27879				//Trigger the onAfterChange callback
27880				if (typeof opts.callback.onAfterChange == 'function') opts.callback.onAfterChange.call(iL, iL.ui);
27881			}
27882		},
27883
27884		moveTo: function(side) {
27885			var iL = this,
27886				vars = iL.vars,
27887				opts = iL.options,
27888				path = opts.path.toLowerCase(),
27889				viewport = getViewport(),
27890				switchSpeed = opts.effects.switchSpeed;
27891
27892			if (vars.nextLock || vars.prevLock) return false;
27893			else {
27894
27895				var item = (side == "next") ? vars.next : vars.prev;
27896
27897				if (opts.linkId) {
27898					vars.hashLock = true;
27899					window.location.hash = opts.linkId + '/' + item;
27900				}
27901
27902				if (side == "next") {
27903					if (!iL.items[item]) return false;
27904					var firstHolder = vars.nextPhoto,
27905						secondHolder = vars.holder,
27906						lastHolder = vars.prevPhoto,
27907						firstClass = 'ilightbox-prev',
27908						secondClass = 'ilightbox-next';
27909				} else if (side == "prev") {
27910					if (!iL.items[item]) return false;
27911					var firstHolder = vars.prevPhoto,
27912						secondHolder = vars.holder,
27913						lastHolder = vars.nextPhoto,
27914						firstClass = 'ilightbox-next',
27915						secondClass = 'ilightbox-prev';
27916				}
27917
27918				//Trigger the onBeforeChange callback
27919				if (typeof opts.callback.onBeforeChange == 'function')
27920					opts.callback.onBeforeChange.call(iL, iL.ui);
27921
27922				(side == "next") ? vars.nextLock = true: vars.prevLock = true;
27923
27924				var captionFirst = $('div.ilightbox-caption', secondHolder),
27925					socialFirst = $('div.ilightbox-social', secondHolder);
27926
27927				if (captionFirst.length)
27928					captionFirst.stop().fadeOut(switchSpeed, function() {
27929						$(this).remove();
27930					});
27931				if (socialFirst.length)
27932					socialFirst.stop().fadeOut(switchSpeed, function() {
27933						$(this).remove();
27934					});
27935
27936				if (iL.items[item].caption) {
27937					iL.setCaption(iL.items[item], firstHolder);
27938					var caption = $('div.ilightbox-caption', firstHolder),
27939						percent = parseInt((caption.outerHeight() / firstHolder.outerHeight()) * 100);
27940					if (opts.caption.start && percent <= 50) caption.fadeIn(switchSpeed);
27941				}
27942
27943				var social = iL.items[item].options.social;
27944				if (social) {
27945					iL.setSocial(social, iL.items[item].URL, firstHolder);
27946					if (opts.social.start) $('div.ilightbox-social', firstHolder).fadeIn(opts.effects.fadeSpeed);
27947				}
27948
27949				$.each([firstHolder, secondHolder, lastHolder], function(key, val) {
27950					val.removeClass('ilightbox-next ilightbox-prev');
27951				});
27952
27953				var firstOffset = firstHolder.data('offset'),
27954					winW = (viewport.width - (opts.styles.pageOffsetX)),
27955					winH = (viewport.height - (opts.styles.pageOffsetY)),
27956					width = firstOffset.newDims.width,
27957					height = firstOffset.newDims.height,
27958					thumbsOffset = firstOffset.thumbsOffset,
27959					diff = firstOffset.diff,
27960					top = parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)),
27961					left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2));
27962
27963				var secondOffset = secondHolder.data('offset'),
27964					object = secondOffset.object;
27965
27966				/*if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) {
27967					var objRatio = width / height;
27968					height = height - vars.captionHeight;
27969					width = height * objRatio;
27970					top = path == 'horizontal' ? parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)) : top,
27971					left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2));
27972				}*/
27973
27974				firstHolder.show().css(transform, gpuAcceleration).animate({
27975					top: top,
27976					left: left,
27977					opacity: 1
27978				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() {
27979					firstHolder.css(transform, '');
27980				});
27981
27982				$('div.ilightbox-container', firstHolder).animate({
27983					width: width,
27984					height: height
27985				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc');
27986
27987				diff = secondOffset.diff;
27988
27989				width = secondOffset.newDims.width,
27990					height = secondOffset.newDims.height;
27991
27992				width = parseInt(width * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']),
27993					height = parseInt(height * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']),
27994					top = (path == 'horizontal') ? parseInt((winH / 2) - object.offsetY - (height / 2) - diff.H - (thumbsOffset.H / 2)) : parseInt(winH - object.offsetX - diff.H - (thumbsOffset.H / 2));
27995
27996				if (side == 'prev')
27997					left = (path == 'horizontal') ? parseInt(winW - object.offsetX - diff.W - (thumbsOffset.W / 2)) : parseInt((winW / 2) - (width / 2) - diff.W - object.offsetY - (thumbsOffset.W / 2));
27998				else {
27999					top = (path == 'horizontal') ? top : parseInt(object.offsetX - diff.H - height - (thumbsOffset.H / 2)),
28000					left = (path == 'horizontal') ? parseInt(object.offsetX - diff.W - width - (thumbsOffset.W / 2)) : parseInt((winW / 2) - object.offsetY - (width / 2) - diff.W - (thumbsOffset.W / 2));
28001				}
28002
28003				/*if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) {
28004					var objRatio = width / height;
28005					height = height - vars.captionHeight;
28006					width = height * objRatio;
28007					top = path == 'horizontal' ? parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)) : top;
28008				}*/
28009
28010				$('div.ilightbox-container', secondHolder).animate({
28011					width: width,
28012					height: height
28013				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc');
28014
28015				secondHolder.addClass(firstClass).css(transform, gpuAcceleration).animate({
28016					top: top,
28017					left: left,
28018					opacity: opts.styles.prevOpacity,
28019				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() {
28020					secondHolder.css(transform, '');
28021
28022					$('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(item).addClass('ilightbox-active');
28023					iL.positionThumbnails();
28024
28025					if (iL.items[item]) {
28026						if (!iL.items[item].options.mousewheel) vars.lockWheel = true;
28027						else vars.lockWheel = false;
28028
28029						if (!iL.items[item].options.swipe) vars.lockSwipe = true;
28030						else vars.lockSwipe = false;
28031					}
28032
28033					vars.isSwipe = false;
28034
28035					// Remove iframe & video from previous slide
28036					if (['iframe', 'video'].indexOf(iL.items[vars.current].type) !== -1) {
28037						$('div.ilightbox-container', secondHolder).empty();
28038					}
28039
28040					if (side == "next") {
28041						vars.nextPhoto = lastHolder,
28042							vars.prevPhoto = secondHolder,
28043							vars.holder = firstHolder;
28044
28045						vars.nextPhoto.hide();
28046
28047						vars.next = vars.next + 1,
28048							vars.prev = vars.current,
28049							vars.current = vars.current + 1;
28050
28051						if (opts.infinite) {
28052							if (vars.current > vars.total - 1) vars.current = 0;
28053							if (vars.current == vars.total - 1) vars.next = 0;
28054							if (vars.current == 0) vars.prev = vars.total - 1;
28055						}
28056
28057						iL.createUI();
28058
28059						if (!iL.items[vars.next])
28060							vars.nextLock = false;
28061						else
28062							iL.loadContent(iL.items[vars.next], 'next');
28063					} else {
28064						vars.prevPhoto = lastHolder;
28065						vars.nextPhoto = secondHolder;
28066						vars.holder = firstHolder;
28067
28068						vars.prevPhoto.hide();
28069
28070						vars.next = vars.current;
28071						vars.current = vars.prev;
28072						vars.prev = vars.current - 1;
28073
28074						if (opts.infinite) {
28075							if (vars.current == vars.total - 1) vars.next = 0;
28076							if (vars.current == 0) vars.prev = vars.total - 1;
28077						}
28078
28079						iL.createUI();
28080
28081						if (!iL.items[vars.prev])
28082							vars.prevLock = false;
28083						else
28084							iL.loadContent(iL.items[vars.prev], 'prev');
28085					}
28086
28087					// Add iframe & video content for current slide
28088					if (['iframe', 'video'].indexOf(iL.items[vars.current].type) !== -1) {
28089						iL.loadContent(iL.items[vars.current], 'current');
28090					}
28091
28092					if (opts.linkId) setTimeout(function() {
28093						vars.hashLock = false;
28094					}, 55);
28095
28096					// Configure arrow buttons
28097					if (!opts.infinite) {
28098						vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
28099
28100						if (vars.current == 0)
28101							vars.prevButton.add(vars.innerPrevButton).addClass('disabled');
28102						if (vars.current >= vars.total - 1)
28103							vars.nextButton.add(vars.innerNextButton).addClass('disabled');
28104					}
28105
28106					iL.repositionPhoto();
28107
28108					// Reset next cycle timeout
28109					iL.resetCycle();
28110
28111					//Trigger the onAfterChange callback
28112					if (typeof opts.callback.onAfterChange == 'function')
28113						opts.callback.onAfterChange.call(iL, iL.ui);
28114				});
28115
28116				top = (path == 'horizontal') ? getPixel(lastHolder, 'top') : ((side == "next") ? parseInt(-(winH / 2) - lastHolder.outerHeight()) : parseInt(top * 2)),
28117					left = (path == 'horizontal') ? ((side == "next") ? parseInt(-(winW / 2) - lastHolder.outerWidth()) : parseInt(left * 2)) : getPixel(lastHolder, 'left');
28118
28119				lastHolder.css(transform, gpuAcceleration).animate({
28120					top: top,
28121					left: left,
28122					opacity: opts.styles.nextOpacity
28123				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() {
28124					lastHolder.css(transform, '');
28125				}).addClass(secondClass);
28126			}
28127		},
28128
28129		setCaption: function(obj, target) {
28130			var iL = this,
28131				caption = $('<div class="ilightbox-caption"></div>');
28132
28133			if (obj.caption) {
28134				caption.html(obj.caption);
28135				$('div.ilightbox-container', target).append(caption);
28136			}
28137		},
28138
28139		normalizeSocial: function(obj, url) {
28140			var iL = this,
28141				vars = iL.vars,
28142				opts = iL.options,
28143				baseURL = window.location.href;
28144
28145			$.each(obj, function(key, value) {
28146				if (!value)
28147					return true;
28148
28149				var item = key.toLowerCase(),
28150					source, text;
28151
28152				switch (item) {
28153					case 'facebook':
28154						source = "http://www.facebook.com/share.php?v=4&src=bm&u={URL}",
28155							text = "Share on Facebook";
28156						break;
28157					case 'twitter':
28158						source = "http://twitter.com/home?status={URL}",
28159							text = "Share on Twitter";
28160						break;
28161					case 'digg':
28162						source = "http://digg.com/submit?phase=2&url={URL}",
28163							text = "Share on Digg";
28164						break;
28165					case 'reddit':
28166						source = "http://reddit.com/submit?url={URL}",
28167							text = "Share on reddit";
28168						break;
28169				}
28170
28171				obj[key] = {
28172					URL: value.URL && absolutizeURI(baseURL, value.URL) || opts.linkId && window.location.href || typeof url !== 'string' && baseURL || url && absolutizeURI(baseURL, url) || baseURL,
28173					source: value.source || source || value.URL && absolutizeURI(baseURL, value.URL) || url && absolutizeURI(baseURL, url),
28174					text: value.text || text || "Share on " + key,
28175					width: (typeof(value.width) != 'undefined' && !isNaN(value.width)) ? parseInt(value.width) : 640,
28176					height: value.height || 360
28177				};
28178
28179			});
28180
28181			return obj;
28182		},
28183
28184		setSocial: function(obj, url, target) {
28185			var iL = this,
28186				socialBar = $('<div class="ilightbox-social"></div>'),
28187				buttons = '<ul>';
28188
28189			obj = iL.normalizeSocial(obj, url);
28190
28191			$.each(obj, function(key, value) {
28192				var item = key.toLowerCase(),
28193					source = value.source.replace(/\{URL\}/g, encodeURIComponent(value.URL).replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/\*/g, '%2A').replace(/%20/g, '+'));
28194				buttons += '<li class="' + key + '"><a href="' + source + '" onclick="javascript:window.open(this.href' + ((value.width <= 0 || value.height <= 0) ? '' : ', \'\', \'menubar=no,toolbar=no,resizable=yes,scrollbars=yes,height=' + value.height + ',width=' + value.width + ',left=40,top=40\'') + ');return false;" title="' + value.text + '" target="_blank"></a></li>';
28195			});
28196
28197			buttons += '</ul>';
28198
28199			socialBar.html(buttons);
28200			$('div.ilightbox-container', target).append(socialBar);
28201		},
28202
28203		fullScreenAction: function() {
28204			var iL = this,
28205				vars = iL.vars;
28206
28207			if (fullScreenApi.supportsFullScreen) {
28208				if (fullScreenApi.isFullScreen()) fullScreenApi.cancelFullScreen(document.documentElement);
28209				else fullScreenApi.requestFullScreen(document.documentElement);
28210			} else {
28211				iL.doFullscreen();
28212			}
28213		},
28214
28215		doFullscreen: function() {
28216			var iL = this,
28217				vars = iL.vars,
28218				viewport = getViewport(),
28219				opts = iL.options;
28220
28221			if (opts.fullAlone) {
28222				var currentHolder = vars.holder,
28223					current = iL.items[vars.current],
28224					windowWidth = viewport.width,
28225					windowHeight = viewport.height,
28226					elements = [currentHolder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.overlay, vars.toolbar, vars.thumbnails, vars.loader],
28227					hideElements = [vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails];
28228
28229				if (!vars.isInFullScreen) {
28230					vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = true;
28231					vars.overlay.css({
28232						opacity: 1
28233					});
28234
28235					$.each(hideElements, function(i, element) {
28236						element.hide();
28237					});
28238
28239					vars.fullScreenButton.attr('title', opts.text.exitFullscreen);
28240
28241					if (opts.fullStretchTypes.indexOf(current.type) != -1) currentHolder.data({
28242						naturalWidthOld: currentHolder.data('naturalWidth'),
28243						naturalHeightOld: currentHolder.data('naturalHeight'),
28244						naturalWidth: windowWidth,
28245						naturalHeight: windowHeight
28246					});
28247					else {
28248						var viewport = current.options.fullViewPort || opts.fullViewPort || '',
28249							newWidth = windowWidth,
28250							newHeight = windowHeight,
28251							width = currentHolder.data('naturalWidth'),
28252							height = currentHolder.data('naturalHeight');
28253
28254						if (viewport.toLowerCase() == 'fill') {
28255							newHeight = (newWidth / width) * height;
28256
28257							if (newHeight < windowHeight) {
28258								newWidth = (windowHeight / height) * width,
28259									newHeight = windowHeight;
28260							}
28261						} else if (viewport.toLowerCase() == 'fit') {
28262							var dims = iL.getNewDimenstions(newWidth, newHeight, width, height, true);
28263
28264							newWidth = dims.width,
28265								newHeight = dims.height;
28266						} else if (viewport.toLowerCase() == 'stretch') {
28267							newWidth = newWidth,
28268								newHeight = newHeight;
28269						} else {
28270							var scale = (width > newWidth || height > newHeight) ? true : false,
28271								dims = iL.getNewDimenstions(newWidth, newHeight, width, height, scale);
28272							newWidth = dims.width,
28273								newHeight = dims.height;
28274						}
28275
28276						currentHolder.data({
28277							naturalWidthOld: currentHolder.data('naturalWidth'),
28278							naturalHeightOld: currentHolder.data('naturalHeight'),
28279							naturalWidth: newWidth,
28280							naturalHeight: newHeight
28281						});
28282					}
28283
28284					$.each(elements, function(key, val) {
28285						val.addClass('ilightbox-fullscreen');
28286					});
28287
28288					//Trigger the onEnterFullScreen callback
28289					if (typeof opts.callback.onEnterFullScreen == 'function') opts.callback.onEnterFullScreen.call(iL, iL.ui);
28290				} else {
28291					vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = false;
28292					vars.overlay.css({
28293						opacity: iL.options.overlay.opacity
28294					});
28295
28296					$.each(hideElements, function(i, element) {
28297						element.show();
28298					});
28299
28300					vars.fullScreenButton.attr('title', opts.text.enterFullscreen);
28301
28302					currentHolder.data({
28303						naturalWidth: currentHolder.data('naturalWidthOld'),
28304						naturalHeight: currentHolder.data('naturalHeightOld'),
28305						naturalWidthOld: null,
28306						naturalHeightOld: null
28307					});
28308
28309					$.each(elements, function(key, val) {
28310						val.removeClass('ilightbox-fullscreen');
28311					});
28312
28313					//Trigger the onExitFullScreen callback
28314					if (typeof opts.callback.onExitFullScreen == 'function') opts.callback.onExitFullScreen.call(iL, iL.ui);
28315				}
28316			} else {
28317				if (!vars.isInFullScreen) vars.isInFullScreen = true;
28318				else vars.isInFullScreen = false;
28319			}
28320			iL.repositionPhoto(true);
28321		},
28322
28323		closeAction: function() {
28324			var iL = this,
28325				vars = iL.vars,
28326				opts = iL.options;
28327
28328			$win.unbind('.iLightBox');
28329			$doc.off('.iLightBox');
28330
28331			if (vars.isInFullScreen) fullScreenApi.cancelFullScreen(document.documentElement);
28332
28333			$('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails').off('.iLightBox');
28334
28335			if (opts.hide.effect) vars.overlay.stop().fadeOut(opts.hide.speed, function() {
28336				vars.overlay.remove();
28337				vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox');
28338			});
28339			else {
28340				vars.overlay.remove();
28341				vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox');
28342			}
28343
28344			var fadeOuts = [vars.toolbar, vars.holder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails];
28345
28346			$.each(fadeOuts, function(i, element) {
28347				element.removeAttr('style').remove();
28348			});
28349
28350			vars.dontGenerateThumbs = vars.isInFullScreen = false;
28351
28352			window.iLightBox = null;
28353
28354			if (opts.linkId) {
28355				vars.hashLock = true;
28356				removeHash();
28357				setTimeout(function() {
28358					vars.hashLock = false;
28359				}, 55);
28360			}
28361
28362			vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
28363
28364			//Trigger the onHide callback
28365			if (typeof opts.callback.onHide == 'function') opts.callback.onHide.call(iL, iL.ui);
28366		},
28367
28368		repositionPhoto: function() {
28369			var iL = this,
28370				vars = iL.vars,
28371				opts = iL.options,
28372				path = opts.path.toLowerCase(),
28373				viewport = getViewport(),
28374				winWidth = viewport.width,
28375				winHeight = viewport.height;
28376
28377			if (viewport.width < UNCODE.mediaQuery) opts.styles.nextOffsetX = 0;
28378
28379			var thumbsOffsetW = (vars.isInFullScreen && opts.fullAlone || vars.isMobile) ? 0 : ((path == 'horizontal') ? 0 : vars.thumbnails.outerWidth()),
28380				thumbsOffsetH = vars.isMobile ? vars.toolbar.outerHeight() : ((vars.isInFullScreen && opts.fullAlone) ? 0 : ((path == 'horizontal') ? vars.thumbnails.outerHeight() : 0)),
28381				width = (vars.isInFullScreen && opts.fullAlone) ? winWidth : (winWidth - (opts.styles.pageOffsetX)),
28382				height = (vars.isInFullScreen && opts.fullAlone) ? winHeight : (winHeight - (opts.styles.pageOffsetY)),
28383				offsetW = (path == 'horizontal') ? parseInt((iL.items[vars.next] || iL.items[vars.prev]) ? ((opts.styles.nextOffsetX + opts.styles.prevOffsetX)) * 2 : (((width / 10) <= 30) ? 30 : (width / 10))) : parseInt(((width / 10) <= 30) ? 30 : (width / 10)) + thumbsOffsetW,
28384				offsetH = (path == 'horizontal') ? parseInt(((height / 10) <= 30) ? 30 : (height / 10)) + thumbsOffsetH : parseInt((iL.items[vars.next] || iL.items[vars.prev]) ? ((opts.styles.nextOffsetX + opts.styles.prevOffsetX)) * 2 : (((height / 10) <= 30) ? 30 : (height / 10)));
28385
28386			var elObject = {
28387				type: 'current',
28388				width: width,
28389				height: height,
28390				item: iL.items[vars.current],
28391				offsetW: offsetW,
28392				offsetH: offsetH,
28393				thumbsOffsetW: thumbsOffsetW,
28394				thumbsOffsetH: thumbsOffsetH,
28395				animate: arguments.length,
28396				holder: vars.holder
28397			};
28398
28399			iL.repositionEl(elObject);
28400
28401			if (iL.items[vars.next]) {
28402				elObject = $.extend(elObject, {
28403					type: 'next',
28404					item: iL.items[vars.next],
28405					offsetX: opts.styles.nextOffsetX,
28406					offsetY: opts.styles.nextOffsetY,
28407					holder: vars.nextPhoto
28408				});
28409
28410				iL.repositionEl(elObject);
28411			}
28412
28413			if (iL.items[vars.prev]) {
28414				elObject = $.extend(elObject, {
28415					type: 'prev',
28416					item: iL.items[vars.prev],
28417					offsetX: opts.styles.nextOffsetX,
28418					offsetY: opts.styles.prevOffsetY,
28419					holder: vars.prevPhoto
28420				});
28421
28422				iL.repositionEl(elObject);
28423			}
28424
28425			var loaderCss = (path == "horizontal") ? {
28426				left: parseInt((width / 2) - (vars.loader.outerWidth() / 2))
28427			} : {
28428				top: parseInt((height / 2) - (vars.loader.outerHeight() / 2))
28429			};
28430			vars.loader.css(loaderCss);
28431		},
28432
28433		repositionEl: function(obj) {
28434			var iL = this,
28435				vars = iL.vars,
28436				opts = iL.options,
28437				path = opts.path.toLowerCase(),
28438				widthAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.width : (obj.width - obj.offsetW)) : (obj.width - obj.offsetW),
28439				heightAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.height : (obj.height - obj.offsetH)) : (obj.height - obj.offsetH),
28440				itemParent = obj.item,
28441				item = obj.item.options,
28442				holder = obj.holder,
28443				offsetX = obj.offsetX || 0,
28444				offsetY = obj.offsetY || 0,
28445				//Uncode change ##START##
28446				toolbarHeight = $('.ilightbox-inner-toolbar', holder).length ? parseInt( $('.ilightbox-inner-toolbar', holder).outerHeight() ) : 0,
28447				//Uncode change ##END##
28448				thumbsOffsetW = obj.thumbsOffsetW,
28449				thumbsOffsetH = obj.thumbsOffsetH;
28450
28451			if (obj.type == 'current') {
28452				if (typeof item.width == 'number' && item.width) widthAvail = ((vars.isInFullScreen && opts.fullAlone) && (opts.fullStretchTypes.indexOf(itemParent.type) != -1 || item.fullViewPort || opts.fullViewPort)) ? widthAvail : ((item.width > widthAvail) ? widthAvail : item.width);
28453				if (typeof item.height == 'number' && item.height) heightAvail = ((vars.isInFullScreen && opts.fullAlone) && (opts.fullStretchTypes.indexOf(itemParent.type) != -1 || item.fullViewPort || opts.fullViewPort)) ? heightAvail : ((item.height > heightAvail) ? heightAvail : item.height);
28454			} else {
28455				if (typeof item.width == 'number' && item.width) widthAvail = (item.width > widthAvail) ? widthAvail : item.width;
28456				if (typeof item.height == 'number' && item.height) heightAvail = (item.height > heightAvail) ? heightAvail : item.height;
28457			}
28458
28459
28460			//Uncode change ##START##
28461			heightAvail = parseInt(heightAvail - toolbarHeight);
28462			// heightAvail = parseInt(heightAvail - $('.ilightbox-inner-toolbar', holder).outerHeight());
28463			//Uncode change ##END##
28464
28465			var width = (typeof item.width == 'string' && item.width.indexOf('%') != -1) ? percentToValue(parseInt(item.width.replace('%', '')), obj.width) : holder.data('naturalWidth'),
28466				height = (typeof item.height == 'string' && item.height.indexOf('%') != -1) ? percentToValue(parseInt(item.height.replace('%', '')), obj.height) : holder.data('naturalHeight');
28467
28468			var dims = ((typeof item.width == 'string' && item.width.indexOf('%') != -1 || typeof item.height == 'string' && item.height.indexOf('%') != -1) ? {
28469					width: width,
28470					height: height
28471				} : iL.getNewDimenstions(widthAvail, heightAvail, width, height)),
28472				newDims = $.extend({}, dims, {});
28473
28474			if (obj.type == 'prev' || obj.type == 'next')
28475				width = parseInt(dims.width * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale)),
28476				height = parseInt(dims.height * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale));
28477			else
28478				width = dims.width,
28479				height = dims.height;
28480
28481			var widthDiff = parseInt((getPixel(holder, 'padding-left') + getPixel(holder, 'padding-right') + getPixel(holder, 'border-left-width') + getPixel(holder, 'border-right-width')) / 2),
28482				heightDiff = parseInt((getPixel(holder, 'padding-top') + getPixel(holder, 'padding-bottom') + getPixel(holder, 'border-top-width') + getPixel(holder, 'border-bottom-width') + ($('.ilightbox-inner-toolbar', holder).outerHeight() || 0)) / 2);
28483
28484			switch (obj.type) {
28485				case 'current':
28486					var top = parseInt((obj.height / 2) - (height / 2) - heightDiff - (thumbsOffsetH / 2)),
28487						left = parseInt((obj.width / 2) - (width / 2) - widthDiff - (thumbsOffsetW / 2));
28488					break;
28489
28490				case 'next':
28491					var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(obj.height - offsetX - heightDiff - (thumbsOffsetH / 2)),
28492						left = (path == 'horizontal') ? parseInt(obj.width - offsetX - widthDiff - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - (width / 2) - widthDiff - offsetY - (thumbsOffsetW / 2));
28493					break;
28494
28495				case 'prev':
28496					var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(offsetX - heightDiff - height - (thumbsOffsetH / 2)),
28497						left = (path == 'horizontal') ? parseInt(offsetX - widthDiff - width - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - offsetY - (width / 2) - widthDiff - (thumbsOffsetW / 2));
28498					break;
28499			}
28500
28501			holder.data('offset', {
28502				top: top,
28503				left: left,
28504				newDims: newDims,
28505				diff: {
28506					W: widthDiff,
28507					H: heightDiff
28508				},
28509				thumbsOffset: {
28510					W: thumbsOffsetW,
28511					H: thumbsOffsetH
28512				},
28513				object: obj
28514			});
28515
28516			var opacityMobile;
28517			if ( isMobile ) {
28518				opacityMobile = {
28519					opacity: 1,
28520					top: top,
28521					left: left
28522				};
28523			} else {
28524				opacityMobile = {
28525					top: top,
28526					left: left
28527				};
28528			}
28529
28530			if (obj.animate > 0 && opts.effects.reposition) {
28531				holder.css(transform, gpuAcceleration).stop().animate(
28532					opacityMobile,
28533					opts.effects.repositionSpeed, 'easeOutCirc', function() {
28534					holder.css(transform, '');
28535				});
28536				$('div.ilightbox-container', holder).stop().animate({
28537					width: width,
28538					height: height
28539				}, opts.effects.repositionSpeed, 'easeOutCirc');
28540				$('div.ilightbox-inner-toolbar', holder).stop().animate({
28541					width: width
28542				}, opts.effects.repositionSpeed, 'easeOutCirc', function() {
28543					$(this).css('overflow', 'visible');
28544				});
28545			} else {
28546				holder.css(opacityMobile);
28547				$('div.ilightbox-container', holder).css({
28548					width: width,
28549					height: height
28550				});
28551				$('div.ilightbox-inner-toolbar', holder).css({
28552					width: width
28553				});
28554			}
28555		},
28556
28557
28558		resume: function(priority) {
28559			var iL = this,
28560				vars = iL.vars,
28561				opts = iL.options;
28562
28563			if (!opts.slideshow.pauseTime || opts.controls.slideshow && vars.total <= 1 || priority < vars.isPaused) {
28564				return;
28565			}
28566
28567			vars.isPaused = 0;
28568
28569			if (vars.cycleID) {
28570				vars.cycleID = clearTimeout(vars.cycleID);
28571			}
28572
28573			vars.cycleID = setTimeout(function() {
28574				if (vars.current == vars.total - 1) iL.goTo(0);
28575				else iL.moveTo('next');
28576			}, opts.slideshow.pauseTime);
28577		},
28578
28579		pause: function(priority) {
28580			var iL = this,
28581				vars = iL.vars,
28582				opts = iL.options;
28583
28584			if (priority < vars.isPaused) {
28585				return;
28586			}
28587
28588			vars.isPaused = priority || 100;
28589
28590			if (vars.cycleID) {
28591				vars.cycleID = clearTimeout(vars.cycleID);
28592			}
28593		},
28594
28595		resetCycle: function() {
28596			var iL = this,
28597				vars = iL.vars,
28598				opts = iL.options;
28599
28600			if (opts.controls.slideshow && vars.cycleID && !vars.isPaused) {
28601				iL.resume();
28602			}
28603		},
28604
28605		getNewDimenstions: function(width, height, width_old, height_old, thumb) {
28606			var iL = this;
28607
28608			if (!width) factor = height / height_old;
28609			else if (!height) factor = width / width_old;
28610			else factor = min(width / width_old, height / height_old);
28611
28612			if (!thumb) {
28613				if (factor > iL.options.maxScale) factor = iL.options.maxScale;
28614				else if (factor < iL.options.minScale) factor = iL.options.minScale;
28615			}
28616
28617			var final_width = (iL.options.keepAspectRatio) ? round(width_old * factor) : width,
28618				final_height = (iL.options.keepAspectRatio) ? round(height_old * factor) : height;
28619
28620			return {
28621				width: final_width,
28622				height: final_height,
28623				ratio: factor
28624			};
28625		},
28626
28627		setOption: function(options) {
28628			var iL = this;
28629
28630			iL.options = $.extend(true, iL.options, options || {});
28631			iL.refresh();
28632		},
28633
28634		availPlugins: function() {
28635			var iL = this,
28636				testEl = document.createElement("video");
28637
28638			iL.plugins = {
28639				flash: !isMobile,
28640				quicktime: (parseInt(PluginDetect.getVersion("QuickTime")) >= 0) ? true : false,
28641				html5H264: !!(testEl.canPlayType && testEl.canPlayType('video/mp4').replace(/no/, '')),
28642				html5WebM: !!(testEl.canPlayType && testEl.canPlayType('video/webm').replace(/no/, '')),
28643				html5Vorbis: !!(testEl.canPlayType && testEl.canPlayType('video/ogg').replace(/no/, '')),
28644				html5QuickTime: !!(testEl.canPlayType && testEl.canPlayType('video/quicktime').replace(/no/, ''))
28645			};
28646		},
28647
28648		addContent: function(element, obj) {
28649			var iL = this,
28650				el;
28651
28652			switch (obj.type) {
28653				case 'video':
28654					var HTML5 = false,
28655						videoType = obj.videoType,
28656						html5video = obj.options.html5video;
28657
28658					if (((videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v') || html5video.h264) && iL.plugins.html5H264)
28659						obj.ext = 'mp4',
28660						obj.URL = html5video.h264 || obj.URL;
28661					else if (html5video.webm && iL.plugins.html5WebM)
28662						obj.ext = 'webm',
28663						obj.URL = html5video.webm || obj.URL;
28664					else if (html5video.ogg && iL.plugins.html5Vorbis)
28665						obj.ext = 'ogv',
28666						obj.URL = html5video.ogg || obj.URL;
28667
28668					if (iL.plugins.html5H264 && (videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v')) HTML5 = true, videoType = "video/mp4";
28669					else if (iL.plugins.html5WebM && (videoType == 'video/webm' || obj.ext == 'webm')) HTML5 = true, videoType = "video/webm";
28670					else if (iL.plugins.html5Vorbis && (videoType == 'video/ogg' || obj.ext == 'ogv')) HTML5 = true, videoType = "video/ogg";
28671					else if (iL.plugins.html5QuickTime && (videoType == 'video/quicktime' || obj.ext == 'mov' || obj.ext == 'qt')) HTML5 = true, videoType = "video/quicktime";
28672
28673					if (HTML5) {
28674						el = $('<video />
28674', {
28675							"width": "100%",
28676							"height": "100%",
28677							"preload": html5video.preload,
28678							"autoplay": html5video.autoplay,
28679							"loop": html5video.loop,
28680							"poster": html5video.poster,
28681							"controls": html5video.controls,
28682							"controlslist": "nodownload"
28683						}).append($('<source />', {
28684							"src": obj.URL,
28685							"type": videoType
28686						}));
28687					} else {
28688						if (!iL.plugins.quicktime) el = $('<span />', {
28689							"class": "ilightbox-alert",
28690							html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.quicktime).replace('{type}', 'QuickTime')
28691						});
28692						else {
28693
28694							el = $('<object />', {
28695								"type": "video/quicktime",
28696								"pluginspage": pluginspages.quicktime
28697							}).attr({
28698								"data": obj.URL,
28699								"width": "100%",
28700								"height": "100%"
28701							}).append($('<param />', {
28702								"name": "src",
28703								"value": obj.URL
28704							})).append($('<param />', {
28705								"name": "autoplay",
28706								"value": "false"
28707							})).append($('<param />', {
28708								"name": "loop",
28709								"value": "false"
28710							})).append($('<param />', {
28711								"name": "scale",
28712								"value": "tofit"
28713							}));
28714
28715							if (browser.msie) el = QT_GenerateOBJECTText(obj.URL, '100%', '100%', '', 'SCALE', 'tofit', 'AUTOPLAY', 'false', 'LOOP', 'false');
28716						}
28717					}
28718
28719					break;
28720
28721				case 'flash':
28722					if (!iL.plugins.flash) el = $('<span />', {
28723						"class": "ilightbox-alert",
28724						html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.flash).replace('{type}', 'Adobe Flash player')
28725					});
28726					else {
28727						var flashvars = "",
28728							i = 0;
28729
28730						if (obj.options.flashvars) $.each(obj.options.flashvars, function(k, v) {
28731							if (i != 0) flashvars += "&";
28732							flashvars += k + "=" + encodeURIComponent(v);
28733							i++;
28734						});
28735						else flashvars = null;
28736
28737						el = $('<embed />').attr({
28738							"type": "application/x-shockwave-flash",
28739							"src": obj.URL,
28740							"width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%",
28741							"height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%",
28742							"quality": "high",
28743							"bgcolor": "#000000",
28744							"play": "true",
28745							"loop": "true",
28746							"menu": "true",
28747							"wmode": "transparent",
28748							"scale": "showall",
28749							"allowScriptAccess": "always",
28750							"allowFullScreen": "true",
28751							"flashvars": flashvars,
28752							"fullscreen": "yes"
28753						});
28754					}
28755
28756					break;
28757
28758				case 'iframe':
28759					el = $('<iframe />').attr({
28760						"width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%",
28761						"height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%",
28762						src: obj.URL,
28763						frameborder: 0,
28764						'hspace': 0,
28765						'vspace': 0,
28766						'scrolling': supportTouch ? 'auto' : 'scroll',
28767						'webkitAllowFullScreen': '',
28768						'mozallowfullscreen': '',
28769						'allowFullScreen': ''
28770					});
28771
28772					break;
28773
28774				case 'inline':
28775					el = $('<div class="ilightbox-wrapper"></div>').html($(obj.URL).clone(true));
28776
28777					break;
28778
28779				case 'html':
28780					var object = obj.URL,
28781						el;
28782
28783					if (object[0].nodeName) {
28784						el = $('<div class="ilightbox-wrapper"></div>').html(object);
28785					} else {
28786						var dom = $(obj.URL),
28787							html = (dom.selector) ? $('<div>' + dom + '</div>') : dom;
28788						el = $('<div class="ilightbox-wrapper"></div>').html(html);
28789					}
28790
28791					break;
28792			}
28793
28794			$('div.ilightbox-container', element).empty().html(el);
28795
28796			// For fixing Chrome about just playing the video for first time
28797			if (el[0].tagName.toLowerCase() === 'video' && browser.webkit) setTimeout(function() {
28798				var src = el[0].currentSrc + '?' + floor(random() * 30000);
28799				el[0].currentSrc = src;
28800				el[0].src = src;
28801			});
28802
28803			return el;
28804		},
28805
28806		ogpRecognition: function(obj, callback) {
28807			var iL = this,
28808				url = obj.URL;
28809
28810			iL.showLoader();
28811			doAjax(url, function(data) {
28812				iL.hideLoader();
28813				if (data) {
28814					var object = new Object();
28815
28816					object.length = false,
28817					object.url = data.url;
28818
28819					if (data.status == 200) {
28820						var result = data.results,
28821							type = result.type,
28822							source = result.source;
28823
28824						object.source = source.src,
28825						object.width = source.width && parseInt(source.width) || 0,
28826						object.height = source.height && parseInt(source.height) || 0,
28827						object.type = type,
28828						object.thumbnail = source.thumbnail || result.images && result.images[0],
28829						object.html5video = result.html5video || {},
28830						object.length = true;
28831
28832						if (source.type == 'application/x-shockwave-flash') object.type = "flash";
28833						else if (source.type.indexOf("video/") != -1) object.type = "video";
28834						else if (source.type.indexOf("/html") != -1) object.type = "iframe";
28835						else if (source.type.indexOf("image/") != -1) object.type = "image";
28836
28837					} else if (typeof data.response != 'undefined')
28838						throw data.response;
28839
28840					callback.call(this, object.length ? object : false);
28841				}
28842			});
28843		},
28844
28845		hashChangeHandler: function(url) {
28846			var iL = this,
28847				vars = iL.vars,
28848				opts = iL.options,
28849				URL = url || window.location.href,
28850				hash = parseURI(URL).hash,
28851				split = hash.split('/'),
28852				index = split[1];
28853
28854			if (vars.hashLock || ('#' + opts.linkId != split[0] && hash.length > 1)) return;
28855
28856			if (index) {
28857				var target = split[1] || 0;
28858				if (iL.items[target]) {
28859					var overlay = $('.ilightbox-overlay');
28860					if (overlay.length && overlay.attr('linkid') == opts.linkId) {
28861						iL.goTo(target);
28862					} else {
28863						iL.itemsObject[target].trigger(ishybrid ? "itap click" : supportTouch ? 'itap' : 'click');
28864						//iL.goTo(target);
28865					}
28866				} else {
28867					var overlay = $('.ilightbox-overlay');
28868					if (overlay.length) iL.closeAction();
28869				}
28870			} else {
28871				var overlay = $('.ilightbox-overlay');
28872				if (overlay.length) iL.closeAction();
28873			}
28874		}
28875	};
28876
28877	/**
28878	 * Parse style to pixels.
28879	 *
28880	 * @param {Object}   $element   jQuery object with element.
28881	 * @param {Property} property   CSS property to get the pixels from.
28882	 *
28883	 * @return {Int}
28884	 */
28885	function getPixel($element, property) {
28886		return parseInt($element.css(property), 10) || 0;
28887	}
28888
28889	/**
28890	 * Make sure that number is within the limits.
28891	 *
28892	 * @param {Number} number
28893	 * @param {Number} min
28894	 * @param {Number} max
28895	 *
28896	 * @return {Number}
28897	 */
28898	function within(number, min, max) {
28899		return number < min ? min : number > max ? max : number;
28900	}
28901
28902	/**
28903	 * Get viewport/window size (width and height).
28904	 *
28905	 * @return {Object}
28906	 */
28907	function getViewport() {
28908		var e = window,
28909			a = 'inner';
28910		if (!('innerWidth' in window)) {
28911			a = 'client';
28912			e = document.documentElement || document.body;
28913		}
28914		return {
28915			width: e[a + 'Width'],
28916			height: e[a + 'Height']
28917		}
28918	}
28919
28920	/**
28921	 * Remove hash tag from the URL
28922	 *
28923	 * @return {Void}
28924	 */
28925	function removeHash() {
28926		var scroll = getScrollXY();
28927
28928		//UNCODE change
28929		// window.location.hash = "";
28930		// history.pushState("", document.title, window.location.pathname + window.location.search);
28931		history.replaceState({}, document.title, window.location.pathname + window.location.search);
28932
28933		// Restore the scroll offset, should be flicker free
28934		window.scrollTo(scroll.x, scroll.y);
28935	}
28936
28937	/**
28938	 * Do the ajax requests with callback.
28939	 *
28940	 * @param {String}   url
28941	 * @param {Function} callback
28942	 *
28943	 * @return {Void}
28944	 */
28945	function doAjax(url, callback) {
28946		var url = "//ilightbox.net/getSource/jsonp.php?url=" + encodeURIComponent(url).replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/\*/g, '%2A');
28947		$.ajax({
28948			url: url,
28949			dataType: 'jsonp'
28950		});
28951
28952		iLCallback = function(data) {
28953			callback.call(this, data);
28954		};
28955	}
28956
28957	/**
28958	 * Find image from DOM elements
28959	 *
28960	 * @param {Element} element
28961	 *
28962	 * @return {Void}
28963	 */
28964	function findImageInElement(element) {
28965		var elements = $('*', element),
28966			imagesArr = new Array();
28967
28968		elements.each(function() {
28969			var url = "",
28970				element = this;
28971
28972			if ($(element).css("background-image") != "none") {
28973				url = $(element).css("background-image");
28974			} else if (typeof($(element).attr("src")) != "undefined" && element.nodeName.toLowerCase() == "img") {
28975				url = $(element).attr("src");
28976			}
28977
28978			if (url.indexOf("gradient") == -1) {
28979				url = url.replace(/url\(\"/g, "");
28980				url = url.replace(/url\(/g, "");
28981				url = url.replace(/\"\)/g, "");
28982				url = url.replace(/\)/g, "");
28983
28984				var urls = url.split(",");
28985
28986				for (var i = 0; i < urls.length; i++) {
28987					if (urls[i].length > 0 && $.inArray(urls[i], imagesArr) == -1) {
28988						var extra = "";
28989						if (browser.msie && browser.version < 9) {
28990							extra = "?" + floor(random() * 3000);
28991						}
28992						imagesArr.push(urls[i] + extra);
28993					}
28994				}
28995			}
28996		});
28997
28998		return imagesArr;
28999	}
29000
29001	/**
29002	 * Get file extension.
29003	 *
29004	 * @param {String} URL
29005	 *
29006	 * @return {String}
29007	 */
29008	function getExtension(URL) {
29009		if (URL !== null) {
29010			//UNCODE: fix issue to detect media type with query strings
29011			var ext = URL.indexOf('?') !== -1 ? URL.split('?')[0] : URL;
29012			ext = ext.split('.').pop().toLowerCase();
29013
29014			return ext;
29015		}
29016	}
29017
29018	/**
29019	 * Get type via extension.
29020	 *
29021	 * @param {String} URL
29022	 *
29023	 * @return {String}
29024	 */
29025	function getTypeByExtension(URL) {
29026		var type,
29027			ext = getExtension(URL);
29028
29029		//Uncode addition ##START##
29030		if (URL == undefined) {
29031			return false;
29032		}
29033		//Uncode addition ##END##
29034
29035		if (extensions.image.indexOf(ext) !== -1) type = 'image';
29036		else if (extensions.flash.indexOf(ext) !== -1) type = 'flash';
29037		else if (extensions.video.indexOf(ext) !== -1) type = 'video';
29038		else if (ext.substring(0, 1) == "#") type = 'inline'; //Uncode addition
29039		else type = 'iframe';
29040
29041		return type;
29042	}
29043
29044	/**
29045	 * Return value from percent of a number.
29046	 *
29047	 * @param {Number} percent
29048	 * @param {Number} total
29049	 *
29050	 * @return {Number}
29051	 */
29052	function percentToValue(percent, total) {
29053		return parseInt((total / 100) * percent);
29054	}
29055
29056	/**
29057	 * A JavaScript equivalent of PHP’s parse_url.
29058	 *
29059	 * @param {String} url           The URL to parse.
29060	 *
29061	 * @return {Mixed}
29062	 */
29063	function parseURI(url) {
29064		var m = String(url).replace(/^\s+|\s+$/g, '').match(/^([^:\/?#]+:)?(\/\/(?:[^:@]*(?::[^:@]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/);
29065		// authority = '//' + user + ':' + pass '@' + hostname + ':' port
29066		return (m ? {
29067			href: m[0] || '',
29068			protocol: m[1] || '',
29069			authority: m[2] || '',
29070			host: m[3] || '',
29071			hostname: m[4] || '',
29072			port: m[5] || '',
29073			pathname: m[6] || '',
29074			search: m[7] || '',
29075			hash: m[8] || ''
29076		} : null);
29077	}
29078
29079	/**
29080	 * Gets the absolute URI.
29081	 *
29082	 * @param {String} href     The relative URL.
29083	 * @param {String} base     The base URL.
29084	 *
29085	 * @return {String}         The absolute URL.
29086	 */
29087	function absolutizeURI(base, href) { // RFC 3986
29088		var iL = this;
29089
29090		function removeDotSegments(input) {
29091			var output = [];
29092			input.replace(/^(\.\.?(\/|$))+/, '')
29093				.replace(/\/(\.(\/|$))+/g, '/')
29094				.replace(/\/\.\.$/, '/../')
29095				.replace(/\/?[^\/]*/g, function(p) {
29096					if (p === '/..') {
29097						output.pop();
29098					} else {
29099						output.push(p);
29100					}
29101				});
29102			return output.join('').replace(/^\//, input.charAt(0) === '/' ? '/' : '');
29103		}
29104
29105		href = parseURI(href || '');
29106		base = parseURI(base || '');
29107
29108		return !href || !base ? null : (href.protocol || base.protocol) +
29109			(href.protocol || href.authority ? href.authority : base.authority) +
29110			removeDotSegments(href.protocol || href.authority || href.pathname.charAt(0) === '/' ? href.pathname : (href.pathname ? ((base.authority && !base.pathname ? '/' : '') + base.pathname.slice(0, base.pathname.lastIndexOf('/') + 1) + href.pathname) : base.pathname)) +
29111			(href.protocol || href.authority || href.pathname ? href.search : (href.search || base.search)) +
29112			href.hash;
29113	}
29114
29115	/**
29116	 * A JavaScript equivalent of PHP’s version_compare.
29117	 *
29118	 * @param {String} v1
29119	 * @param {String} v2
29120	 * @param {String} operator
29121	 *
29122	 * @return {Boolean}
29123	 */
29124	function version_compare(v1, v2, operator) {
29125		this.php_js = this.php_js || {};
29126		this.php_js.ENV = this.php_js.ENV || {};
29127		var i = 0,
29128			x = 0,
29129			compare = 0,
29130			vm = {
29131				'dev': -6,
29132				'alpha': -5,
29133				'a': -5,
29134				'beta': -4,
29135				'b': -4,
29136				'RC': -3,
29137				'rc': -3,
29138				'#': -2,
29139				'p': 1,
29140				'pl': 1
29141			},
29142			prepVersion = function(v) {
29143				v = ('' + v).replace(/[_\-+]/g, '.');
29144				v = v.replace(/([^.\d]+)/g, '.$1.').replace(/\.{2,}/g, '.');
29145				return (!v.length ? [-8] : v.split('.'));
29146			},
29147			numVersion = function(v) {
29148				return !v ? 0 : (isNaN(v) ? vm[v] || -7 : parseInt(v, 10));
29149			};
29150		v1 = prepVersion(v1);
29151		v2 = prepVersion(v2);
29152		x = max(v1.length, v2.length);
29153		for (i = 0; i < x; i++) {
29154			if (v1[i] == v2[i]) {
29155				continue;
29156			}
29157			v1[i] = numVersion(v1[i]);
29158			v2[i] = numVersion(v2[i]);
29159			if (v1[i] < v2[i]) {
29160				compare = -1;
29161				break;
29162			} else if (v1[i] > v2[i]) {
29163				compare = 1;
29164				break;
29165			}
29166		}
29167		if (!operator) {
29168			return compare;
29169		}
29170
29171		switch (operator) {
29172			case '>':
29173			case 'gt':
29174				return (compare > 0);
29175			case '>=':
29176			case 'ge':
29177				return (compare >= 0);
29178			case '<=':
29179			case 'le':
29180				return (compare <= 0);
29181			case '==':
29182			case '=':
29183			case 'eq':
29184				return (compare === 0);
29185			case '<>':
29186			case '!=':
29187			case 'ne':
29188				return (compare !== 0);
29189			case '':
29190			case '<':
29191			case 'lt':
29192				return (compare < 0);
29193			default:
29194				return null;
29195		}
29196	}
29197
29198
29199	// Begin the iLightBox plugin
29200	$.fn.iLightBox = function() {
29201
29202		var args = arguments,
29203			opt = ($.isPlainObject(args[0])) ? args[0] : args[1],
29204			items = ($.isArray(args[0]) || typeof args[0] == 'string') ? args[0] : args[1];
29205
29206		if (!opt) opt = {};
29207
29208		// Default options. Play carefully.
29209		var options = $.extend(true, {
29210			attr: 'href',
29211			path: 'vertical',
29212			skin: 'dark',
29213			linkId: false,
29214			infinite: false,
29215			startFrom: 0,
29216			randomStart: false,
29217			keepAspectRatio: true,
29218			maxScale: 1,
29219			minScale: .2,
29220			innerToolbar: false,
29221			smartRecognition: false,
29222			mobileOptimizer: true,
29223			fullAlone: true,
29224			fullViewPort: null,
29225			fullStretchTypes: 'flash, video',
29226			overlay: {
29227				blur: true,
29228				opacity: .85
29229			},
29230			controls: {
29231				arrows: false,
29232				slideshow: false,
29233				toolbar: true,
29234				fullscreen: true,
29235				thumbnail: true,
29236				keyboard: true,
29237				mousewheel: true,
29238				swipe: true
29239			},
29240			keyboard: {
29241				left: true, // previous
29242				right: true, // next
29243				up: true, // previous
29244				down: true, // next
29245				esc: true, // close
29246				shift_enter: true // fullscreen
29247			},
29248			show: {
29249				effect: true,
29250				speed: 300,
29251				title: true
29252			},
29253			hide: {
29254				effect: true,
29255				speed: 300
29256			},
29257			caption: {
29258				start: true,
29259				show: 'mouseenter',
29260				hide: 'mouseleave'
29261			},
29262			social: {
29263				start: true,
29264				show: 'mouseenter',
29265				hide: 'mouseleave',
29266				buttons: false
29267			},
29268			styles: {
29269				pageOffsetX: 0,
29270				pageOffsetY: 0,
29271				nextOffsetX: 45,
29272				nextOffsetY: 0,
29273				nextOpacity: 1,
29274				nextScale: 1,
29275				prevOffsetX: 45,
29276				prevOffsetY: 0,
29277				prevOpacity: 1,
29278				prevScale: 1
29279			},
29280			thumbnails: {
29281				maxWidth: 120,
29282				maxHeight: 80,
29283				normalOpacity: 1,
29284				activeOpacity: .6
29285			},
29286			effects: {
29287				reposition: true,
29288				repositionSpeed: 200,
29289				switchSpeed: 500,
29290				loadedFadeSpeed: 180,
29291				fadeSpeed: 200
29292			},
29293			slideshow: {
29294				pauseTime: 5000,
29295				pauseOnHover: false,
29296				startPaused: true
29297			},
29298			text: {
29299				close: "Press Esc to close",
29300				enterFullscreen: "Enter Fullscreen (Shift+Enter)",
29301				exitFullscreen: "Exit Fullscreen (Shift+Enter)",
29302				slideShow: "Slideshow",
29303				next: "Next",
29304				previous: "Previous"
29305			},
29306			errors: {
29307				loadImage: "An error occurred when trying to load photo.",
29308				loadContents: "An error occurred when trying to load contents.",
29309				missingPlugin: "The content your are attempting to view requires the <a href='{pluginspage}' target='_blank'>{type} plugin<\/a>."
29310			},
29311			ajaxSetup: {
29312				url: '',
29313				beforeSend: function(jqXHR, settings) {},
29314				cache: false,
29315				complete: function(jqXHR, textStatus) {},
29316				crossDomain: false,
29317				error: function(jqXHR, textStatus, errorThrown) {},
29318				success: function(data, textStatus, jqXHR) {},
29319				global: true,
29320				ifModified: false,
29321				username: null,
29322				password: null,
29323				type: 'GET'
29324			},
29325			callback: {}
29326		}, opt);
29327
29328		var instant = ($.isArray(items) || typeof items == 'string') ? true : false;
29329
29330		items = $.isArray(items) ? items : new Array();
29331
29332		if (typeof args[0] == 'string') items[0] = args[0];
29333
29334		if (version_compare($.fn.jquery, '1.8', '>=')) {
29335			var iLB = new iLightBox($(this), options, items, instant);
29336			return {
29337				close: function() {
29338					iLB.closeAction();
29339				},
29340				fullscreen: function() {
29341					iLB.fullScreenAction();
29342				},
29343				moveNext: function() {
29344					iLB.moveTo('next');
29345				},
29346				movePrev: function() {
29347					iLB.moveTo('prev');
29348				},
29349				goTo: function(index) {
29350					iLB.goTo(index);
29351				},
29352				refresh: function() {
29353					iLB.refresh();
29354				},
29355				reposition: function() {
29356					(arguments.length > 0) ? iLB.repositionPhoto(true): iLB.repositionPhoto();
29357				},
29358				setOption: function(options) {
29359					iLB.setOption(options);
29360				},
29361				destroy: function() {
29362					iLB.closeAction();
29363					iLB.dispatchItemsEvents();
29364				}
29365			};
29366		} else {
29367			throw "The jQuery version that was loaded is too old. iLightBox requires jQuery 1.8+";
29368		}
29369
29370	};
29371
29372
29373	$.iLightBox = function() {
29374		return $.fn.iLightBox(arguments[0], arguments[1]);
29375	};
29376
29377	function getScrollXY() {
29378		var scrOfX = 0,
29379			scrOfY = 0;
29380		if (typeof(window.pageYOffset) == 'number') {
29381			//Netscape compliant
29382			scrOfY = window.pageYOffset;
29383			scrOfX = window.pageXOffset;
29384		} else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) {
29385			//DOM compliant
29386			scrOfY = document.body.scrollTop;
29387			scrOfX = document.body.scrollLeft;
29388		} else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
29389			//IE6 standards compliant mode
29390			scrOfY = document.documentElement.scrollTop;
29391			scrOfX = document.documentElement.scrollLeft;
29392		}
29393		return {
29394			x: scrOfX,
29395			y: scrOfY
29396		};
29397	}
29398
29399	(function() {
29400		// add new event shortcuts
29401		$.each(("touchstart touchmove touchend " +
29402			"tap taphold " +
29403			"swipe swipeleft swiperight " +
29404			"scrollstart scrollstop").split(" "), function(i, name) {
29405
29406			$.fn[name] = function(fn) {
29407				return fn ? this.bind(name, fn) : this.trigger(name);
29408			};
29409
29410			// jQuery < 1.8
29411			// if ($.attrFn) {
29412			// 	$.attrFn[name] = true;
29413			// }
29414		});
29415
29416		var tapSettings = {
29417			startEvent: 'touchstart.iTap',
29418			endEvent: 'touchend.iTap'
29419		};
29420
29421		// tap Event:
29422		$.event.special.itap = {
29423			setup: function() {
29424
29425				var self = this,
29426					$self = $(this),
29427					start, stop;
29428
29429				$self.bind(tapSettings.startEvent, function(event) {
29430					start = getScrollXY();
29431
29432					$self.one(tapSettings.endEvent, function(event) {
29433						stop = getScrollXY();
29434
29435						var orgEvent = event || window.event;
29436						event = $.event.fix(orgEvent);
29437						event.type = "itap";
29438
29439						if ((start && stop) && (start.x == stop.x && start.y == stop.y))($.event.dispatch || $.event.handle).call(self, event);
29440
29441						start = stop = undefined;
29442					});
29443				});
29444			},
29445
29446			teardown: function() {
29447				$(this).unbind(tapSettings.startEvent);
29448			}
29449		};
29450	}());
29451
29452
29453	//Fullscreen API
29454	(function() {
29455		fullScreenApi = {
29456				supportsFullScreen: false,
29457				isFullScreen: function() {
29458					return false;
29459				},
29460				requestFullScreen: function() {},
29461				cancelFullScreen: function() {},
29462				fullScreenEventName: '',
29463				prefix: ''
29464			},
29465			browserPrefixes = 'webkit moz o ms khtml'.split(' ');
29466
29467		// check for native support
29468		if (typeof document.cancelFullScreen != 'undefined') {
29469			fullScreenApi.supportsFullScreen = true;
29470		} else {
29471			// check for fullscreen support by vendor prefix
29472			for (var i = 0, il = browserPrefixes.length; i < il; i++) {
29473				fullScreenApi.prefix = browserPrefixes[i];
29474
29475				if (typeof document[fullScreenApi.prefix + 'CancelFullScreen'] != 'undefined') {
29476					fullScreenApi.supportsFullScreen = true;
29477
29478					break;
29479				}
29480			}
29481		}
29482
29483		// update methods to do something useful
29484		if (fullScreenApi.supportsFullScreen) {
29485			fullScreenApi.fullScreenEventName = fullScreenApi.prefix + 'fullscreenchange';
29486
29487			fullScreenApi.isFullScreen = function() {
29488				switch (this.prefix) {
29489					case '':
29490						return document.fullScreen;
29491					case 'webkit':
29492						return document.webkitIsFullScreen;
29493					default:
29494						return document[this.prefix + 'FullScreen'];
29495				}
29496			}
29497			fullScreenApi.requestFullScreen = function(el) {
29498				return (this.prefix === '') ? el.requestFullScreen() : el[this.prefix + 'RequestFullScreen']();
29499			}
29500			fullScreenApi.cancelFullScreen = function(el) {
29501				return (this.prefix === '') ? document.cancelFullScreen() : document[this.prefix + 'CancelFullScreen']();
29502			}
29503		}
29504	}());
29505
29506	// Browser detect
29507	(function() {
29508		function uaMatch(ua) {
29509			ua = ua.toLowerCase();
29510
29511			var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
29512				/(webkit)[ \/]([\w.]+)/.exec(ua) ||
29513				/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
29514				/(msie) ([\w.]+)/.exec(ua) ||
29515				ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || [];
29516
29517			return {
29518				browser: match[1] || "",
29519				version: match[2] || "0"
29520			};
29521		}
29522
29523		var matched = uaMatch(navigator.userAgent);
29524		browser = {};
29525
29526		if (matched.browser) {
29527			browser[matched.browser] = true;
29528			browser.version = matched.version;
29529		}
29530
29531		// Chrome is Webkit, but Webkit is also Safari.
29532		if (browser.chrome) {
29533			browser.webkit = true;
29534		} else if (browser.webkit) {
29535			browser.safari = true;
29536		}
29537	}());
29538
29539	// Feature detects
29540	(function() {
29541		var prefixes = ['', 'webkit', 'moz', 'ms', 'o'];
29542		var el = document.createElement('div');
29543
29544		function testProp(prop) {
29545			for (var p = 0, pl = prefixes.length; p < pl; p++) {
29546				var prefixedProp = prefixes[p] ? prefixes[p] + prop.charAt(0).toUpperCase() + prop.slice(1) : prop;
29547				if (el.style[prefixedProp] !== undefined) {
29548					return prefixedProp;
29549				}
29550			}
29551		}
29552
29553		// Global support indicators
29554		transform = testProp('transform') || '';
29555		gpuAcceleration = testProp('perspective') ? 'translateZ(0) ' : '';
29556	}());
29557
29558
29559	/*
29560		PluginDetect v0.7.9
29561		www.pinlady.net/PluginDetect/license/
29562		[ getVersion onWindowLoaded BetterIE ]
29563		[ Flash QuickTime Shockwave ]
29564	*/
29565	var PluginDetect={version:"0.7.9",name:"PluginDetect",handler:function(c,b,a){return function(){c(b,a)}},openTag:"<",isDefined:function(b){return typeof b!="undefined"},isArray:function(b){return(/array/i).test(Object.prototype.toString.call(b))},isFunc:function(b){return typeof b=="function"},isString:function(b){return typeof b=="string"},isNum:function(b){return typeof b=="number"},isStrNum:function(b){return(typeof b=="string"&&(/\d/).test(b))},getNumRegx:/[\d][\d\.\_,-]*/,splitNumRegx:/[\.\_,-]/g,getNum:function(b,c){var d=this,a=d.isStrNum(b)?(d.isDefined(c)?new RegExp(c):d.getNumRegx).exec(b):null;return a?a[0]:null},compareNums:function(h,f,d){var e=this,c,b,a,g=parseInt;if(e.isStrNum(h)&&e.isStrNum(f)){if(e.isDefined(d)&&d.compareNums){return d.compareNums(h,f)}c=h.split(e.splitNumRegx);b=f.split(e.splitNumRegx);for(a=0;a<min(c.length,b.length);a++){if(g(c[a],10)>g(b[a],10)){return 1}if(g(c[a],10)<g(b[a],10)){return -1}}}return 0},formatNum:function(b,c){var d=this,a,e;if(!d.isStrNum(b)){return null}if(!d.isNum(c)){c=4}c--;e=b.replace(/\s/g,"").split(d.splitNumRegx).concat(["0","0","0","0"]);for(a=0;a<4;a++){if(/^(0+)(.+)$/.test(e[a])){e[a]=RegExp.$2}if(a>c||!(/\d/).test(e[a])){e[a]="0"}}return e.slice(0,4).join(",")},$$hasMimeType:function(a){return function(c){if(!a.isIE&&c){var f,e,b,d=a.isArray(c)?c:(a.isString(c)?[c]:[]);for(b=0;b<d.length;b++){if(a.isString(d[b])&&/[^\s]/.test(d[b])){f=navigator.mimeTypes[d[b]];e=f?f.enabledPlugin:0;if(e&&(e.name||e.description)){return f}}}}return null}},findNavPlugin:function(l,e,c){var j=this,h=new RegExp(l,"i"),d=(!j.isDefined(e)||e)?/\d/:0,k=c?new RegExp(c,"i"):0,a=navigator.plugins,g="",f,b,m;for(f=0;f<a.length;f++){m=a[f].description||g;b=a[f].name||g;if((h.test(m)&&(!d||d.test(RegExp.leftContext+RegExp.rightContext)))||(h.test(b)&&(!d||d.test(RegExp.leftContext+RegExp.rightContext)))){if(!k||!(k.test(m)||k.test(b))){return a[f]}}}return null},getMimeEnabledPlugin:function(k,m,c){var e=this,f,b=new RegExp(m,"i"),h="",g=c?new RegExp(c,"i"):0,a,l,d,j=e.isString(k)?[k]:k;for(d=0;d<j.length;
29565d++){if((f=e.hasMimeType(j[d]))&&(f=f.enabledPlugin)){l=f.description||h;a=f.name||h;if(b.test(l)||b.test(a)){if(!g||!(g.test(l)||g.test(a))){return f}}}}return 0},getPluginFileVersion:function(f,b){var h=this,e,d,g,a,c=-1;if(h.OS>2||!f||!f.version||!(e=h.getNum(f.version))){return b}if(!b){return e}e=h.formatNum(e);b=h.formatNum(b);d=b.split(h.splitNumRegx);g=e.split(h.splitNumRegx);for(a=0;a<d.length;a++){if(c>-1&&a>c&&d[a]!="0"){return b}if(g[a]!=d[a]){if(c==-1){c=a}if(d[a]!="0"){return b}}}return e},AXO:window.ActiveXObject,getAXO:function(a){var f=null,d,b=this,c={};try{f=new b.AXO(a)}catch(d){}return f},convertFuncs:function(f){var a,g,d,b=/^[\$][\$]/,c=this;for(a in f){if(b.test(a)){try{g=a.slice(2);if(g.length>0&&!f[g]){f[g]=f[a](f);delete f[a]}}catch(d){}}}},initObj:function(e,b,d){var a,c;if(e){if(e[b[0]]==1||d){for(a=0;a<b.length;a=a+2){e[b[a]]=b[a+1]}}for(a in e){c=e[a];if(c&&c[b[0]]==1){this.initObj(c,b)}}}},initScript:function(){var d=this,a=navigator,h,i=document,l=a.userAgent||"",j=a.vendor||"",b=a.platform||"",k=a.product||"";d.initObj(d,["$",d]);for(h in d.Plugins){if(d.Plugins[h]){d.initObj(d.Plugins[h],["$",d,"$$",d.Plugins[h]],1)}}d.convertFuncs(d);d.OS=100;if(b){var g=["Win",1,"Mac",2,"Linux",3,"FreeBSD",4,"iPhone",21.1,"iPod",21.2,"iPad",21.3,"Win.*CE",22.1,"Win.*Mobile",22.2,"Pocket\\s*PC",22.3,"",100];for(h=g.length-2;h>=0;h=h-2){if(g[h]&&new RegExp(g[h],"i").test(b)){d.OS=g[h+1];break}}};d.head=i.getElementsByTagName("head")[0]||i.getElementsByTagName("body")[0]||i.body||null;d.isIE=new Function("return/*@cc_on!@*/!1")();d.verIE=d.isIE&&(/MSIE\s*(\d+\.?\d*)/i).test(l)?parseFloat(RegExp.$1,10):null;d.verIEfull=null;d.docModeIE=null;if(d.isIE){var f,n,c=document.createElement("div");try{c.style.behavior="url(#default#clientcaps)";d.verIEfull=(c.getComponentVersion("{89820200-ECBD-11CF-8B85-00AA005B4383}","componentid")).replace(/,/g,".")}catch(f){}n=parseFloat(d.verIEfull||"0",10);d.docModeIE=i.documentMode||((/back/i).test(i.compatMode||"")?5:n)||d.verIE;d.verIE=n||d.docModeIE};d.ActiveXEnabled=false;if(d.isIE){var h,m=["Msxml2.XMLHTTP","Msxml2.DOMDocument","Microsoft.XMLDOM","ShockwaveFlash.ShockwaveFlash","TDCCtl.TDCCtl","Shell.UIHelper","Scripting.Dictionary","wmplayer.ocx"];for(h=0;h<m.length;h++){if(d.getAXO(m[h])){d.ActiveXEnabled=true;break}}};d.isGecko=(/Gecko/i).test(k)&&(/Gecko\s*\/\s*\d/i).test(l);
29565d.verGecko=d.isGecko?d.formatNum((/rv\s*\:\s*([\.\,\d]+)/i).test(l)?RegExp.$1:"0.9"):null;d.isChrome=(/Chrome\s*\/\s*(\d[\d\.]*)/i).test(l);d.verChrome=d.isChrome?d.formatNum(RegExp.$1):null;d.isSafari=((/Apple/i).test(j)||(!j&&!d.isChrome))&&(/Safari\s*\/\s*(\d[\d\.]*)/i).test(l);d.verSafari=d.isSafari&&(/Version\s*\/\s*(\d[\d\.]*)/i).test(l)?d.formatNum(RegExp.$1):null;d.isOpera=(/Opera\s*[\/]?\s*(\d+\.?\d*)/i).test(l);d.verOpera=d.isOpera&&((/Version\s*\/\s*(\d+\.?\d*)/i).test(l)||1)?parseFloat(RegExp.$1,10):null;d.addWinEvent("load",d.handler(d.runWLfuncs,d))},init:function(d){var c=this,b,d,a={status:-3,plugin:0};if(!c.isString(d)){return a}if(d.length==1){c.getVersionDelimiter=d;return a}d=d.toLowerCase().replace(/\s/g,"");b=c.Plugins[d];if(!b||!b.getVersion){return a}a.plugin=b;if(!c.isDefined(b.installed)){b.installed=null;b.version=null;b.version0=null;b.getVersionDone=null;b.pluginName=d}c.garbage=false;if(c.isIE&&!c.ActiveXEnabled&&d!=="java"){a.status=-2;return a}a.status=1;return a},fPush:function(b,a){var c=this;if(c.isArray(a)&&(c.isFunc(b)||(c.isArray(b)&&b.length>0&&c.isFunc(b[0])))){a.push(b)}},callArray:function(b){var c=this,a;if(c.isArray(b)){for(a=0;a<b.length;a++){if(b[a]===null){return}c.call(b[a]);b[a]=null}}},call:function(c){var b=this,a=b.isArray(c)?c.length:-1;if(a>0&&b.isFunc(c[0])){c[0](b,a>1?c[1]:0,a>2?c[2]:0,a>3?c[3]:0)}else{if(b.isFunc(c)){c(b)}}},getVersionDelimiter:",",$$getVersion:function(a){return function(g,d,c){var e=a.init(g),f,b,h={};if(e.status<0){return null};f=e.plugin;if(f.getVersionDone!=1){f.getVersion(null,d,c);if(f.getVersionDone===null){f.getVersionDone=1}}a.cleanup();b=(f.version||f.version0);b=b?b.replace(a.splitNumRegx,a.getVersionDelimiter):b;return b}},cleanup:function(){var a=this;if(a.garbage&&a.isDefined(window.CollectGarbage)){window.CollectGarbage()}},isActiveXObject:function(d,b){var f=this,a=false,g,c='<object width="1" height="1" style="display:none" '+d.getCodeBaseVersion(b)+">"+d.HTML+f.openTag+"/object>";if(!f.head){return a}f.head.insertBefore(document.createElement("object"),f.head.firstChild);f.head.firstChild.outerHTML=c;try{f.head.firstChild.classid=d.classID}catch(g){}try{if(f.head.firstChild.object){a=true}}catch(g){}try{if(a&&f.head.firstChild.readyState<4){f.garbage=true}}catch(g){}f.head.removeChild(f.head.firstChild);return a},codebaseSearch:function(f,b){var c=this;if(!c.ActiveXEnabled||!f){return null}if(f.BIfuncs&&f.BIfuncs.length&&f.BIfuncs[f.BIfuncs.length-1]!==null){c.callArray(f.BIfuncs)}var d,o=f.SEARCH,k={};if(c.isStrNum(b)){if(o.match&&o.min&&c.compareNums(b,o.min)<=0){return true}if(o.match&&o.max&&c.compareNums(b,o.max)>=0){return false}d=c.isActiveXObject(f,b);if(d&&(!o.min||c.compareNums(b,o.min)>0)){o.min=b}if(!d&&(!o.max||c.compareNums(b,o.max)<0)){o.max=b}return d};var e=[0,0,0,0],l=[].concat(o.digits),a=o.min?1:0,j,i,h,g,m,n=function(p,r){var q=[].concat(e);q[p]=r;return c.isActiveXObject(f,q.join(","))};if(o.max){g=o.max.split(c.splitNumRegx);for(j=0;j<g.length;j++){g[j]=parseInt(g[j],10)}if(g[0]<l[0]){l[0]=g[0]}}if(o.min){m=o.min.split(c.splitNumRegx);for(j=0;j<m.length;j++){m[j]=parseInt(m[j],10)}if(m[0]>e[0]){e[0]=m[0]}}if(m&&g){for(j=1;j<m.length;j++){if(m[j-1]!=g[j-1]){break}if(g[j]<l[j]){l[j]=g[j]}if(m[j]>e[j]){e[j]=m[j]}}}if(o.max){for(j=1;j<l.length;j++){if(g[j]>0&&l[j]==0&&l[j-1]<o.digits[j-1]){l[j-1]+=1;break}}};for(j=0;j<l.length;j++){h={};for(i=0;i<20;i++){if(l[j]-e[j]<1){break}d=round((l[j]+e[j])/2);if(h["a"+d]){break}h["a"+d]=1;if(n(j,d)){e[j]=d;a=1}else{l[j]=d}}l[j]=e[j];if(!a&&n(j,e[j])){a=1};if(!a){break}};return a?e.join(","):null},addWinEvent:function(d,c){var e=this,a=window,b;if(e.isFunc(c)){if(a.addEventListener){a.addEventListener(d,c,false)}else{if(a.attachEvent){a.attachEvent("on"+d,c)}else{b=a["on"+d];a["on"+d]=e.winHandler(c,b)}}}},winHandler:function(d,c){return function(){d();if(typeof c=="function"){c()}}},WLfuncs0:[],WLfuncs:[],runWLfuncs:function(a){var b={};a.winLoaded=true;a.callArray(a.WLfuncs0);a.callArray(a.WLfuncs);if(a.onDoneEmptyDiv){a.onDoneEmptyDiv()}},winLoaded:false,$$onWindowLoaded:function(a){return function(b){if(a.winLoaded){a.call(b)}else{a.fPush(b,a.WLfuncs)}}},div:null,divID:"plugindetect",divWidth:50,pluginSize:1,emptyDiv:function(){var d=this,b,h,c,a,f,g;if(d.div&&d.div.childNodes){for(b=d.div.childNodes.length-1;b>=0;b--){c=d.div.childNodes[b];if(c&&c.childNodes){for(h=c.childNodes.length-1;h>=0;h--){g=c.childNodes[h];try{c.removeChild(g)}catch(f){}}}if(c){try{d.div.removeChild(c)}catch(f){}}}}if(!d.div){a=document.getElementById(d.divID);if(a){d.div=a}}if(d.div&&d.div.parentNode){try{d.div.parentNode.removeChild(d.div)}catch(f){}d.div=null}},DONEfuncs:[],onDoneEmptyDiv:function(){var c=this,a,b;if(!c.winLoaded){return}if(c.WLfuncs&&c.WLfuncs.length&&c.WLfuncs[c.WLfuncs.length-1]!==null){return}for(a in c){b=c[a];if(b&&b.funcs){if(b.OTF==3){return}if(b.funcs.length&&b.funcs[b.funcs.length-1]!==null){return}}}for(a=0;a<c.DONEfuncs.length;a++){c.callArray(c.DONEfuncs)}
29565c.emptyDiv()},getWidth:function(c){if(c){var a=c.scrollWidth||c.offsetWidth,b=this;if(b.isNum(a)){return a}}return -1},getTagStatus:function(m,g,a,b){var c=this,f,k=m.span,l=c.getWidth(k),h=a.span,j=c.getWidth(h),d=g.span,i=c.getWidth(d);if(!k||!h||!d||!c.getDOMobj(m)){return -2}if(j<i||l<0||j<0||i<0||i<=c.pluginSize||c.pluginSize<1){return 0}if(l>=i){return -1}try{if(l==c.pluginSize&&(!c.isIE||c.getDOMobj(m).readyState==4)){if(!m.winLoaded&&c.winLoaded){return 1}if(m.winLoaded&&c.isNum(b)){if(!c.isNum(m.count)){m.count=b}if(b-m.count>=10){return 1}}}}catch(f){}return 0},getDOMobj:function(g,a){var f,d=this,c=g?g.span:0,b=c&&c.firstChild?1:0;try{if(b&&a){d.div.focus()}}catch(f){}return b?c.firstChild:null},setStyle:function(b,g){var f=b.style,a,d,c=this;if(f&&g){for(a=0;a<g.length;a=a+2){try{f[g[a]]=g[a+1]}catch(d){}}}},insertDivInBody:function(i,g){var f,c=this,h="pd33993399",b=null,d=g?window.top.document:window.document,a=d.getElementsByTagName("body")[0]||d.body;if(!a){try{d.write('<div id="'+h+'">.'+c.openTag+"/div>");b=d.getElementById(h)}catch(f){}}a=d.getElementsByTagName("body")[0]||d.body;if(a){a.insertBefore(i,a.firstChild);if(b){a.removeChild(b)}}},insertHTML:function(f,b,g,a,k){var l,m=document,j=this,p,o=m.createElement("span"),n,i;var c=["outlineStyle","none","borderStyle","none","padding","0px","margin","0px","visibility","visible"];var h="outline-style:none;border-style:none;padding:0px;margin:0px;visibility:visible;";if(!j.isDefined(a)){a=""}if(j.isString(f)&&(/[^\s]/).test(f)){f=f.toLowerCase().replace(/\s/g,"");p=j.openTag+f+' width="'+j.pluginSize+'" height="'+j.pluginSize+'" ';p+='style="'+h+'display:inline;" ';for(n=0;n<b.length;n=n+2){if(/[^\s]/.test(b[n+1])){p+=b[n]+'="'+b[n+1]+'" '}}p+=">";for(n=0;n<g.length;n=n+2){if(/[^\s]/.test(g[n+1])){p+=j.openTag+'param name="'+g[n]+'" value="'+g[n+1]+'" />'}}p+=a+j.openTag+"/"+f+">"}else{p=a}if(!j.div){i=m.getElementById(j.divID);if(i){j.div=i}else{j.div=m.createElement("div");j.div.id=j.divID}j.setStyle(j.div,c.concat(["width",j.divWidth+"px","height",(j.pluginSize+3)+"px","fontSize",(j.pluginSize+3)+"px","lineHeight",(j.pluginSize+3)+"px","verticalAlign","baseline","display","block"]));if(!i){j.setStyle(j.div,["position","absolute","right","0px","top","0px"]);j.insertDivInBody(j.div)}}if(j.div&&j.div.parentNode){j.setStyle(o,c.concat(["fontSize",(j.pluginSize+3)+"px","lineHeight",(j.pluginSize+3)+"px","verticalAlign","baseline","display","inline"]));try{o.innerHTML=p}catch(l){};try{j.div.appendChild(o)}catch(l){};return{span:o,winLoaded:j.winLoaded,tagName:f,outerHTML:p}}return{span:null,winLoaded:j.winLoaded,tagName:"",outerHTML:p}},Plugins:{quicktime:{mimeType:["video/quicktime","application/x-quicktimeplayer","image/x-macpaint","image/x-quicktime"],progID:"QuickTimeCheckObject.QuickTimeCheck.1",progID0:"QuickTime.QuickTime",classID:"clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B",minIEver:7,HTML:'<param name="src" value="" /><param name="controller" value="false" />',getCodeBaseVersion:function(a){return'codebase="#version='+a+'"'},SEARCH:{min:0,max:0,match:0,digits:[16,128,128,0]},getVersion:function(c){var f=this,d=f.$,a=null,e=null,b;if(!d.isIE){if(d.hasMimeType(f.mimeType)){e=d.OS!=3?d.findNavPlugin("QuickTime.*Plug-?in",0):null;if(e&&e.name){a=d.getNum(e.name)}}}else{if(d.isStrNum(c)){b=c.split(d.splitNumRegx);if(b.length>3&&parseInt(b[3],10)>0){b[3]="9999"}c=b.join(",")}if(d.isStrNum(c)&&d.verIE>=f.minIEver&&f.canUseIsMin()>0){f.installed=f.isMin(c);f.getVersionDone=0;return}f.getVersionDone=1;if(!a&&d.verIE>=f.minIEver){a=f.CDBASE2VER(d.codebaseSearch(f))}if(!a){e=d.getAXO(f.progID);if(e&&e.QuickTimeVersion){a=e.QuickTimeVersion.toString(16);a=parseInt(a.charAt(0),16)+"."+parseInt(a.charAt(1),16)+"."+parseInt(a.charAt(2),16)}}}f.installed=a?1:(e?0:-1);f.version=d.formatNum(a,3)},cdbaseUpper:["7,60,0,0","0,0,0,0"],cdbaseLower:["7,50,0,0",null],cdbase2ver:[function(c,b){var a=b.split(c.$.splitNumRegx);return[a[0],a[1].charAt(0),a[1].charAt(1),a[2]].join(",")},null],CDBASE2VER:function(f){var e=this,c=e.$,b,a=e.cdbaseUpper,d=e.cdbaseLower;
29565if(f){f=c.formatNum(f);for(b=0;b<a.length;b++){if(a[b]&&c.compareNums(f,a[b])<0&&d[b]&&c.compareNums(f,d[b])>=0&&e.cdbase2ver[b]){return e.cdbase2ver[b](e,f)}}}return f},canUseIsMin:function(){var f=this,d=f.$,b,c=f.canUseIsMin,a=f.cdbaseUpper,e=f.cdbaseLower;if(!c.value){c.value=-1;for(b=0;b<a.length;b++){if(a[b]&&d.codebaseSearch(f,a[b])){c.value=1;break}if(e[b]&&d.codebaseSearch(f,e[b])){c.value=-1;break}}}f.SEARCH.match=c.value==1?1:0;return c.value},isMin:function(c){var b=this,a=b.$;return a.codebaseSearch(b,c)?0.7:-1}},flash:{mimeType:"application/x-shockwave-flash",progID:"ShockwaveFlash.ShockwaveFlash",classID:"clsid:D27CDB6E-AE6D-11CF-96B8-444553540000",getVersion:function(){var b=function(i){if(!i){return null}var e=/[\d][\d\,\.\s]*[rRdD]{0,1}[\d\,]*/.exec(i);return e?e[0].replace(/[rRdD\.]/g,",").replace(/\s/g,""):null};var j=this,g=j.$,k,h,l=null,c=null,a=null,f,m,d;if(!g.isIE){m=g.hasMimeType(j.mimeType);if(m){f=g.getDOMobj(g.insertHTML("object",["type",j.mimeType],[],"",j));try{l=g.getNum(f.GetVariable("$version"))}catch(k){}}if(!l){d=m?m.enabledPlugin:null;if(d&&d.description){l=b(d.description)}if(l){l=g.getPluginFileVersion(d,l)}}}else{for(h=15;h>2;h--){c=g.getAXO(j.progID+"."+h);if(c){a=h.toString();break}}if(!c){c=g.getAXO(j.progID)}if(a=="6"){try{c.AllowScriptAccess="always"}catch(k){return"6,0,21,0"}}try{l=b(c.GetVariable("$version"))}catch(k){}if(!l&&a){l=a}}j.installed=l?1:-1;j.version=g.formatNum(l);return true}},shockwave:{mimeType:"application/x-director",progID:"SWCtl.SWCtl",classID:"clsid:166B1BCA-3F9C-11CF-8075-444553540000",getVersion:function(){var a=null,b=null,g,f,d=this,c=d.$;if(!c.isIE){f=c.findNavPlugin("Shockwave\\s*for\\s*Director");if(f&&f.description&&c.hasMimeType(d.mimeType)){a=c.getNum(f.description)}if(a){a=c.getPluginFileVersion(f,a)}}else{try{b=c.getAXO(d.progID).ShockwaveVersion("")}catch(g){}if(c.isString(b)&&b.length>0){a=c.getNum(b)}else{if(c.getAXO(d.progID+".8")){a="8"}else{if(c.getAXO(d.progID+".7")){a="7"}else{if(c.getAXO(d.progID+".1")){a="6"}}}}}d.installed=a?1:-1;d.version=c.formatNum(a)}},zz:0}};PluginDetect.initScript();
29566
29567	var gArgCountErr='The "%%" function requires an even number of arguments.\nArguments should be in the form "atttributeName", "attributeValue", ...',gTagAttrs=null,gQTGeneratorVersion=1;function AC_QuickTimeVersion(){return gQTGeneratorVersion}function _QTComplain(a,b){b=b.replace("%%",a);alert(b)}function _QTAddAttribute(a,b,c){var d;d=gTagAttrs[a+b];null==d&&(d=gTagAttrs[b]);return null!=d?(0==b.indexOf(a)&&null==c&&(c=b.substring(a.length)),null==c&&(c=b),c+'="'+d+'" '):""}function _QTAddObjectAttr(a,b){if(0==a.indexOf("emb#"))return"";0==a.indexOf("obj#")&&null==b&&(b=a.substring(4));return _QTAddAttribute("obj#",a,b)}function _QTAddEmbedAttr(a,b){if(0==a.indexOf("obj#"))return"";0==a.indexOf("emb#")&&null==b&&(b=a.substring(4));return _QTAddAttribute("emb#",a,b)}function _QTAddObjectParam(a,b){var c,d="",e=b?" />":">";-1==a.indexOf("emb#")&&(c=gTagAttrs["obj#"+a],null==c&&(c=gTagAttrs[a]),0==a.indexOf("obj#")&&(a=a.substring(4)),null!=c&&(d='  <param name="'+a+'" value="'+c+'"'+e+"\n"));return d}function _QTDeleteTagAttrs(){for(var a=0;a<arguments.length;a++){var b=arguments[a];delete gTagAttrs[b];delete gTagAttrs["emb#"+b];delete gTagAttrs["obj#"+b]}}function _QTGenerate(a,b,c){if(4>c.length||0!=c.length%2)return _QTComplain(a,gArgCountErr),"";gTagAttrs=[];gTagAttrs.src=c[0];gTagAttrs.width=c[1];gTagAttrs.height=c[2];gTagAttrs.classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B";gTagAttrs.pluginspage="http://www.apple.com/quicktime/download/";a=c[3];if(null==a||""==a)a="6,0,2,0";gTagAttrs.codebase="http://www.apple.com/qtactivex/qtplugin.cab#version="+a;for(var d,e=4;e<c.length;e+=2)d=c[e].toLowerCase(),a=c[e+1],"name"==d||"id"==d?gTagAttrs.name=a:gTagAttrs[d]=a;c="<object "+_QTAddObjectAttr("classid")+_QTAddObjectAttr("width")+_QTAddObjectAttr("height")+_QTAddObjectAttr("codebase")+_QTAddObjectAttr("name","id")+_QTAddObjectAttr("tabindex")+_QTAddObjectAttr("hspace")+_QTAddObjectAttr("vspace")+_QTAddObjectAttr("border")+_QTAddObjectAttr("align")+_QTAddObjectAttr("class")+_QTAddObjectAttr("title")+_QTAddObjectAttr("accesskey")+_QTAddObjectAttr("noexternaldata")+">\n"+_QTAddObjectParam("src",b);e="  <embed "+_QTAddEmbedAttr("src")+_QTAddEmbedAttr("width")+_QTAddEmbedAttr("height")+_QTAddEmbedAttr("pluginspage")+_QTAddEmbedAttr("name")+_QTAddEmbedAttr("align")+_QTAddEmbedAttr("tabindex");_QTDeleteTagAttrs("src","width","height","pluginspage","classid","codebase","name","tabindex","hspace","vspace","border","align","noexternaldata","class","title","accesskey");for(d in gTagAttrs)a=gTagAttrs[d],null!=a&&(e+=_QTAddEmbedAttr(d),c+=_QTAddObjectParam(d,b));return c+e+"> </embed>\n</object>"}function QT_GenerateOBJECTText(){return _QTGenerate("QT_GenerateOBJECTText",!1,arguments)};
29568
29569
29570	/*
29571		jQuery hashchange event v1.3
29572		https://github.com/cowboy/jquery-hashchange
29573		Copyright (c) 2010 "Cowboy" Ben Alman
29574		Dual licensed under the MIT and GPL licenses.
29575	*/
29576	(function(){function e(a){a=a||location.href;return"#"+a.replace(/^[^#]*#?(.*)$/,"$1")}var k=document,b,f=$.event.special,p=k.documentMode,m="oniLightBoxHashChange"in window&&(void 0===p||7<p);$.fn.iLightBoxHashChange=function(a){return a?this.bind("iLightBoxHashChange",a):this.trigger("iLightBoxHashChange")};$.fn.iLightBoxHashChange.delay=50;f.iLightBoxHashChange=$.extend(f.iLightBoxHashChange,{setup:function(){if(m)return!1;$(b.start)},teardown:function(){if(m)return!1;$(b.stop)}});b=function(){function a(){var c=
29577	e(),d=f(l);c!==l?(n(l=c,d),$(window).trigger("iLightBoxHashChange")):d!==l&&(location.href=location.href.replace(/#.*/,"")+d);g=setTimeout(a,$.fn.iLightBoxHashChange.delay)}var h={},g,l=e(),b=function(c){return c},n=b,f=b;h.start=function(){g||a()};h.stop=function(){g&&clearTimeout(g);g=void 0};browser.msie&&!m&&function(){var c,d;h.start=function(){c||(d=(d=$.fn.iLightBoxHashChange.src)&&d+e(),c=$('<iframe tabindex="-1" title="empty"/>').hide().one("load",function(){d||n(e());a()}).attr("src",d||
29578	"javascript:0").insertAfter("body")[0].contentWindow,k.onpropertychange=function(){try{"title"===event.propertyName&&(c.document.title=k.title)}catch(a){}})};h.stop=b;f=function(){return e(c.location.href)};n=function(a,d){var b=c.document,e=$.fn.iLightBoxHashChange.domain;
29578a!==d&&(b.title=k.title,b.open(),e&&b.write('<script>document.domain="'+e+'"\x3c/script>'),b.close(),c.location.hash=a)}}();return h}()})();
29579
29580	if (!Array.prototype.filter) {
29581		Array.prototype.filter = function(fun /*, thisp */ ) {
29582			"use strict";
29583
29584			if (this == null)
29585				throw new TypeError();
29586
29587			var t = Object(this);
29588			var len = t.length >>> 0;
29589			if (typeof fun != "function")
29590				throw new TypeError();
29591
29592			var res = [];
29593			var thisp = arguments[1];
29594			for (var i = 0; i < len; i++) {
29595				if (i in t) {
29596					var val = t[i]; // in case fun mutates this
29597					if (fun.call(thisp, val, i, t))
29598						res.push(val);
29599				}
29600			}
29601
29602			return res;
29603		};
29604	}
29605
29606	if (!Array.prototype.indexOf) {
29607		Array.prototype.indexOf = function(searchElement, fromIndex) {
29608			var k;
29609
29610			if (this == null) {
29611				throw new TypeError('"this" is null or not defined');
29612			}
29613
29614			var O = Object(this);
29615
29616			var len = O.length >>> 0;
29617
29618			if (len === 0) {
29619				return -1;
29620			}
29621
29622			var n = +fromIndex || 0;
29623
29624			if (abs(n) === Infinity) {
29625				n = 0;
29626			}
29627
29628			if (n >= len) {
29629				return -1;
29630			}
29631
29632			k = max(n >= 0 ? n : len - abs(n), 0);
29633
29634			while (k < len) {
29635				var kValue;
29636				if (k in O && O[k] === searchElement) {
29637					return k;
29638				}
29639				k++;
29640			}
29641			return -1;
29642		};
29643	}
29644
29645	if (!Array.prototype.lastIndexOf) {
29646		Array.prototype.lastIndexOf = function(searchElement /*, fromIndex*/ ) {
29647			"use strict";
29648
29649			if (this == null)
29650				throw new TypeError();
29651
29652			var t = Object(this);
29653			var len = t.length >>> 0;
29654			if (len === 0)
29655				return -1;
29656
29657			var n = len;
29658			if (arguments.length > 1) {
29659				n = Number(arguments[1]);
29660				if (n != n)
29661					n = 0;
29662				else if (n != 0 && n != (1 / 0) && n != -(1 / 0))
29663					n = (n > 0 || -1) * floor(abs(n));
29664			}
29665
29666			var k = n >= 0 ? min(n, len - 1) : len - abs(n);
29667
29668			for (; k >= 0; k--) {
29669				if (k in t && t[k] === searchElement)
29670					return k;
29671			}
29672			return -1;
29673		};
29674	}
29675})(jQuery, this);
29676
29677/*!
29678 * lightgallery | 2.5.0 | June 13th 2022
29679 * http://www.lightgalleryjs.com/
29680 * Copyright (c) 2020 Sachin Neravath;
29681 * @license GPLv3
29682 */
29683
29684(function (global, factory) {
29685	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
29686	typeof define === 'function' && define.amd ? define(factory) :
29687	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lightGallery = factory());
29688}(this, (function () { 'use strict';
29689
29690	/*! *****************************************************************************
29691	Copyright (c) Microsoft Corporation.
29692
29693	Permission to use, copy, modify, and/or distribute this software for any
29694	purpose with or without fee is hereby granted.
29695
29696	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
29697	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
29698	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
29699	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
29700	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
29701	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
29702	PERFORMANCE OF THIS SOFTWARE.
29703	***************************************************************************** */
29704
29705	var __assign = function() {
29706		__assign = Object.assign || function __assign(t) {
29707			for (var s, i = 1, n = arguments.length; i < n; i++) {
29708				s = arguments[i];
29709				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
29710			}
29711			return t;
29712		};
29713		return __assign.apply(this, arguments);
29714	};
29715
29716	function __spreadArrays() {
29717		for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
29718		for (var r = Array(s), k = 0, i = 0; i < il; i++)
29719			for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
29720				r[k] = a[j];
29721		return r;
29722	}
29723
29724	/**
29725	 * List of lightGallery events
29726	 * All events should be documented here
29727	 * Below interfaces are used to build the website documentations
29728	 * */
29729	var lGEvents = {
29730		afterAppendSlide: 'lgAfterAppendSlide',
29731		init: 'lgInit',
29732		hasVideo: 'lgHasVideo',
29733		containerResize: 'lgContainerResize',
29734		updateSlides: 'lgUpdateSlides',
29735		afterAppendSubHtml: 'lgAfterAppendSubHtml',
29736		beforeOpen: 'lgBeforeOpen',
29737		afterOpen: 'lgAfterOpen',
29738		slideItemLoad: 'lgSlideItemLoad',
29739		beforeSlide: 'lgBeforeSlide',
29740		afterSlide: 'lgAfterSlide',
29741		posterClick: 'lgPosterClick',
29742		dragStart: 'lgDragStart',
29743		dragMove: 'lgDragMove',
29744		dragEnd: 'lgDragEnd',
29745		beforeNextSlide: 'lgBeforeNextSlide',
29746		beforePrevSlide: 'lgBeforePrevSlide',
29747		beforeClose: 'lgBeforeClose',
29748		afterClose: 'lgAfterClose',
29749		rotateLeft: 'lgRotateLeft',
29750		rotateRight: 'lgRotateRight',
29751		flipHorizontal: 'lgFlipHorizontal',
29752		flipVertical: 'lgFlipVertical',
29753		autoplay: 'lgAutoplay',
29754		autoplayStart: 'lgAutoplayStart',
29755		autoplayStop: 'lgAutoplayStop',
29756	};
29757
29758	var lightGalleryCoreSettings = {
29759		mode: 'lg-slide',
29760		easing: 'ease',
29761		speed: 400,
29762		licenseKey: '0000-0000-000-0000',
29763		height: '100%',
29764		width: '100%',
29765		addClass: '',
29766		startClass: 'lg-start-zoom',
29767		backdropDuration: 300,
29768		container: '',
29769		startAnimationDuration: 400,
29770		zoomFromOrigin: true,
29771		hideBarsDelay: 0,
29772		showBarsAfter: 10000,
29773		slideDelay: 0,
29774		supportLegacyBrowser: true,
29775		allowMediaOverlap: false,
29776		videoMaxSize: '1280-720',
29777		loadYouTubePoster: true,
29778		defaultCaptionHeight: 0,
29779		ariaLabelledby: '',
29780		ariaDescribedby: '',
29781		resetScrollPosition: true,
29782		hideScrollbar: false,
29783		closable: true,
29784		swipeToClose: true,
29785		closeOnTap: true,
29786		showCloseIcon: true,
29787		showMaximizeIcon: false,
29788		loop: true,
29789		escKey: true,
29790		keyPress: true,
29791		trapFocus: true,
29792		controls: true,
29793		slideEndAnimation: true,
29794		hideControlOnEnd: false,
vendor: 15,066 bytes, lines 29795-30342
29795		mousewheel: false,
29796		getCaptionFromTitleOrAlt: true,
29797		appendSubHtmlTo: '.lg-sub-html',
29798		subHtmlSelectorRelative: false,
29799		preload: 2,
29800		numberOfSlideItemsInDom: 10,
29801		selector: '',
29802		selectWithin: '',
29803		nextHtml: '',
29804		prevHtml: '',
29805		index: 0,
29806		iframeWidth: '100%',
29807		iframeHeight: '100%',
29808		iframeMaxWidth: '100%',
29809		iframeMaxHeight: '100%',
29810		download: true,
29811		counter: true,
29812		appendCounterTo: '.lg-toolbar',
29813		swipeThreshold: 50,
29814		enableSwipe: true,
29815		enableDrag: true,
29816		dynamic: false,
29817		dynamicEl: [],
29818		extraProps: [],
29819		exThumbImage: '',
29820		isMobile: undefined,
29821		mobileSettings: {
29822			controls: false,
29823			showCloseIcon: false,
29824			download: false,
29825		},
29826		plugins: [],
29827		strings: {
29828			closeGallery: 'Close gallery',
29829			toggleMaximize: 'Toggle maximize',
29830			previousSlide: 'Previous slide',
29831			nextSlide: 'Next slide',
29832			download: 'Download',
29833			playVideo: 'Play video',
29834		},
29835	};
29836
29837	function initLgPolyfills() {
29838		(function () {
29839			if (typeof window.CustomEvent === 'function')
29840				return false;
29841			function CustomEvent(event, params) {
29842				params = params || {
29843					bubbles: false,
29844					cancelable: false,
29845					detail: null,
29846				};
29847				var evt = document.createEvent('CustomEvent');
29848				evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
29849				return evt;
29850			}
29851			window.CustomEvent = CustomEvent;
29852		})();
29853		(function () {
29854			if (!Element.prototype.matches) {
29855				Element.prototype.matches =
29856					Element.prototype.msMatchesSelector ||
29857						Element.prototype.webkitMatchesSelector;
29858			}
29859		})();
29860	}
29861	var lgQuery = /** @class */ (function () {
29862		function lgQuery(selector) {
29863			this.cssVenderPrefixes = [
29864				'TransitionDuration',
29865				'TransitionTimingFunction',
29866				'Transform',
29867				'Transition',
29868			];
29869			this.selector = this._getSelector(selector);
29870			this.firstElement = this._getFirstEl();
29871			return this;
29872		}
29873		lgQuery.generateUUID = function () {
29874			return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
29875				var r = (Math.random() * 16) | 0, v = c == 'x' ? r : (r & 0x3) | 0x8;
29876				return v.toString(16);
29877			});
29878		};
29879		lgQuery.prototype._getSelector = function (selector, context) {
29880			if (context === void 0) { context = document; }
29881			if (typeof selector !== 'string') {
29882				return selector;
29883			}
29884			context = context || document;
29885			var fl = selector.substring(0, 1);
29886			if (fl === '#') {
29887				return context.querySelector(selector);
29888			}
29889			else {
29890				return context.querySelectorAll(selector);
29891			}
29892		};
29893		lgQuery.prototype._each = function (func) {
29894			if (!this.selector) {
29895				return this;
29896			}
29897			if (this.selector.length !== undefined) {
29898				[].forEach.call(this.selector, func);
29899			}
29900			else {
29901				func(this.selector, 0);
29902			}
29903			return this;
29904		};
29905		lgQuery.prototype._setCssVendorPrefix = function (el, cssProperty, value) {
29906			// prettier-ignore
29907			var property = cssProperty.replace(/-([a-z])/gi, function (s, group1) {
29908				return group1.toUpperCase();
29909			});
29910			if (this.cssVenderPrefixes.indexOf(property) !== -1) {
29911				el.style[property.charAt(0).toLowerCase() + property.slice(1)] = value;
29912				el.style['webkit' + property] = value;
29913				el.style['moz' + property] = value;
29914				el.style['ms' + property] = value;
29915				el.style['o' + property] = value;
29916			}
29917			else {
29918				el.style[property] = value;
29919			}
29920		};
29921		lgQuery.prototype._getFirstEl = function () {
29922			if (this.selector && this.selector.length !== undefined) {
29923				return this.selector[0];
29924			}
29925			else {
29926				return this.selector;
29927			}
29928		};
29929		lgQuery.prototype.isEventMatched = function (event, eventName) {
29930			var eventNamespace = eventName.split('.');
29931			return event
29932				.split('.')
29933				.filter(function (e) { return e; })
29934				.every(function (e) {
29935				return eventNamespace.indexOf(e) !== -1;
29936			});
29937		};
29938		lgQuery.prototype.attr = function (attr, value) {
29939			if (value === undefined) {
29940				if (!this.firstElement) {
29941					return '';
29942				}
29943				return this.firstElement.getAttribute(attr);
29944			}
29945			this._each(function (el) {
29946				el.setAttribute(attr, value);
29947			});
29948			return this;
29949		};
29950		lgQuery.prototype.find = function (selector) {
29951			return $LG(this._getSelector(selector, this.selector));
29952		};
29953		lgQuery.prototype.first = function () {
29954			if (this.selector && this.selector.length !== undefined) {
29955				return $LG(this.selector[0]);
29956			}
29957			else {
29958				return $LG(this.selector);
29959			}
29960		};
29961		lgQuery.prototype.eq = function (index) {
29962			return $LG(this.selector[index]);
29963		};
29964		lgQuery.prototype.parent = function () {
29965			return $LG(this.selector.parentElement);
29966		};
29967		lgQuery.prototype.get = function () {
29968			return this._getFirstEl();
29969		};
29970		lgQuery.prototype.removeAttr = function (attributes) {
29971			var attrs = attributes.split(' ');
29972			this._each(function (el) {
29973				attrs.forEach(function (attr) { return el.removeAttribute(attr); });
29974			});
29975			return this;
29976		};
29977		lgQuery.prototype.wrap = function (className) {
29978			if (!this.firstElement) {
29979				return this;
29980			}
29981			var wrapper = document.createElement('div');
29982			wrapper.className = className;
29983			this.firstElement.parentNode.insertBefore(wrapper, this.firstElement);
29984			this.firstElement.parentNode.removeChild(this.firstElement);
29985			wrapper.appendChild(this.firstElement);
29986			return this;
29987		};
29988		lgQuery.prototype.addClass = function (classNames) {
29989			if (classNames === void 0) { classNames = ''; }
29990			this._each(function (el) {
29991				// IE doesn't support multiple arguments
29992				classNames.split(' ').forEach(function (className) {
29993					if (className) {
29994						el.classList.add(className);
29995					}
29996				});
29997			});
29998			return this;
29999		};
30000		lgQuery.prototype.removeClass = function (classNames) {
30001			this._each(function (el) {
30002				// IE doesn't support multiple arguments
30003				classNames.split(' ').forEach(function (className) {
30004					if (className) {
30005						el.classList.remove(className);
30006					}
30007				});
30008			});
30009			return this;
30010		};
30011		lgQuery.prototype.hasClass = function (className) {
30012			if (!this.firstElement) {
30013				return false;
30014			}
30015			return this.firstElement.classList.contains(className);
30016		};
30017		lgQuery.prototype.hasAttribute = function (attribute) {
30018			if (!this.firstElement) {
30019				return false;
30020			}
30021			return this.firstElement.hasAttribute(attribute);
30022		};
30023		lgQuery.prototype.toggleClass = function (className) {
30024			if (!this.firstElement) {
30025				return this;
30026			}
30027			if (this.hasClass(className)) {
30028				this.removeClass(className);
30029			}
30030			else {
30031				this.addClass(className);
30032			}
30033			return this;
30034		};
30035		lgQuery.prototype.css = function (property, value) {
30036			var _this = this;
30037			this._each(function (el) {
30038				_this._setCssVendorPrefix(el, property, value);
30039			});
30040			return this;
30041		};
30042		// Need to pass separate namespaces for separate elements
30043		lgQuery.prototype.on = function (events, listener) {
30044			var _this = this;
30045			if (!this.selector) {
30046				return this;
30047			}
30048			events.split(' ').forEach(function (event) {
30049				if (!Array.isArray(lgQuery.eventListeners[event])) {
30050					lgQuery.eventListeners[event] = [];
30051				}
30052				lgQuery.eventListeners[event].push(listener);
30053				_this.selector.addEventListener(event.split('.')[0], listener);
30054			});
30055			return this;
30056		};
30057		// @todo - test this
30058		lgQuery.prototype.once = function (event, listener) {
30059			var _this = this;
30060			this.on(event, function () {
30061				_this.off(event);
30062				listener(event);
30063			});
30064			return this;
30065		};
30066		lgQuery.prototype.off = function (event) {
30067			var _this = this;
30068			if (!this.selector) {
30069				return this;
30070			}
30071			Object.keys(lgQuery.eventListeners).forEach(function (eventName) {
30072				if (_this.isEventMatched(event, eventName)) {
30073					lgQuery.eventListeners[eventName].forEach(function (listener) {
30074						_this.selector.removeEventListener(eventName.split('.')[0], listener);
30075					});
30076					lgQuery.eventListeners[eventName] = [];
30077				}
30078			});
30079			return this;
30080		};
30081		lgQuery.prototype.trigger = function (event, detail) {
30082			if (!this.firstElement) {
30083				return this;
30084			}
30085			var customEvent = new CustomEvent(event.split('.')[0], {
30086				detail: detail || null,
30087			});
30088			this.firstElement.dispatchEvent(customEvent);
30089			return this;
30090		};
30091		// Does not support IE
30092		lgQuery.prototype.load = function (url) {
30093			var _this = this;
30094			fetch(url)
30095				.then(function (res) { return res.text(); })
30096				.then(function (html) {
30097				_this.selector.innerHTML = html;
30098			});
30099			return this;
30100		};
30101		lgQuery.prototype.html = function (html) {
30102			if (html === undefined) {
30103				if (!this.firstElement) {
30104					return '';
30105				}
30106				return this.firstElement.innerHTML;
30107			}
30108			this._each(function (el) {
30109				el.innerHTML = html;
30110			});
30111			return this;
30112		};
30113		lgQuery.prototype.append = function (html) {
30114			this._each(function (el) {
30115				if (typeof html === 'string') {
30116					el.insertAdjacentHTML('beforeend', html);
30117				}
30118				else {
30119					el.appendChild(html);
30120				}
30121			});
30122			return this;
30123		};
30124		lgQuery.prototype.prepend = function (html) {
30125			this._each(function (el) {
30126				el.insertAdjacentHTML('afterbegin', html);
30127			});
30128			return this;
30129		};
30130		lgQuery.prototype.remove = function () {
30131			this._each(function (el) {
30132				el.parentNode.removeChild(el);
30133			});
30134			return this;
30135		};
30136		lgQuery.prototype.empty = function () {
30137			this._each(function (el) {
30138				el.innerHTML = '';
30139			});
30140			return this;
30141		};
30142		lgQuery.prototype.scrollTop = function (scrollTop) {
30143			if (scrollTop !== undefined) {
30144				document.body.scrollTop = scrollTop;
30145				document.documentElement.scrollTop = scrollTop;
30146				return this;
30147			}
30148			else {
30149				return (window.pageYOffset ||
30150					document.documentElement.scrollTop ||
30151					document.body.scrollTop ||
30152					0);
30153			}
30154		};
30155		lgQuery.prototype.scrollLeft = function (scrollLeft) {
30156			if (scrollLeft !== undefined) {
30157				document.body.scrollLeft = scrollLeft;
30158				document.documentElement.scrollLeft = scrollLeft;
30159				return this;
30160			}
30161			else {
30162				return (window.pageXOffset ||
30163					document.documentElement.scrollLeft ||
30164					document.body.scrollLeft ||
30165					0);
30166			}
30167		};
30168		lgQuery.prototype.offset = function () {
30169			if (!this.firstElement) {
30170				return {
30171					left: 0,
30172					top: 0,
30173				};
30174			}
30175			var rect = this.firstElement.getBoundingClientRect();
30176			var bodyMarginLeft = $LG('body').style().marginLeft;
30177			// Minus body margin - https://stackoverflow.com/questions/30711548/is-getboundingclientrect-left-returning-a-wrong-value
30178			return {
30179				left: rect.left - parseFloat(bodyMarginLeft) + this.scrollLeft(),
30180				top: rect.top + this.scrollTop(),
30181			};
30182		};
30183		lgQuery.prototype.style = function () {
30184			if (!this.firstElement) {
30185				return {};
30186			}
30187			return (this.firstElement.currentStyle ||
30188				window.getComputedStyle(this.firstElement));
30189		};
30190		// Width without padding and border even if box-sizing is used.
30191		lgQuery.prototype.width = function () {
30192			var style = this.style();
30193			return (this.firstElement.clientWidth -
30194				parseFloat(style.paddingLeft) -
30195				parseFloat(style.paddingRight));
30196		};
30197		// Height without padding and border even if box-sizing is used.
30198		lgQuery.prototype.height = function () {
30199			var style = this.style();
30200			return (this.firstElement.clientHeight -
30201				parseFloat(style.paddingTop) -
30202				parseFloat(style.paddingBottom));
30203		};
30204		lgQuery.eventListeners = {};
30205		return lgQuery;
30206	}());
30207	function $LG(selector) {
30208		initLgPolyfills();
30209		return new lgQuery(selector);
30210	}
30211
30212	var defaultDynamicOptions = [
30213		'src',
30214		'sources',
30215		'subHtml',
30216		'subHtmlUrl',
30217		'html',
30218		'video',
30219		'poster',
30220		'slideName',
30221		'responsive',
30222		'srcset',
30223		'sizes',
30224		'iframe',
30225		'downloadUrl',
30226		'download',
30227		'width',
30228		'facebookShareUrl',
30229		'tweetText',
30230		'iframeTitle',
30231		'twitterShareUrl',
30232		'pinterestShareUrl',
30233		'pinterestText',
30234		'fbHtml',
30235		'disqusIdentifier',
30236		'disqusUrl',
30237	];
30238	// Convert html data-attribute to camalcase
30239	function convertToData(attr) {
30240		// FInd a way for lgsize
30241		if (attr === 'href') {
30242			return 'src';
30243		}
30244		attr = attr.replace('data-', '');
30245		attr = attr.charAt(0).toLowerCase() + attr.slice(1);
30246		attr = attr.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); });
30247		return attr;
30248	}
30249	var utils = {
30250		/**
30251		 * get possible width and height from the lgSize attribute. Used for ZoomFromOrigin option
30252		 */
30253		//Uncode edit ##START##
30254		getSize: function (el, container, spacing, defaultLgSize, galleryItem) {
30255		// getSize: function (el, container, spacing, defaultLgSize) {
30256		//Uncode edit ##END##
30257			if (spacing === void 0) { spacing = 0; }
30258			var LGel = $LG(el);
30259			var lgSize = LGel.attr('data-lg-size') || defaultLgSize;
30260			//Uncode edit ##START##
30261			if ( typeof galleryItem.size && galleryItem.size != null ) {
30262				lgSize = galleryItem.size;
30263			}
30264			//Uncode edit ##END##
30265			if (!lgSize) {
30266				return;
30267			}
30268			var isResponsiveSizes = lgSize.split(',');
30269			// if at-least two viewport sizes are available
30270			if (isResponsiveSizes[1]) {
30271				var wWidth = window.innerWidth;
30272				for (var i = 0; i < isResponsiveSizes.length; i++) {
30273					var size_1 = isResponsiveSizes[i];
30274					var responsiveWidth = parseInt(size_1.split('-')[2], 10);
30275					if (responsiveWidth > wWidth) {
30276						lgSize = size_1;
30277						break;
30278					}
30279					// take last item as last option
30280					if (i === isResponsiveSizes.length - 1) {
30281						lgSize = size_1;
30282					}
30283				}
30284			}
30285			var size = lgSize.split('-');
30286			var width = parseInt(size[0], 10);
30287			var height = parseInt(size[1], 10);
30288			var cWidth = container.width();
30289			var cHeight = container.height() - spacing;
30290			var maxWidth = Math.min(cWidth, width);
30291			var maxHeight = Math.min(cHeight, height);
30292			var ratio = Math.min(maxWidth / width, maxHeight / height);
30293			return { width: width * ratio, height: height * ratio };
30294		},
30295		/**
30296		 * @desc Get transform value based on the imageSize. Used for ZoomFromOrigin option
30297		 * @param {jQuery Element}
30298		 * @returns {String} Transform CSS string
30299		 */
30300		getTransform: function (el, container, top, bottom, imageSize) {
30301			if (!imageSize) {
30302				return;
30303			}
30304			var LGel = $LG(el).find('img').first();
30305			if (!LGel.get()) {
30306				return;
30307			}
30308			var containerRect = container.get().getBoundingClientRect();
30309			var wWidth = containerRect.width;
30310			// using innerWidth to include mobile safari bottom bar
30311			var wHeight = container.height() - (top + bottom);
30312			var elWidth = LGel.width();
30313			var elHeight = LGel.height();
30314			var elStyle = LGel.style();
30315			var x = (wWidth - elWidth) / 2 -
30316				LGel.offset().left +
30317				(parseFloat(elStyle.paddingLeft) || 0) +
30318				(parseFloat(elStyle.borderLeft) || 0) +
30319				$LG(window).scrollLeft() +
30320				containerRect.left;
30321			var y = (wHeight - elHeight) / 2 -
30322				LGel.offset().top +
30323				(parseFloat(elStyle.paddingTop) || 0) +
30324				(parseFloat(elStyle.borderTop) || 0) +
30325				$LG(window).scrollTop() +
30326				top;
30327			var scX = elWidth / imageSize.width;
30328			var scY = elHeight / imageSize.height;
30329			var transform = 'translate3d(' +
30330				(x *= -1) +
30331				'px, ' +
30332				(y *= -1) +
30333				'px, 0) scale3d(' +
30334				scX +
30335				', ' +
30336				scY +
30337				', 1)';
30338			return transform;
30339		},
30340		getIframeMarkup: function (iframeWidth, iframeHeight, iframeMaxWidth, iframeMaxHeight, src, iframeTitle) {
30341			var title = iframeTitle ? 'title="' + iframeTitle + '"' : '';
30342			return "<div class=\"lg-video-cont lg-has-iframe\" style=\"width:" 
vendor: 2,803 bytes, lines 30342-30414
30342+ iframeWidth + "; max-width:" + iframeMaxWidth + "; height: " + iframeHeight + "; max-height:" + iframeMaxHeight + "\">\n                    <iframe class=\"lg-object\" frameborder=\"0\" " + title + " src=\"" + src + "\"  allowfullscreen=\"true\"></iframe>\n                </div>";
30343		},
30344		getImgMarkup: function (index, src, altAttr, srcset, sizes, sources) {
30345			var srcsetAttr = srcset ? "srcset=\"" + srcset + "\"" : '';
30346			var sizesAttr = sizes ? "sizes=\"" + sizes + "\"" : '';
30347			var imgMarkup = "<img " + altAttr + " " + srcsetAttr + "  " + sizesAttr + " class=\"lg-object lg-image\" data-index=\"" + index + "\" src=\"" + src + "\" />";
30348			var sourceTag = '';
30349			if (sources) {
30350				var sourceObj = typeof sources === 'string' ? JSON.parse(sources) : sources;
30351				sourceTag = sourceObj.map(function (source) {
30352					var attrs = '';
30353					Object.keys(source).forEach(function (key) {
30354						// Do not remove the first space as it is required to separate the attributes
30355						attrs += " " + key + "=\"" + source[key] + "\"";
30356					});
30357					return "<source " + attrs + "></source>";
30358				});
30359			}
30360			return "" + sourceTag + imgMarkup;
30361		},
30362		// Get src from responsive src
30363		getResponsiveSrc: function (srcItms) {
30364			var rsWidth = [];
30365			var rsSrc = [];
30366			var src = '';
30367			for (var i = 0; i < srcItms.length; i++) {
30368				var _src = srcItms[i].split(' ');
30369				// Manage empty space
30370				if (_src[0] === '') {
30371					_src.splice(0, 1);
30372				}
30373				rsSrc.push(_src[0]);
30374				rsWidth.push(_src[1]);
30375			}
30376			var wWidth = window.innerWidth;
30377			for (var j = 0; j < rsWidth.length; j++) {
30378				if (parseInt(rsWidth[j], 10) > wWidth) {
30379					src = rsSrc[j];
30380					break;
30381				}
30382			}
30383			return src;
30384		},
30385		isImageLoaded: function (img) {
30386			if (!img)
30387				return false;
30388			// During the onload event, IE correctly identifies any images that
30389			// weren’t downloaded as not complete. Others should too. Gecko-based
30390			// browsers act like NS4 in that they report this incorrectly.
30391			if (!img.complete) {
30392				return false;
30393			}
30394			// However, they do have two very useful properties: naturalWidth and
30395			// naturalHeight. These give the true size of the image. If it failed
30396			// to load, either of these should be zero.
30397			if (img.naturalWidth === 0) {
30398				return false;
30399			}
30400			// No other way of checking: assume it’s ok.
30401			return true;
30402		},
30403		getVideoPosterMarkup: function (_poster, dummyImg, videoContStyle, playVideoString, _isVideo) {
30404			var videoClass = '';
30405			if (_isVideo && _isVideo.youtube) {
30406				videoClass = 'lg-has-youtube';
30407			}
30408			else if (_isVideo && _isVideo.vimeo) {
30409				videoClass = 'lg-has-vimeo';
30410			}
30411			else {
30412				videoClass = 'lg-has-html5';
30413			}
30414			return "<div class=\"lg-video-cont " + videoClass + "\" style=\"" + videoContStyle + "\">\n                <div class=\"lg-video-play-button\">
30414\n                <svg\n                    viewBox=\"0 0 20 20\"\n                    preserveAspectRatio=\"xMidYMid\"\n                    focusable=\"false\"\n                    aria-labelledby=\"" + playVideoString + "\"\n                    role=\"img\"\n                    class=\"lg-video-play-icon\"\n                >\n                    <title>" + playVideoString + "</title>\n                    <polygon class=\"lg-video-play-icon-inner\" points=\"1,0 20,10 1,20\"></polygon>\n                </svg>\n                <svg class=\"lg-video-play-icon-bg\" viewBox=\"0 0 50 50\" focusable=\"false\">\n                    <circle cx=\"50%\" cy=\"50%\" r=\"20\"></circle></svg>\n                <svg class=\"lg-video-play-icon-circle\" viewBox=\"0 0 50 50\" focusable=\"false\">\n                    <circle cx=\"50%\" cy=\"50%\" r=\"20\"></circle>\n                </svg>\n            </div>\n            " + (dummyImg || '') + "\n            <img class=\"lg-object lg-video-poster\" src=\"" + _poster + "\" />\n        </div>";
30415		},
30416		getFocusableElements: function (container) {
30417			var elements = container.querySelectorAll('a[href]:not([disabled]), button:not([disabled]), textarea:not([disabled]), input[type="text"]:not([disabled]), input[type="radio"]:not([disabled]), input[type="checkbox"]:not([disabled]), select:not([disabled])');
30418			var visibleElements = [].filter.call(elements, function (element) {
30419				var style = window.getComputedStyle(element);
30420				return style.display !== 'none' && style.visibility !== 'hidden';
30421			});
30422			return visibleElements;
30423		},
30424		/**
30425		 * @desc Create dynamic elements array from gallery items when dynamic option is false
30426		 * It helps to avoid frequent DOM interaction
30427		 * and avoid multiple checks for dynamic elments
30428		 *
30429		 * @returns {Array} dynamicEl
30430		 */
30431		getDynamicOptions: function (items, extraProps, getCaptionFromTitleOrAlt, exThumbImage) {
30432			var dynamicElements = [];
30433			var availableDynamicOptions = __spreadArrays(defaultDynamicOptions, extraProps);
30434			[].forEach.call(items, function (item) {
30435				var dynamicEl = {};
30436				for (var i = 0; i < item.attributes.length; i++) {
30437					var attr = item.attributes[i];
30438					if (attr.specified) {
30439						var dynamicAttr = convertToData(attr.name);
30440						var label = '';
30441						if (availableDynamicOptions.indexOf(dynamicAttr) > -1) {
30442							label = dynamicAttr;
30443						}
30444						if (label) {
30445							dynamicEl[label] = attr.value;
30446						}
30447					}
30448				}
30449				var currentItem = $LG(item);
30450				var alt = currentItem.find('img').first().attr('alt') || currentItem.attr('data-alt');
30451				var title = currentItem.attr('title');
30452				//Uncode edit ##START##
30453				// var thumb = exThumbImage
30454				var thumb = exThumbImage && currentItem.attr(exThumbImage)
30455				//Uncode edit ##END##
30456					? currentItem.attr(exThumbImage)
30457					: currentItem.find('img').first().attr('src');
30458				dynamicEl.thumb = thumb;
30459				//Uncode edit ##START##
30460				if (getCaptionFromTitleOrAlt && !dynamicEl.subHtml) {
30461					// dynamicEl.subHtml = title || alt || '';
30462					dynamicEl.subHtml = title || '';
30463				}
30464				// dynamicEl.alt = alt || title || '';
30465				dynamicEl.alt = alt || title;
30466				var inlineType = currentItem.attr('data-type');
30467				dynamicEl.type = inlineType;
30468				//Uncode edit ##END##
30469				dynamicElements.push(dynamicEl);
30470			});
30471			return dynamicElements;
30472		},
30473		isMobile: function () {
30474			return /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
30475		},
30476		/**
30477		 * @desc Check the given src is video
30478		 * @param {String} src
30479		 * @return {Object} video type
30480		 * Ex:{ youtube  :  ["//www.youtube.com/watch?v=c0asJgSyxcY", "c0asJgSyxcY"] }
30481		 *
30482		 * @todo - this information can be moved to dynamicEl to avoid frequent calls
30483		 */
30484		isVideo: function (src, isHTML5VIdeo, index) {
30485			if (!src || src.match(/\.(mp4|m4v|ogg|webm)$/) ) {
30486				if (isHTML5VIdeo) {
30487					return {
30488						html5: true,
30489					};
30490				}
30491				else {
30492					console.warn('lightGallery :- data-src is not provided on slide item ' +
30493						(index + 1) +
30494						'. Please make sure the selector property is properly configured. More info - https://www.lightgalleryjs.com/demos/html-markup/');
30495					return;
30496				}
30497			}
30498			var youtube = src.match(/\/\/(?:www\.)?youtu(?:\.be|be\.com|be-nocookie\.com)\/(?:watch\?v=|embed\/)?([a-z0-9\-\_\%]+)([\&|?][\S]*)*/i);
30499			var vimeo = src.match(/\/\/(?:www\.)?(?:player\.)?vimeo.com\/(?:video\/)?([0-9a-z\-_]+)(.*)?/i);
30500			var wistia = src.match(/https?:\/\/(.+)?(wistia\.com|wi\.st)\/(medias|embed)\/([0-9a-z\-_]+)(.*)/);
30501			if (youtube) {
30502				return {
30503					youtube: youtube,
30504				};
30505			}
30506			else if (vimeo) {
30507				return {
30508					vimeo: vimeo,
30509				};
30510			}
30511			else if (wistia) {
30512				return {
30513					wistia: wistia,
30514				};
30515			}
30516		},
30517	};
30518
30519	// @ref - https://stackoverflow.com/questions/3971841/how-to-resize-images-proportionally-keeping-the-aspect-ratio
30520	// @ref - https://2ality.com/2017/04/setting-up-multi-platform-packages.html
30521	// Unique id for each gallery
30522	var lgId = 0;
30523	var LightGallery = /** @class */ (function () {
30524		function LightGallery(element, options) {
30525			this.lgOpened = false;
vendor: 4,563 bytes, lines 30526-30660
30526			this.index = 0;
30527			// lightGallery modules
30528			this.plugins = [];
30529			// false when lightGallery load first slide content;
30530			this.lGalleryOn = false;
30531			// True when a slide animation is in progress
30532			this.lgBusy = false;
30533			this.currentItemsInDom = [];
30534			// Scroll top value before lightGallery is opened
30535			this.prevScrollTop = 0;
30536			this.bodyPaddingRight = 0;
30537			this.isDummyImageRemoved = false;
30538			this.dragOrSwipeEnabled = false;
30539			this.mediaContainerPosition = {
30540				top: 0,
30541				bottom: 0,
30542			};
30543			if (!element) {
30544				return this;
30545			}
30546			lgId++;
30547			this.lgId = lgId;
30548			this.el = element;
30549			this.LGel = $LG(element);
30550			this.generateSettings(options);
30551			this.buildModules();
30552			// When using dynamic mode, ensure dynamicEl is an array
30553			if (this.settings.dynamic &&
30554				this.settings.dynamicEl !== undefined &&
30555				!Array.isArray(this.settings.dynamicEl)) {
30556				throw 'When using dynamic mode, you must also define dynamicEl as an Array.';
30557			}
30558			this.galleryItems = this.getItems();
30559			this.normalizeSettings();
30560			// Gallery items
30561			this.init();
30562			//Uncode edit ##START##
30563			// this.validateLicense();
30564			//Uncode edit ##END##
30565			return this;
30566		}
30567		LightGallery.prototype.generateSettings = function (options) {
30568			// lightGallery settings
30569			this.settings = __assign(__assign({}, lightGalleryCoreSettings), options);
30570			if (this.settings.isMobile &&
30571				typeof this.settings.isMobile === 'function'
30572				? this.settings.isMobile()
30573				: utils.isMobile()) {
30574				var mobileSettings = __assign(__assign({}, this.settings.mobileSettings), this.settings.mobileSettings);
30575				this.settings = __assign(__assign({}, this.settings), mobileSettings);
30576			}
30577		};
30578		LightGallery.prototype.normalizeSettings = function () {
30579			if (this.settings.slideEndAnimation) {
30580				this.settings.hideControlOnEnd = false;
30581			}
30582			if (!this.settings.closable) {
30583				this.settings.swipeToClose = false;
30584			}
30585			// And reset it on close to get the correct value next time
30586			this.zoomFromOrigin = this.settings.zoomFromOrigin;
30587			// At the moment, Zoom from image doesn't support dynamic options
30588			// @todo add zoomFromOrigin support for dynamic images
30589			if (this.settings.dynamic) {
30590				this.zoomFromOrigin = false;
30591			}
30592			if (!this.settings.container) {
30593				this.settings.container = document.body;
30594			}
30595			// settings.preload should not be grater than $item.length
30596			this.settings.preload = Math.min(this.settings.preload, this.galleryItems.length);
30597		};
30598		LightGallery.prototype.init = function () {
30599			var _this = this;
30600			this.addSlideVideoInfo(this.galleryItems);
30601			this.buildStructure();
30602			this.LGel.trigger(lGEvents.init, {
30603				instance: this,
30604			});
30605			if (this.settings.keyPress) {
30606				this.keyPress();
30607			}
30608			setTimeout(function () {
30609				_this.enableDrag();
30610				_this.enableSwipe();
30611				_this.triggerPosterClick();
30612			}, 50);
30613			this.arrow();
30614			if (this.settings.mousewheel) {
30615				this.mousewheel();
30616			}
30617			if (!this.settings.dynamic) {
30618				this.openGalleryOnItemClick();
30619			}
30620		};
30621		LightGallery.prototype.openGalleryOnItemClick = function () {
30622			var _this = this;
30623			var _loop_1 = function (index) {
30624				var element = this_1.items[index];
30625				var $element = $LG(element);
30626				// Using different namespace for click because click event should not unbind if selector is same object('this')
30627				// @todo manage all event listners - should have namespace that represent element
30628				var uuid = lgQuery.generateUUID();
30629				$element
30630					.attr('data-lg-id', uuid)
30631					.on("click.lgcustom-item-" + uuid, function (e) {
30632					e.preventDefault();
30633					var currentItemIndex = _this.settings.index || index;
30634					_this.openGallery(currentItemIndex, element);
30635				});
30636			};
30637			var this_1 = this;
30638			// Using for loop instead of using bubbling as the items can be any html element.
30639			for (var index = 0; index < this.items.length; index++) {
30640				_loop_1(index);
30641			}
30642		};
30643		/**
30644		 * Module constructor
30645		 * Modules are build incrementally.
30646		 * Gallery should be opened only once all the modules are initialized.
30647		 * use moduleBuildTimeout to make sure this
30648		 */
30649		LightGallery.prototype.buildModules = function () {
30650			var _this = this;
30651			this.settings.plugins.forEach(function (plugin) {
30652				_this.plugins.push(new plugin(_this, $LG));
30653			});
30654		};
30655		LightGallery.prototype.validateLicense = function () {
30656			if (!this.settings.licenseKey) {
30657				console.warn('Please provide a valid license key');
30658			}
30659			else if (this.settings.licenseKey === '0000-0000-000-0000') {
30660				console.warn("lightGallery: " + this.settings.licenseKey + " license key is not val
vendor: 17,473 bytes, lines 30660-31074
30660id for production use");
30661			}
30662		};
30663		LightGallery.prototype.getSlideItem = function (index) {
30664			return $LG(this.getSlideItemId(index));
30665		};
30666		LightGallery.prototype.getSlideItemId = function (index) {
30667			return "#lg-item-" + this.lgId + "-" + index;
30668		};
30669		LightGallery.prototype.getIdName = function (id) {
30670			return id + "-" + this.lgId;
30671		};
30672		LightGallery.prototype.getElementById = function (id) {
30673			return $LG("#" + this.getIdName(id));
30674		};
30675		LightGallery.prototype.manageSingleSlideClassName = function () {
30676			if (this.galleryItems.length < 2) {
30677				this.outer.addClass('lg-single-item');
30678			}
30679			else {
30680				this.outer.removeClass('lg-single-item');
30681			}
30682		};
30683		LightGallery.prototype.buildStructure = function () {
30684			var _this = this;
30685			var container = this.$container && this.$container.get();
30686			if (container) {
30687				return;
30688			}
30689			var controls = '';
30690			var subHtmlCont = '';
30691			// Create controls
30692			if (this.settings.controls) {
30693				controls = "<button type=\"button\" id=\"" + this.getIdName('lg-prev') + "\" aria-label=\"" + this.settings.strings['previousSlide'] + "\" class=\"lg-prev lg-icon\"> " + this.settings.prevHtml + " </button>\n                <button type=\"button\" id=\"" + this.getIdName('lg-next') + "\" aria-label=\"" + this.settings.strings['nextSlide'] + "\" class=\"lg-next lg-icon\"> " + this.settings.nextHtml + " </button>";
30694			}
30695			if (this.settings.appendSubHtmlTo !== '.lg-item') {
30696				subHtmlCont =
30697					'<div class="lg-sub-html" role="status" aria-live="polite"></div>';
30698			}
30699			var addClasses = '';
30700			if (this.settings.allowMediaOverlap) {
30701				// Do not remove space before last single quote
30702				addClasses += 'lg-media-overlap ';
30703			}
30704			var ariaLabelledby = this.settings.ariaLabelledby
30705				? 'aria-labelledby="' + this.settings.ariaLabelledby + '"'
30706				: '';
30707			var ariaDescribedby = this.settings.ariaDescribedby
30708				? 'aria-describedby="' + this.settings.ariaDescribedby + '"'
30709				: '';
30710			var containerClassName = "lg-container " + this.settings.addClass + " " + (document.body !== this.settings.container ? 'lg-inline' : '');
30711			var closeIcon = this.settings.closable && this.settings.showCloseIcon
30712				? "<button type=\"button\" aria-label=\"" + this.settings.strings['closeGallery'] + "\" id=\"" + this.getIdName('lg-close') + "\" class=\"lg-close lg-icon\"></button>"
30713				: '';
30714			var maximizeIcon = this.settings.showMaximizeIcon
30715				? "<button type=\"button\" aria-label=\"" + this.settings.strings['toggleMaximize'] + "\" id=\"" + this.getIdName('lg-maximize') + "\" class=\"lg-maximize lg-icon\"></button>"
30716				: '';
30717			var template = "\n        <div class=\"" + containerClassName + "\" id=\"" + this.getIdName('lg-container') + "\" tabindex=\"-1\" aria-modal=\"true\" " + ariaLabelledby + " " + ariaDescribedby + " role=\"dialog\"\n        >\n            <div id=\"" + this.getIdName('lg-backdrop') + "\" class=\"lg-backdrop\"></div>\n\n            <div id=\"" + this.getIdName('lg-outer') + "\" class=\"lg-outer lg-use-css3 lg-css3 lg-hide-items " + addClasses + " \">\n\n              <div id=\"" + this.getIdName('lg-content') + "\" class=\"lg-content\">\n                <div id=\"" + this.getIdName('lg-inner') + "\" class=\"lg-inner\">\n                </div>\n                " + controls + "\n              </div>\n                <div id=\"" + this.getIdName('lg-toolbar') + "\" class=\"lg-toolbar lg-group\">\n                    " + maximizeIcon + "\n                    " + closeIcon + "\n                    </div>\n                    " + (this.settings.appendSubHtmlTo === '.lg-outer'
30718				? subHtmlCont
30719				: '') + "\n                <div id=\"" + this.getIdName('lg-components') + "\" class=\"lg-components\">\n                    " + (this.settings.appendSubHtmlTo === '.lg-sub-html'
30720				? subHtmlCont
30721				: '') + "\n                </div>\n            </div>\n        </div>\n        ";
30722			$LG(this.settings.container).append(template);
30723			if (document.body !== this.settings.container) {
30724				$LG(this.settings.container).css('position', 'relative');
30725			}
30726			this.outer = this.getElementById('lg-outer');
30727			this.$lgComponents = this.getElementById('lg-components');
30728			this.$backdrop = this.getElementById('lg-backdrop');
30729			this.$container = this.getElementById('lg-container');
30730			this.$inner = this.getElementById('lg-inner');
30731			this.$content = this.getElementById('lg-content');
30732			this.$toolbar = this.getElementById('lg-toolbar');
30733			this.$backdrop.css('transition-duration', this.settings.backdropDuration + 'ms');
30734			var outerClassNames = this.settings.mode + " ";
30735			this.manageSingleSlideClassName();
30736			if (this.settings.enableDrag) {
30737				outerClassNames += 'lg-grab ';
30738			}
30739			this.outer.addClass(outerClassNames);
30740			this.$inner.css('transition-timing-function', this.settings.easing);
30741			this.$inner.css('transition-duration', this.settings.speed + 'ms');
30742			if (this.settings.download) {
30743				this.$toolbar.append("<a id=\"" + this.getIdName('lg-download') + "\" target=\"_blank\" rel=\"noopener\" aria-label=\"" + this.settings.strings['download'] + "\" download class=\"lg-download lg-icon\"></a>");
30744			}
30745			this.counter();
30746			$LG(window).on("resize.lg.global" + this.lgId + " orientationchange.lg.global" + this.lgId, function () {
30747				_this.refreshOnResize();
30748			});
30749			this.hideBars();
30750			this.manageCloseGallery();
30751			this.toggleMaximize();
30752			this.initModules();
30753		};
30754		LightGallery.prototype.refreshOnResize = function () {
30755			if (this.lgOpened) {
30756				var currentGalleryItem = this.galleryItems[this.index];
30757				var __slideVideoInfo = currentGalleryItem.__slideVideoInfo;
30758				this.mediaContainerPosition = this.getMediaContainerPosition();
30759				var _a = this.mediaContainerPosition, top_1 = _a.top, bottom = _a.bottom;
30760				//Uncode edit ##START##
30761				this.currentImageSize = utils.getSize(this.items[this.index], this.outer, top_1 + bottom, __slideVideoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
30762				// this.currentImageSize = utils.getSize(this.items[this.index], this.outer, top_1 + bottom, __slideVideoInfo && this.settings.videoMaxSize);
30763				//Uncode edit ##END##
30764				if (__slideVideoInfo) {
30765					this.resizeVideoSlide(this.index, this.currentImageSize);
30766				}
30767				if (this.zoomFromOrigin && !this.isDummyImageRemoved) {
30768					var imgStyle = this.getDummyImgStyles(this.currentImageSize);
30769					this.outer
30770						.find('.lg-current .lg-dummy-img')
30771						.first()
30772						.attr('style', imgStyle);
30773				}
30774				this.LGel.trigger(lGEvents.containerResize);
30775			}
30776		};
30777		LightGallery.prototype.resizeVideoSlide = function (index, imageSize) {
30778			var lgVideoStyle = this.getVideoContStyle(imageSize);
30779			var currentSlide = this.getSlideItem(index);
30780			currentSlide.find('.lg-video-cont').attr('style', lgVideoStyle);
30781		};
30782		/**
30783		 * Update slides dynamically.
30784		 * Add, edit or delete slides dynamically when lightGallery is opened.
30785		 * Modify the current gallery items and pass it via updateSlides method
30786		 * @note
30787		 * - Do not mutate existing lightGallery items directly.
30788		 * - Always pass new list of gallery items
30789		 * - You need to take care of thumbnails outside the gallery if any
30790		 * - user this method only if you want to update slides when the gallery is opened. Otherwise, use `refresh()` method.
30791		 * @param items Gallery items
30792		 * @param index After the update operation, which slide gallery should navigate to
30793		 * @category lGPublicMethods
30794		 * @example
30795		 * const plugin = lightGallery();
30796		 *
30797		 * // Adding slides dynamically
30798		 * let galleryItems = [
30799		 * // Access existing lightGallery items
30800		 * // galleryItems are automatically generated internally from the gallery HTML markup
30801		 * // or directly from galleryItems when dynamic gallery is used
30802		 *   ...plugin.galleryItems,
30803		 *     ...[
30804		 *       {
30805		 *         src: 'img/img-1.png',
30806		 *           thumb: 'img/thumb1.png',
30807		 *         },
30808		 *     ],
30809		 *   ];
30810		 *   plugin.updateSlides(
30811		 *     galleryItems,
30812		 *     plugin.index,
30813		 *   );
30814		 *
30815		 *
30816		 * // Remove slides dynamically
30817		 * galleryItems = JSON.parse(
30818		 *   JSON.stringify(updateSlideInstance.galleryItems),
30819		 * );
30820		 * galleryItems.shift();
30821		 * updateSlideInstance.updateSlides(galleryItems, 1);
30822		 * @see <a href="/demos/update-slides/">Demo</a>
30823		 */
30824		LightGallery.prototype.updateSlides = function (items, index) {
30825			if (this.index > items.length - 1) {
30826				this.index = items.length - 1;
30827			}
30828			if (items.length === 1) {
30829				this.index = 0;
30830			}
30831			if (!items.length) {
30832				this.closeGallery();
30833				return;
30834			}
30835			var currentSrc = this.galleryItems[index].src;
30836			this.galleryItems = items;
30837			this.updateControls();
30838			this.$inner.empty();
30839			this.currentItemsInDom = [];
30840			var _index = 0;
30841			// Find the current index based on source value of the slide
30842			this.galleryItems.some(function (galleryItem, itemIndex) {
30843				if (galleryItem.src === currentSrc) {
30844					_index = itemIndex;
30845					return true;
30846				}
30847				return false;
30848			});
30849			this.currentItemsInDom = this.organizeSlideItems(_index, -1);
30850			this.loadContent(_index, true);
30851			this.getSlideItem(_index).addClass('lg-current');
30852			this.index = _index;
30853			this.updateCurrentCounter(_index);
30854			this.LGel.trigger(lGEvents.updateSlides);
30855		};
30856		// Get gallery items based on multiple conditions
30857		LightGallery.prototype.getItems = function () {
30858			// Gallery items
30859			this.items = [];
30860			if (!this.settings.dynamic) {
30861				if (this.settings.selector === 'this') {
30862					this.items.push(this.el);
30863				}
30864				else if (this.settings.selector) {
30865					if (typeof this.settings.selector === 'string') {
30866						if (this.settings.selectWithin) {
30867							var selectWithin = $LG(this.settings.selectWithin);
30868							this.items = selectWithin
30869								.find(this.settings.selector)
30870								.get();
30871						}
30872						else {
30873							this.items = this.el.querySelectorAll(this.settings.selector);
30874						}
30875					}
30876					else {
30877						this.items = this.settings.selector;
30878					}
30879				}
30880				else {
30881					this.items = this.el.children;
30882				}
30883				return utils.getDynamicOptions(this.items, this.settings.extraProps, this.settings.getCaptionFromTitleOrAlt, this.settings.exThumbImage);
30884			}
30885			else {
30886				return this.settings.dynamicEl || [];
30887			}
30888		};
30889		LightGallery.prototype.shouldHideScrollbar = function () {
30890			return (this.settings.hideScrollbar &&
30891				document.body === this.settings.container);
30892		};
30893		LightGallery.prototype.hideScrollbar = function () {
30894			if (!this.shouldHideScrollbar()) {
30895				return;
30896			}
30897			this.bodyPaddingRight = parseFloat($LG('body').style().paddingRight);
30898			var bodyRect = document.documentElement.getBoundingClientRect();
30899			var scrollbarWidth = window.innerWidth - bodyRect.width;
30900			$LG(document.body).css('padding-right', scrollbarWidth + this.bodyPaddingRight + 'px');
30901			$LG(document.body).addClass('lg-overlay-open');
30902		};
30903		LightGallery.prototype.resetScrollBar = function () {
30904			if (!this.shouldHideScrollbar()) {
30905				return;
30906			}
30907			$LG(document.body).css('padding-right', this.bodyPaddingRight + 'px');
30908			$LG(document.body).removeClass('lg-overlay-open');
30909		};
30910		/**
30911		 * Open lightGallery.
30912		 * Open gallery with specific slide by passing index of the slide as parameter.
30913		 * @category lGPublicMethods
30914		 * @param {Number} index  - index of the slide
30915		 * @param {HTMLElement} element - Which image lightGallery should zoom from
30916		 *
30917		 * @example
30918		 * const $dynamicGallery = document.getElementById('dynamic-gallery-demo');
30919		 * const dynamicGallery = lightGallery($dynamicGallery, {
30920		 *     dynamic: true,
30921		 *     dynamicEl: [
30922		 *         {
30923		 *              src: 'img/1.jpg',
30924		 *              thumb: 'img/thumb-1.jpg',
30925		 *              subHtml: '<h4>Image 1 title</h4><p>Image 1 descriptions.</p>',
30926		 *         },
30927		 *         ...
30928		 *     ],
30929		 * });
30930		 * $dynamicGallery.addEventListener('click', function () {
30931		 *     // Starts with third item.(Optional).
30932		 *     // This is useful if you want use dynamic mode with
30933		 *     // custom thumbnails (thumbnails outside gallery),
30934		 *     dynamicGallery.openGallery(2);
30935		 * });
30936		 *
30937		 */
30938		LightGallery.prototype.openGallery = function (index, element) {
30939			var _this = this;
30940			if (index === void 0) { index = this.settings.index; }
30941			// prevent accidental double execution
30942			if (this.lgOpened)
30943				return;
30944			this.lgOpened = true;
30945			this.outer.removeClass('lg-hide-items');
30946			this.hideScrollbar();
30947			// Add display block, but still has opacity 0
30948			this.$container.addClass('lg-show');
30949			var itemsToBeInsertedToDom = this.getItemsToBeInsertedToDom(index, index);
30950			this.currentItemsInDom = itemsToBeInsertedToDom;
30951			var items = '';
30952			itemsToBeInsertedToDom.forEach(function (item) {
30953				items = items + ("<div id=\"" + item + "\" class=\"lg-item\"></div>");
30954			});
30955			this.$inner.append(items);
30956			this.addHtml(index);
30957			var transform = '';
30958			this.mediaContainerPosition = this.getMediaContainerPosition();
30959			var _a = this.mediaContainerPosition, top = _a.top, bottom = _a.bottom;
30960			if (!this.settings.allowMediaOverlap) {
30961				this.setMediaContainerPosition(top, bottom);
30962			}
30963			var __slideVideoInfo = this.galleryItems[index].__slideVideoInfo;
30964			if (this.zoomFromOrigin && element) {
30965				//Uncode edit ##START##
30966				this.currentImageSize = utils.getSize(element, this.outer, top + bottom, __slideVideoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
30967				// this.currentImageSize = utils.getSize(element, this.outer, top + bottom, __slideVideoInfo && this.settings.videoMaxSize);
30968				//Uncode edit ##END##
30969				transform = utils.getTransform(element, this.outer, top, bottom, this.currentImageSize);
30970			}
30971			if (!this.zoomFromOrigin || !transform) {
30972				this.outer.addClass(this.settings.startClass);
30973				this.getSlideItem(index).removeClass('lg-complete');
30974			}
30975			var timeout = this.settings.zoomFromOrigin
30976				? 100
30977				: this.settings.backdropDuration;
30978			setTimeout(function () {
30979				_this.outer.addClass('lg-components-open');
30980			}, timeout);
30981			this.index = index;
30982			//Uncode edit ##START##
30983			// this.LGel.trigger(lGEvents.beforeOpen);
30984			this.LGel.trigger(lGEvents.beforeOpen, {
30985				galleryItems: this.galleryItems,
30986				items: this.items,
30987				outer: this.outer,
30988			});
30989			//Uncode edit ##END##
30990			// add class lg-current to remove initial transition
30991			this.getSlideItem(index).addClass('lg-current');
30992			this.lGalleryOn = false;
30993			// Store the current scroll top value to scroll back after closing the gallery..
30994			this.prevScrollTop = $LG(window).scrollTop();
30995			setTimeout(function () {
30996				// Need to check both zoomFromOrigin and transform values as we need to set set the
30997				// default opening animation if user missed to add the lg-size attribute
30998				if (_this.zoomFromOrigin && transform) {
30999					var currentSlide_1 = _this.getSlideItem(index);
31000					currentSlide_1.css('transform', transform);
31001					setTimeout(function () {
31002						currentSlide_1
31003							.addClass('lg-start-progress lg-start-end-progress')
31004							.css('transition-duration', _this.settings.startAnimationDuration + 'ms');
31005						_this.outer.addClass('lg-zoom-from-image');
31006					});
31007					setTimeout(function () {
31008						currentSlide_1.css('transform', 'translate3d(0, 0, 0)');
31009					}, 100);
31010				}
31011				setTimeout(function () {
31012					_this.$backdrop.addClass('in');
31013					_this.$container.addClass('lg-show-in');
31014				}, 10);
31015				setTimeout(function () {
31016					if (_this.settings.trapFocus &&
31017						document.body === _this.settings.container) {
31018						_this.trapFocus();
31019					}
31020				}, _this.settings.backdropDuration + 50);
31021				// lg-visible class resets gallery opacity to 1
31022				if (!_this.zoomFromOrigin || !transform) {
31023					setTimeout(function () {
31024						_this.outer.addClass('lg-visible');
31025					}, _this.settings.backdropDuration);
31026				}
31027				// initiate slide function
31028				_this.slide(index, false, false, false);
31029				_this.LGel.trigger(lGEvents.afterOpen);
31030			});
31031			if (document.body === this.settings.container) {
31032				$LG('html').addClass('lg-on');
31033			}
31034		};
31035		/**
31036		 * Note - Changing the position of the media on every slide transition creates a flickering effect.
31037		 * Therefore, The height of the caption is calculated dynamically, only once based on the first slide caption.
31038		 * if you have dynamic captions for each media,
31039		 * you can provide an appropriate height for the captions via allowMediaOverlap option
31040		 */
31041		LightGallery.prototype.getMediaContainerPosition = function () {
31042			if (this.settings.allowMediaOverlap) {
31043				return {
31044					top: 0,
31045					bottom: 0,
31046				};
31047			}
31048			var top = this.$toolbar.get().clientHeight || 0;
31049			var subHtml = this.outer.find('.lg-components .lg-sub-html').get();
31050			var captionHeight = this.settings.defaultCaptionHeight ||
31051				(subHtml && subHtml.clientHeight) ||
31052				0;
31053			var thumbContainer = this.outer.find('.lg-thumb-outer').get();
31054			var thumbHeight = thumbContainer ? thumbContainer.clientHeight : 0;
31055			var bottom = thumbHeight + captionHeight;
31056			//Uncode edit ##START##
31057			bottom = bottom < 55 ? 55 : bottom;
31058			//Uncode edit ##END##
31059			return {
31060				top: top,
31061				bottom: bottom,
31062			};
31063		};
31064		LightGallery.prototype.setMediaContainerPosition = function (top, bottom) {
31065			if (top === void 0) { top = 0; }
31066			if (bottom === void 0) { bottom = 0; }
31067			this.$content.css('top', top + 'px').css('bottom', bottom + 'px');
31068		};
31069		LightGallery.prototype.hideBars = function () {
31070			var _this = this;
31071			// Hide controllers if mouse doesn't move for some period
31072			setTimeout(function () {
31073				_this.outer.removeClass('lg-hide-items');
31074				if (_this.settings.hideBarsDelay > 0) {
vendor: 4,223 bytes, lines 31075-31205
31075					_this.outer.on('mousemove.lg click.lg touchstart.lg', function () {
31076						_this.outer.removeClass('lg-hide-items');
31077						clearTimeout(_this.hideBarTimeout);
31078						// Timeout will be cleared on each slide movement also
31079						_this.hideBarTimeout = setTimeout(function () {
31080							_this.outer.addClass('lg-hide-items');
31081						}, _this.settings.hideBarsDelay);
31082					});
31083					_this.outer.trigger('mousemove.lg');
31084				}
31085			}, this.settings.showBarsAfter);
31086		};
31087		LightGallery.prototype.initPictureFill = function ($img) {
31088			if (this.settings.supportLegacyBrowser) {
31089				try {
31090					picturefill({
31091						elements: [$img.get()],
31092					});
31093				}
31094				catch (e) {
31095					console.warn('lightGallery :- If you want srcset or picture tag to be supported for older browser please include picturefil javascript library in your document.');
31096				}
31097			}
31098		};
31099		/**
31100		 *  @desc Create image counter
31101		 *  Ex: 1/10
31102		 */
31103		LightGallery.prototype.counter = function () {
31104			if (this.settings.counter) {
31105				var counterHtml = "<div class=\"lg-counter\" role=\"status\" aria-live=\"polite\">\n                <span id=\"" + this.getIdName('lg-counter-current') + "\" class=\"lg-counter-current\">" + (this.index + 1) + " </span> /\n                <span id=\"" + this.getIdName('lg-counter-all') + "\" class=\"lg-counter-all\">" + this.galleryItems.length + " </span></div>";
31106				this.outer.find(this.settings.appendCounterTo).append(counterHtml);
31107			}
31108		};
31109		/**
31110		 *  @desc add sub-html into the slide
31111		 *  @param {Number} index - index of the slide
31112		 */
31113		LightGallery.prototype.addHtml = function (index) {
31114			var subHtml;
31115			var subHtmlUrl;
31116			if (this.galleryItems[index].subHtmlUrl) {
31117				subHtmlUrl = this.galleryItems[index].subHtmlUrl;
31118			}
31119			else {
31120				subHtml = this.galleryItems[index].subHtml;
31121			}
31122			if (!subHtmlUrl) {
31123				if (subHtml) {
31124					// get first letter of sub-html
31125					// if first letter starts with . or # get the html form the jQuery object
31126					var fL = subHtml.substring(0, 1);
31127					if (fL === '.' || fL === '#') {
31128						if (this.settings.subHtmlSelectorRelative &&
31129							!this.settings.dynamic) {
31130							subHtml = $LG(this.items)
31131								.eq(index)
31132								.find(subHtml)
31133								.first()
31134								.html();
31135						}
31136						else {
31137							subHtml = $LG(subHtml).first().html();
31138						}
31139					}
31140				}
31141				else {
31142					subHtml = '';
31143				}
31144			}
31145			if (this.settings.appendSubHtmlTo !== '.lg-item') {
31146				if (subHtmlUrl) {
31147					this.outer.find('.lg-sub-html').load(subHtmlUrl);
31148				}
31149				else {
31150					this.outer.find('.lg-sub-html').html(subHtml);
31151				}
31152			}
31153			else {
31154				var currentSlide = $LG(this.getSlideItemId(index));
31155				if (subHtmlUrl) {
31156					currentSlide.load(subHtmlUrl);
31157				}
31158				else {
31159					currentSlide.append("<div class=\"lg-sub-html\">" + subHtml + "</div>");
31160				}
31161			}
31162			// Add lg-empty-html class if title doesn't exist
31163			if (typeof subHtml !== 'undefined' && subHtml !== null) {
31164				if (subHtml === '') {
31165					this.outer
31166						.find(this.settings.appendSubHtmlTo)
31167						.addClass('lg-empty-html');
31168				}
31169				else {
31170					this.outer
31171						.find(this.settings.appendSubHtmlTo)
31172						.removeClass('lg-empty-html');
31173				}
31174			}
31175			this.LGel.trigger(lGEvents.afterAppendSubHtml, {
31176				index: index,
31177			});
31178		};
31179		/**
31180		 *  @desc Preload slides
31181		 *  @param {Number} index - index of the slide
31182		 * @todo preload not working for the first slide, Also, should work for the first and last slide as well
31183		 */
31184		LightGallery.prototype.preload = function (index) {
31185			for (var i = 1; i <= this.settings.preload; i++) {
31186				if (i >= this.galleryItems.length - index) {
31187					break;
31188				}
31189				this.loadContent(index + i, false);
31190			}
31191			for (var j = 1; j <= this.settings.preload; j++) {
31192				if (index - j < 0) {
31193					break;
31194				}
31195				this.loadContent(index - j, false);
31196			}
31197		};
31198		LightGallery.prototype.getDummyImgStyles = function (imageSize) {
31199			if (!imageSize)
31200				return '';
31201			return "width:" + imageSize.width + "px;\n                margin-left: -" + imageSize.width / 2 + "px;\n                margin-top: -" + imageSize.height / 2 + "px;\n                height:" + imageSize.height + "px";
31202		};
31203		LightGallery.prototype.getVideoContStyle = function (imageSize) {
31204			if (!imageSize)
31205				return '';
31206			return "width:" + imageSize.width + "px;\n                height:" + imageSize.height + "px";
31207		};
31208		LightGallery.prototype.getDummyImageContent = function ($currentSlide, index, alt) {
31209			var $currentItem;
31210			if (!this.settings.dynamic) {
31211				$currentItem = $LG(this.items).eq(index);
31212			}
31213			if ($currentItem) {
31214				var _dummyImgSrc = void 0;
31215				if (!this.settings.exThumbImage) {
31216					_dummyImgSrc = $currentItem.find('img').first().attr('src');
31217				}
31218				else {
31219					_dummyImgSrc = $currentItem.attr(this.settings.exThumbImage);
31220				}
31221				if (!_dummyImgSrc)
31222					return '';
31223				var imgStyle = this.getDummyImgStyles(this.currentImageSize);
31224				var dummyImgContent = "<img " + alt + " style=\"" + imgStyle + "\" class=\"lg-dummy-img\" src=\"" + _dummyImgSrc + "\" />";
31225				$currentSlide.addClass('lg-first-slide');
31226				this.outer.addClass('lg-first-slide-loading');
31227				return dummyImgContent;
31228			}
31229			return '';
31230		};
31231		LightGallery.prototype.setImgMarkup = function (src, $currentSlide, index) {
31232			var currentGalleryItem = this.galleryItems[index];
31233			var alt = currentGalleryItem.alt, srcset = currentGalleryItem.srcset, sizes = currentGalleryItem.sizes, sources = currentGalleryItem.sources;
31234			// Use the thumbnail as dummy image which will be resized to actual image size and
31235			// displayed on top of actual image
31236			var imgContent = '';
31237			var altAttr = alt ? 'alt="' + alt + '"' : '';
31238			if (this.isFirstSlideWithZoomAnimation()) {
31239				imgContent = this.getDummyImageContent($currentSlide, index, altAttr);
31240			}
31241			else {
31242				imgContent = utils.getImgMarkup(index, src, altAttr, srcset, sizes, sources);
31243			}
31244			var imgMarkup = "<picture class=\"lg-img-wrap\"> " + imgContent + "</picture>";
31245			$currentSlide.prepend(imgMarkup);
31246		};
31247		LightGallery.prototype.onSlideObjectLoad = function ($slide, isHTML5VideoWithoutPoster, onLoad, onError) {
31248			var mediaObject = $slide.find('.lg-object').first();
31249			if (utils.isImageLoaded(mediaObject.get()) ||
31250				isHTML5VideoWithoutPoster) {
31251				onLoad();
31252			}
31253			else {
31254				mediaObject.on('load.lg error.lg', function () {
31255					onLoad && onLoad();
31256				});
31257				mediaObject.on('error.lg', function () {
31258					onError && onError();
31259				});
31260			}
31261		};
31262		/**
31263		 *
31264		 * @param $el Current slide item
31265		 * @param index
31266		 * @param delay Delay is 0 except first time
31267		 * @param speed Speed is same as delay, except it is 0 if gallery is opened via hash plugin
31268		 * @param isFirstSlide
31269		 */
31270		LightGallery.prototype.onLgObjectLoad = function (currentSlide, index, delay, speed, isFirstSlide, isHTML5VideoWithoutPoster) {
31271			var _this = this;
31272			//Uncode edit ##START##
31273			var $item = _this.galleryItems[index],
31274				type = $item.type;
31275
31276			if ( typeof $item.src !== 'undefined' ) {
31277				var inline_id = $item.src.replace('#', ''),
31278					$inline = document.getElementById(inline_id),
31279					inline_html;
31280
31281				if ( type === 'inline' && inline_id != null && typeof $inline !== 'undefined' ) {
31282					inline_html = $inline.innerHTML;
31283				} else {
31284					inline_html = '';
31285				}
31286			}
31287			//Uncode edit ##END##
31288			this.onSlideObjectLoad(currentSlide, true, function () {
31289				_this.triggerSlideItemLoad(currentSlide, index, delay, speed, isFirstSlide);
31290			}, function () {
31291				currentSlide.addClass('lg-complete lg-complete_');
31292				//Uncode edit ##START##
31293				// currentSlide.html('<span class="lg-error-msg">Oops... Failed to load content...</span>');
31294				if ( inline_html !== '' ) {
31295					currentSlide.html(inline_html);
31296				} else {
31297					currentSlide.html('<span class="lg-error-msg">Oops... Failed to load content...</span>');
31298				}
31299				//Uncode edit ##END##
31300			});
31301		};
31302		LightGallery.prototype.triggerSlideItemLoad = function ($currentSlide, index, delay, speed, isFirstSlide) {
31303			var _this = this;
31304			var currentGalleryItem = this.galleryItems[index];
31305			// Adding delay for video slides without poster for better performance and user experience
31306			// Videos should start playing once once the gallery is completely loaded
31307			var _speed = isFirstSlide &&
vendor: 3,676 bytes, lines 31308-31396
31308				this.getSlideType(currentGalleryItem) === 'video' &&
31309				!currentGalleryItem.poster
31310				? speed
31311				: 0;
31312			setTimeout(function () {
31313				$currentSlide.addClass('lg-complete lg-complete_');
31314				_this.LGel.trigger(lGEvents.slideItemLoad, {
31315					index: index,
31316					delay: delay || 0,
31317					isFirstSlide: isFirstSlide,
31318				});
31319			}, _speed);
31320		};
31321		LightGallery.prototype.isFirstSlideWithZoomAnimation = function () {
31322			return !!(!this.lGalleryOn &&
31323				this.zoomFromOrigin &&
31324				this.currentImageSize);
31325		};
31326		// Add video slideInfo
31327		LightGallery.prototype.addSlideVideoInfo = function (items) {
31328			var _this = this;
31329			items.forEach(function (element, index) {
31330				element.__slideVideoInfo = utils.isVideo(element.src, !!element.video, index);
31331				if (element.__slideVideoInfo &&
31332					_this.settings.loadYouTubePoster &&
31333					!element.poster &&
31334					element.__slideVideoInfo.youtube) {
31335					element.poster = "//img.youtube.com/vi/" + element.__slideVideoInfo.youtube[1] + "/maxresdefault.jpg";
31336				}
31337			});
31338		};
31339		/**
31340		 *  Load slide content into slide.
31341		 *  This is used to load content into slides that is not visible too
31342		 *  @param {Number} index - index of the slide.
31343		 *  @param {Boolean} rec - if true call loadcontent() function again.
31344		 */
31345		LightGallery.prototype.loadContent = function (index, rec) {
31346			var _this = this;
31347			var currentGalleryItem = this.galleryItems[index];
31348			var $currentSlide = $LG(this.getSlideItemId(index));
31349			var poster = currentGalleryItem.poster, srcset = currentGalleryItem.srcset, sizes = currentGalleryItem.sizes, sources = currentGalleryItem.sources;
31350			var src = currentGalleryItem.src;
31351			var video = currentGalleryItem.video;
31352			var _html5Video = video && typeof video === 'string' ? JSON.parse(video) : video;
31353			if (currentGalleryItem.responsive) {
31354				var srcDyItms = currentGalleryItem.responsive.split(',');
31355				src = utils.getResponsiveSrc(srcDyItms) || src;
31356			}
31357			var videoInfo = currentGalleryItem.__slideVideoInfo;
31358			var lgVideoStyle = '';
31359			var iframe = !!currentGalleryItem.iframe;
31360			var isFirstSlide = !this.lGalleryOn;
31361			// delay for adding complete class. it is 0 except first time.
31362			var delay = 0;
31363			if (isFirstSlide) {
31364				if (this.zoomFromOrigin && this.currentImageSize) {
31365					delay = this.settings.startAnimationDuration + 10;
31366				}
31367				else {
31368					delay = this.settings.backdropDuration + 10;
31369				}
31370			}
31371			if (!$currentSlide.hasClass('lg-loaded')) {
31372				if (videoInfo) {
31373					var _a = this.mediaContainerPosition, top_2 = _a.top, bottom = _a.bottom;
31374					//Uncode edit ##START##
31375					var videoSize = utils.getSize(this.items[index], this.outer, top_2 + bottom, videoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
31376					// var videoSize = utils.getSize(this.items[index], this.outer, top_2 + bottom, videoInfo && this.settings.videoMaxSize);
31377					//Uncode edit ##END##
31378					lgVideoStyle = this.getVideoContStyle(videoSize);
31379				}
31380				if (iframe) {
31381					var markup = utils.getIframeMarkup(this.settings.iframeWidth, this.settings.iframeHeight, this.settings.iframeMaxWidth, this.settings.iframeMaxHeight, src, currentGalleryItem.iframeTitle);
31382					$currentSlide.prepend(markup);
31383				}
31384				else if (poster) {
31385					var dummyImg = '';
31386					var hasStartAnimation = isFirstSlide &&
31387						this.zoomFromOrigin &&
31388						this.currentImageSize;
31389					if (hasStartAnimation) {
31390						dummyImg = this.getDummyImageContent($currentSlide, index, '');
31391					}
31392					var markup = utils.getVideoPosterMarkup(poster, dummyImg || '', lgVideoStyle, this.settings.strings['playVideo'], videoInfo);
31393					$currentSlide.prepend(markup);
31394				}
31395				//Uncode edit ##START##
31396				// else if (videoInfo) {
31397				else if (videoInfo || this.getSlideType(currentGalleryItem) === 'audio') {
31398					if (! _html5Video) {
31399						var markup = "<div class=\"lg-video-cont \" style=\"" + lgVideoStyle + "\"></div>";
31400					}
31401					//Uncode edit ##END##
31402					$currentSlide.prepend(markup);
31403				}
31404				else {
31405					//Uncode edit ##START##
31406					var $item = _this.galleryItems[index],
31407						type = $item.type;
31408
31409					if ( typeof $item.src !== 'undefined' ) {
31410						var inline_id = $item.src.replace('#', ''),
31411							$inline = document.getElementById(inline_id),
31412							inline_html;
31413
31414						if ( type === 'inline' && inline_id != null && typeof $inline !== 'undefined' ) {
31415							inline_html = $inline.innerHTML;
31416						} else {
31417							inline_html = '';
31418						}
31419					}
31420					if ( inline_html !== '' ) {
31421						$currentSlide.html(inline_html);
31422					} else {
31423						this.setImgMarkup(src, $currentSlide, index);
31424						if (srcset || sources) {
31425							var $img = $currentSlide.find('.lg-object');
31426							this.initPictureFill($img);
31427						}
31428					}
31429					/*this.setImgMarkup(src, $currentSlide, index);
31430					if (srcset || sources) {
31431						var $img = $currentSlide.find('.lg-object');
31432						this.initPictureFill($img);
31433					}*/
31434					//Uncode edit ##END##
31435				}
31436				if (poster || videoInfo) {
31437					this.LGel.trigger(lGEvents.hasVideo, {
31438						index: index,
31439						src: src,
31440						html5Video: _html5Video,
31441						hasPoster: !!poster,
31442					});
31443				}
31444				this.LGel.trigger(lGEvents.afterAppendSlide, { index: index });
31445				if (this.lGalleryOn &&
31446					this.settings.appendSubHtmlTo === '.lg-item') {
31447					this.addHtml(index);
31448				}
31449			}
31450			// For first time add some delay for displaying the start animation.
31451			var _speed = 0;
31452			// Do not change the delay value because it is required for zoom plugin.
31453			// If gallery opened from direct url (hash) speed value should be 0
31454			if (delay && !$LG(document.body).hasClass('lg-from-hash')) {
31455				_speed = delay;
31456			}
31457			// Only for first slide and zoomFromOrigin is enabled
31458			if (this.isFirstSlideWithZoomAnimation()) {
31459				setTimeout(function () {
31460					$currentSlide
31461						.removeClass('lg-start-end-progress lg-start-progress')
31462						.removeAttr('style');
31463				}, this.settings.startAnimationDuration + 100);
31464				if (!$currentSlide.hasClass('lg-loaded')) {
31465					setTimeout(function () {
31466						if (_this.getSlideType(currentGalleryItem) === 'image') {
31467							var alt = currentGalleryItem.alt;
31468							var altAttr = alt ? 'alt="' + alt + '"' : '';
31469							$currentSlide
31470								.find('.lg-img-wrap')
31471								.append(utils.getImgMarkup(index, src, altAttr, srcset, sizes, currentGalleryItem.sources));
31472							if (srcset || sources) {
31473								var $img = $currentSlide.find('.lg-object');
31474								_this.initPictureFill($img);
31475							}
31476						}
31477						if (_this.getSlideType(currentGalleryItem) === 'image' ||
31478							(_this.getSlideType(currentGalleryItem) === 'video' &&
31479								poster)) {
31480							_this.onLgObjectLoad($currentSlide, index, delay, _speed, true, false);
31481							// load remaining slides once the slide is completely loaded
31482							_this.onSlideObjectLoad($currentSlide, !!(videoInfo && videoInfo.html5 && !poster), function () {
31483								_this.loadContentOnFirstSlideLoad(index, $currentSlide, _speed);
31484							}, function () {
31485								_this.loadContentOnFirstSlideLoad(index, $currentSlide, _speed);
31486							});
31487						}
31488					}, this.settings.startAnimationDuration + 100);
31489				}
31490			}
31491			// SLide content has been added to dom
31492			$currentSlide.addClass('lg-loaded');
31493			if (!this.isFirstSlideWithZoomAnimation() ||
31494				(this.getSlideType(currentGalleryItem) === 'video' && !poster)) {
31495				//Uncode edit ##START##
31496				// this.onLgObjectLoad($currentSlide, index, delay, _speed, isFirstSlide, !!(videoInfo && videoInfo.html5 && !poster));
31497				this.onLgObjectLoad($currentSlide, index, delay, _speed, isFirstSlide, !!( (videoInfo && videoInfo.html5 && !poster) || this.get
vendor: 31,133 bytes, lines 31497-32421
31497SlideType(currentGalleryItem) === 'audio'));
31498				//Uncode edit ##END##
31499			}
31500			// When gallery is opened once content is loaded (second time) need to add lg-complete class for css styling
31501			if ((!this.zoomFromOrigin || !this.currentImageSize) &&
31502				$currentSlide.hasClass('lg-complete_') &&
31503				!this.lGalleryOn) {
31504				setTimeout(function () {
31505					$currentSlide.addClass('lg-complete');
31506				}, this.settings.backdropDuration);
31507			}
31508			// Content loaded
31509			// Need to set lGalleryOn before calling preload function
31510			this.lGalleryOn = true;
31511			if (rec === true) {
31512				if (!$currentSlide.hasClass('lg-complete_')) {
31513					$currentSlide
31514						.find('.lg-object')
31515						.first()
31516						.on('load.lg error.lg', function () {
31517						_this.preload(index);
31518					});
31519				}
31520				else {
31521					this.preload(index);
31522				}
31523			}
31524		};
31525		/**
31526		 * @desc Remove dummy image content and load next slides
31527		 * Called only for the first time if zoomFromOrigin animation is enabled
31528		 * @param index
31529		 * @param $currentSlide
31530		 * @param speed
31531		 */
31532		LightGallery.prototype.loadContentOnFirstSlideLoad = function (index, $currentSlide, speed) {
31533			var _this = this;
31534			setTimeout(function () {
31535				$currentSlide.find('.lg-dummy-img').remove();
31536				$currentSlide.removeClass('lg-first-slide');
31537				_this.outer.removeClass('lg-first-slide-loading');
31538				_this.isDummyImageRemoved = true;
31539				_this.preload(index);
31540			}, speed + 300);
31541		};
31542		LightGallery.prototype.getItemsToBeInsertedToDom = function (index, prevIndex, numberOfItems) {
31543			var _this = this;
31544			if (numberOfItems === void 0) { numberOfItems = 0; }
31545			var itemsToBeInsertedToDom = [];
31546			// Minimum 2 items should be there
31547			var possibleNumberOfItems = Math.max(numberOfItems, 3);
31548			possibleNumberOfItems = Math.min(possibleNumberOfItems, this.galleryItems.length);
31549			var prevIndexItem = "lg-item-" + this.lgId + "-" + prevIndex;
31550			if (this.galleryItems.length <= 3) {
31551				this.galleryItems.forEach(function (_element, index) {
31552					itemsToBeInsertedToDom.push("lg-item-" + _this.lgId + "-" + index);
31553				});
31554				return itemsToBeInsertedToDom;
31555			}
31556			if (index < (this.galleryItems.length - 1) / 2) {
31557				for (var idx = index; idx > index - possibleNumberOfItems / 2 && idx >= 0; idx--) {
31558					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + idx);
31559				}
31560				var numberOfExistingItems = itemsToBeInsertedToDom.length;
31561				for (var idx = 0; idx < possibleNumberOfItems - numberOfExistingItems; idx++) {
31562					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (index + idx + 1));
31563				}
31564			}
31565			else {
31566				for (var idx = index; idx <= this.galleryItems.length - 1 &&
31567					idx < index + possibleNumberOfItems / 2; idx++) {
31568					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + idx);
31569				}
31570				var numberOfExistingItems = itemsToBeInsertedToDom.length;
31571				for (var idx = 0; idx < possibleNumberOfItems - numberOfExistingItems; idx++) {
31572					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (index - idx - 1));
31573				}
31574			}
31575			if (this.settings.loop) {
31576				if (index === this.galleryItems.length - 1) {
31577					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + 0);
31578				}
31579				else if (index === 0) {
31580					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (this.galleryItems.length - 1));
31581				}
31582			}
31583			if (itemsToBeInsertedToDom.indexOf(prevIndexItem) === -1) {
31584				itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + prevIndex);
31585			}
31586			return itemsToBeInsertedToDom;
31587		};
31588		LightGallery.prototype.organizeSlideItems = function (index, prevIndex) {
31589			var _this = this;
31590			var itemsToBeInsertedToDom = this.getItemsToBeInsertedToDom(index, prevIndex, this.settings.numberOfSlideItemsInDom);
31591			itemsToBeInsertedToDom.forEach(function (item) {
31592				if (_this.currentItemsInDom.indexOf(item) === -1) {
31593					_this.$inner.append("<div id=\"" + item + "\" class=\"lg-item\"></div>");
31594				}
31595			});
31596			this.currentItemsInDom.forEach(function (item) {
31597				if (itemsToBeInsertedToDom.indexOf(item) === -1) {
31598					$LG("#" + item).remove();
31599				}
31600			});
31601			return itemsToBeInsertedToDom;
31602		};
31603		/**
31604		 * Get previous index of the slide
31605		 */
31606		LightGallery.prototype.getPreviousSlideIndex = function () {
31607			var prevIndex = 0;
31608			try {
31609				var currentItemId = this.outer
31610					.find('.lg-current')
31611					.first()
31612					.attr('id');
31613				prevIndex = parseInt(currentItemId.split('-')[3]) || 0;
31614			}
31615			catch (error) {
31616				prevIndex = 0;
31617			}
31618			return prevIndex;
31619		};
31620		LightGallery.prototype.setDownloadValue = function (index) {
31621			if (this.settings.download) {
31622				var currentGalleryItem = this.galleryItems[index];
31623				var hideDownloadBtn = currentGalleryItem.downloadUrl === false ||
31624					currentGalleryItem.downloadUrl === 'false';
31625				if (hideDownloadBtn) {
31626					this.outer.addClass('lg-hide-download');
31627				}
31628				else {
31629					var $download = this.getElementById('lg-download');
31630					this.outer.removeClass('lg-hide-download');
31631					$download.attr('href', currentGalleryItem.downloadUrl ||
31632						currentGalleryItem.src);
31633					if (currentGalleryItem.download) {
31634						//Uncode edit ##START##
31635						if ( typeof currentGalleryItem.video !== 'undefined' && currentGalleryItem.video ) {
31636							var currentVideo = JSON.parse( currentGalleryItem.video ),
31637								download_name = currentVideo.source[0].src;
31638							$download.attr('href', download_name).removeAttr('download');
31639						} else {
31640							var download_url = currentGalleryItem.downloadUrl || currentGalleryItem.src,
31641								download_name = download_url.substring(download_url.lastIndexOf('/')+1);
31642							$download.attr('download', download_name);
31643						}
31644						// $download.attr('download', currentGalleryItem.download);
31645						//Uncode edit ##END##
31646					}
31647				}
31648			}
31649		};
31650		LightGallery.prototype.makeSlideAnimation = function (direction, currentSlideItem, previousSlideItem) {
31651			var _this = this;
31652			if (this.lGalleryOn) {
31653				previousSlideItem.addClass('lg-slide-progress');
31654			}
31655			setTimeout(function () {
31656				// remove all transitions
31657				_this.outer.addClass('lg-no-trans');
31658				_this.outer
31659					.find('.lg-item')
31660					.removeClass('lg-prev-slide lg-next-slide');
31661				if (direction === 'prev') {
31662					//prevslide
31663					currentSlideItem.addClass('lg-prev-slide');
31664					previousSlideItem.addClass('lg-next-slide');
31665				}
31666				else {
31667					// next slide
31668					currentSlideItem.addClass('lg-next-slide');
31669					previousSlideItem.addClass('lg-prev-slide');
31670				}
31671				// give 50 ms for browser to add/remove class
31672				setTimeout(function () {
31673					_this.outer.find('.lg-item').removeClass('lg-current');
31674					currentSlideItem.addClass('lg-current');
31675					// reset all transitions
31676					_this.outer.removeClass('lg-no-trans');
31677				}, 50);
31678			}, this.lGalleryOn ? this.settings.slideDelay : 0);
31679		};
31680		/**
31681		 * Goto a specific slide.
31682		 * @param {Number} index - index of the slide
31683		 * @param {Boolean} fromTouch - true if slide function called via touch event or mouse drag
31684		 * @param {Boolean} fromThumb - true if slide function called via thumbnail click
31685		 * @param {String} direction - Direction of the slide(next/prev)
31686		 * @category lGPublicMethods
31687		 * @example
31688		 *  const plugin = lightGallery();
31689		 *  // to go to 3rd slide
31690		 *  plugin.slide(2);
31691		 *
31692		 */
31693		LightGallery.prototype.slide = function (index, fromTouch, fromThumb, direction) {
31694			var _this = this;
31695			var prevIndex = this.getPreviousSlideIndex();
31696			this.currentItemsInDom = this.organizeSlideItems(index, prevIndex);
31697			// Prevent multiple call, Required for hsh plugin
31698			if (this.lGalleryOn && prevIndex === index) {
31699				return;
31700			}
31701			var numberOfGalleryItems = this.galleryItems.length;
31702			if (!this.lgBusy) {
31703				if (this.settings.counter) {
31704					this.updateCurrentCounter(index);
31705				}
31706				var currentSlideItem = this.getSlideItem(index);
31707				var previousSlideItem_1 = this.getSlideItem(prevIndex);
31708				var currentGalleryItem = this.galleryItems[index];
31709				var videoInfo = currentGalleryItem.__slideVideoInfo;
31710				this.outer.attr('data-lg-slide-type', this.getSlideType(currentGalleryItem));
31711				this.setDownloadValue(index);
31712				if (videoInfo) {
31713					var _a = this.mediaContainerPosition, top_3 = _a.top, bottom = _a.bottom;
31714					//Uncode edit ##START##
31715					var videoSize = utils.getSize(this.items[index], this.outer, top_3 + bottom, videoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
31716					// var videoSize = utils.getSize(this.items[index], this.outer, top_3 + bottom, videoInfo && this.settings.videoMaxSize);
31717					//Uncode edit ##END##
31718					this.resizeVideoSlide(index, videoSize);
31719				}
31720				this.LGel.trigger(lGEvents.beforeSlide, {
31721					prevIndex: prevIndex,
31722					index: index,
31723					fromTouch: !!fromTouch,
31724					fromThumb: !!fromThumb,
31725					//Uncode edit ##START##
31726					currentSlide: currentSlideItem,
31727					previousSlide: previousSlideItem_1,
31728					info: currentGalleryItem,
31729					item: this.items[index]
31730					//Uncode edit ##END##
31731				});
31732				this.lgBusy = true;
31733				clearTimeout(this.hideBarTimeout);
31734				this.arrowDisable(index);
31735				if (!direction) {
31736					if (index < prevIndex) {
31737						direction = 'prev';
31738					}
31739					else if (index > prevIndex) {
31740						direction = 'next';
31741					}
31742				}
31743				if (!fromTouch) {
31744					this.makeSlideAnimation(direction, currentSlideItem, previousSlideItem_1);
31745				}
31746				else {
31747					this.outer
31748						.find('.lg-item')
31749						.removeClass('lg-prev-slide lg-current lg-next-slide');
31750					var touchPrev = void 0;
31751					var touchNext = void 0;
31752					if (numberOfGalleryItems > 2) {
31753						touchPrev = index - 1;
31754						touchNext = index + 1;
31755						if (index === 0 && prevIndex === numberOfGalleryItems - 1) {
31756							// next slide
31757							touchNext = 0;
31758							touchPrev = numberOfGalleryItems - 1;
31759						}
31760						else if (index === numberOfGalleryItems - 1 &&
31761							prevIndex === 0) {
31762							// prev slide
31763							touchNext = 0;
31764							touchPrev = numberOfGalleryItems - 1;
31765						}
31766					}
31767					else {
31768						touchPrev = 0;
31769						touchNext = 1;
31770					}
31771					if (direction === 'prev') {
31772						this.getSlideItem(touchNext).addClass('lg-next-slide');
31773					}
31774					else {
31775						this.getSlideItem(touchPrev).addClass('lg-prev-slide');
31776					}
31777					currentSlideItem.addClass('lg-current');
31778				}
31779				// Do not put load content in set timeout as it needs to load immediately when the gallery is opened
31780				if (!this.lGalleryOn) {
31781					this.loadContent(index, true);
31782				}
31783				else {
31784					setTimeout(function () {
31785						_this.loadContent(index, true);
31786						// Add title if this.settings.appendSubHtmlTo === lg-sub-html
31787						if (_this.settings.appendSubHtmlTo !== '.lg-item') {
31788							_this.addHtml(index);
31789						}
31790					}, this.settings.speed + 50 + (fromTouch ? 0 : this.settings.slideDelay));
31791				}
31792				setTimeout(function () {
31793					_this.lgBusy = false;
31794					previousSlideItem_1.removeClass('lg-slide-progress');
31795					_this.LGel.trigger(lGEvents.afterSlide, {
31796						prevIndex: prevIndex,
31797						index: index,
31798						fromTouch: fromTouch,
31799						fromThumb: fromThumb,
31800					});
31801				}, (this.lGalleryOn ? this.settings.speed + 100 : 100) + (fromTouch ? 0 : this.settings.slideDelay));
31802			}
31803			this.index = index;
31804		};
31805		LightGallery.prototype.updateCurrentCounter = function (index) {
31806			this.getElementById('lg-counter-current').html(index + 1 + '');
31807		};
31808		LightGallery.prototype.updateCounterTotal = function () {
31809			this.getElementById('lg-counter-all').html(this.galleryItems.length + '');
31810		};
31811		LightGallery.prototype.getSlideType = function (item) {
31812			if (item.__slideVideoInfo) {
31813				return 'video';
31814			}
31815			else if (item.iframe) {
31816				return 'iframe';
31817			}
31818			//Uncode edit ##START##
31819			else if (typeof item.src !== '' && item.src.search(/.mp3|.m4a/i) > -1) {
31820				return 'audio';
31821			}
31822			//Uncode edit ##END##
31823			else {
31824				return 'image';
31825			}
31826		};
31827		LightGallery.prototype.touchMove = function (startCoords, endCoords, e) {
31828			var distanceX = endCoords.pageX - startCoords.pageX;
31829			var distanceY = endCoords.pageY - startCoords.pageY;
31830			var allowSwipe = false;
31831			if (this.swipeDirection) {
31832				allowSwipe = true;
31833			}
31834			else {
31835				if (Math.abs(distanceX) > 15) {
31836					this.swipeDirection = 'horizontal';
31837					allowSwipe = true;
31838				}
31839				else if (Math.abs(distanceY) > 15) {
31840					this.swipeDirection = 'vertical';
31841					allowSwipe = true;
31842				}
31843			}
31844			if (!allowSwipe) {
31845				return;
31846			}
31847			var $currentSlide = this.getSlideItem(this.index);
31848			if (this.swipeDirection === 'horizontal') {
31849				e === null || e === void 0 ? void 0 : e.preventDefault();
31850				// reset opacity and transition duration
31851				this.outer.addClass('lg-dragging');
31852				// move current slide
31853				this.setTranslate($currentSlide, distanceX, 0);
31854				// move next and prev slide with current slide
31855				var width = $currentSlide.get().offsetWidth;
31856				var slideWidthAmount = (width * 15) / 100;
31857				var gutter = slideWidthAmount - Math.abs((distanceX * 10) / 100);
31858				this.setTranslate(this.outer.find('.lg-prev-slide').first(), -width + distanceX - gutter, 0);
31859				this.setTranslate(this.outer.find('.lg-next-slide').first(), width + distanceX + gutter, 0);
31860			}
31861			else if (this.swipeDirection === 'vertical') {
31862				if (this.settings.swipeToClose) {
31863					e === null || e === void 0 ? void 0 : e.preventDefault();
31864					this.$container.addClass('lg-dragging-vertical');
31865					var opacity = 1 - Math.abs(distanceY) / window.innerHeight;
31866					this.$backdrop.css('opacity', opacity);
31867					var scale = 1 - Math.abs(distanceY) / (window.innerWidth * 2);
31868					this.setTranslate($currentSlide, 0, distanceY, scale, scale);
31869					if (Math.abs(distanceY) > 100) {
31870						this.outer
31871							.addClass('lg-hide-items')
31872							.removeClass('lg-components-open');
31873					}
31874				}
31875			}
31876		};
31877		LightGallery.prototype.touchEnd = function (endCoords, startCoords, event) {
31878			var _this = this;
31879			var distance;
31880			// keep slide animation for any mode while dragg/swipe
31881			if (this.settings.mode !== 'lg-slide') {
31882				this.outer.addClass('lg-slide');
31883			}
31884			// set transition duration
31885			setTimeout(function () {
31886				_this.$container.removeClass('lg-dragging-vertical');
31887				_this.outer
31888					.removeClass('lg-dragging lg-hide-items')
31889					.addClass('lg-components-open');
31890				var triggerClick = true;
31891				if (_this.swipeDirection === 'horizontal') {
31892					distance = endCoords.pageX - startCoords.pageX;
31893					var distanceAbs = Math.abs(endCoords.pageX - startCoords.pageX);
31894					if (distance < 0 &&
31895						distanceAbs > _this.settings.swipeThreshold) {
31896						_this.goToNextSlide(true);
31897						triggerClick = false;
31898					}
31899					else if (distance > 0 &&
31900						distanceAbs > _this.settings.swipeThreshold) {
31901						_this.goToPrevSlide(true);
31902						triggerClick = false;
31903					}
31904				}
31905				else if (_this.swipeDirection === 'vertical') {
31906					distance = Math.abs(endCoords.pageY - startCoords.pageY);
31907					if (_this.settings.closable &&
31908						_this.settings.swipeToClose &&
31909						distance > 100) {
31910						_this.closeGallery();
31911						return;
31912					}
31913					else {
31914						_this.$backdrop.css('opacity', 1);
31915					}
31916				}
31917				_this.outer.find('.lg-item').removeAttr('style');
31918				if (triggerClick &&
31919					Math.abs(endCoords.pageX - startCoords.pageX) < 5) {
31920					// Trigger click if distance is less than 5 pix
31921					var target = $LG(event.target);
31922					if (_this.isPosterElement(target)) {
31923						_this.LGel.trigger(lGEvents.posterClick);
31924					}
31925				}
31926				_this.swipeDirection = undefined;
31927			});
31928			// remove slide class once drag/swipe is completed if mode is not slide
31929			setTimeout(function () {
31930				if (!_this.outer.hasClass('lg-dragging') &&
31931					_this.settings.mode !== 'lg-slide') {
31932					_this.outer.removeClass('lg-slide');
31933				}
31934			}, this.settings.speed + 100);
31935		};
31936		LightGallery.prototype.enableSwipe = function () {
31937			var _this = this;
31938			var startCoords = {};
31939			var endCoords = {};
31940			var isMoved = false;
31941			var isSwiping = false;
31942			if (this.settings.enableSwipe) {
31943				this.$inner.on('touchstart.lg', function (e) {
31944					_this.dragOrSwipeEnabled = true;
31945					var $item = _this.getSlideItem(_this.index);
31946					if (($LG(e.target).hasClass('lg-item') ||
31947						$item.get().contains(e.target)) &&
31948						!_this.outer.hasClass('lg-zoomed') &&
31949						!_this.lgBusy &&
31950						e.targetTouches.length === 1) {
31951						isSwiping = true;
31952						_this.touchAction = 'swipe';
31953						_this.manageSwipeClass();
31954						startCoords = {
31955							pageX: e.targetTouches[0].pageX,
31956							pageY: e.targetTouches[0].pageY,
31957						};
31958					}
31959				});
31960				this.$inner.on('touchmove.lg', function (e) {
31961					if (isSwiping &&
31962						_this.touchAction === 'swipe' &&
31963						e.targetTouches.length === 1) {
31964						endCoords = {
31965							pageX: e.targetTouches[0].pageX,
31966							pageY: e.targetTouches[0].pageY,
31967						};
31968						_this.touchMove(startCoords, endCoords, e);
31969						isMoved = true;
31970					}
31971				});
31972				this.$inner.on('touchend.lg', function (event) {
31973					if (_this.touchAction === 'swipe') {
31974						if (isMoved) {
31975							isMoved = false;
31976							_this.touchEnd(endCoords, startCoords, event);
31977						}
31978						else if (isSwiping) {
31979							var target = $LG(event.target);
31980							if (_this.isPosterElement(target)) {
31981								_this.LGel.trigger(lGEvents.posterClick);
31982							}
31983						}
31984						_this.touchAction = undefined;
31985						isSwiping = false;
31986					}
31987				});
31988			}
31989		};
31990		LightGallery.prototype.enableDrag = function () {
31991			var _this = this;
31992			var startCoords = {};
31993			var endCoords = {};
31994			var isDraging = false;
31995			var isMoved = false;
31996			if (this.settings.enableDrag) {
31997				this.outer.on('mousedown.lg', function (e) {
31998					_this.dragOrSwipeEnabled = true;
31999					var $item = _this.getSlideItem(_this.index);
32000					if ($LG(e.target).hasClass('lg-item') ||
32001						$item.get().contains(e.target)) {
32002						if (!_this.outer.hasClass('lg-zoomed') && !_this.lgBusy) {
32003							e.preventDefault();
32004							if (!_this.lgBusy) {
32005								_this.manageSwipeClass();
32006								startCoords = {
32007									pageX: e.pageX,
32008									pageY: e.pageY,
32009								};
32010								isDraging = true;
32011								// ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723
32012								_this.outer.get().scrollLeft += 1;
32013								_this.outer.get().scrollLeft -= 1;
32014								// *
32015								_this.outer
32016									.removeClass('lg-grab')
32017									.addClass('lg-grabbing');
32018								_this.LGel.trigger(lGEvents.dragStart);
32019							}
32020						}
32021					}
32022				});
32023				$LG(window).on("mousemove.lg.global" + this.lgId, function (e) {
32024					if (isDraging && _this.lgOpened) {
32025						isMoved = true;
32026						endCoords = {
32027							pageX: e.pageX,
32028							pageY: e.pageY,
32029						};
32030						_this.touchMove(startCoords, endCoords);
32031						_this.LGel.trigger(lGEvents.dragMove);
32032					}
32033				});
32034				$LG(window).on("mouseup.lg.global" + this.lgId, function (event) {
32035					if (!_this.lgOpened) {
32036						return;
32037					}
32038					var target = $LG(event.target);
32039					if (isMoved) {
32040						isMoved = false;
32041						_this.touchEnd(endCoords, startCoords, event);
32042						_this.LGel.trigger(lGEvents.dragEnd);
32043					}
32044					else if (_this.isPosterElement(target)) {
32045						_this.LGel.trigger(lGEvents.posterClick);
32046					}
32047					// Prevent execution on click
32048					if (isDraging) {
32049						isDraging = false;
32050						_this.outer.removeClass('lg-grabbing').addClass('lg-grab');
32051					}
32052				});
32053			}
32054		};
32055		LightGallery.prototype.triggerPosterClick = function () {
32056			var _this = this;
32057			this.$inner.on('click.lg', function (event) {
32058				if (!_this.dragOrSwipeEnabled &&
32059					_this.isPosterElement($LG(event.target))) {
32060					_this.LGel.trigger(lGEvents.posterClick);
32061				}
32062			});
32063		};
32064		LightGallery.prototype.manageSwipeClass = function () {
32065			var _touchNext = this.index + 1;
32066			var _touchPrev = this.index - 1;
32067			if (this.settings.loop && this.galleryItems.length > 2) {
32068				if (this.index === 0) {
32069					_touchPrev = this.galleryItems.length - 1;
32070				}
32071				else if (this.index === this.galleryItems.length - 1) {
32072					_touchNext = 0;
32073				}
32074			}
32075			this.outer.find('.lg-item').removeClass('lg-next-slide lg-prev-slide');
32076			if (_touchPrev > -1) {
32077				this.getSlideItem(_touchPrev).addClass('lg-prev-slide');
32078			}
32079			this.getSlideItem(_touchNext).addClass('lg-next-slide');
32080		};
32081		/**
32082		 * Go to next slide
32083		 * @param {Boolean} fromTouch - true if slide function called via touch event
32084		 * @category lGPublicMethods
32085		 * @example
32086		 *  const plugin = lightGallery();
32087		 *  plugin.goToNextSlide();
32088		 * @see <a href="/demos/methods/">Demo</a>
32089		 */
32090		LightGallery.prototype.goToNextSlide = function (fromTouch) {
32091			var _this = this;
32092			var _loop = this.settings.loop;
32093			if (fromTouch && this.galleryItems.length < 3) {
32094				_loop = false;
32095			}
32096			if (!this.lgBusy) {
32097				if (this.index + 1 < this.galleryItems.length) {
32098					this.index++;
32099					this.LGel.trigger(lGEvents.beforeNextSlide, {
32100						index: this.index,
32101					});
32102					this.slide(this.index, !!fromTouch, false, 'next');
32103				}
32104				else {
32105					if (_loop) {
32106						this.index = 0;
32107						this.LGel.trigger(lGEvents.beforeNextSlide, {
32108							index: this.index,
32109						});
32110						this.slide(this.index, !!fromTouch, false, 'next');
32111					}
32112					else if (this.settings.slideEndAnimation && !fromTouch) {
32113						this.outer.addClass('lg-right-end');
32114						setTimeout(function () {
32115							_this.outer.removeClass('lg-right-end');
32116						}, 400);
32117					}
32118				}
32119			}
32120		};
32121		/**
32122		 * Go to previous slides
32123		 * @param {Boolean} fromTouch - true if slide function called via touch event
32124		 * @category lGPublicMethods
32125		 * @example
32126		 *  const plugin = lightGallery({});
32127		 *  plugin.goToPrevSlide();
32128		 * @see <a href="/demos/methods/">Demo</a>
32129		 *
32130		 */
32131		LightGallery.prototype.goToPrevSlide = function (fromTouch) {
32132			var _this = this;
32133			var _loop = this.settings.loop;
32134			if (fromTouch && this.galleryItems.length < 3) {
32135				_loop = false;
32136			}
32137			if (!this.lgBusy) {
32138				if (this.index > 0) {
32139					this.index--;
32140					this.LGel.trigger(lGEvents.beforePrevSlide, {
32141						index: this.index,
32142						fromTouch: fromTouch,
32143					});
32144					this.slide(this.index, !!fromTouch, false, 'prev');
32145				}
32146				else {
32147					if (_loop) {
32148						this.index = this.galleryItems.length - 1;
32149						this.LGel.trigger(lGEvents.beforePrevSlide, {
32150							index: this.index,
32151							fromTouch: fromTouch,
32152						});
32153						this.slide(this.index, !!fromTouch, false, 'prev');
32154					}
32155					else if (this.settings.slideEndAnimation && !fromTouch) {
32156						this.outer.addClass('lg-left-end');
32157						setTimeout(function () {
32158							_this.outer.removeClass('lg-left-end');
32159						}, 400);
32160					}
32161				}
32162			}
32163		};
32164		LightGallery.prototype.keyPress = function () {
32165			var _this = this;
32166			$LG(window).on("keydown.lg.global" + this.lgId, function (e) {
32167				if (_this.lgOpened &&
32168					_this.settings.escKey === true &&
32169					e.keyCode === 27) {
32170					e.preventDefault();
32171					if (_this.settings.allowMediaOverlap &&
32172						_this.outer.hasClass('lg-can-toggle') &&
32173						_this.outer.hasClass('lg-components-open')) {
32174						_this.outer.removeClass('lg-components-open');
32175					}
32176					else {
32177						_this.closeGallery();
32178					}
32179				}
32180				if (_this.lgOpened && _this.galleryItems.length > 1) {
32181					if (e.keyCode === 37) {
32182						e.preventDefault();
32183						_this.goToPrevSlide();
32184					}
32185					if (e.keyCode === 39) {
32186						e.preventDefault();
32187						_this.goToNextSlide();
32188					}
32189				}
32190			});
32191		};
32192		LightGallery.prototype.arrow = function () {
32193			var _this = this;
32194			this.getElementById('lg-prev').on('click.lg', function () {
32195				_this.goToPrevSlide();
32196			});
32197			this.getElementById('lg-next').on('click.lg', function () {
32198				_this.goToNextSlide();
32199			});
32200		};
32201		LightGallery.prototype.arrowDisable = function (index) {
32202			// Disable arrows if settings.hideControlOnEnd is true
32203			if (!this.settings.loop && this.settings.hideControlOnEnd) {
32204				var $prev = this.getElementById('lg-prev');
32205				var $next = this.getElementById('lg-next');
32206				if (index + 1 === this.galleryItems.length) {
32207					$next.attr('disabled', 'disabled').addClass('disabled');
32208				}
32209				else {
32210					$next.removeAttr('disabled').removeClass('disabled');
32211				}
32212				if (index === 0) {
32213					$prev.attr('disabled', 'disabled').addClass('disabled');
32214				}
32215				else {
32216					$prev.removeAttr('disabled').removeClass('disabled');
32217				}
32218			}
32219		};
32220		LightGallery.prototype.setTranslate = function ($el, xValue, yValue, scaleX, scaleY) {
32221			if (scaleX === void 0) { scaleX = 1; }
32222			if (scaleY === void 0) { scaleY = 1; }
32223			$el.css('transform', 'translate3d(' +
32224				xValue +
32225				'px, ' +
32226				yValue +
32227				'px, 0px) scale3d(' +
32228				scaleX +
32229				', ' +
32230				scaleY +
32231				', 1)');
32232		};
32233		LightGallery.prototype.mousewheel = function () {
32234			var _this = this;
32235			var lastCall = 0;
32236			this.outer.on('wheel.lg', function (e) {
32237				if (!e.deltaY || _this.galleryItems.length < 2) {
32238					return;
32239				}
32240				e.preventDefault();
32241				var now = new Date().getTime();
32242				if (now - lastCall < 1000) {
32243					return;
32244				}
32245				lastCall = now;
32246				if (e.deltaY > 0) {
32247					_this.goToNextSlide();
32248				}
32249				else if (e.deltaY < 0) {
32250					_this.goToPrevSlide();
32251				}
32252			});
32253		};
32254		LightGallery.prototype.isSlideElement = function (target) {
32255			return (target.hasClass('lg-outer') ||
32256				target.hasClass('lg-item') ||
32257				target.hasClass('lg-img-wrap'));
32258		};
32259		LightGallery.prototype.isPosterElement = function (target) {
32260			var playButton = this.getSlideItem(this.index)
32261				.find('.lg-video-play-button')
32262				.get();
32263			return (target.hasClass('lg-video-poster') ||
32264				target.hasClass('lg-video-play-button') ||
32265				(playButton && playButton.contains(target.get())));
32266		};
32267		/**
32268		 * Maximize minimize inline gallery.
32269		 * @category lGPublicMethods
32270		 */
32271		LightGallery.prototype.toggleMaximize = function () {
32272			var _this = this;
32273			this.getElementById('lg-maximize').on('click.lg', function () {
32274				_this.$container.toggleClass('lg-inline');
32275				_this.refreshOnResize();
32276			});
32277		};
32278		LightGallery.prototype.invalidateItems = function () {
32279			for (var index = 0; index < this.items.length; index++) {
32280				var element = this.items[index];
32281				var $element = $LG(element);
32282				$element.off("click.lgcustom-item-" + $element.attr('data-lg-id'));
32283			}
32284		};
32285		LightGallery.prototype.trapFocus = function () {
32286			var _this = this;
32287			this.$container.get().focus({
32288				preventScroll: true,
32289			});
32290			$LG(window).on("keydown.lg.global" + this.lgId, function (e) {
32291				if (!_this.lgOpened) {
32292					return;
32293				}
32294				var isTabPressed = e.key === 'Tab' || e.keyCode === 9;
32295				if (!isTabPressed) {
32296					return;
32297				}
32298				var focusableEls = utils.getFocusableElements(_this.$container.get());
32299				var firstFocusableEl = focusableEls[0];
32300				var lastFocusableEl = focusableEls[focusableEls.length - 1];
32301				if (e.shiftKey) {
32302					if (document.activeElement === firstFocusableEl) {
32303						lastFocusableEl.focus();
32304						e.preventDefault();
32305					}
32306				}
32307				else {
32308					if (document.activeElement === lastFocusableEl) {
32309						firstFocusableEl.focus();
32310						e.preventDefault();
32311					}
32312				}
32313			});
32314		};
32315		LightGallery.prototype.manageCloseGallery = function () {
32316			var _this = this;
32317			if (!this.settings.closable)
32318				return;
32319			var mousedown = false;
32320			this.getElementById('lg-close').on('click.lg', function () {
32321				_this.closeGallery();
32322			});
32323			if (this.settings.closeOnTap) {
32324				// If you drag the slide and release outside gallery gets close on chrome
32325				// for preventing this check mousedown and mouseup happened on .lg-item or lg-outer
32326				this.outer.on('mousedown.lg', function (e) {
32327					var target = $LG(e.target);
32328					if (_this.isSlideElement(target)) {
32329						mousedown = true;
32330					}
32331					else {
32332						mousedown = false;
32333					}
32334				});
32335				this.outer.on('mousemove.lg', function () {
32336					mousedown = false;
32337				});
32338				this.outer.on('mouseup.lg', function (e) {
32339					var target = $LG(e.target);
32340					if (_this.isSlideElement(target) && mousedown) {
32341						if (!_this.outer.hasClass('lg-dragging')) {
32342							_this.closeGallery();
32343						}
32344					}
32345				});
32346			}
32347		};
32348		/**
32349		 * Close lightGallery if it is opened.
32350		 *
32351		 * @description If closable is false in the settings, you need to pass true via closeGallery method to force close gallery
32352		 * @return returns the estimated time to close gallery completely including the close animation duration
32353		 * @category lGPublicMethods
32354		 * @example
32355		 *  const plugin = lightGallery();
32356		 *  plugin.closeGallery();
32357		 *
32358		 */
32359		LightGallery.prototype.closeGallery = function (force) {
32360			var _this = this;
32361			if (!this.lgOpened || (!this.settings.closable && !force)) {
32362				return 0;
32363			}
32364			this.LGel.trigger(lGEvents.beforeClose);
32365			if (this.settings.resetScrollPosition && !this.settings.hideScrollbar) {
32366				$LG(window).scrollTop(this.prevScrollTop);
32367			}
32368			var currentItem = this.items[this.index];
32369			var transform;
32370			if (this.zoomFromOrigin && currentItem) {
32371				var _a = this.mediaContainerPosition, top_4 = _a.top, bottom = _a.bottom;
32372				var _b = this.galleryItems[this.index], __slideVideoInfo = _b.__slideVideoInfo, poster = _b.poster;
32373				//Uncode edit ##START##
32374				var imageSize = utils.getSize(currentItem, this.outer, top_4 + bottom, __slideVideoInfo && poster && this.settings.videoMaxSize, this.galleryItems[this.index]);
32375				// var imageSize = utils.getSize(currentItem, this.outer, top_4 + bottom, __slideVideoInfo && poster && this.settings.videoMaxSize);
32376				//Uncode edit ##END##
32377				transform = utils.getTransform(currentItem, this.outer, top_4, bottom, imageSize);
32378			}
32379			if (this.zoomFromOrigin && transform) {
32380				this.outer.addClass('lg-closing lg-zoom-from-image');
32381				this.getSlideItem(this.index)
32382					.addClass('lg-start-end-progress')
32383					.css('transition-duration', this.settings.startAnimationDuration + 'ms')
32384					.css('transform', transform);
32385			}
32386			else {
32387				this.outer.addClass('lg-hide-items');
32388				// lg-zoom-from-image is used for setting the opacity to 1 if zoomFromOrigin is true
32389				// If the closing item doesn't have the lg-size attribute, remove this class to avoid the closing css conflicts
32390				this.outer.removeClass('lg-zoom-from-image');
32391			}
32392			// Unbind all events added by lightGallery
32393			// @todo
32394			//this.$el.off('.lg.tm');
32395			this.destroyModules();
32396			this.lGalleryOn = false;
32397			this.isDummyImageRemoved = false;
32398			this.zoomFromOrigin = this.settings.zoomFromOrigin;
32399			clearTimeout(this.hideBarTimeout);
32400			this.hideBarTimeout = false;
32401			$LG('html').removeClass('lg-on');
32402			this.outer.removeClass('lg-visible lg-components-open');
32403			// Resetting opacity to 0 isd required as  vertical swipe to close function adds inline opacity.
32404			this.$backdrop.removeClass('in').css('opacity', 0);
32405			var removeTimeout = this.zoomFromOrigin && transform
32406				? Math.max(this.settings.startAnimationDuration, this.settings.backdropDuration)
32407				: this.settings.backdropDuration;
32408			this.$container.removeClass('lg-show-in');
32409			// Once the closign animation is completed and gallery is invisible
32410			setTimeout(function () {
32411				if (_this.zoomFromOrigin && transform) {
32412					_this.outer.removeClass('lg-zoom-from-image');
32413				}
32414				_this.$container.removeClass('lg-show');
32415				// Reset scrollbar
32416				_this.resetScrollBar();
32417				// Need to remove inline opacity as it is used in the stylesheet as well
32418				_this.$backdrop
32419					.removeAttr('style')
32420					.css('transition-duration', _this.settings.backdropDuration + 'ms');
32421				_this.outer.removeClass("lg-closing " + _this.settings.startClass);
vendor: 6,259 bytes, lines 32422-32625
32422				_this.getSlideItem(_this.index).removeClass('lg-start-end-progress');
32423				_this.$inner.empty();
32424				if (_this.lgOpened) {
32425					_this.LGel.trigger(lGEvents.afterClose, {
32426						instance: _this,
32427					});
32428				}
32429				if (_this.$container.get()) {
32430					_this.$container.get().blur();
32431				}
32432				_this.lgOpened = false;
32433			}, removeTimeout + 100);
32434			return removeTimeout + 100;
32435		};
32436		LightGallery.prototype.initModules = function () {
32437			this.plugins.forEach(function (module) {
32438				try {
32439					module.init();
32440				}
32441				catch (err) {
32442					console.warn("lightGallery:- make sure lightGallery module is properly initiated");
32443				}
32444			});
32445		};
32446		LightGallery.prototype.destroyModules = function (destroy) {
32447			this.plugins.forEach(function (module) {
32448				try {
32449					if (destroy) {
32450						module.destroy();
32451					}
32452					else {
32453						module.closeGallery && module.closeGallery();
32454					}
32455				}
32456				catch (err) {
32457					console.warn("lightGallery:- make sure lightGallery module is properly destroyed");
32458				}
32459			});
32460		};
32461		/**
32462		 * Refresh lightGallery with new set of children.
32463		 *
32464		 * @description This is useful to update the gallery when the child elements are changed without calling destroy method.
32465		 *
32466		 * If you are using dynamic mode, you can pass the modified array of dynamicEl as the first parameter to refresh the dynamic gallery
32467		 * @see <a href="/demos/dynamic-mode/">Demo</a>
32468		 * @category lGPublicMethods
32469		 * @example
32470		 *  const plugin = lightGallery();
32471		 *  // Delete or add children, then call
32472		 *  plugin.refresh();
32473		 *
32474		 */
32475		LightGallery.prototype.refresh = function (galleryItems) {
32476			if (!this.settings.dynamic) {
32477				this.invalidateItems();
32478			}
32479			if (galleryItems) {
32480				this.galleryItems = galleryItems;
32481			}
32482			else {
32483				this.galleryItems = this.getItems();
32484			}
32485			this.updateControls();
32486			this.openGalleryOnItemClick();
32487			this.LGel.trigger(lGEvents.updateSlides);
32488		};
32489		LightGallery.prototype.updateControls = function () {
32490			this.addSlideVideoInfo(this.galleryItems);
32491			this.updateCounterTotal();
32492			this.manageSingleSlideClassName();
32493		};
32494		/**
32495		 * Destroy lightGallery.
32496		 * Destroy lightGallery and its plugin instances completely
32497		 *
32498		 * @description This method also calls CloseGallery function internally. Returns the time takes to completely close and destroy the instance.
32499		 * In case if you want to re-initialize lightGallery right after destroying it, initialize it only once the destroy process is completed.
32500		 * You can use refresh method most of the times.
32501		 * @category lGPublicMethods
32502		 * @example
32503		 *  const plugin = lightGallery();
32504		 *  plugin.destroy();
32505		 *
32506		 */
32507		LightGallery.prototype.destroy = function () {
32508			var _this = this;
32509			var closeTimeout = this.closeGallery(true);
32510			setTimeout(function () {
32511				_this.destroyModules(true);
32512				if (!_this.settings.dynamic) {
32513					_this.invalidateItems();
32514				}
32515				$LG(window).off(".lg.global" + _this.lgId);
32516				_this.LGel.off('.lg');
32517				_this.$container.remove();
32518			}, closeTimeout);
32519			return closeTimeout;
32520		};
32521		return LightGallery;
32522	}());
32523
32524	function lightGallery(el, options) {
32525		return new LightGallery(el, options);
32526	}
32527
32528	return lightGallery;
32529
32530})));
32531
32532/*!
32533 * lightgallery | 2.5.0 | June 13th 2022
32534 * http://www.lightgalleryjs.com/
32535 * Copyright (c) 2020 Sachin Neravath;
32536 * @license GPLv3
32537 */
32538
32539(function (global, factory) {
32540	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
32541	typeof define === 'function' && define.amd ? define(factory) :
32542	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgZoom = factory());
32543}(this, (function () { 'use strict';
32544
32545	/*! *****************************************************************************
32546	Copyright (c) Microsoft Corporation.
32547
32548	Permission to use, copy, modify, and/or distribute this software for any
32549	purpose with or without fee is hereby granted.
32550
32551	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
32552	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
32553	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
32554	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
32555	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
32556	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
32557	PERFORMANCE OF THIS SOFTWARE.
32558	***************************************************************************** */
32559
32560	var __assign = function() {
32561		__assign = Object.assign || function __assign(t) {
32562			for (var s, i = 1, n = arguments.length; i < n; i++) {
32563				s = arguments[i];
32564				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
32565			}
32566			return t;
32567		};
32568		return __assign.apply(this, arguments);
32569	};
32570
32571	var zoomSettings = {
32572		scale: 1,
32573		zoom: true,
32574		actualSize: true,
32575		showZoomInOutIcons: false,
32576		actualSizeIcons: {
32577			zoomIn: 'lg-zoom-in',
32578			zoomOut: 'lg-zoom-out',
32579		},
32580		enableZoomAfter: 300,
32581		zoomPluginStrings: {
32582			zoomIn: 'Zoom in',
32583			zoomOut: 'Zoom out',
32584			viewActualSize: 'View actual size',
32585		},
32586	};
32587
32588	/**
32589	 * List of lightGallery events
32590	 * All events should be documented here
32591	 * Below interfaces are used to build the website documentations
32592	 * */
32593	var lGEvents = {
32594		afterAppendSlide: 'lgAfterAppendSlide',
32595		init: 'lgInit',
32596		hasVideo: 'lgHasVideo',
32597		containerResize: 'lgContainerResize',
32598		updateSlides: 'lgUpdateSlides',
32599		afterAppendSubHtml: 'lgAfterAppendSubHtml',
32600		beforeOpen: 'lgBeforeOpen',
32601		afterOpen: 'lgAfterOpen',
32602		slideItemLoad: 'lgSlideItemLoad',
32603		beforeSlide: 'lgBeforeSlide',
32604		afterSlide: 'lgAfterSlide',
32605		posterClick: 'lgPosterClick',
32606		dragStart: 'lgDragStart',
32607		dragMove: 'lgDragMove',
32608		dragEnd: 'lgDragEnd',
32609		beforeNextSlide: 'lgBeforeNextSlide',
32610		beforePrevSlide: 'lgBeforePrevSlide',
32611		beforeClose: 'lgBeforeClose',
32612		afterClose: 'lgAfterClose',
32613		rotateLeft: 'lgRotateLeft',
32614		rotateRight: 'lgRotateRight',
32615		flipHorizontal: 'lgFlipHorizontal',
32616		flipVertical: 'lgFlipVertical',
32617		autoplay: 'lgAutoplay',
32618		autoplayStart: 'lgAutoplayStart',
32619		autoplayStop: 'lgAutoplayStop',
32620	};
32621
32622	var Zoom = /** @class */ (function () {
32623		function Zoom(instance, $LG) {
32624			// get lightGallery core plugin instance
32625			this.core = instance;
32626			this.$LG = $LG;
32627			this.settings = __assign(__assign({}, zoomSettings), this.core.settings);
32628			return this;
32629		}
32630		// Append Zoom controls. Actual size, Zoom-in, Zoom-out
32631		Zoom.prototype.buildTemplates = function () {
32632			var zoomIcons = this.settings.showZoomInOutIcons
32633				? "<button id=\"" + this.core.getIdName('lg-zoom-in') + "\" type=\"button\" aria-label=\"" + this.settings.zoomPluginStrings['zoomIn'] + "\" class=\"lg-zoom-in lg-icon\"></button><button id=\"" + this.core.getIdName('lg-zoom-out') + "\" type=\"button\" aria-label=\"" + this.settings.zoomPluginStrings['zoomIn'] + "\" class=\"lg-zoom-out lg-icon\"></button>"
32634				: '';
32635			if (this.settings.actualSize) {
32636				zoomIcons += "<button id=\"" + this.core.getIdName('lg-actual-size') + "\" type=\"button\" aria-label=\"" + this.settings.zoomPluginStrings['viewActualSize'] + "\" class=\"" + this.settings.actualSizeIcons.zoomIn + " lg-icon\"></button>";
32637			}
32638			this.core.outer.addClass('lg-use-transition-for-zoom');
32639			this.core.$toolbar.first().append(zoomIcons);
32640		};
32641		/**
32642		 * @desc Enable zoom option only once the image is completely loaded
32643		 * If zoomFromOrigin is true, Zoom is enabled once the dummy image has been inserted
32644		 *
32645		 * Zoom styles are defined under lg-zoomable CSS class.
32646		 */
32647		Zoom.prototype.enableZoom = function (event) {
32648			var _this = this;
32649			// delay will be 0 except first time
32650			var _speed = this.settings.enableZoomAfter + event.detail.delay;
32651			// set _speed value 0 if gallery opened from direct url and if it is first slide
32652			if (this.$LG('body').first().hasClass('lg-from-hash') &&
32653				event.detail.delay) {
32654				// will execute only once
32655				_speed = 0;
32656			}
32657			else {
32658				// Remove lg-from-hash to enable starting animation.
32659				this.$LG('body').first().removeClass('lg-from-hash');
32660			}
32661			this.zoomableTimeout = setTimeout(function () {
32662				if (!_this.isImageSlide()) {
32663					return;
32664				}
32665				_this.core.getSlideItem(event.detail.index).addClass('lg-zoomable');
32666				if (event.detail.index === _this.core.index) {
32667					_this.setZoomEssentials();
32668				}
32669			}, _speed + 30);
32670		};
32671		Zoom.prototype.enableZoomOnSlideItemLoad = function () {
32672			// Add zoomable class
32673			this.core.LGel.on(lGEvents.slideItemLoad + ".zoom", this.enableZoom.bind(this));
32674		};
32675		Zoom.prototype.getModifier = function (rotateValue, axis, el) {
32676			var originalRotate = rotateValue;
32677			rotateValue = Math.abs(rotateValue);
32678			var transformValues = this.getCurrentTransform(el);
32679			if (!transformValues) {
32680				return 1;
32681			}
32682			var modifier = 1;
32683			if (axis === 'X') {
32684				var flipHorizontalValue = Math.sign(parseFloat(transformValues[0]));
32685				if (rotateValue === 0 || rotateValue === 180) {
32686					modifier = 1;
32687				}
32688				else if (rotateValue === 90) {
32689					if ((originalRotate === -90 && flipHorizontalValue === 1) ||
32690						(originalRotate === 90 && flipHorizontalValue === -1)) {
32691						modifier = -1;
32692					}
32693					else {
32694						modifier = 1;
32695					}
32696				}
32697				modifier = modifier * flipHorizontalValue;
32698			}
32699			else {
32700				var flipVerticalValue = Math.sign(parseFloat(transformValues[3]));
32701				if (rotateValue === 0 || rotateValue === 180) {
32702					modifier = 1;
32703				}
32704				else if (rotateValue === 90) {
32705					var sinX = parseFloat(transformValues[1]);
32706					var sinMinusX = parseFloat(transformValues[2]);
32707					modifier = Math.sign(sinX * sinMinusX * originalRotate * flipVerticalValue);
32708				}
32709				modifier = modifier * flipVerticalValue;
32710			}
32711			return modifier;
32712		};
32713		Zoom.prototype.getImageSize = function ($image, rotateValue, axis) {
32714			var imageSizes = {
32715				y: 'offsetHeight',
32716				x: 'offsetWidth',
32717			};
32718			if (Math.abs(rotateValue) === 90) {
32719				// Swap axis
32720				if (axis === 'x') {
32721					axis = 'y';
32722				}
32723				else {
32724					axis = 'x';
32725				}
32726			}
32727			return $image[imageSizes[axis]];
32728		};
32729		Zoom.prototype.getDragCords = function (e, rotateValue) {
32730			if (rotateValue === 90) {
32731				return {
32732					x: e.pageY,
32733					y: e.pageX,
32734				};
32735			}
32736			else {
32737				return {
32738					x: e.pageX,
32739					y: e.pageY,
32740				};
32741			}
32742		};
32743		Zoom.prototype.getSwipeCords = function (e, rotateValue) {
32744			var x = e.targetTouches[0].pageX;
32745			var y = e.targetTouches[0].pageY;
32746			if (rotateValue === 90) {
32747				return {
32748					x: y,
32749					y: x,
32750				};
32751			}
32752			else {
32753				return {
32754					x: x,
32755					y: y,
32756				};
32757			}
32758		};
32759		Zoom.prototype.getDragAllowedAxises = function (rotateValue, scale) {
32760			scale = scale || this.scale || 1;
32761			var allowY = this.imageYSize * scale > this.containerRect.height;
32762			var allowX = this.imageXSize * scale > this.containerRect.width;
32763			if (rotateValue === 90) {
32764				return {
32765					allowX: allowY,
32766					allowY: allowX,
32767				};
32768			}
32769			else {
32770				return {
32771					allowX: allowX,
32772					allowY: allowY,
32773				};
32774			}
32775		};
32776		/**
32777		 *
32778		 * @param {Element} el
32779		 * @return matrix(cos(X), sin(X), -sin(X), cos(X), 0, 0);
32780		 * Get the current transform value
32781		 */
32782		Zoom.prototype.getCurrentTransform = function (el) {
32783			if (!el) {
32784				return;
32785			}
32786			var st = window.getComputedStyle(el, null);
32787			var tm = st.getPropertyValue('-webkit-transform') ||
32788				st.getPropertyValue('-moz-transform') ||
32789				st.getPropertyValue('-ms-transform') ||
32790				st.getPropertyValue('-o-transform') ||
32791				st.getPropertyValue('transform') ||
32792				'none';
32793			if (tm !== 'none') {
32794				return tm.split('(')[1].split(')')[0].split(',');
32795			}
32796			return;
32797		};
32798		Zoom.prototype.getCurrentRotation = function (el) {
32799			if (!el) {
32800				return 0;
32801			}
32802			var values = this.getCurrentTransform(el);
32803			if (values) {
32804				return Math.round(Math.atan2(parseFloat(values[1]), parseFloat(values[0])) *
32805					(180 / Math.PI));
32806				// If you want rotate in 360
32807				//return (angle < 0 ? angle + 360 : angle);
32808			}
32809			return 0;
32810		};
32811		Zoom.prototype.setZoomEssentials = function () {
32812			var $image = this.core
32813				.getSlideItem(this.core.index)
32814				.find('.lg-image')
32815				.first();
32816			var rotateEl = this.core
32817				.getSlideItem(this.core.index)
32818				.find('.lg-img-rotate')
32819				.first()
32820				.get();
32821			this.rotateValue = this.getCurrentRotation(rotateEl);
32822			this.imageYSize = this.getImageSize($image.get(), this.rotateValue, 'y');
32823			this.imageXSize = this.getImageSize($image.get(), this.rotateValue, 'x');
32824			this.containerRect = this.core.outer.get().getBoundingClientRect();
32825			this.modifierX = this.getModifier(this.rotateValue, 'X', rotateEl);
32826			this.modifierY = this.getModifier(this.rotateValue, 'Y', rotateEl);
32827		};
32828		/**
32829		 * @desc Image zoom
32830		 * Translate the wrap and scale the image to get better user experience
32831		 *
32832		 * @param {String} scale - Zoom decrement/increment value
32833		 */
32834		Zoom.prototype.zoomImage = function (scale) {
32835			// Find offset manually to avoid issue after zoom
32836			var offsetX = (this.containerRect.width - this.imageXSize) / 2 +
32837				this.containerRect.left;
32838			var _a = this.core.mediaContainerPosition, top = _a.top, bottom = _a.bottom;
32839			var topBottomSpacing = Math.abs(top - bottom) / 2;
32840			var offsetY = (this.containerRect.height -
32841				this.imageYSize -
32842				topBottomSpacing * this.modifierX) /
32843				2 +
32844				this.scrollTop +
32845				this.containerRect.top;
32846			var originalX;
32847			var originalY;
32848			if (scale === 1) {
32849				this.positionChanged = false;
32850			}
32851			var dragAllowedAxises = this.getDragAllowedAxises(Math.abs(this.rotateValue), scale);
32852			var allowY = dragAllowedAxises.allowY, allowX = dragAllowedAxises.allowX;
32853			if (this.positionChanged) {
32854				originalX = this.left / (this.scale - 1);
32855				originalY = this.top / (this.scale - 1);
32856				this.pageX = Math.abs(originalX) + offsetX;
32857				this.pageY = Math.abs(originalY) + offsetY;
32858				this.positionChanged = false;
32859			}
32860			var possibleSwipeCords = this.getPossibleSwipeDragCords(this.rotateValue, scale);
32861			var _x = offsetX - this.pageX;
32862			var _y = offsetY - this.pageY;
32863			var x = (scale - 1) * _x;
32864			var y = (scale - 1) * _y;
32865			if (allowX) {
32866				if (this.isBeyondPossibleLeft(x, possibleSwipeCords.minX)) {
32867					x = possibleSwipeCords.minX;
32868				}
32869				else if (this.isBeyondPossibleRight(x, possibleSwipeCords.maxX)) {
32870					x = possibleSwipeCords.maxX;
32871				}
32872			}
32873			else {
32874				if (scale > 1) {
32875					if (x < possibleSwipeCords.minX) {
32876						x = possibleSwipeCords.minX;
32877					}
32878					else if (x > possibleSwipeCords.maxX) {
32879						x = possibleSwipeCords.maxX;
32880					}
32881				}
32882			}
32883			if (allowY) {
32884				if (this.isBeyondPossibleTop(y, possibleSwipeCords.minY)) {
32885					y = possibleSwipeCords.minY;
32886				}
32887				else if (this.isBeyondPossibleBottom(y, possibleSwipeCords.maxY)) {
32888					y = possibleSwipeCords.maxY;
32889				}
32890			}
32891			else {
32892				// If the translate value based on index of beyond the viewport, utilize the available space to prevent image being cut out
32893				if (scale > 1) {
32894					//If image goes beyond viewport top, use the minim possible translate value
32895					if (y < possibleSwipeCords.minY) {
32896						y = possibleSwipeCords.minY;
32897					}
32898					else if (y > possibleSwipeCords.maxY) {
32899						y = possibleSwipeCords.maxY;
32900					}
32901				}
32902			}
32903			this.setZoomStyles({
32904				x: x,
32905				y: y,
32906				scale: scale,
32907			});
32908		};
32909		/**
32910		 * @desc apply scale3d to image and translate to image wrap
32911		 * @param {style} X,Y and scale
32912		 */
32913		Zoom.prototype.setZoomStyles = function (style) {
32914			var $image = this.core
32915				.getSlideItem(this.core.index)
32916				.find('.lg-image')
32917				.first();
32918			var $dummyImage = this.core.outer
32919				.find('.lg-current .lg-dummy-img')
32920				.first();
32921			var $imageWrap = $image.parent();
32922			this.scale = style.scale;
32923			$image.css('transform', 'scale3d(' + style.scale + ', ' + style.scale + ', 1)');
32924			$dummyImage.css('transform', 'scale3d(' + style.scale + ', ' + style.scale + ', 1)');
32925			var transform = 'translate3d(' + style.x + 'px, ' + style.y + 'px, 0)';
32926			$imageWrap.css('transform', transform);
32927			this.left = style.x;
32928			this.top = style.y;
32929		};
32930		/**
32931		 * @param index - Index of the current slide
32932		 * @param event - event will be available only if the function is called on clicking/taping the imags
32933		 */
32934		Zoom.prototype.setActualSize = function (index, event) {
32935			var _this = this;
32936			// Allow zoom only on image
32937			if (!this.isImageSlide() ||
32938				this.core.outer.hasClass('lg-first-slide-loading')) {
32939				return;
32940			}
32941			var scale = this.getCurrentImageActualSizeScale();
32942			if (this.core.outer.hasClass('lg-zoomed')) {
32943				this.scale = 1;
32944			}
32945			else {
32946				this.scale = this.getScale(scale);
32947			}
32948			this.setPageCords(event);
32949			this.beginZoom(this.scale);
32950			this.zoomImage(this.scale);
32951			setTimeout(function () {
32952				_this.core.outer.removeClass('lg-grabbing').addClass('lg-grab');
32953			}, 10);
32954		};
32955		Zoom.prototype.getNaturalWidth = function (index) {
32956			var $image = this.core.getSlideItem(index).find('.lg-image').first();
32957			var naturalWidth = this.core.galleryItems[index].width;
32958			return naturalWidth
32959				? parseFloat(naturalWidth)
32960				: $image.get().naturalWidth;
32961		};
32962		Zoom.prototype.getActualSizeScale = function (naturalWidth, width) {
32963			var _scale;
32964			var scale;
32965			if (naturalWidth > width) {
32966				_scale = naturalWidth / width;
32967				scale = _scale || 2;
32968			}
32969			else {
32970				scale = 1;
32971			}
32972			return scale;
32973		};
32974		Zoom.prototype.getCurrentImageActualSizeScale = function () {
32975			var $image = this.core
32976				.getSlideItem(this.core.index)
32977				.find('.lg-image')
32978				.first();
32979			var width = $image.get().offsetWidth;
32980			var naturalWidth = this.getNaturalWidth(this.core.index) || width;
32981			return this.getActualSizeScale(naturalWidth, width);
32982		};
32983		Zoom.prototype.getPageCords = function (event) {
32984			var cords = {};
32985			if (event) {
32986				cords.x = event.pageX || event.targetTouches[0].pageX;
32987				cords.y = event.pageY || event.targetTouches[0].pageY;
32988			}
32989			else {
32990				var containerRect = this.core.outer.get().getBoundingClientRect();
32991				cords.x = containerRect.width / 2 + containerRect.left;
32992				cords.y =
32993					containerRect.height / 2 + this.scrollTop + containerRect.top;
32994			}
32995			return cords;
32996		};
32997		Zoom.prototype.setPageCords = function (event) {
32998			var pageCords = this.getPageCords(event);
32999			this.pageX = pageCords.x;
33000			this.pageY = pageCords.y;
33001		};
33002		// If true, zoomed - in else zoomed out
33003		Zoom.prototype.beginZoom = function (scale) {
33004			this.core.outer.removeClass('lg-zoom-drag-transition lg-zoom-dragging');
33005			if (scale > 1) {
33006				this.core.outer.addClass('lg-zoomed');
33007				var $actualSize = this.core.getElementById('lg-actual-size');
33008				$actualSize
33009					.removeClass(this.settings.actualSizeIcons.zoomIn)
33010					.addClass(this.settings.actualSizeIcons.zoomOut);
33011			}
33012			else {
33013				this.resetZoom();
33014			}
33015			return scale > 1;
33016		};
33017		Zoom.prototype.getScale = function (scale) {
33018			var actualSizeScale = this.getCurrentImageActualSizeScale();
33019			if (scale < 1) {
33020				scale = 1;
33021			}
33022			else if (scale > actualSizeScale) {
33023				scale = actualSizeScale;
33024			}
33025			return scale;
33026		};
33027		Zoom.prototype.init = function () {
33028			var _this = this;
33029			if (!this.settings.zoom) {
33030				return;
33031			}
33032			this.buildTemplates();
33033			this.enableZoomOnSlideItemLoad();
33034			var tapped = null;
33035			this.core.outer.on('dblclick.lg', function (event) {
33036				if (!_this.$LG(event.target).hasClass('lg-image')) {
33037					return;
33038				}
33039				_this.setActualSize(_this.core.index, event);
33040			});
33041			this.core.outer.on('touchstart.lg', function (event) {
33042				var $target = _this.$LG(event.target);
33043				if (event.targetTouches.length === 1 &&
33044					$target.hasClass('lg-image')) {
33045					if (!tapped) {
33046						tapped = setTimeout(function () {
33047							tapped = null;
33048						}, 300);
33049					}
33050					else {
33051						clearTimeout(tapped);
33052						tapped = null;
33053						event.preventDefault();
33054						_this.setActualSize(_this.core.index, event);
33055					}
33056				}
33057			});
33058			// Update zoom on resize and orientationchange
33059			this.core.LGel.on(lGEvents.containerResize + ".zoom " + lGEvents.rotateRight + ".zoom " + lGEvents.rotateLeft + ".zoom " + lGEvents.flipHorizontal + ".zoom " + lGEvents.flipVertical + ".zoom", function () {
33060				if (!_this.core.lgOpened || !_this.isImageSlide())
33061					return;
33062				_this.setPageCords();
33063				_this.setZoomEssentials();
33064				_this.zoomImage(_this.scale);
33065			});
33066			// Update zoom on resize and orientationchange
33067			this.$LG(window).on("scroll.lg.zoom.global" + this.core.lgId, function () {
33068				if (!_this.core.lgOpened)
33069					return;
33070				_this.scrollTop = _this.$LG(window).scrollTop();
33071			});
33072			this.core.getElementById('lg-zoom-out').on('click.lg', function () {
33073				if (_this.core.outer.find('.lg-current .lg-image').get()) {
33074					_this.scale -= _this.settings.scale;
33075					_this.scale = _this.getScale(_this.scale);
33076					_this.beginZoom(_this.scale);
33077					_this.zoomImage(_this.scale);
33078				}
33079			});
33080			this.core.getElementById('lg-zoom-in').on('click.lg', function () {
33081				_this.zoomIn();
33082			});
33083			this.core.getElementById('lg-actual-size').on('click.lg', function () {
33084				_this.setActualSize(_this.core.index);
33085			});
33086			this.core.LGel.on(lGEvents.beforeOpen + ".zoom", function () {
33087				_this.core.outer.find('.lg-item').removeClass('lg-zoomable');
33088			});
33089			this.core.LGel.on(lGEvents.afterOpen + ".zoom", function () {
33090				_this.scrollTop = _this.$LG(window).scrollTop();
33091				// Set the initial value center
33092				_this.pageX = _this.core.outer.width() / 2;
33093				_this.pageY = _this.core.outer.height() / 2 + _this.scrollTop;
33094				_this.scale = 1;
33095			});
33096			// Reset zoom on slide change
33097			this.core.LGel.on(lGEvents.afterSlide + ".zoom", function (event) {
33098				var prevIndex = event.detail.prevIndex;
33099				_this.scale = 1;
33100				_this.positionChanged = false;
33101				_this.resetZoom(prevIndex);
33102				if (_this.isImageSlide()) {
33103					_this.setZoomEssentials();
33104				}
33105			});
33106			// Drag option after zoom
33107			this.zoomDrag();
33108			this.pinchZoom();
33109			this.zoomSwipe();
33110			// Store the zoomable timeout value just to clear it while closing
33111			this.zoomableTimeout = false;
33112			this.positionChanged = false;
33113		};
33114		Zoom.prototype.zoomIn = function (scale) {
33115			// Allow zoom only on image
33116			if (!this.isImageSlide()) {
33117				return;
33118			}
33119			if (scale) {
33120				this.scale = scale;
33121			}
33122			else {
33123				this.scale += this.settings.scale;
33124			}
33125			this.scale = this.getScale(this.scale);
33126			this.beginZoom(this.scale);
33127			this.zoomImage(this.scale);
33128		};
33129		// Reset zoom effect
33130		Zoom.prototype.resetZoom = function (index) {
33131			this.core.outer.removeClass('lg-zoomed lg-zoom-drag-transition');
33132			var $actualSize = this.core.getElementById('lg-actual-size');
33133			var $item = this.core.getSlideItem(index !== undefined ? index : this.core.index);
33134			$actualSize
33135				.removeClass(this.settings.actualSizeIcons.zoomOut)
33136				.addClass(this.settings.actualSizeIcons.zoomIn);
33137			$item.find('.lg-img-wrap').first().removeAttr('style');
33138			$item.find('.lg-image').first().removeAttr('style');
33139			this.scale = 1;
33140			this.left = 0;
33141			this.top = 0;
33142			// Reset pagx pagy values to center
33143			this.setPageCords();
33144		};
33145		Zoom.prototype.getTouchDistance = function (e) {
33146			return Math.sqrt((e.targetTouches[0].pageX - e.targetTouches[1].pageX) *
33147				(e.targetTouches[0].pageX - e.targetTouches[1].pageX) +
33148				(e.targetTouches[0].pageY - e.targetTouches[1].pageY) *
33149					(e.targetTouches[0].pageY - e.targetTouches[1].pageY));
33150		};
33151		Zoom.prototype.pinchZoom = function () {
33152			var _this = this;
33153			var startDist = 0;
33154			var pinchStarted = false;
33155			var initScale = 1;
33156			var $item = this.core.getSlideItem(this.core.index);
33157			this.core.$inner.on('touchstart.lg', function (e) {
33158				$item = _this.core.getSlideItem(_this.core.index);
33159				if (!_this.isImageSlide()) {
33160					return;
33161				}
33162				if (e.targetTouches.length === 2 &&
33163					!_this.core.outer.hasClass('lg-first-slide-loading') &&
33164					(_this.$LG(e.target).hasClass('lg-item') ||
33165						$item.get().contains(e.target))) {
33166					initScale = _this.scale || 1;
33167					_this.core.outer.removeClass('lg-zoom-drag-transition lg-zoom-dragging');
33168					_this.core.touchAction = 'pinch';
33169					startDist = _this.getTouchDistance(e);
33170				}
33171			});
33172			this.core.$inner.on('touchmove.lg', function (e) {
33173				if (e.targetTouches.length === 2 &&
33174					_this.core.touchAction === 'pinch' &&
33175					(_this.$LG(e.target).hasClass('lg-item') ||
33176						$item.get().contains(e.target))) {
33177					e.preventDefault();
33178					var endDist = _this.getTouchDistance(e);
33179					var distance = startDist - endDist;
33180					if (!pinchStarted && Math.abs(distance) > 5) {
33181						pinchStarted = true;
33182					}
33183					if (pinchStarted) {
33184						_this.scale = Math.max(1, initScale + -distance * 0.008);
33185						_this.zoomImage(_this.scale);
33186					}
33187				}
33188			});
33189			this.core.$inner.on('touchend.lg', function (e) {
33190				if (_this.core.touchAction === 'pinch' &&
33191					(_this.$LG(e.target).hasClass('lg-item') ||
33192						$item.get().contains(e.target))) {
33193					pinchStarted = false;
33194					startDist = 0;
33195					if (_this.scale <= 1) {
33196						_this.resetZoom();
33197					}
33198					else {
33199						_this.scale = _this.getScale(_this.scale);
33200						_this.zoomImage(_this.scale);
33201						_this.core.outer.addClass('lg-zoomed');
33202					}
33203					_this.core.touchAction = undefined;
33204				}
33205			});
33206		};
33207		Zoom.prototype.touchendZoom = function (startCoords, endCoords, allowX, allowY, touchDuration, rotateValue) {
33208			var distanceXnew = endCoords.x - startCoords.x;
33209			var distanceYnew = endCoords.y - startCoords.y;
33210			var speedX = Math.abs(distanceXnew) / touchDuration + 1;
33211			var speedY = Math.abs(distanceYnew) / touchDuration + 1;
33212			if (speedX > 2) {
33213				speedX += 1;
33214			}
33215			if (speedY > 2) {
33216				speedY += 1;
33217			}
33218			distanceXnew = distanceXnew * speedX;
33219			distanceYnew = distanceYnew * speedY;
33220			var _LGel = this.core
33221				.getSlideItem(this.core.index)
33222				.find('.lg-img-wrap')
33223				.first();
33224			var distance = {};
33225			distance.x = this.left + distanceXnew * this.modifierX;
33226			distance.y = this.top + distanceYnew * this.modifierY;
33227			var possibleSwipeCords = this.getPossibleSwipeDragCords(rotateValue);
33228			if (Math.abs(distanceXnew) > 15 || Math.abs(distanceYnew) > 15) {
33229				if (allowY) {
33230					if (this.isBeyondPossibleTop(distance.y, possibleSwipeCords.minY)) {
33231						distance.y = possibleSwipeCords.minY;
33232					}
33233					else if (this.isBeyondPossibleBottom(distance.y, possibleSwipeCords.maxY)) {
33234						distance.y = possibleSwipeCords.maxY;
33235					}
33236				}
33237				if (allowX) {
33238					if (this.isBeyondPossibleLeft(distance.x, possibleSwipeCords.minX)) {
33239						distance.x = possibleSwipeCords.minX;
33240					}
33241					else if (this.isBeyondPossibleRight(distance.x, possibleSwipeCords.maxX)) {
33242						distance.x = possibleSwipeCords.maxX;
33243					}
33244				}
33245				if (allowY) {
33246					this.top = distance.y;
33247				}
33248				else {
33249					distance.y = this.top;
33250				}
33251				if (allowX) {
33252					this.left = distance.x;
33253				}
33254				else {
33255					distance.x = this.left;
33256				}
33257				this.setZoomSwipeStyles(_LGel, distance);
33258				this.positionChanged = true;
33259			}
33260		};
33261		Zoom.prototype.getZoomSwipeCords = function (startCoords, endCoords, allowX, allowY, possibleSwipeCords) {
33262			var distance = {};
33263			if (allowY) {
33264				distance.y =
33265					this.top + (endCoords.y - startCoords.y) * this.modifierY;
33266				if (this.isBeyondPossibleTop(distance.y, possibleSwipeCords.minY)) {
33267					var diffMinY = possibleSwipeCords.minY - distance.y;
33268					distance.y = possibleSwipeCords.minY - diffMinY / 6;
33269				}
33270				else if (this.isBeyondPossibleBottom(distance.y, possibleSwipeCords.maxY)) {
33271					var diffMaxY = distance.y - possibleSwipeCords.maxY;
33272					distance.y = possibleSwipeCords.maxY + diffMaxY / 6;
33273				}
33274			}
33275			else {
33276				distance.y = this.top;
33277			}
33278			if (allowX) {
33279				distance.x =
33280					this.left + (endCoords.x - startCoords.x) * this.modifierX;
33281				if (this.isBeyondPossibleLeft(distance.x, possibleSwipeCords.minX)) {
33282					var diffMinX = possibleSwipeCords.minX - distance.x;
33283					distance.x = possibleSwipeCords.minX - diffMinX / 6;
33284				}
33285				else if (this.isBeyondPossibleRight(distance.x, possibleSwipeCords.maxX)) {
33286					var difMaxX = distance.x - possibleSwipeCords.maxX;
33287					distance.x = possibleSwipeCords.maxX + difMaxX / 6;
33288				}
33289			}
33290			else {
33291				distance.x = this.left;
33292			}
33293			return distance;
33294		};
33295		Zoom.prototype.isBeyondPossibleLeft = function (x, minX) {
33296			return x >= minX;
33297		};
33298		Zoom.prototype.isBeyondPossibleRight = function (x, maxX) {
33299			return x <= maxX;
33300		};
33301		Zoom.prototype.isBeyondPossibleTop = function (y, minY) {
33302			return y >= minY;
33303		};
33304		Zoom.prototype.isBeyondPossibleBottom = function (y, maxY) {
33305			return y <= maxY;
33306		};
33307		Zoom.prototype.isImageSlide = function () {
33308			var currentItem = this.core.galleryItems[this.core.index];
33309			return this.core.getSlideType(currentItem) === 'image';
33310		};
33311		Zoom.prototype.getPossibleSwipeDragCords = function (rotateValue, scale) {
33312			var dataScale = scale || this.scale || 1;
33313			var elDataScale = Math.abs(dataScale);
33314			var _a = this.core.mediaContainerPosition, top = _a.top, bottom = _a.bottom;
33315			var topBottomSpacing = Math.abs(top - bottom) / 2;
33316			var minY = (this.imageYSize - this.containerRect.height) / 2 +
33317				topBottomSpacing * this.modifierX;
33318			var maxY = this.containerRect.height - this.imageYSize * elDataScale + minY;
33319			var minX = (this.imageXSize - this.containerRect.width) / 2;
33320			var maxX = this.containerRect.width - this.imageXSize * elDataScale + minX;
33321			var possibleSwipeCords = {
33322				minY: minY,
33323				maxY: maxY,
33324				minX: minX,
33325				maxX: maxX,
33326			};
33327			if (Math.abs(rotateValue) === 90) {
33328				possibleSwipeCords = {
33329					minY: minX,
33330					maxY: maxX,
33331					minX: minY,
33332					maxX: maxY,
33333				};
33334			}
33335			return possibleSwipeCords;
33336		};
33337		Zoom.prototype.setZoomSwipeStyles = function (LGel, distance) {
33338			LGel.css('transform', 'translate3d(' + distance.x + 'px, ' + distance.y + 'px, 0)');
33339		};
33340		Zoom.prototype.zoomSwipe = function () {
33341			var _this = this;
33342			var startCoords = {};
33343			var endCoords = {};
33344			var isMoved = false;
33345			// Allow x direction drag
33346			var allowX = false;
33347			// Allow Y direction drag
33348			var allowY = false;
33349			var startTime = new Date();
33350			var endTime = new Date();
33351			var possibleSwipeCords;
33352			var _LGel;
33353			var $item = this.core.getSlideItem(this.core.index);
33354			this.core.$inner.on('touchstart.lg', function (e) {
33355				// Allow zoom only on image
33356				if (!_this.isImageSlide()) {
33357					return;
33358				}
33359				$item = _this.core.getSlideItem(_this.core.index);
33360				if ((_this.$LG(e.target).hasClass('lg-item') ||
33361					$item.get().contains(e.target)) &&
33362					e.targetTouches.length === 1 &&
33363					_this.core.outer.hasClass('lg-zoomed')) {
33364					e.preventDefault();
33365					startTime = new Date();
33366					_this.core.touchAction = 'zoomSwipe';
33367					_LGel = _this.core
33368						.getSlideItem(_this.core.index)
33369						.find('.lg-img-wrap')
33370						.first();
33371					var dragAllowedAxises = _this.getDragAllowedAxises(Math.abs(_this.rotateValue));
33372					allowY = dragAllowedAxises.allowY;
33373					allowX = dragAllowedAxises.allowX;
33374					if (allowX || allowY) {
33375						startCoords = _this.getSwipeCords(e, Math.abs(_this.rotateValue));
33376					}
33377					possibleSwipeCords = _this.getPossibleSwipeDragCords(_this.rotateValue);
33378					// reset opacity and transition duration
33379					_this.core.outer.addClass('lg-zoom-dragging lg-zoom-drag-transition');
33380				}
33381			});
33382			this.core.$inner.on('touchmove.lg', function (e) {
33383				if (e.targetTouches.length === 1 &&
33384					_this.core.touchAction === 'zoomSwipe' &&
33385					(_this.$LG(e.target).hasClass('lg-item') ||
33386						$item.get().contains(e.target))) {
33387					e.preventDefault();
33388					_this.core.touchAction = 'zoomSwipe';
33389					endCoords = _this.getSwipeCords(e, Math.abs(_this.rotateValue));
33390					var distance = _this.getZoomSwipeCords(startCoords, endCoords, allowX, allowY, possibleSwipeCords);
33391					if (Math.abs(endCoords.x - startCoords.x) > 15 ||
33392						Math.abs(endCoords.y - startCoords.y) > 15) {
33393						isMoved = true;
33394						_this.setZoomSwipeStyles(_LGel, distance);
33395					}
33396				}
33397			});
33398			this.core.$inner.on('touchend.lg', function (e) {
33399				if (_this.core.touchAction === 'zoomSwipe' &&
33400					(_this.$LG(e.target).hasClass('lg-item') ||
33401						$item.get().contains(e.target))) {
33402					_this.core.touchAction = undefined;
33403					_this.core.outer.removeClass('lg-zoom-dragging');
33404					if (!isMoved) {
33405						return;
33406					}
33407					isMoved = false;
33408					endTime = new Date();
33409					var touchDuration = endTime.valueOf() - startTime.valueOf();
33410					_this.touchendZoom(startCoords, endCoords, allowX, allowY, touchDuration, _this.rotateValue);
33411				}
33412			});
33413		};
33414		Zoom.prototype.zoomDrag = function () {
33415			var _this = this;
33416			var startCoords = {};
33417			var endCoords = {};
33418			var isDragging = false;
33419			var isMoved = false;
33420			// Allow x direction drag
33421			var allowX = false;
33422			// Allow Y direction drag
33423			var allowY = false;
33424			var startTime;
33425			var endTime;
33426			var possibleSwipeCords;
33427			var _LGel;
33428			this.core.outer.on('mousedown.lg.zoom', function (e) {
33429				// Allow zoom only on image
33430				if (!_this.isImageSlide()) {
33431					return;
33432				}
33433				var $item = _this.core.getSlideItem(_this.core.index);
33434				if (_this.$LG(e.target).hasClass('lg-item') ||
33435					$item.get().contains(e.target)) {
33436					startTime = new Date();
33437					_LGel = _this.core
33438						.getSlideItem(_this.core.index)
33439						.find('.lg-img-wrap')
33440						.first();
33441					var dragAllowedAxises = _this.getDragAllowedAxises(Math.abs(_this.rotateValue));
33442					allowY = dragAllowedAxises.allowY;
33443					allowX = dragAllowedAxises.allowX;
33444					if (_this.core.outer.hasClass('lg-zoomed')) {
33445						if (_this.$LG(e.target).hasClass('lg-object') &&
33446							(allowX || allowY)) {
33447							e.preventDefault();
33448							startCoords = _this.getDragCords(e, Math.abs(_this.rotateValue));
33449							possibleSwipeCords = _this.getPossibleSwipeDragCords(_this.rotateValue);
33450							isDragging = true;
33451							// ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723
33452							_this.core.outer.get().scrollLeft += 1;
33453							_this.core.outer.get().scrollLeft -= 1;
33454							_this.core.outer
33455								.removeClass('lg-grab')
33456								.addClass('lg-grabbing lg-zoom-drag-transition lg-zoom-dragging');
33457							// reset opacity and transition duration
33458						}
33459					}
33460				}
33461			});
33462			this.$LG(window).on("mousemove.lg.zoom.global" + this.core.lgId, function (e) {
33463				if (isDragging) {
33464					isMoved = true;
33465					endCoords = _this.getDragCords(e, Math.abs(_this.rotateValue));
33466					var distance = _this.getZoomSwipeCords(startCoords, endCoords, allowX, allowY, possibleSwipeCords);
33467					_this.setZoomSwipeStyles(_LGel, distance);
33468				}
33469			});
33470			this.$LG(window).on("mouseup.lg.zoom.global" + this.core.lgId, function (e) {
33471				if (isDragging) {
33472					endTime = new Date();
33473					isDragging = false;
33474					_this.core.outer.removeClass('lg-zoom-dragging');
33475					// Fix for chrome mouse move on click
33476					if (isMoved &&
33477						(startCoords.x !== endCoords.x ||
33478							startCoords.y !== endCoords.y)) {
33479						endCoords = _this.getDragCords(e, Math.abs(_this.rotateValue));
33480						var touchDuration = endTime.valueOf() - startTime.valueOf();
33481						_this.touchendZoom(startCoords, endCoords, allowX, allowY, touchDuration, _this.rotateValue);
33482					}
33483					isMoved = false;
33484				}
33485				_this.core.outer.removeClass('lg-grabbing').addClass('lg-grab');
33486			});
33487		};
33488		Zoom.prototype.closeGallery = function () {
33489			this.resetZoom();
33490		};
33491		Zoom.prototype.destroy = function () {
33492			// Unbind all events added by lightGallery zoom plugin
33493			this.$LG(window).off(".lg.zoom.global" + this.core.lgId);
33494			this.core.LGel.off('.lg.zoom');
33495			this.core.LGel.off('.zoom');
33496			clearTimeout(this.zoomableTimeout);
33497			this.zoomableTimeout = false;
33498		};
33499		return Zoom;
33500	}());
33501
33502	return Zoom;
33503
33504})));
33505/*!
33506 * lightgallery | 2.5.0 | June 13th 2022
33507 * http://www.lightgalleryjs.com/
33508 * Copyright (c) 2020 Sachin Neravath;
33509 * @license GPLv3
33510 */
33511
33512(function (global, factory) {
33513	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
33514	typeof define === 'function' && define.amd ? define(factory) :
33515	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgFullscreen = factory());
33516}(this, (function () { 'use strict';
33517
33518	/*! *****************************************************************************
33519	Copyright (c) Microsoft Corporation.
33520
33521	Permission to use, copy, modify, and/or distribute this software for any
33522	purpose with or without fee is hereby granted.
33523
33524	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
33525	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
33526	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
33527	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
33528	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
33529	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
33530	PERFORMANCE OF THIS SOFTWARE.
33531	***************************************************************************** */
33532
33533	var __assign = function() {
33534		__assign = Object.assign || function __assign(t) {
33535			for (var s, i = 1, n = arguments.length; i < n; i++) {
33536				s = arguments[i];
33537				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
33538			}
33539			return t;
33540		};
33541		return __assign.apply(this, arguments);
33542	};
33543
33544	var fullscreenSettings = {
33545		fullScreen: true,
33546		fullscreenPluginStrings: {
33547			toggleFullscreen: 'Toggle Fullscreen',
33548		},
33549	};
33550
33551	var FullScreen = /** @class */ (function () {
33552		function FullScreen(instance, $LG) {
33553			// get lightGallery core plugin instance
33554			this.core = instance;
33555			this.$LG = $LG;
33556			// extend module default settings with lightGallery core settings
33557			this.settings = __assign(__assign({}, fullscreenSettings), this.core.settings);
33558			return this;
33559		}
33560		FullScreen.prototype.init = function () {
33561			var fullScreen = '';
33562			if (this.settings.fullScreen) {
33563				// check for fullscreen browser support
33564				if (!document.fullscreenEnabled &&
33565					!document.webkitFullscreenEnabled &&
33566					!document.mozFullScreenEnabled &&
33567					!document.msFullscreenEnabled) {
33568					return;
33569				}
33570				else {
33571					fullScreen = "<button type=\"button\" aria-label=\"" + this.settings.fullscreenPluginStrings['toggleFullscreen'] + "\" class=\"lg-fullscreen lg-icon\"></button>";
33572					this.core.$toolbar.append(fullScreen);
33573					this.fullScreen();
33574				}
33575			}
33576		};
33577		FullScreen.prototype.isFullScreen = function () {
33578			return (document.fullscreenElement ||
33579				document.mozFullScreenElement ||
33580				document.webkitFullscreenElement ||
33581				document.msFullscreenElement);
33582		};
33583		FullScreen.prototype.requestFullscreen = function () {
33584			var el = document.documentElement;
33585			if (el.requestFullscreen) {
33586				el.requestFullscreen();
33587			}
33588			else if (el.msRequestFullscreen) {
33589				el.msRequestFullscreen();
33590			}
33591			else if (el.mozRequestFullScreen) {
33592				el.mozRequestFullScreen();
33593			}
33594			else if (el.webkitRequestFullscreen) {
33595				el.webkitRequestFullscreen();
33596			}
33597		};
33598		FullScreen.prototype.exitFullscreen = function () {
33599			if (document.exitFullscreen) {
33600				document.exitFullscreen();
33601			}
33602			else if (document.msExitFullscreen) {
33603				document.msExitFullscreen();
33604			}
33605			else if (document.mozCancelFullScreen) {
33606				document.mozCancelFullScreen();
33607			}
33608			else if (document.webkitExitFullscreen) {
33609				document.webkitExitFullscreen();
33610			}
33611		};
33612		// https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Using_full_screen_mode
33613		FullScreen.prototype.fullScreen = function () {
33614			var _this = this;
33615			this.$LG(document).on("fullscreenchange.lg.global" + this.core.lgId + " \n            webkitfullscreenchange.lg.global" + this.core.lgId + " \n            mozfullscreenchange.lg.global" + this.core.lgId + " \n            MSFullscreenChange.lg.global" + this.core.lgId, function () {
33616				if (!_this.core.lgOpened)
33617					return;
33618				_this.core.outer.toggleClass('lg-fullscreen-on');
33619			});
33620			this.core.outer
33621				.find('.lg-fullscreen')
33622				.first()
33623				.on('click.lg', function () {
33624				if (_this.isFullScreen()) {
33625					_this.exitFullscreen();
33626				}
33627				else {
33628					_this.requestFullscreen();
33629				}
33630			});
33631		};
33632		FullScreen.prototype.closeGallery = function () {
33633			// exit from fullscreen if activated
33634			if (this.isFullScreen()) {
33635				this.exitFullscreen();
33636			}
33637		};
33638		FullScreen.prototype.destroy = function () {
33639			this.$LG(document).off("fullscreenchange.lg.global" + this.core.lgId + " \n            webkitfullscreenchange.lg.global" + this.core.lgId + " \n            mozfullscreenchange.lg.global" + this.core.lgId + " \n            MSFullscreenChange.lg.global" + this.core.lgId);
33640		};
33641		return FullScreen;
33642	}());
33643
33644	return FullScreen;
33645
33646})));
33647
33648/*!
33649 * lightgallery | 2.5.0 | June 13th 2022
33650 * http://www.lightgalleryjs.com/
33651 * Copyright (c) 2020 Sachin Neravath;
33652 * @license GPLv3
33653 */
33654
33655(function (global, factory) {
33656	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
33657	typeof define === 'function' && define.amd ? define(factory) :
33658	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgHash = factory());
33659}(this, (function () { 'use strict';
33660
33661	/*! *****************************************************************************
33662	Copyright (c) Microsoft Corporation.
33663
33664	Permission to use, copy, modify, and/or distribute this software for any
33665	purpose with or without fee is hereby granted.
33666
33667	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
33668	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
33669	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
33670	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
33671	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
33672	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
33673	PERFORMANCE OF THIS SOFTWARE.
33674	***************************************************************************** */
33675
33676	var __assign = function() {
33677		__assign = Object.assign || function __assign(t) {
33678			for (var s, i = 1, n = arguments.length; i < n; i++) {
33679				s = arguments[i];
33680				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
33681			}
33682			return t;
33683		};
33684		return __assign.apply(this, arguments);
33685	};
33686
33687	/**
33688	 * List of lightGallery events
33689	 * All events should be documented here
33690	 * Below interfaces are used to build the website documentations
33691	 * */
33692	var lGEvents = {
33693		afterAppendSlide: 'lgAfterAppendSlide',
33694		init: 'lgInit',
33695		hasVideo: 'lgHasVideo',
33696		containerResize: 'lgContainerResize',
33697		updateSlides: 'lgUpdateSlides',
33698		afterAppendSubHtml: 'lgAfterAppendSubHtml',
33699		beforeOpen: 'lgBeforeOpen',
33700		afterOpen: 'lgAfterOpen',
33701		slideItemLoad: 'lgSlideItemLoad',
33702		beforeSlide: 'lgBeforeSlide',
33703		afterSlide: 'lgAfterSlide',
33704		posterClick: 'lgPosterClick',
33705		dragStart: 'lgDragStart',
33706		dragMove: 'lgDragMove',
33707		dragEnd: 'lgDragEnd',
33708		beforeNextSlide: 'lgBeforeNextSlide',
33709		beforePrevSlide: 'lgBeforePrevSlide',
33710		beforeClose: 'lgBeforeClose',
33711		afterClose: 'lgAfterClose',
33712		rotateLeft: 'lgRotateLeft',
33713		rotateRight: 'lgRotateRight',
33714		flipHorizontal: 'lgFlipHorizontal',
33715		flipVertical: 'lgFlipVertical',
33716		autoplay: 'lgAutoplay',
33717		autoplayStart: 'lgAutoplayStart',
33718		autoplayStop: 'lgAutoplayStop',
33719	};
33720
33721	var hashSettings = {
33722		hash: true,
33723		galleryId: '1',
33724		customSlideName: false,
33725	};
33726
33727	var Hash = /** @class */ (function () {
33728		function Hash(instance, $LG) {
33729			// get lightGallery core plugin instance
33730			this.core = instance;
33731			this.$LG = $LG;
33732			// extend module default settings with lightGallery core settings
33733			this.settings = __assign(__assign({}, hashSettings), this.core.settings);
33734			return this;
33735		}
33736		Hash.prototype.init = function () {
33737			var _this = this;
33738			if (!this.settings.hash) {
33739				return;
33740			}
33741			this.oldHash = window.location.hash;
33742			setTimeout(function () {
33743				_this.buildFromHash();
33744			}, 100);
33745			// Change hash value on after each slide transition
33746			this.core.LGel.on(lGEvents.afterSlide + ".hash", this.onAfterSlide.bind(this));
33747			this.core.LGel.on(lGEvents.afterClose + ".hash", this.onCloseAfter.bind(this));
33748			// Listen hash change and change the slide according to slide value
33749			this.$LG(window).on("hashchange.lg.hash.global" + this.core.lgId, this.onHashchange.bind(this));
33750		};
33751		Hash.prototype.onAfterSlide = function (event) {
33752			var slideName = this.core.galleryItems[event.detail.index].slideName;
33753			slideName = this.settings.customSlideName
33754				? slideName || event.detail.index
33755				: event.detail.index;
33756			if (history.replaceState) {
33757				history.replaceState(null, '', window.location.pathname +
33758					window.location.search +
33759					'#lg=' +
33760					this.settings.galleryId +
33761					'&slide=' +
33762					slideName);
33763			}
33764			else {
33765				window.location.hash =
33766					'lg=' + this.settings.galleryId + '&slide=' + slideName;
33767			}
33768		};
33769		/**
33770		 * Get index of the slide from custom slideName. Has to be a public method. Used in hash plugin
33771		 * @param {String} hash
33772		 * @returns {Number} Index of the slide.
33773		 */
33774		Hash.prototype.getIndexFromUrl = function (hash) {
33775			if (hash === void 0) { hash = window.location.hash; }
33776			var slideName = hash.split('&slide=')[1];
33777			var _idx = 0;
33778			if (this.settings.customSlideName) {
33779				for (var index = 0; index < this.core.galleryItems.length; index++) {
33780					var dynamicEl = this.core.galleryItems[index];
33781					if (dynamicEl.slideName === slideName) {
33782						_idx = index;
33783						break;
33784					}
33785				}
33786			}
33787			else {
33788				_idx = parseInt(slideName, 10);
33789			}
33790			return isNaN(_idx) ? 0 : _idx;
33791		};
33792		// Build Gallery if gallery id exist in the URL
33793		Hash.prototype.buildFromHash = function () {
33794			// if dynamic option is enabled execute immediately
33795			var _hash = window.location.hash;
33796			//Uncode edit ##START##
33797			// if (_hash.indexOf('lg=' + this.settings.galleryId) > 0) {
33798			if (_hash.indexOf('lg=' + this.settings.galleryId + '&') > 0) {
33799			//Uncode edit ##END##
33800				// This class is used to remove the initial animation if galleryId present in the URL
33801				this.$LG(document.body).addClass('lg-from-hash');
33802				var index = this.getIndexFromUrl(_hash);
33803				this.core.openGallery(index);
33804				return true;
33805			}
33806		};
33807		Hash.prototype.onCloseAfter = function () {
33808			// Reset to old hash value
33809			if (this.oldHash &&
33810				this.oldHash.indexOf('lg=' + this.settings.galleryId) < 0) {
33811				if (history.replaceState) {
33812					history.replaceState(null, '', this.oldHash);
33813				}
33814				else {
33815					window.location.hash = this.oldHash;
33816				}
33817			}
33818			else {
33819				if (history.replaceState) {
33820					history.replaceState(null, document.title, window.location.pathname + window.location.search);
33821				}
33822				else {
33823					window.location.hash = '';
33824				}
33825			}
33826		};
33827		Hash.prototype.onHashchange = function () {
33828			if (!this.core.lgOpened)
33829				return;
33830			var _hash = window.location.hash;
33831			var index = this.getIndexFromUrl(_hash);
33832			// it galleryId doesn't exist in the url close the gallery
33833			if (_hash.indexOf('lg=' + this.settings.galleryId) > -1) {
33834				this.core.slide(index, false, false);
33835			}
33836			else if (this.core.lGalleryOn) {
33837				this.core.closeGallery();
33838			}
33839		};
33840		Hash.prototype.closeGallery = function () {
33841			if (this.settings.hash) {
33842				this.$LG(document.body).removeClass('lg-from-hash');
33843			}
33844		};
33845		Hash.prototype.destroy = function () {
33846			this.core.LGel.off('.lg.hash');
33847			this.core.LGel.off('.hash');
33848			this.$LG(window).off("hashchange.lg.hash.global" + this.core.lgId);
33849		};
33850		return Hash;
33851	}());
33852
33853	return Hash;
33854
33855})));
33856/*!
33857 * lightgallery | 2.5.0 | June 13th 2022
33858 * http://www.lightgalleryjs.com/
33859 * Copyright (c) 2020 Sachin Neravath;
33860 * @license GPLv3
33861 */
33862
33863(function (global, factory) {
33864	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
33865	typeof define === 'function' && define.amd ? define(factory) :
33866	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgShare = factory());
33867}(this, (function () { 'use strict';
33868
33869	/*! *****************************************************************************
33870	Copyright (c) Microsoft Corporation.
33871
33872	Permission to use, copy, modify, and/or distribute this software for any
33873	purpose with or without fee is hereby granted.
33874
33875	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
33876	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
33877	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
33878	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
33879	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
33880	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
33881	PERFORMANCE OF THIS SOFTWARE.
33882	***************************************************************************** */
33883
33884	var __assign = function() {
33885		__assign = Object.assign || function __assign(t) {
33886			for (var s, i = 1, n = arguments.length; i < n; i++) {
33887				s = arguments[i];
33888				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
33889			}
33890			return t;
33891		};
33892		return __assign.apply(this, arguments);
33893	};
33894
33895	function __spreadArrays() {
33896		for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
33897		for (var r = Array(s), k = 0, i = 0; i < il; i++)
33898			for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
33899				r[k] = a[j];
33900		return r;
33901	}
33902
33903	var shareSettings = {
33904		share: true,
33905		facebook: true,
33906		facebookDropdownText: 'Facebook',
33907		twitter: true,
33908		twitterDropdownText: 'Twitter',
33909		pinterest: true,
33910		pinterestDropdownText: 'Pinterest',
33911		additionalShareOptions: [],
33912		sharePluginStrings: { share: 'Share' },
33913	};
33914
33915	function getFacebookShareLink(galleryItem) {
33916		var facebookBaseUrl = '//www.facebook.com/sharer/sharer.php?u=';
33917		return (facebookBaseUrl +
33918			encodeURIComponent(galleryItem.facebookShareUrl || window.location.href));
33919	}
33920
33921	function getTwitterShareLink(galleryItem) {
33922		var twitterBaseUrl = '//twitter.com/intent/tweet?text=';
33923		var url = encodeURIComponent(galleryItem.twitterShareUrl || window.location.href);
33924		var text = galleryItem.tweetText;
33925		return twitterBaseUrl + text + '&url=' + url;
33926	}
33927
33928	function getPinterestShareLink(galleryItem) {
33929		var pinterestBaseUrl = 'http://www.pinterest.com/pin/create/button/?url=';
33930		var description = galleryItem.pinterestText;
33931		var media = encodeURIComponent(galleryItem.src);
33932		var url = encodeURIComponent(galleryItem.pinterestShareUrl || window.location.href);
33933		return (pinterestBaseUrl +
33934			url +
33935			'&media=' +
33936			media +
33937			'&description=' +
33938			description);
33939	}
33940
33941	/**
33942	 * List of lightGallery events
33943	 * All events should be documented here
33944	 * Below interfaces are used to build the website documentations
33945	 * */
33946	var lGEvents = {
33947		afterAppendSlide: 'lgAfterAppendSlide',
33948		init: 'lgInit',
33949		hasVideo: 'lgHasVideo',
33950		containerResize: 'lgContainerResize',
33951		updateSlides: 'lgUpdateSlides',
33952		afterAppendSubHtml: 'lgAfterAppendSubHtml',
33953		beforeOpen: 'lgBeforeOpen',
33954		afterOpen: 'lgAfterOpen',
33955		slideItemLoad: 'lgSlideItemLoad',
33956		beforeSlide: 'lgBeforeSlide',
33957		afterSlide: 'lgAfterSlide',
33958		posterClick: 'lgPosterClick',
33959		dragStart: 'lgDragStart',
33960		dragMove: 'lgDragMove',
33961		dragEnd: 'lgDragEnd',
33962		beforeNextSlide: 'lgBeforeNextSlide',
33963		beforePrevSlide: 'lgBeforePrevSlide',
33964		beforeClose: 'lgBeforeClose',
33965		afterClose: 'lgAfterClose',
33966		rotateLeft: 'lgRotateLeft',
33967		rotateRight: 'lgRotateRight',
33968		flipHorizontal: 'lgFlipHorizontal',
33969		flipVertical: 'lgFlipVertical',
33970		autoplay: 'lgAutoplay',
33971		autoplayStart: 'lgAutoplayStart',
33972		autoplayStop: 'lgAutoplayStop',
33973	};
33974
33975	var Share = /** @class */ (function () {
33976		function Share(instance) {
33977			this.shareOptions = [];
33978			// get lightGallery core plugin instance
33979			this.core = instance;
33980			// extend module default settings with lightGallery core settings
33981			this.settings = __assign(__assign({}, shareSettings), this.core.settings);
33982			return this;
33983		}
33984		Share.prototype.init = function () {
33985			if (!this.settings.share) {
33986				return;
33987			}
33988			this.shareOptions = __spreadArrays(this.getDefaultShareOptions(), this.settings.additionalShareOptions);
33989			this.setLgShareMarkup();
33990			this.core.outer
33991				.find('.lg-share .lg-dropdown')
33992				.append(this.getShareListHtml());
33993			this.core.LGel.on(lGEvents.afterSlide + ".share", this.onAfterSlide.bind(this));
33994		};
33995		Share.prototype.getShareListHtml = function () {
33996			var shareHtml = '';
33997			this.shareOptions.forEach(function (shareOption) {
33998				shareHtml += shareOption.dropdownHTML;
33999			});
34000			return shareHtml;
34001		};
34002		Share.prototype.setLgShareMarkup = function () {
34003			var _this = this;
34004			this.core.$toolbar.append("<button type=\"button\" aria-label=\"" + this.settings.sharePluginStrings['share'] + "\" aria-haspopup=\"true\" aria-expanded=\"false\" class=\"lg-share lg-icon\">\n                <ul class=\"lg-dropdown\" style=\"position: absolute;\"></ul></button>");
34005			this.core.outer.append('<div class="lg-dropdown-overlay"></div>');
34006			var $shareButton = this.core.outer.find('.lg-share');
34007			$shareButton.first().on('click.lg', function () {
34008				_this.core.outer.toggleClass('lg-dropdown-active');
34009				if (_this.core.outer.hasClass('lg-dropdown-active')) {
34010					_this.core.outer.attr('aria-expanded', true);
34011				}
34012				else {
34013					_this.core.outer.attr('aria-expanded', false);
34014				}
34015			});
34016			this.core.outer
34017				.find('.lg-dropdown-overlay')
34018				.first()
34019				.on('click.lg', function () {
34020				_this.core.outer.removeClass('lg-dropdown-active');
34021				_this.core.outer.attr('aria-expanded', false);
34022			});
34023		};
34024		Share.prototype.onAfterSlide = function (event) {
34025			var _this = this;
34026			var index = event.detail.index;
34027			var currentItem = this.core.galleryItems[index];
34028			setTimeout(function () {
34029				_this.shareOptions.forEach(function (shareOption) {
34030					var selector = shareOption.selector;
34031					_this.core.outer
34032						.find(selector)
34033						.attr('href', shareOption.generateLink(currentItem));
34034				});
34035			}, 100);
34036		};
34037		Share.prototype.getShareListItemHTML = function (type, text) {
34038			return "<li><a class=\"lg-share-" + type + "\" rel=\"noopener\" target=\"_blank\"><span class=\"lg-icon\"></span><span class=\"lg-dropdown-text\">" + text + "</span></a></li>";
34039		};
34040		Share.prototype.getDefaultShareOptions = function () {
34041			return __spreadArrays((this.settings.facebook
34042				? [
34043					{
34044						type: 'facebook',
34045						generateLink: getFacebookShareLink,
34046						dropdownHTML: this.getShareListItemHTML('facebook', this.settings.facebookDropdownText),
34047						selector: '.lg-share-facebook',
34048					},
34049				]
34050				: []), (this.settings.twitter
34051				? [
34052					{
34053						type: 'twitter',
34054						generateLink: getTwitterShareLink,
34055						dropdownHTML: this.getShareListItemHTML('twitter', this.settings.twitterDropdownText),
34056						selector: '.lg-share-twitter',
34057					},
34058				]
34059				: []), (this.settings.pinterest
34060				? [
34061					{
34062						type: 'pinterest',
34063						generateLink: getPinterestShareLink,
34064						dropdownHTML: this.getShareListItemHTML('pinterest', this.settings.pinterestDropdownText),
34065						selector: '.lg-share-pinterest',
34066					},
34067				]
34068				: []));
34069		};
34070		Share.prototype.destroy = function () {
34071			this.core.outer.find('.lg-dropdown-overlay').remove();
34072			this.core.outer.find('.lg-share').remove();
34073			this.core.LGel.off('.lg.share');
34074			this.core.LGel.off('.share');
34075		};
34076		return Share;
34077	}());
34078
34079	return Share;
34080
34081})));
34082/*!
34083 * lightgallery | 2.5.0 | June 13th 2022
34084 * http://www.lightgalleryjs.com/
34085 * Copyright (c) 2020 Sachin Neravath;
34086 * @license GPLv3
34087 */
34088
34089(function (global, factory) {
34090	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
34091	typeof define === 'function' && define.amd ? define(factory) :
34092	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgThumbnail = factory());
34093}(this, (function () { 'use strict';
34094
34095	/*! *****************************************************************************
34096	Copyright (c) Microsoft Corporation.
34097
34098	Permission to use, copy, modify, and/or distribute this software for any
34099	purpose with or without fee is hereby granted.
34100
34101	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
34102	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
34103	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
34104	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
34105	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
34106	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
34107	PERFORMANCE OF THIS SOFTWARE.
34108	***************************************************************************** */
34109
34110	var __assign = function() {
34111		__assign = Object.assign || function __assign(t) {
34112			for (var s, i = 1, n = arguments.length; i < n; i++) {
34113				s = arguments[i];
34114				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
34115			}
34116			return t;
34117		};
34118		return __assign.apply(this, arguments);
34119	};
34120
34121	var thumbnailsSettings = {
34122		thumbnail: true,
34123		animateThumb: true,
34124		currentPagerPosition: 'middle',
34125		alignThumbnails: 'middle',
34126		thumbWidth: 100,
34127		thumbHeight: '80px',
34128		thumbMargin: 5,
34129		appendThumbnailsTo: '.lg-components',
34130		toggleThumb: false,
34131		enableThumbDrag: true,
34132		enableThumbSwipe: true,
34133		thumbnailSwipeThreshold: 10,
34134		loadYouTubeThumbnail: true,
34135		youTubeThumbSize: 1,
34136		thumbnailPluginStrings: {
34137			toggleThumbnails: 'Toggle thumbnails',
34138		},
34139	};
34140
34141	/**
34142	 * List of lightGallery events
34143	 * All events should be documented here
34144	 * Below interfaces are used to build the website documentations
34145	 * */
34146	var lGEvents = {
34147		afterAppendSlide: 'lgAfterAppendSlide',
34148		init: 'lgInit',
34149		hasVideo: 'lgHasVideo',
34150		containerResize: 'lgContainerResize',
34151		updateSlides: 'lgUpdateSlides',
34152		afterAppendSubHtml: 'lgAfterAppendSubHtml',
34153		beforeOpen: 'lgBeforeOpen',
34154		afterOpen: 'lgAfterOpen',
34155		slideItemLoad: 'lgSlideItemLoad',
34156		beforeSlide: 'lgBeforeSlide',
34157		afterSlide: 'lgAfterSlide',
34158		posterClick: 'lgPosterClick',
34159		dragStart: 'lgDragStart',
34160		dragMove: 'lgDragMove',
34161		dragEnd: 'lgDragEnd',
34162		beforeNextSlide: 'lgBeforeNextSlide',
34163		beforePrevSlide: 'lgBeforePrevSlide',
34164		beforeClose: 'lgBeforeClose',
34165		afterClose: 'lgAfterClose',
34166		rotateLeft: 'lgRotateLeft',
34167		rotateRight: 'lgRotateRight',
34168		flipHorizontal: 'lgFlipHorizontal',
34169		flipVertical: 'lgFlipVertical',
34170		autoplay: 'lgAutoplay',
34171		autoplayStart: 'lgAutoplayStart',
34172		autoplayStop: 'lgAutoplayStop',
34173	};
34174
34175	var Thumbnail = /** @class */ (function () {
34176		function Thumbnail(instance, $LG) {
34177			this.thumbOuterWidth = 0;
34178			this.thumbTotalWidth = 0;
34179			this.translateX = 0;
34180			this.thumbClickable = false;
34181			// get lightGallery core plugin instance
34182			this.core = instance;
34183			this.$LG = $LG;
34184			return this;
34185		}
34186		Thumbnail.prototype.init = function () {
34187			// extend module default settings with lightGallery core settings
34188			this.settings = __assign(__assign({}, thumbnailsSettings), this.core.settings);
34189			this.thumbOuterWidth = 0;
34190			this.thumbTotalWidth =
34191				this.core.galleryItems.length *
34192					(this.settings.thumbWidth + this.settings.thumbMargin);
34193			// Thumbnail animation value
34194			this.translateX = 0;
34195			this.setAnimateThumbStyles();
34196			if (!this.core.settings.allowMediaOverlap) {
34197				this.settings.toggleThumb = false;
34198			}
34199			if (this.settings.thumbnail) {
34200				this.build();
34201				if (this.settings.animateThumb) {
34202					if (this.settings.enableThumbDrag) {
34203						this.enableThumbDrag();
34204					}
34205					if (this.settings.enableThumbSwipe) {
34206						this.enableThumbSwipe();
34207					}
34208					this.thumbClickable = false;
34209				}
34210				else {
34211					this.thumbClickable = true;
34212				}
34213				this.toggleThumbBar();
34214				this.thumbKeyPress();
34215			}
34216		};
34217		Thumbnail.prototype.build = function () {
34218			var _this = this;
34219			this.setThumbMarkup();
34220			this.manageActiveClassOnSlideChange();
34221			this.$lgThumb.first().on('click.lg touchend.lg', function (e) {
34222				var $target = _this.$LG(e.target);
34223				if (!$target.hasAttribute('data-lg-item-id')) {
34224					return;
34225				}
34226				setTimeout(function () {
34227					// In IE9 and bellow touch does not support
34228					// Go to slide if browser does not support css transitions
34229					if (_this.thumbClickable && !_this.core.lgBusy) {
34230						var index = parseInt($target.attr('data-lg-item-id'));
34231						_this.core.slide(index, false, true, false);
34232					}
34233				}, 50);
34234			});
34235			//Uncode edit ##START##
34236			// this.core.LGel.on(lGEvents.beforeSlide + ".thumb", function (event) {
34237			this.core.LGel.on(lGEvents.beforeSlide, function (event) {
34238			//Uncode edit ##END##
34239				var index = event.detail.index;
34240				_this.animateThumb(index);
34241			});
34242			//Uncode edit ##START##
34243			// this.core.LGel.on(lGEvents.beforeOpen + ".thumb", function () {
34244			this.core.LGel.on(lGEvents.beforeOpen, function () {
34245			//Uncode edit ##END##
34246				_this.thumbOuterWidth = _this.core.outer.get().offsetWidth;
34247			});
34248			//Uncode edit ##START##
34249			// this.core.LGel.on(lGEvents.updateSlides + ".thumb", function () {
34250			this.core.LGel.on(lGEvents.updateSlides, function () {
34251			//Uncode edit ##END##
34252				_this.rebuildThumbnails();
34253			});
34254			//Uncode edit ##START##
34255			// this.core.LGel.on(lGEvents.containerResize + ".thumb", function () {
34256			this.core.LGel.on(lGEvents.containerResize, function () {
34257			//Uncode edit ##END##
34258				if (!_this.core.lgOpened)
34259					return;
34260				setTimeout(function () {
34261					_this.thumbOuterWidth = _this.core.outer.get().offsetWidth;
34262					_this.animateThumb(_this.core.index);
34263					_this.thumbOuterWidth = _this.core.outer.get().offsetWidth;
34264				}, 50);
34265			});
34266		};
34267		Thumbnail.prototype.setThumbMarkup = function () {
34268			var thumbOuterClassNames = 'lg-thumb-outer ';
34269			if (this.settings.alignThumbnails) {
34270				thumbOuterClassNames += "lg-thumb-align-" + this.settings.alignThumbnails;
34271			}
34272			var html = "<div class=\"" + thumbOuterClassNames + "\">\n        <div class=\"lg-thumb lg-group\">\n        </div>\n        </div>";
34273			this.core.outer.addClass('lg-has-thumb');
34274			if (this.settings.appendThumbnailsTo === '.lg-components') {
34275				this.core.$lgComponents.append(html);
34276			}
34277			else {
34278				this.core.outer.append(html);
34279			}
34280			this.$thumbOuter = this.core.outer.find('.lg-thumb-outer').first();
34281			this.$lgThumb = this.core.outer.find('.lg-thumb').first();
34282			if (this.settings.animateThumb) {
34283				this.core.outer
34284					.find('.lg-thumb')
34285					.css('transition-duration', this.core.settings.speed + 'ms')
34286					.css('width', this.thumbTotalWidth + 'px')
34287					.css('position', 'relative');
34288			}
34289			this.setThumbItemHtml(this.core.galleryItems);
34290		};
34291		Thumbnail.prototype.enableThumbDrag = function () {
34292			var _this = this;
34293			var thumbDragUtils = {
34294				cords: {
34295					startX: 0,
34296					endX: 0,
34297				},
34298				isMoved: false,
34299				newTranslateX: 0,
34300				startTime: new Date(),
34301				endTime: new Date(),
34302				touchMoveTime: 0,
34303			};
34304			var isDragging = false;
34305			this.$thumbOuter.addClass('lg-grab');
34306			this.core.outer
34307				.find('.lg-thumb')
34308				.first()
34309				.on('mousedown.lg.thumb', function (e) {
34310				if (_this.thumbTotalWidth > _this.thumbOuterWidth) {
34311					// execute only on .lg-object
34312					e.preventDefault();
34313					thumbDragUtils.cords.startX = e.pageX;
34314					thumbDragUtils.startTime = new Date();
34315					_this.thumbClickable = false;
34316					isDragging = true;
34317					// ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723
34318					_this.core.outer.get().scrollLeft += 1;
34319					_this.core.outer.get().scrollLeft -= 1;
34320					// *
34321					_this.$thumbOuter
34322						.removeClass('lg-grab')
34323						.addClass('lg-grabbing');
34324				}
34325			});
34326			this.$LG(window).on("mousemove.lg.thumb.global" + this.core.lgId, function (e) {
34327				if (!_this.core.lgOpened)
34328					return;
34329				if (isDragging) {
34330					thumbDragUtils.cords.endX = e.pageX;
34331					thumbDragUtils = _this.onThumbTouchMove(thumbDragUtils);
34332				}
34333			});
34334			this.$LG(window).on("mouseup.lg.thumb.global" + this.core.lgId, function () {
34335				if (!_this.core.lgOpened)
34336					return;
34337				if (thumbDragUtils.isMoved) {
34338					thumbDragUtils = _this.onThumbTouchEnd(thumbDragUtils);
34339				}
34340				else {
34341					_this.thumbClickable = true;
34342				}
34343				if (isDragging) {
34344					isDragging = false;
34345					_this.$thumbOuter.removeClass('lg-grabbing').addClass('lg-grab');
34346				}
34347			});
34348		};
34349		Thumbnail.prototype.enableThumbSwipe = function () {
34350			var _this = this;
34351			var thumbDragUtils = {
34352				cords: {
34353					startX: 0,
34354					endX: 0,
34355				},
34356				isMoved: false,
34357				newTranslateX: 0,
34358				startTime: new Date(),
34359				endTime: new Date(),
34360				touchMoveTime: 0,
34361			};
34362			this.$lgThumb.on('touchstart.lg', function (e) {
34363				if (_this.thumbTotalWidth > _this.thumbOuterWidth) {
34364					e.preventDefault();
34365					thumbDragUtils.cords.startX = e.targetTouches[0].pageX;
34366					_this.thumbClickable = false;
34367					thumbDragUtils.startTime = new Date();
34368				}
34369			});
34370			this.$lgThumb.on('touchmove.lg', function (e) {
34371				if (_this.thumbTotalWidth > _this.thumbOuterWidth) {
34372					e.preventDefault();
34373					thumbDragUtils.cords.endX = e.targetTouches[0].pageX;
34374					thumbDragUtils = _this.onThumbTouchMove(thumbDragUtils);
34375				}
34376			});
34377			this.$lgThumb.on('touchend.lg', function () {
34378				if (thumbDragUtils.isMoved) {
34379					thumbDragUtils = _this.onThumbTouchEnd(thumbDragUtils);
34380				}
34381				else {
34382					_this.thumbClickable = true;
34383				}
34384			});
34385		};
34386		// Rebuild thumbnails
34387		Thumbnail.prototype.rebuildThumbnails = function () {
34388			var _this = this;
34389			// Remove transitions
34390			this.$thumbOuter.addClass('lg-rebuilding-thumbnails');
34391			setTimeout(function () {
34392				_this.thumbTotalWidth =
34393					_this.core.galleryItems.length *
34394						(_this.settings.thumbWidth + _this.settings.thumbMargin);
34395				_this.$lgThumb.css('width', _this.thumbTotalWidth + 'px');
34396				_this.$lgThumb.empty();
34397				_this.setThumbItemHtml(_this.core.galleryItems);
34398				_this.animateThumb(_this.core.index);
34399			}, 50);
34400			setTimeout(function () {
34401				_this.$thumbOuter.removeClass('lg-rebuilding-thumbnails');
34402			}, 200);
34403		};
34404		// @ts-check
34405		Thumbnail.prototype.setTranslate = function (value) {
34406			this.$lgThumb.css('transform', 'translate3d(-' + value + 'px, 0px, 0px)');
34407		};
34408		Thumbnail.prototype.getPossibleTransformX = function (left) {
34409			if (left > this.thumbTotalWidth - this.thumbOuterWidth) {
34410				left = this.thumbTotalWidth - this.thumbOuterWidth;
34411			}
34412			if (left < 0) {
34413				left = 0;
34414			}
34415			return left;
34416		};
34417		Thumbnail.prototype.animateThumb = function (index) {
34418			this.$lgThumb.css('transition-duration', this.core.settings.speed + 'ms');
34419			if (this.settings.animateThumb) {
34420				var position = 0;
34421				switch (this.settings.currentPagerPosition) {
34422					case 'left':
34423						position = 0;
34424						break;
34425					case 'middle':
34426						position =
34427							this.thumbOuterWidth / 2 - this.settings.thumbWidth / 2;
34428						break;
34429					case 'right':
34430						position = this.thumbOuterWidth - this.settings.thumbWidth;
34431				}
34432				this.translateX =
34433					(this.settings.thumbWidth + this.settings.thumbMargin) * index -
34434						1 -
34435						position;
34436				if (this.translateX > this.thumbTotalWidth - this.thumbOuterWidth) {
34437					this.translateX = this.thumbTotalWidth - this.thumbOuterWidth;
34438				}
34439				if (this.translateX < 0) {
34440					this.translateX = 0;
34441				}
34442				this.setTranslate(this.translateX);
34443			}
34444		};
34445		Thumbnail.prototype.onThumbTouchMove = function (thumbDragUtils) {
34446			thumbDragUtils.newTranslateX = this.translateX;
34447			thumbDragUtils.isMoved = true;
34448			thumbDragUtils.touchMoveTime = new Date().valueOf();
34449			thumbDragUtils.newTranslateX -=
34450				thumbDragUtils.cords.endX - thumbDragUtils.cords.startX;
34451			thumbDragUtils.newTranslateX = this.getPossibleTransformX(thumbDragUtils.newTranslateX);
34452			// move current slide
34453			this.setTranslate(thumbDragUtils.newTranslateX);
34454			this.$thumbOuter.addClass('lg-dragging');
34455			return thumbDragUtils;
34456		};
34457		Thumbnail.prototype.onThumbTouchEnd = function (thumbDragUtils) {
34458			thumbDragUtils.isMoved = false;
34459			thumbDragUtils.endTime = new Date();
34460			this.$thumbOuter.removeClass('lg-dragging');
34461			var touchDuration = thumbDragUtils.endTime.valueOf() -
34462				thumbDragUtils.startTime.valueOf();
34463			var distanceXnew = thumbDragUtils.cords.endX - thumbDragUtils.cords.startX;
34464			var speedX = Math.abs(distanceXnew) / touchDuration;
34465			// Some magical numbers
34466			// Can be improved
34467			if (speedX > 0.15 &&
34468				thumbDragUtils.endTime.valueOf() - thumbDragUtils.touchMoveTime < 30) {
34469				speedX += 1;
34470				if (speedX > 2) {
34471					speedX += 1;
34472				}
34473				speedX =
34474					speedX +
34475						speedX * (Math.abs(distanceXnew) / this.thumbOuterWidth);
34476				this.$lgThumb.css('transition-duration', Math.min(speedX - 1, 2) + 'settings');
34477				distanceXnew = distanceXnew * speedX;
34478				this.translateX = this.getPossibleTransformX(this.translateX - distanceXnew);
34479				this.setTranslate(this.translateX);
34480			}
34481			else {
34482				this.translateX = thumbDragUtils.newTranslateX;
34483			}
34484			if (Math.abs(thumbDragUtils.cords.endX - thumbDragUtils.cords.startX) <
34485				this.settings.thumbnailSwipeThreshold) {
34486				this.thumbClickable = true;
34487			}
34488			return thumbDragUtils;
34489		};
34490		Thumbnail.prototype.getThumbHtml = function (thumb, index, alt) {
34491			var slideVideoInfo = this.core.galleryItems[index].__slideVideoInfo || {};
34492			var thumbImg,
34493				altTh = this.core.galleryItems[index].subHtml,
34494				altApp = '';
34495			if (slideVideoInfo.youtube) {
34496				if (this.settings.loadYouTubeThumbnail) {
34497					thumbImg =
34498						'//img.youtube.com/vi/' +
34499							slideVideoInfo.youtube[1] +
34500							'/' +
34501							this.settings.youTubeThumbSize +
34502							'.jpg';
34503				}
34504				else {
34505					thumbImg = thumb;
34506				}
34507			}
34508			else {
34509				thumbImg = thumb;
34510			}
34511
34512			if ( altTh ) {
34513				altTh = altTh.replace(/<\/?[^>]+(>|$)/g, "");
34514				altApp = 'alt=\"' + altTh + ' \" ';
34515			} else if ( typeof alt !== 'undefined' ) {
34516				altApp = 'alt=\"' + alt + ' \" ';
34517			}
34518
34519			if ( thumbImg ) {
34520				return "<div data-lg-item-id=\"" + index + "\" class=\"lg-thumb-item " + (index === this.core.index ? ' active' : '') + "\" \n        style=\"width:" + this.settings.thumbWidth + "px; height: " + this.settings.thumbHeight + ";\n            margin-right: " + this.settings.thumbMargin + "px;\">\n            <img data-lg-item-id=\"" + index + "\" " + altApp + "src=\"" + thumbImg + "\" />\n        </div>";
34521			} else {
34522				return "<div data-lg-item-id=\"" + index + "\" class=\"lg-thumb-item " + (index === this.core.index ? ' active' : '') + "\" \n        style=\"width:" + this.settings.thumbWidth + "px; height: " + this.settings.thumbHeight + ";\n            margin-right: " + this.settings.thumbMargin + "px;\">\n        </div>";
34523			}
34524		};
34525		Thumbnail.prototype.getThumbItemHtml = function (items) {
34526			var thumbList = '';
34527			for (var i = 0; i < items.length; i++) {
34528				thumbList += this.getThumbHtml(items[i].thumb, i, items[i].alt);
34529			}
34530			return thumbList;
34531		};
34532		Thumbnail.prototype.setThumbItemHtml = function (items) {
34533			var thumbList = this.getThumbItemHtml(items);
34534			this.$lgThumb.html(thumbList);
34535		};
34536		Thumbnail.prototype.setAnimateThumbStyles = function () {
34537			if (this.settings.animateThumb) {
34538				this.core.outer.addClass('lg-animate-thumb');
34539			}
34540		};
34541		// Manage thumbnail active calss
34542		Thumbnail.prototype.manageActiveClassOnSlideChange = function () {
34543			var _this = this;
34544			// manage active class for thumbnail
34545			//Uncode edit ##START##
34546			// this.core.LGel.on(lGEvents.beforeSlide + ".thumb", function (event) {
34547			this.core.LGel.on(lGEvents.beforeSlide, function (event) {
34548			//Uncode edit ##END##
34549				var $thumb = _this.core.outer.find('.lg-thumb-item');
34550				var index = event.detail.index;
34551				$thumb.removeClass('active');
34552				$thumb.eq(index).addClass('active');
34553			});
34554		};
34555		// Toggle thumbnail bar
34556		Thumbnail.prototype.toggleThumbBar = function () {
34557			var _this = this;
34558			if (this.settings.toggleThumb) {
34559				this.core.outer.addClass('lg-can-toggle');
34560				this.core.$toolbar.append('<button type="button" aria-label="' +
34561					this.settings.thumbnailPluginStrings['toggleThumbnails'] +
34562					'" class="lg-toggle-thumb lg-icon"></button>');
34563				this.core.outer
34564					.find('.lg-toggle-thumb')
34565					.first()
34566					.on('click.lg', function () {
34567					_this.core.outer.toggleClass('lg-components-open');
34568				});
34569			}
34570		};
34571		Thumbnail.prototype.thumbKeyPress = function () {
34572			var _this = this;
34573			this.$LG(window).on("keydown.lg.thumb.global" + this.core.lgId, function (e) {
34574				if (!_this.core.lgOpened || !_this.settings.toggleThumb)
34575					return;
34576				if (e.keyCode === 38) {
34577					e.preventDefault();
34578					_this.core.outer.addClass('lg-components-open');
34579				}
34580				else if (e.keyCode === 40) {
34581					e.preventDefault();
34582					_this.core.outer.removeClass('lg-components-open');
34583				}
34584			});
34585		};
34586		Thumbnail.prototype.destroy = function () {
34587			if (this.settings.thumbnail) {
34588				this.$LG(window).off(".lg.thumb.global" + this.core.lgId);
34589				this.core.LGel.off('.lg.thumb');
34590				this.core.LGel.off('.thumb');
34591				this.$thumbOuter.remove();
34592				this.core.outer.removeClass('lg-has-thumb');
34593			}
34594		};
34595		return Thumbnail;
34596	}());
34597
34598	return Thumbnail;
34599
34600})));
34601/*!
34602 * lightgallery | 2.5.0 | June 13th 2022
34603 * http://www.lightgalleryjs.com/
34604 * Copyright (c) 2020 Sachin Neravath;
34605 * @license GPLv3
34606 */
34607
34608(function (global, factory) {
34609	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
34610	typeof define === 'function' && define.amd ? define(factory) :
34611	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgVideo = factory());
34612}(this, (function () { 'use strict';
34613
34614	/*! *****************************************************************************
34615	Copyright (c) Microsoft Corporation.
34616
34617	Permission to use, copy, modify, and/or distribute this software for any
34618	purpose with or without fee is hereby granted.
34619
34620	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
34621	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
34622	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
34623	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
34624	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
34625	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
34626	PERFORMANCE OF THIS SOFTWARE.
34627	***************************************************************************** */
34628
34629	var __assign = function() {
34630		__assign = Object.assign || function __assign(t) {
34631			for (var s, i = 1, n = arguments.length; i < n; i++) {
34632				s = arguments[i];
34633				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
34634			}
34635			return t;
34636		};
34637		return __assign.apply(this, arguments);
34638	};
34639
34640	var videoSettings = {
34641		autoplayFirstVideo: true,
34642		youTubePlayerParams: false,
34643		vimeoPlayerParams: false,
34644		wistiaPlayerParams: false,
34645		gotoNextSlideOnVideoEnd: true,
34646		autoplayVideoOnSlide: false,
34647		videojs: false,
34648		videojsTheme: '',
34649		videojsOptions: {},
34650	};
34651
34652	/**
34653	 * List of lightGallery events
34654	 * All events should be documented here
34655	 * Below interfaces are used to build the website documentations
34656	 * */
34657	var lGEvents = {
34658		afterAppendSlide: 'lgAfterAppendSlide',
34659		init: 'lgInit',
34660		hasVideo: 'lgHasVideo',
34661		containerResize: 'lgContainerResize',
34662		updateSlides: 'lgUpdateSlides',
34663		afterAppendSubHtml: 'lgAfterAppendSubHtml',
34664		beforeOpen: 'lgBeforeOpen',
34665		afterOpen: 'lgAfterOpen',
34666		slideItemLoad: 'lgSlideItemLoad',
34667		beforeSlide: 'lgBeforeSlide',
34668		afterSlide: 'lgAfterSlide',
34669		posterClick: 'lgPosterClick',
34670		dragStart: 'lgDragStart',
34671		dragMove: 'lgDragMove',
34672		dragEnd: 'lgDragEnd',
34673		beforeNextSlide: 'lgBeforeNextSlide',
34674		beforePrevSlide: 'lgBeforePrevSlide',
34675		beforeClose: 'lgBeforeClose',
34676		afterClose: 'lgAfterClose',
34677		rotateLeft: 'lgRotateLeft',
34678		rotateRight: 'lgRotateRight',
34679		flipHorizontal: 'lgFlipHorizontal',
34680		flipVertical: 'lgFlipVertical',
34681		autoplay: 'lgAutoplay',
34682		autoplayStart: 'lgAutoplayStart',
34683		autoplayStop: 'lgAutoplayStop',
34684	};
34685
34686	var param = function (obj) {
34687		return Object.keys(obj)
34688			.map(function (k) {
34689			return encodeURIComponent(k) + '=' + encodeURIComponent(obj[k]);
34690		})
34691			.join('&');
34692	};
34693	var getVimeoURLParams = function (defaultParams, videoInfo) {
34694		if (!videoInfo || !videoInfo.vimeo)
34695			return '';
34696		var urlParams = videoInfo.vimeo[2] || '';
34697		var defaultPlayerParams = defaultParams && Object.keys(defaultParams).length !== 0
34698			? '&' + param(defaultParams)
34699			: '';
34700		// Support private video
34701		var urlWithHash = videoInfo.vimeo[0].split('/').pop() || '';
34702		var urlWithHashWithParams = urlWithHash.split('?')[0] || '';
34703		var hash = urlWithHashWithParams.split('#')[0];
34704		var isPrivate = videoInfo.vimeo[1] !== hash;
34705		if (isPrivate) {
34706			urlParams = urlParams.replace("/" + hash, '');
34707		}
34708		urlParams =
34709			urlParams[0] == '?' ? '&' + urlParams.slice(1) : urlParams || '';
34710		// For vimeo last params gets priority if duplicates found
34711		// Uncode edit ##START##
34712		var vimeoPlayerParams = '?autoplay=0';
34713		if ( videoInfo.autoplay !== '' ) {
34714			vimeoPlayerParams = vimeoPlayerParams.replace(new RegExp('([?&])autoplay=(.*?)(&|$)'), '$1$3' );
34715			vimeoPlayerParams = vimeoPlayerParams.replace(new RegExp('([?&])autoplay(&|$)'), '$1$2' );
34716		} else {
34717			if ( typeof SiteParameters !== 'undefined' && typeof SiteParameters.vimeoPlayerParams !== 'undefined' && SiteParameters.vimeoPlayerParams !== '' ) {
34718				vimeoPlayerParams = SiteParameters.vimeoPlayerParams;
34719			}
34720		}
34721		if ( videoInfo.muted !== '' ) {
34722			vimeoPlayerParams += '&muted=' + (videoInfo.muted === 'yes');
34723		} else {
34724			if ( urlParams.indexOf('muted=') < 0 && vimeoPlayerParams.indexOf('muted=') < 0 ) {
34725				vimeoPlayerParams += '&muted=1';
34726			}
34727		}
34728		// var vimeoPlayerParams = "?autoplay=0&muted=1" + (isPrivate ? "&h=" + hash : '') + defaultPlayerParams + urlParams;
34729		vimeoPlayerParams += (isPrivate ? "&h=" + hash : '') + defaultPlayerParams + urlParams;
34730		// Uncode edit ##END##
34731		return vimeoPlayerParams;
34732	};
34733
34734	/**
34735	 * Video module for lightGallery
34736	 * Supports HTML5, YouTube, Vimeo, wistia videos
34737	 *
34738	 *
34739	 * @ref Wistia
34740	 * https://wistia.com/support/integrations/wordpress(How to get url)
34741	 * https://wistia.com/support/developers/embed-options#using-embed-options
34742	 * https://wistia.com/support/developers/player-api
34743	 * https://wistia.com/support/developers/construct-an-embed-code
34744	 * http://jsfiddle.net/xvnm7xLm/
34745	 * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video
34746	 * https://wistia.com/support/embed-and-share/sharing-videos
34747	 * https://private-sharing.wistia.com/medias/mwhrulrucj
34748	 *
34749	 * @ref Youtube
34750	 * https://developers.google.com/youtube/player_parameters#enablejsapi
34751	 * https://developers.google.com/youtube/iframe_api_reference
34752	 * https://developer.chrome.com/blog/autoplay/#iframe-delegation
34753	 *
34754	 * @ref Vimeo
34755	 * https://stackoverflow.com/questions/10488943/easy-way-to-get-vimeo-id-from-a-vimeo-url
34756	 * https://vimeo.zendesk.com/hc/en-us/articles/360000121668-Starting-playback-at-a-specific-timecode
34757	 * https://vimeo.zendesk.com/hc/en-us/articles/360001494447-Using-Player-Parameters
34758	 */
34759	var Video = /** @class */ (function () {
34760		function Video(instance) {
34761			// get lightGallery core plugin instance
34762			this.core = instance;
34763			this.settings = __assign(__assign({}, videoSettings), this.core.settings);
34764			return this;
34765		}
34766		Video.prototype.init = function () {
34767			var _this = this;
34768			/**
34769			 * Event triggered when video url found without poster
34770			 * Append video HTML
34771			 * Play if autoplayFirstVideo is true
34772			 */
34773			this.core.LGel.on(lGEvents.hasVideo + ".video", this.onHasVideo.bind(this));
34774			this.core.LGel.on(lGEvents.posterClick + ".video", function () {
34775				var $el = _this.core.getSlideItem(_this.core.index);
34776				_this.loadVideoOnPosterClick($el);
34777			});
34778			this.core.LGel.on(lGEvents.slideItemLoad + ".video", this.onSlideItemLoad.bind(this));
34779			// @desc fired immediately before each slide transition.
34780			this.core.LGel.on(lGEvents.beforeSlide + ".video", this.onBeforeSlide.bind(this));
34781			// @desc fired immediately after each slide transition.
34782			this.core.LGel.on(lGEvents.afterSlide + ".video", this.onAfterSlide.bind(this));
34783		};
34784		/**
34785		 * @desc Event triggered when a slide is completely loaded
34786		 *
34787		 * @param {Event} event - lightGalley custom event
34788		 */
34789		Video.prototype.onSlideItemLoad = function (event) {
34790			var _this = this;
34791			var _a = event.detail, isFirstSlide = _a.isFirstSlide, index = _a.index;
34792			// Should check the active slide as well as user may have moved to different slide before the first slide is loaded
34793			if (this.settings.autoplayFirstVideo &&
34794				isFirstSlide &&
34795				index === this.core.index) {
34796				// Delay is just for the transition effect on video load
34797				setTimeout(function () {
34798					_this.loadAndPlayVideo(index);
34799				}, 200);
34800			}
34801			// Should not call on first slide. should check only if the slide is active
34802			if (!isFirstSlide &&
34803				this.settings.autoplayVideoOnSlide &&
34804				index === this.core.index) {
34805					setTimeout(function () {
34806						_this.loadAndPlayVideo(index);
34807					}, 500);
34808				}
34809		};
34810		/**
34811		 * @desc Event triggered when video url or poster found
34812		 * Append video HTML is poster is not given
34813		 * Play if autoplayFirstVideo is true
34814		 *
34815		 * @param {Event} event - Javascript Event object.
34816		 */
34817		Video.prototype.onHasVideo = function (event) {
34818			var _a = event.detail, index = _a.index, src = _a.src, html5Video = _a.html5Video, hasPoster = _a.hasPoster;
34819			if (!hasPoster) {
34820				// All functions are called separately if poster exist in loadVideoOnPosterClick function
34821				this.appendVideos(this.core.getSlideItem(index), {
34822					src: src,
34823					addClass: 'lg-object',
34824					index: index,
34825					html5Video: html5Video,
34826					// Uncode edit ##START##
34827					autoplay: event.target.getAttribute('data-lb-autoplay'),
34828					muted: event.target.getAttribute('data-lb-muted'),
34829					// Uncode edit ##END##
34830				});
34831				// Automatically navigate to next slide once video reaches the end.
34832				this.gotoNextSlideOnVideoEnd(src, index);
34833			}
34834		};
34835		/**
34836		 * @desc fired immediately before each slide transition.
34837		 * Pause the previous video
34838		 * Hide the download button if the slide contains YouTube, Vimeo, or Wistia videos.
34839		 *
34840		 * @param {Event} event - Javascript Event object.
34841		 * @param {number} prevIndex - Previous index of the slide.
34842		 * @param {number} index - Current index of the slide
34843		 */
34844		Video.prototype.onBeforeSlide = function (event) {
34845			if (this.core.lGalleryOn) {
34846				var prevIndex = event.detail.prevIndex;
34847				this.pauseVideo(prevIndex);
34848			}
34849			// Uncode edit ##START##
34850			var _a = event.detail, index = _a.index;
34851			var $slide = this.core.getSlideItem(index);
34852			
34853			var iframe = $slide.selector.querySelector('iframe');
34854			if ( iframe != null ) {
34855
34856				var data_play = iframe.getAttribute('data-autoplay');
34857				if ( typeof data_play !== 'undefined' && data_play === '1' ) {
34858					this.loadAndPlayVideo(index);
34859
34860					var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {},
34861						$videoElement = this.core.getSlideItem(index).find('.lg-video-object').first();
34862					if (videoInfo.vimeo) {
34863						var vimeoPlayer = new Vimeo.Player($videoElement.get());
34864						vimeoPlayer.on('play', function () {
34865							vimeoPlayer.setCurrentTime(0);
34866						});
34867					} else if ( videoInfo.youtube ) {
34868						try {
34869							$videoElement.get().contentWindow.postMessage("{\"event\":\"command\",\"func\":\"seekTo\",\"args\":[0, true]}", '*');
34870						}
34871						catch (e) {
34872							console.warn(e);
34873						}
34874					}
34875				}
34876			}
34877			// Uncode edit ##END##
34878		};
34879		/**
34880		 * @desc fired immediately after each slide transition.
34881		 * Play video if autoplayVideoOnSlide option is enabled.
34882		 *
34883		 * @param {Event} event - Javascript Event object.
34884		 * @param {number} prevIndex - Previous index of the slide.
34885		 * @param {number} index - Current index of the slide
34886		 * @todo should check on onSlideLoad as well if video is not loaded on after slide
34887		 */
34888		Video.prototype.onAfterSlide = function (event) {
34889			var _this = this;
34890			var _a = event.detail, index = _a.index, prevIndex = _a.prevIndex;
34891			// Do not call on first slide
34892			var $slide = this.core.getSlideItem(index);
34893			if (this.settings.autoplayVideoOnSlide && index !== prevIndex) {
34894				if ($slide.hasClass('lg-complete')) {
34895					setTimeout(function () {
34896						_this.loadAndPlayVideo(index);
34897					}, 100);
34898				}
34899			}
34900		};
34901		Video.prototype.loadAndPlayVideo = function (index) {
34902			var $slide = this.core.getSlideItem(index);
34903			var currentGalleryItem = this.core.galleryItems[index];
34904			if (currentGalleryItem.poster) {
34905				this.loadVideoOnPosterClick($slide, true);
34906			}
34907			else {
34908				//Uncode edit ##START##
34909				// this.playVideo(index);
34910				var iframe = $slide.selector.querySelector('iframe');
34911				if ( iframe != null ) {
34912					var data_play = iframe.getAttribute('data-autoplay');
34913					if ( typeof data_play !== 'undefined' ) {
34914						if ( data_play === '1' && this.core.index == index ) {
34915							this.playVideo(index);
34916						} else {
34917							this.pauseVideo(index);
34918						}
34919					}
34920				}
34921				//Uncode edit ##END##
34922			}
34923		};
34924		/**
34925		 * Play HTML5, Youtube, Vimeo or Wistia videos in a particular slide.
34926		 * @param {number} index - Index of the slide
34927		 */
34928		Video.prototype.playVideo = function (index) {
34929			this.controlVideo(index, 'play');
34930		};
34931		/**
34932		 * Pause HTML5, Youtube, Vimeo or Wistia videos in a particular slide.
34933		 * @param {number} index - Index of the slide
34934		 */
34935		Video.prototype.pauseVideo = function (index) {
34936			this.controlVideo(index, 'pause');
34937		};
34938		// Uncode edit ##START##
34939		//Video.prototype.getVideoHtml = function (src, addClass, index, html5Video) {
34940		Video.prototype.getVideoHtml = function (src, addClass, index, html5Video, autoplay, muted) {
34941		// Uncode edit ##END##
34942			var video = '';
34943			var videoInfo = this.core.galleryItems[index]
34944				.__slideVideoInfo || {};
34945			var currentGalleryItem = this.core.galleryItems[index];
34946			var videoTitle = currentGalleryItem.title || currentGalleryItem.alt;
34947			videoTitle = videoTitle ? 'title="' + videoTitle + '"' : '';
34948			var commonIframeProps = "allowtransparency=\"true\"\n            frameborder=\"0\"\n            scrolling=\"no\"\n            allowfullscreen\n            mozallowfullscreen\n            webkitallowfullscreen\n            oallowfullscreen\n            msallowfullscreen";
34949			if (videoInfo.youtube) {
34950				var videoId = 'lg-youtube' + index;
34951				var slideUrlParams = videoInfo.youtube[2]
34952					? videoInfo.youtube[2] + '&'
34953					: '';
34954				// For youtube first parms gets priority if duplicates found
34955				// Uncode edit ##START##
34956				// var youTubePlayerParams = "?" + slideUrlParams + "wmode=opaque&autoplay=0&mute=1&enablejsapi=1";
34957				var youTubePlayerParams = "?" + slideUrlParams + "wmode=opaque&enablejsapi=1";
34958				if ( ( slideUrlParams.indexOf('autoplay=') < 0 && youTubePlayerParams.indexOf('autoplay=') < 0 ) ) {
34959					youTubePlayerParams += '&autoplay=0';
34960				}
34961				if ( slideUrlParams.indexOf('mute=') < 0 && youTubePlayerParams.indexOf('mute=') < 0 ) {
34962					youTubePlayerParams += '&mute=1';
34963				}
34964				var data_video = '';
34965				if ( autoplay !== '' ) {
34966					//youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])autoplay=(.*?)(&|$)'), '$1autoplay=' + (autoplay === 'yes' ? 1 : 0) + '$3' );
34967					youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])autoplay=(.*?)(&|$)'), '$1$3' );
34968					youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])autoplay'), '$1' );
34969					data_video = ' data-autoplay="' + (autoplay === 'yes' ? 1 : 0) + '"';
34970				}
34971				// if ( muted !== '' ) {
34972				// 	youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])mute=(.*?)(&|$)'), '$1mute=' + (muted === 'yes' ? 1 : 0) + '$3' );
34973				// }
34974				youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])mute=(.*?)(&|$)'), '$1$3' );
34975
34976				youTubePlayerParams = youTubePlayerParams.replace('??', '?');
34977				// Uncode edit ##END##
34978				var playerParams = youTubePlayerParams +
34979					(this.settings.youTubePlayerParams
34980						? '&' + param(this.settings.youTubePlayerParams)
34981						: '');
34982				// Uncode edit ##START##
34983				// video = "<iframe allow=\"autoplay\" id=" + videoId + " class=\"lg-video-object lg-youtube " + addClass + "\" " + videoTitle + " src=\"//www.youtube.com/embed/" + (videoInfo.youtube[1] + playerParams) + "\" " + commonIframeProps + "></iframe>";
34984				var nocookie = typeof SiteParameters.uncode_nocookie !== 'undefined' ? SiteParameters.uncode_nocookie : '';
34985				video = "<iframe allow=\"autoplay\"" + data_video + " id=" + videoId + " class=\"lg-video-object lg-youtube " + addClass + "\" " + videoTitle + " src=\"//www.youtube" + nocookie + ".com/embed/" + (videoInfo.youtube[1] + playerParams) + "\" " + commonIframeProps + "></iframe>";
34986				var tag = document.createElement('script');
34987				tag.src = "//www.youtube.com/player_api";
34988				var firstScriptTag = document.getElementsByTagName('script')[0];
34989				firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
34990
34991				// Replace the 'ytplayer' element with an <iframe> and
34992				// YouTube player after the API code downloads.
34993				var ytIframeplayer,
34994					setMute = muted === 'yes' ? 0 : 100;
34995				window.onYouTubePlayerAPIReady = function() {
34996					ytIframeplayer = new YT.Player(videoId, {
34997						videoId: videoInfo.youtube[1],
34998						events: {
34999							'onReady': function (event) {
35000								event.target.setVolume(setMute);
35001							}
35002						}
35003					});
35004				}
35005				// Uncode edit ##END##
35006			}
35007			else if (videoInfo.vimeo) {
35008				var videoId = 'lg-vimeo' + index;
35009				// Uncode edit ##START##
35010				videoInfo.autoplay = autoplay;
35011				videoInfo.muted = muted;
35012				// Uncode edit ##END##
35013				var playerParams = getVimeoURLParams(this.settings.vimeoPlayerParams, videoInfo);
35014				// Uncode edit ##START##
35015				// video = "<iframe allow=\"autoplay\" id=" + videoId + " class=\"lg-video-object lg-vimeo " + addClass + "\" " + videoTitle + " src=\"//player.vimeo.com/video/" + (videoInfo.vimeo[1] + playerParams) + "\" " + commonIframeProps + "></iframe>";
35016				var data_video = '';
35017				if ( autoplay !== '' ) {
35018					data_video = ' data-autoplay="' + (autoplay === 'yes' ? 1 : 0) + '"';
35019				}
35020				video = "<iframe allow=\"autoplay\"" + data_video + " id=" + videoId + " class=\"lg-video-object lg-vimeo " + addClass + "\" " + videoTitle + " src=\"//player.vimeo.com/video/" + (videoInfo.vimeo[1] + playerParams) + "\" " + commonIframeProps + "></iframe>";
35021				// Uncode edit ##END##
35022			}
35023			else if (videoInfo.wistia) {
35024				var wistiaId = 'lg-wistia' + index;
35025				var playerParams = param(this.settings.wistiaPlayerParams);
35026				playerParams = playerParams ? '?' + playerParams : '';
35027				video = "<iframe allow=\"autoplay\" id=\"" + wistiaId + "\" src=\"//fast.wistia.net/embed/iframe/" + (videoInfo.wistia[4] + playerParams) + "\" " + videoTitle + " class=\"wistia_embed lg-video-object lg-wistia " + addClass + "\" name=\"wistia_embed\" " + commonIframeProps + "></iframe>";
35028			}
35029			else if (videoInfo.html5) {
35030				var html5VideoMarkup = '';
35031				for (var i = 0; i < html5Video.source.length; i++) {
35032					html5VideoMarkup += "<source src=\"" + html5Video.source[i].src + "\" type=\"" + html5Video.source[i].type + "\">";
35033				}
35034				if (html5Video.tracks) {
35035					var _loop_1 = function (i) {
35036						var trackAttributes = '';
35037						var track = html5Video.tracks[i];
35038						Object.keys(track || {}
35038).forEach(function (key) {
35039							trackAttributes += key + "=\"" + track[key] + "\" ";
35040						});
35041						html5VideoMarkup += "<track " + trackAttributes + ">";
35042					};
35043					for (var i = 0; i < html5Video.tracks.length; i++) {
35044						_loop_1(i);
35045					}
35046				}
35047				var html5VideoAttrs_1 = '';
35048				var videoAttributes_1 = html5Video.attributes || {};
35049				Object.keys(videoAttributes_1 || {}).forEach(function (key) {
35050					html5VideoAttrs_1 += key + "=\"" + videoAttributes_1[key] + "\" ";
35051				});
35052				video = "<video class=\"lg-video-object lg-html5 " + (this.settings.videojs && this.settings.videojsTheme
35053					? this.settings.videojsTheme + ' '
35054					: '') + " " + (this.settings.videojs ? ' video-js' : '') + "\" " + html5VideoAttrs_1 + ">\n                " + html5VideoMarkup + "\n                Your browser does not support HTML5 video.\n            </video>";
35055			}
35056			return video;
35057		};
35058		/**
35059		 * @desc - Append videos to the slide
35060		 *
35061		 * @param {HTMLElement} el - slide element
35062		 * @param {Object} videoParams - Video parameters, Contains src, class, index, htmlVideo
35063		 */
35064		Video.prototype.appendVideos = function (el, videoParams) {
35065			var _a;
35066			// Uncode edit ##START##
35067			// var videoHtml = this.getVideoHtml(videoParams.src, videoParams.addClass, videoParams.index, videoParams.html5Video);
35068			var videoHtml = this.getVideoHtml(videoParams.src, videoParams.addClass, videoParams.index, videoParams.html5Video, videoParams.autoplay, videoParams.muted);
35069			// Uncode edit ##END##
35070			el.find('.lg-video-cont').append(videoHtml);
35071			var $videoElement = el.find('.lg-video-object').first();
35072			if (videoParams.html5Video) {
35073				$videoElement.on('mousedown.lg.video', function (e) {
35074					e.stopPropagation();
35075				});
35076			}
35077			if (this.settings.videojs && ((_a = this.core.galleryItems[videoParams.index].__slideVideoInfo) === null || _a === void 0 ? void 0 : _a.html5)) {
35078				try {
35079					return videojs($videoElement.get(), this.settings.videojsOptions);
35080				}
35081				catch (e) {
35082					console.warn('lightGallery:- Make sure you have included videojs');
35083				}
35084			}
35085		};
35086		Video.prototype.gotoNextSlideOnVideoEnd = function (src, index) {
35087			var _this = this;
35088			var $videoElement = this.core
35089				.getSlideItem(index)
35090				.find('.lg-video-object')
35091				.first();
35092			var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {};
35093			if (this.settings.gotoNextSlideOnVideoEnd) {
35094				if (videoInfo.html5) {
35095					$videoElement.on('ended', function () {
35096						_this.core.goToNextSlide();
35097					});
35098				}
35099				else if (videoInfo.vimeo) {
35100					try {
35101						// https://github.com/vimeo/player.js/#ended
35102						new Vimeo.Player($videoElement.get()).on('ended', function () {
35103							_this.core.goToNextSlide();
35104						});
35105					}
35106					catch (e) {
35107						console.warn('lightGallery:- Make sure you have included //github.com/vimeo/player.js');
35108					}
35109				}
35110				else if (videoInfo.wistia) {
35111					try {
35112						window._wq = window._wq || [];
35113						// @todo Event is gettign triggered multiple times
35114						window._wq.push({
35115							id: $videoElement.attr('id'),
35116							onReady: function (video) {
35117								video.bind('end', function () {
35118									_this.core.goToNextSlide();
35119								});
35120							},
35121						});
35122					}
35123					catch (e) {
35124						console.warn('lightGallery:- Make sure you have included //fast.wistia.com/assets/external/E-v1.js');
35125					}
35126				}
35127			}
35128		};
35129		Video.prototype.controlVideo = function (index, action) {
35130			var $videoElement = this.core
35131				.getSlideItem(index)
35132				.find('.lg-video-object')
35133				.first();
35134			var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {};
35135			if (!$videoElement.get())
35136				return;
35137			if (videoInfo.youtube) {
35138				try {
35139					$videoElement.get().contentWindow.postMessage("{\"event\":\"command\",\"func\":\"" + action + "Video\",\"args\":\"\"}", '*');
35140				}
35141				catch (e) {
35142					console.warn("lightGallery:- " + e);
35143				}
35144			}
35145			else if (videoInfo.vimeo) {
35146				try {
35147					new Vimeo.Player($videoElement.get())[action]();
35148				}
35149				catch (e) {
35150					console.warn('lightGallery:- Make sure you have included //github.com/vimeo/player.js');
35151				}
35152			}
35153			else if (videoInfo.html5) {
35154				if (this.settings.videojs) {
35155					try {
35156						videojs($videoElement.get())[action]();
35157					}
35158					catch (e) {
35159						console.warn('lightGallery:- Make sure you have included videojs');
35160					}
35161				}
35162				else {
35163					$videoElement.get()[action]();
35164				}
35165			}
35166			else if (videoInfo.wistia) {
35167				try {
35168					window._wq = window._wq || [];
35169					// @todo Find a way to destroy wistia player instance
35170					window._wq.push({
35171						id: $videoElement.attr('id'),
35172						onReady: function (video) {
35173							video[action]();
35174						},
35175					});
35176				}
35177				catch (e) {
35178					console.warn('lightGallery:- Make sure you have included //fast.wistia.com/assets/external/E-v1.js');
35179				}
35180			}
35181		};
35182		Video.prototype.loadVideoOnPosterClick = function ($el, forcePlay) {
35183			var _this = this;
35184			// check slide has poster
35185			if (!$el.hasClass('lg-video-loaded')) {
35186				// check already video element present
35187				if (!$el.hasClass('lg-has-video')) {
35188					$el.addClass('lg-has-video');
35189					var _html = void 0;
35190					var _src = this.core.galleryItems[this.core.index].src;
35191					var video = this.core.galleryItems[this.core.index].video;
35192					if (video) {
35193						_html =
35194							typeof video === 'string' ? JSON.parse(video) : video;
35195					}
35196					var videoJsPlayer_1 = this.appendVideos($el, {
35197						src: _src,
35198						addClass: '',
35199						index: this.core.index,
35200						html5Video: _html,
35201					});
35202					this.gotoNextSlideOnVideoEnd(_src, this.core.index);
35203					var $tempImg = $el.find('.lg-object').first().get();
35204					// @todo make sure it is working
35205					$el.find('.lg-video-cont').first().append($tempImg);
35206					$el.addClass('lg-video-loading');
35207					videoJsPlayer_1 &&
35208						videoJsPlayer_1.ready(function () {
35209							videoJsPlayer_1.on('loadedmetadata', function () {
35210								_this.onVideoLoadAfterPosterClick($el, _this.core.index);
35211							});
35212						});
35213					$el.find('.lg-video-object')
35214						.first()
35215						.on('load.lg error.lg loadedmetadata.lg', function () {
35216						setTimeout(function () {
35217							_this.onVideoLoadAfterPosterClick($el, _this.core.index);
35218						}, 50);
35219					});
35220				}
35221				else {
35222					this.playVideo(this.core.index);
35223				}
35224			}
35225			else if (forcePlay) {
35226				this.playVideo(this.core.index);
35227			}
35228		};
35229		Video.prototype.onVideoLoadAfterPosterClick = function ($el, index) {
35230			$el.addClass('lg-video-loaded');
35231			this.playVideo(index);
35232		};
35233		Video.prototype.destroy = function () {
35234			this.core.LGel.off('.lg.video');
35235			this.core.LGel.off('.video');
35236		};
35237		return Video;
35238	}());
35239
35240	return Video;
35241
35242})));
35243
35244
35245/*! @vimeo/player v2.17.1 | (c) 2022 Vimeo | MIT License | https://github.com/vimeo/player.js */
35246!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):((e="undefined"!=typeof globalThis?globalThis:e||self).Vimeo=e.Vimeo||{},e.Vimeo.Player=t())}(this,function(){"use strict";function r(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}var e="undefined"!=typeof global&&"[object global]"==={}.toString.call(global);function i(e,t){return 0===e.indexOf(t.toLowerCase())?e:"".concat(t.toLowerCase()).concat(e.substr(0,1).toUpperCase()).concat(e.substr(1))}function c(e){return/^(https?:)?\/\/((player|www)\.)?vimeo\.com(?=$|\/)/.test(e)}function s(e){var t,n=0<arguments.length&&void 0!==e?e:{},r=n.id,o=n.url,i=r||o;if(!i)throw new Error("An id or url must be passed, either in an options object or as a data-vimeo-id or data-vimeo-url attribute.");if(t=i,!isNaN(parseFloat(t))&&isFinite(t)&&Math.floor(t)==t)return"https://vimeo.com/".concat(i);if(c(i))return i.replace("http:","https:");if(r)throw new TypeError("“".concat(r,"” is not a valid video id."));throw new TypeError("“".concat(i,"” is not a vimeo.com url."))}var t=void 0!==Array.prototype.indexOf,n="undefined"!=typeof window&&void 0!==window.postMessage;if(!(e||t&&n))throw new Error("Sorry, the Vimeo Player API is not available in this browser.");var o,a,u,l,f="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function d(){if(void 0===this)throw new TypeError("Constructor WeakMap requires 'new'");if(l(this,"_id","_WeakMap_"+v()+"."+v()),0<arguments.length)throw new TypeError("WeakMap iterable is not supported")}function h(e,t){if(!m(e)||!a.call(e,"_id"))throw new TypeError(t+" method called on incompatible receiver "+typeof e)}function v(){return Math.random().toString().substring(2)}function m(e){return Object(e)===e}(o="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:f).WeakMap||(a=Object.prototype.hasOwnProperty,u=Object.defineProperty&&function(){try{return 1===Object.defineProperty({},"x",{value:1}).x}catch(e){}}(),l=function(e,t,n){u?Object.defineProperty(e,t,{configurable:!0,writable:!0,value:n}):e[t]=n},o.WeakMap=(l(d.prototype,"delete",function(e){if(h(this,"delete"),!m(e))return!1;var t=e[this._id];return!(!t||t[0]!==e)&&(delete e[this._id],!0)}),l(d.prototype,"get",function(e){if(h(this,"get"),m(e)){var t=e[this._id];return t&&t[0]===e?t[1]:void 0}}),l(d.prototype,"has",function(e){if(h(this,"has"),!m(e))return!1;var t=e[this._id];return!(!t||t[0]!==e)}),l(d.prototype,"set",function(e,t){if(h(this,"set"),!m(e))throw new TypeError("Invalid value used as weak map key");var n=e[this._id];return n&&n[0]===e?n[1]=t:l(e,this._id,[e,t]),this}),l(d,"_polyfill",!0),d));var p,y=(function(e){var t,n,r;r=function(){var t,n,r,o,i,a,e=Object.prototype.toString,u="undefined"!=typeof setImmediate?function(e){return setImmediate(e)}:setTimeout;try{Object.defineProperty({},"x",{}),t=function(e,t,n,r){return Object.defineProperty(e,t,{value:n,writable:!0,configurable:!1!==r})}}catch(e){t=function(e,t,n){return e[t]=n,e}}function l(e,t){this.fn=e,this.self=t,this.next=void 0}function c(e,t){r.add(e,t),n=n||u(r.drain)}function s(e){var t,n=typeof e;return null==e||"object"!=n&&"function"!=n||(t=e.then),"function"==typeof t&&t}function f(){for(var e=0;e<this.chain.length;e++)!function(e,t,n){var r,o;try{!1===t?n.reject(e.msg):(r=!0===t?e.msg:t.call(void 0,e.msg))===n.promise?n.reject(TypeError("Promise-chain cycle")):(o=s(r))?o.call(r,n.resolve,n.reject):n.resolve(r)}catch(e){n.reject(e)}}(this,1===this.state?this.chain[e].success:this.chain[e].failure,this.chain[e]);this.chain.length=0}function d(e){var n,r=this;if(!r.triggered){r.triggered=!0,r.def&&(r=r.def);try{(n=s(e))?c(function(){var t=new m(r);try{n.call(e,function(){d.apply(t,arguments)},function(){h.apply(t,arguments)})}catch(e){h.call(t,e)}}):(r.msg=e,r.state=1,0<r.chain.length&&c(f,r))}catch(e){h.call(new m(r),e)}}}function h(e){var t=this;t.triggered||(t.triggered=!0,t.def&&(t=t.def),t.msg=e,t.state=2,0<t.chain.length&&c(f,t))}function v(e,n,r,o){for(var t=0;t<n.length;t++)!function(t){e.resolve(n[t]).then(function(e){r(t,e)},o)}(t)}function m(e){this.def=e,this.triggered=!1}function p(e){this.promise=e,this.state=0,this.triggered=!1,this.chain=[],this.msg=void 0}function y(e){if("function"!=typeof e)throw TypeError("Not a function");if(0!==this.__NPO__)throw TypeError("Not a promise");this.__NPO__=1;var r=new p(this);this.then=function(e,t){var n={success:"function"!=typeof e||e,failure:"function"==typeof t&&t};return n.promise=new this.constructor(function(e,t){if("function"!=typeof e||"function"!=typeof t)throw TypeError("Not a function");n.resolve=e,n.reject=t}),r.chain.push(n),0!==r.state&&c(f,r),n.promise},this.catch=function(e){return this.then(void 0,e)};try{e.call(void 0,function(e){d.call(r,e)},function(e){h.call(r,e)})}catch(e){h.call(r,e)}}var g=t({},"constructor",y,!(r={add:function(e,t){a=new l(e,t),i?i.next=a:o=a,i=a,a=void 0},drain:function(){var e=o;for(o=i=n=void 0;e;)e.fn.call(e.self),e=e.next}}));return t(y.prototype=g,"__NPO__",0,!1),t(y,"resolve",function(n){return n&&"object"==typeof n&&1===n.__NPO__?n:new this(function(e,t){if("function"!=typeof e||"function"!=typeof t)throw TypeError("Not a function");e(n)})}),t(y,"reject",function(n){return new this(function(e,t){if("function"!=typeof e||"function"!=typeof t)throw TypeError("Not a function");t(n)})}),t(y,"all",function(t){var a=this;return"[object Array]"!=e.call(t)?a.reject(TypeError("Not an array")):0===t.length?a.resolve([]):new a(function(n,e){if("function"!=typeof n||"function"!=typeof e)throw TypeError("Not a function");var r=t.length,o=Array(r),i=0;v(a,t,function(e,t){o[e]=t,++i===r&&n(o)},e)})}),t(y,"race",function(t){var r=this;return"[object Array]"!=e.call(t)?r.reject(TypeError("Not an array")):new r(function(n,e){if("function"!=typeof n||"function"!=typeof e)throw TypeError("Not a function");v(r,t,function(e,t){n(t)},e)})}),y},(n=f)[t="Promise"]=n[t]||r(),e.exports&&(e.exports=n[t])}(p={exports:{}}
35246),p.exports),g=new WeakMap;function w(e,t,n){var r=g.get(e.element)||{};t in r||(r[t]=[]),r[t].push(n),g.set(e.element,r)}function b(e,t){return(g.get(e.element)||{})[t]||[]}function k(e,t,n){var r=g.get(e.element)||{};if(!r[t])return!0;if(!n)return r[t]=[],g.set(e.element,r),!0;var o=r[t].indexOf(n);return-1!==o&&r[t].splice(o,1),g.set(e.element,r),r[t]&&0===r[t].length}function E(e){if("string"==typeof e)try{e=JSON.parse(e)}catch(e){return console.warn(e),{}}return e}function T(e,t,n){var r,o;e.element.contentWindow&&e.element.contentWindow.postMessage&&(r={method:t},void 0!==n&&(r.value=n),8<=(o=parseFloat(navigator.userAgent.toLowerCase().replace(/^.*msie (\d+).*$/,"$1")))&&o<10&&(r=JSON.stringify(r)),e.element.contentWindow.postMessage(r,e.origin))}function P(n,r){var t,e,o=[];(r=E(r)).event?("error"===r.event&&b(n,r.data.method).forEach(function(e){var t=new Error(r.data.message);t.name=r.data.name,e.reject(t),k(n,r.data.method,e)}),o=b(n,"event:".concat(r.event)),t=r.data):!r.method||(e=function(e,t){var n=b(e,t);if(n.length<1)return!1;var r=n.shift();return k(e,t,r),r}(n,r.method))&&(o.push(e),t=r.value),o.forEach(function(e){try{if("function"==typeof e)return void e.call(n,t);e.resolve(t)}catch(e){}})}var M=["autopause","autoplay","background","byline","color","controls","dnt","height","id","interactive_params","keyboard","loop","maxheight","maxwidth","muted","playsinline","portrait","responsive","speed","texttrack","title","transparent","url","width"];function _(r,e){var t=1<arguments.length&&void 0!==e?e:{};return M.reduce(function(e,t){var n=r.getAttribute("data-vimeo-".concat(t));return!n&&""!==n||(e[t]=""===n?1:n),e},t)}function N(e,t){var n=e.html;if(!t)throw new TypeError("An element must be provided");if(null!==t.getAttribute("data-vimeo-initialized"))return t.querySelector("iframe");var r=document.createElement("div");return r.innerHTML=n,t.appendChild(r.firstChild),t.setAttribute("data-vimeo-initialized","true"),t.querySelector("iframe")}function F(i,e,t){var a=1<arguments.length&&void 0!==e?e:{},u=2<arguments.length?t:void 0;return new Promise(function(t,n){if(!c(i))throw new TypeError("“".concat(i,"” is not a vimeo.com url."));var e="https://vimeo.com/api/oembed.json?url=".concat(encodeURIComponent(i));for(var r in a)a.hasOwnProperty(r)&&(e+="&".concat(r,"=").concat(encodeURIComponent(a[r])));var o=new("XDomainRequest"in window?XDomainRequest:XMLHttpRequest);o.open("GET",e,!0),o.onload=function(){if(404!==o.status)if(403!==o.status)try{var e=JSON.parse(o.responseText);if(403===e.domain_status_code)return N(e,u),void n(new Error("“".concat(i,"” is not embeddable.")));t(e)}catch(e){n(e)}else n(new Error("“".concat(i,"” is not embeddable.")));else n(new Error("“".concat(i,"” was not found.")))},o.onerror=function(){var e=o.status?" (".concat(o.status,")"):"";n(new Error("There was an error fetching the embed code from Vimeo".concat(e,".")))},o.send()})}var x,C,j,A=new WeakMap,S=new WeakMap,q={},Player=function(){function Player(u){var e,t,l=this,n=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{};if(!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,Player),window.jQuery&&u instanceof jQuery&&(1<u.length&&window.console&&console.warn&&console.warn("A jQuery object with multiple elements was passed, using the first element."),u=u[0]),"undefined"!=typeof document&&"string"==typeof u&&(u=document.getElementById(u)),e=u,!Boolean(e&&1===e.nodeType&&"nodeName"in e&&e.ownerDocument&&e.ownerDocument.defaultView))throw new TypeError("You must pass either a valid element or a valid id.");if("IFRAME"===u.nodeName||(t=u.querySelector("iframe"))&&(u=t),"IFRAME"===u.nodeName&&!c(u.getAttribute("src")||""))throw new Error("The player element passed isn’t a Vimeo embed.");if(A.has(u))return A.get(u);this._window=u.ownerDocument.defaultView,this.element=u,this.origin="*";var r,o=new y(function(i,a){var e;l._onMessage=function(e){if(c(e.origin)&&l.element.contentWindow===e.source){"*"===l.origin&&(l.origin=e.origin);var t=E(e.data);if(t&&"error"===t.event&&t.data&&"ready"===t.data.method){var n=new Error(t.data.message);return n.name=t.data.name,void a(n)}
vendor: 5,252 bytes, line 35246
35246var r=t&&"ready"===t.event,o=t&&"ping"===t.method;if(r||o)return l.element.setAttribute("data-ready","true"),void i();P(l,t)}},l._window.addEventListener("message",l._onMessage),"IFRAME"!==l.element.nodeName&&F(s(e=_(u,n)),e,u).then(function(e){var t,n,r,o=N(e,u);return l.element=o,l._originalElement=u,t=u,n=o,r=g.get(t),g.set(n,r),g.delete(t),A.set(l.element,l),e}).catch(a)});return S.set(this,o),A.set(this.element,this),"IFRAME"===this.element.nodeName&&T(this,"ping"),q.isEnabled&&(r=function(){return q.exit()},this.fullscreenchangeHandler=function(){(q.isFullscreen?w:k)(l,"event:exitFullscreen",r),l.ready().then(function(){T(l,"fullscreenchange",q.isFullscreen)})},q.on("fullscreenchange",this.fullscreenchangeHandler)),this}var e,t,n;return e=Player,(t=[{key:"callMethod",value:function(n,e){var r=this,o=1<arguments.length&&void 0!==e?e:{};return new y(function(e,t){return r.ready().then(function(){w(r,n,{resolve:e,reject:t}),T(r,n,o)}).catch(t)})}},{key:"get",value:function(n){var r=this;return new y(function(e,t){return n=i(n,"get"),r.ready().then(function(){w(r,n,{resolve:e,reject:t}),T(r,n)}).catch(t)})}},{key:"set",value:function(n,r){var o=this;return new y(function(e,t){if(n=i(n,"set"),null==r)throw new TypeError("There must be a value to set.");return o.ready().then(function(){w(o,n,{resolve:e,reject:t}),T(o,n,r)}).catch(t)})}},{key:"on",value:function(e,t){if(!e)throw new TypeError("You must pass an event name.");if(!t)throw new TypeError("You must pass a callback function.");if("function"!=typeof t)throw new TypeError("The callback must be a function.");0===b(this,"event:".concat(e)).length&&this.callMethod("addEventListener",e).catch(function(){}),w(this,"event:".concat(e),t)}},{key:"off",value:function(e,t){if(!e)throw new TypeError("You must pass an event name.");if(t&&"function"!=typeof t)throw new TypeError("The callback must be a function.");k(this,"event:".concat(e),t)&&this.callMethod("removeEventListener",e).catch(function(e){})}},{key:"loadVideo",value:function(e){return this.callMethod("loadVideo",e)}},{key:"ready",value:function(){var e=S.get(this)||new y(function(e,t){t(new Error("Unknown player. Probably unloaded."))});return y.resolve(e)}},{key:"addCuePoint",value:function(e,t){var n=1<arguments.length&&void 0!==t?t:{};return this.callMethod("addCuePoint",{time:e,data:n})}},{key:"removeCuePoint",value:function(e){return this.callMethod("removeCuePoint",e)}},{key:"enableTextTrack",value:function(e,t){if(!e)throw new TypeError("You must pass a language.");return this.callMethod("enableTextTrack",{language:e,kind:t})}},{key:"disableTextTrack",value:function(){return this.callMethod("disableTextTrack")}},{key:"pause",value:function(){return this.callMethod("pause")}},{key:"play",value:function(){return this.callMethod("play")}},{key:"requestFullscreen",value:function(){return q.isEnabled?q.request(this.element):this.callMethod("requestFullscreen")}},{key:"exitFullscreen",value:function(){return q.isEnabled?q.exit():this.callMethod("exitFullscreen")}},{key:"getFullscreen",value:function(){return q.isEnabled?y.resolve(q.isFullscreen):this.get("fullscreen")}},{key:"requestPictureInPicture",value:function(){return this.callMethod("requestPictureInPicture")}},{key:"exitPictureInPicture",value:function(){return this.callMethod("exitPictureInPicture")}},{key:"getPictureInPicture",value:function(){return this.get("pictureInPicture")}},{key:"unload",value:function(){return this.callMethod("unload")}},{key:"destroy",value:function(){var n=this;return new y(function(e){var t;S.delete(n),A.delete(n.element),n._originalElement&&(A.delete(n._originalElement),n._originalElement.removeAttribute("data-vimeo-initialized")),n.element&&"IFRAME"===n.element.nodeName&&n.element.parentNode&&(n.element.parentNode.parentNode&&n._originalElement&&n._originalElement!==n.element.parentNode?n.element.parentNode.parentNode.removeChild(n.element.parentNode):n.element.parentNode.removeChild(n.element)),n.element&&"DIV"===n.element.nodeName&&n.element.parentNode&&(n.element.removeAttribute("data-vimeo-initialized"),(t=n.element.querySelector("iframe"))&&t.parentNode&&(t.parentNode.parentNode&&n._originalElement&&n._originalElement!==t.parentNode?t.parentNode.parentNode.removeChild(t.parentNode):t.parentNode.removeChild(t))),n._window.removeEventListener("message",n._onMessage),q.isEnabled&&q.off("fullscreenchange",n.fullscreenchangeHandler),e()})}},{key:"getAutopause",value:function(){return this.get("autopause")}},{key:"setAutopause",value:function(e){return this.set("autopause",e)}},{key:"getBuffered",value:function(){return this.get("buffered")}},{key:"getCameraProps",value:function(){return this.get("cameraProps")}},{key:"setCameraProps",value:function(e){return this.set("cameraProps",e)}},{key:"getChapters",value:function(){return this.get("chapters")}},{key:"getCurrentChapter",value:function(){return this.get("currentChapter")}},{key:"getColor",value:function(){return this.get("color")}},{key:"setColor",value:function(e){return this.set("color",e)}},{key:"getCuePoints",value:function(){return this.get("cuePoints")}},{key:"getCurrentTime",value:function(){return this.get("currentTime")}},{key:"setCurrentTime",value:function(e){return this.set("currentTime",e)}
35246},{key:"getDuration",value:function(){return this.get("duration")}},{key:"getEnded",value:function(){return this.get("ended")}},{key:"getLoop",value:function(){return this.get("loop")}},{key:"setLoop",value:function(e){return this.set("loop",e)}},{key:"setMuted",value:function(e){return this.set("muted",e)}},{key:"getMuted",value:function(){return this.get("muted")}},{key:"getPaused",value:function(){return this.get("paused")}},{key:"getPlaybackRate",value:function(){return this.get("playbackRate")}},{key:"setPlaybackRate",value:function(e){return this.set("playbackRate",e)}},{key:"getPlayed",value:function(){return this.get("played")}},{key:"getQualities",value:function(){return this.get("qualities")}},{key:"getQuality",value:function(){return this.get("quality")}},{key:"setQuality",value:function(e){return this.set("quality",e)}},{key:"getSeekable",value:function(){return this.get("seekable")}},{key:"getSeeking",value:function(){return this.get("seeking")}},{key:"getTextTracks",value:function(){return this.get("textTracks")}},{key:"getVideoEmbedCode",value:function(){return this.get("videoEmbedCode")}},{key:"getVideoId",value:function(){return this.get("videoId")}},{key:"getVideoTitle",value:function(){return this.get("videoTitle")}},{key:"getVideoWidth",value:function(){return this.get("videoWidth")}},{key:"getVideoHeight",value:function(){return this.get("videoHeight")}},{key:"getVideoUrl",value:function(){return this.get("videoUrl")}},{key:"getVolume",value:function(){return this.get("volume")}},{key:"setVolume",value:function(e){return this.set("volume",e)}}])&&r(e.prototype,t),n&&r(e,n),Player}();return e||(x=function(){for(var e,t=[["requestFullscreen","exitFullscreen","fullscreenElement","fullscreenEnabled","fullscreenchange","fullscreenerror"],["webkitRequestFullscreen","webkitExitFullscreen","webkitFullscreenElement","webkitFullscreenEnabled","webkitfullscreenchange","webkitfullscreenerror"],["webkitRequestFullScreen","webkitCancelFullScreen","webkitCurrentFullScreenElement","webkitCancelFullScreen","webkitfullscreenchange","webkitfullscreenerror"],["mozRequestFullScreen","mozCancelFullScreen","mozFullScreenElement","mozFullScreenEnabled","mozfullscreenchange","mozfullscreenerror"],["msRequestFullscreen","msExitFullscreen","msFullscreenElement","msFullscreenEnabled","MSFullscreenChange","MSFullscreenError"]],n=0,r=t.length,o={};n<r;n++)if((e=t[n])&&e[1]in document){for(n=0;n<e.length;n++)o[t[0][n]]=e[n];return o}return!1}(),C={fullscreenchange:x.fullscreenchange,fullscreenerror:x.fullscreenerror},j={request:function(o){return new Promise(function(e,t){function n(){j.off("fullscreenchange",n),e()}j.on("fullscreenchange",n);var r=(o=o||document.documentElement)[x.requestFullscreen]();r instanceof Promise&&r.then(n).catch(t)})},exit:function(){return new Promise(function(t,e){var n,r;j.isFullscreen?(n=function e(){j.off("fullscreenchange",e),t()},j.on("fullscreenchange",n),(r=document[x.exitFullscreen]())instanceof Promise&&r.then(n).catch(e)):t()})},on:function(e,t){var n=C[e];n&&document.addEventListener(n,t)},off:function(e,t){var n=C[e];n&&document.removeEventListener(n,t)}},Object.defineProperties(j,{isFullscreen:{get:function(){return Boolean(document[x.fullscreenElement])}},element:{enumerable:!0,get:function(){return document[x.fullscreenElement]}},isEnabled:{enumerable:!0,get:function(){return Boolean(document[x.fullscreenEnabled])}}}),q=j,function(e){function n(e){"console"in window&&console.error&&console.error("There was an error creating an embed: ".concat(e))}var t=0<arguments.length&&void 0!==e?e:document;[].slice.call(t.querySelectorAll("[data-vimeo-id], [data-vimeo-url]")).forEach(function(t){try{if(null!==t.getAttribute("data-vimeo-defer"))return;var e=_(t);F(s(e),e,t).then(function(e){return N(e,t)}).catch(n)}catch(e){n(e)}})}(),function(e){var r=0<arguments.length&&void 0!==e?e:document;window.VimeoPlayerResizeEmbeds_||(window.VimeoPlayerResizeEmbeds_=!0,window.addEventListener("message",function(e){if(c(e.origin)&&e.data&&"spacechange"===e.data.event)for(var t=r.querySelectorAll("iframe"),n=0;n<t.length;n++)if(t[n].contentWindow===e.source){t[n].parentElement.style.paddingBottom="".concat(e.data.data[0].bottom,"px");break}}
vendor: 6,940 bytes, lines 35246-35573
35246))}(),function(e){var u=0<arguments.length&&void 0!==e?e:document;window.VimeoSeoMetadataAppended||(window.VimeoSeoMetadataAppended=!0,window.addEventListener("message",function(e){if(c(e.origin)){var t=E(e.data);if(t&&"ready"===t.event)for(var n,r=u.querySelectorAll("iframe"),o=0;o<r.length;o++){var i=r[o],a=i.contentWindow===e.source;n=i.src,/^https:\/\/player\.vimeo\.com\/video\/\d+/.test(n)&&a&&new Player(i).callMethod("appendVideoMetadata",window.location.href)}}}))}()),Player});
35247
35248/**
35249 * Owl carousel
35250 * @version 2.0.0-beta.3
35251 * @author Bartosz Wojciechowski
35252 * @license The MIT License (MIT)
35253 * @todo Lazy Load Icon
35254 * @todo prevent animationend bubling
35255 * @todo itemsScaleUp
35256 * @todo Test Zepto
35257 * @todo stagePadding calculate wrong active classes
35258 */
35259;(function($, window, document, undefined) {
35260
35261	/**
35262	 * Creates a carousel.
35263	 * @class The Owl Carousel.
35264	 * @public
35265	 * @param {HTMLElement|jQuery} element - The element to create the carousel for.
35266	 * @param {Object} [options] - The options
35267	 */
35268	function Owl(element, options) {
35269
35270		/**
35271		 * Current settings for the carousel.
35272		 * @public
35273		 */
35274		this.settings = null;
35275
35276		/**
35277		 * Current options set by the caller including defaults.
35278		 * @public
35279		 */
35280		this.options = $.extend({}, Owl.Defaults, options);
35281
35282		/**
35283		 * Plugin element.
35284		 * @public
35285		 */
35286		this.$element = $(element);
35287
35288		/**
35289		 * Proxied event handlers.
35290		 * @protected
35291		 */
35292		this._handlers = {};
35293
35294		/**
35295		 * References to the running plugins of this carousel.
35296		 * @protected
35297		 */
35298		this._plugins = {};
35299
35300		/**
35301		 * Currently suppressed events to prevent them from beeing retriggered.
35302		 * @protected
35303		 */
35304		this._supress = {};
35305
35306		/**
35307		 * Absolute current position.
35308		 * @protected
35309		 */
35310		this._current = null;
35311
35312		/**
35313		 * Animation speed in milliseconds.
35314		 * @protected
35315		 */
35316		this._speed = null;
35317
35318		/**
35319		 * Coordinates of all items in pixel.
35320		 * @todo The name of this member is missleading.
35321		 * @protected
35322		 */
35323		this._coordinates = [];
35324
35325		/**
35326		 * Current breakpoint.
35327		 * @todo Real media queries would be nice.
35328		 * @protected
35329		 */
35330		this._breakpoint = null;
35331
35332		/**
35333		 * Current width of the plugin element.
35334		 */
35335		this._width = null;
35336
35337		/**
35338		 * All real items.
35339		 * @protected
35340		 */
35341		this._items = [];
35342
35343		/**
35344		 * All cloned items.
35345		 * @protected
35346		 */
35347		this._clones = [];
35348
35349		/**
35350		 * Merge values of all items.
35351		 * @todo Maybe this could be part of a plugin.
35352		 * @protected
35353		 */
35354		this._mergers = [];
35355
35356		/**
35357		 * Widths of all items.
35358		 */
35359		this._widths = [];
35360
35361		/**
35362		 * Invalidated parts within the update process.
35363		 * @protected
35364		 */
35365		this._invalidated = {};
35366
35367		/**
35368		 * Ordered list of workers for the update process.
35369		 * @protected
35370		 */
35371		this._pipe = [];
35372
35373		/**
35374		 * Current state information for the drag operation.
35375		 * @todo #261
35376		 * @protected
35377		 */
35378		this._drag = {
35379			time: null,
35380			target: null,
35381			pointer: null,
35382			stage: {
35383				start: null,
35384				current: null
35385			},
35386			direction: null
35387		};
35388
35389		/**
35390		 * Current state information and their tags.
35391		 * @type {Object}
35392		 * @protected
35393		 */
35394		this._states = {
35395			current: {},
35396			tags: {
35397				'initializing': [ 'busy' ],
35398				'animating': [ 'busy' ],
35399				'dragging': [ 'interacting' ]
35400			}
35401		};
35402
35403		$.each([ 'onResize', 'onThrottledResize' ], $.proxy(function(i, handler) {
35404			this._handlers[handler] = $.proxy(this[handler], this);
35405		}, this));
35406
35407		$.each(Owl.Plugins, $.proxy(function(key, plugin) {
35408			this._plugins[key.charAt(0).toLowerCase() + key.slice(1)]
35409				= new plugin(this);
35410		}, this));
35411
35412		$.each(Owl.Workers, $.proxy(function(priority, worker) {
35413			this._pipe.push({
35414				'filter': worker.filter,
35415				'run': $.proxy(worker.run, this)
35416			});
35417		}, this));
35418
35419		this.setup();
35420		this.initialize();
35421	}
35422
35423	/**
35424	 * Default options for the carousel.
35425	 * @public
35426	 */
35427	Owl.Defaults = {
35428		items: 3,
35429		loop: false,
35430		center: false,
35431		rewind: false,
35432
35433		mouseDrag: true,
35434		touchDrag: true,
35435		pullDrag: true,
35436		freeDrag: false,
35437
35438		margin: 0,
35439		stagePadding: 0,
35440
35441		merge: false,
35442		mergeFit: true,
35443		autoWidth: false,
35444
35445		startPosition: 0,
35446		rtl: false,
35447
35448		smartSpeed: 250,
35449		fluidSpeed: false,
35450		dragEndSpeed: false,
35451
35452		responsive: {},
35453		responsiveRefreshRate: 200,
35454		responsiveBaseElement: window,
35455
35456		fallbackEasing: 'swing',
35457
35458		info: false,
35459
35460		nestedItemSelector: false,
35461		itemSelector: false,
35462		itemElement: 'div',
35463		stageElement: 'div',
35464
35465		refreshClass: 'owl-refresh',
35466		loadedClass: 'owl-loaded',
35467		loadingClass: 'owl-loading',
35468		rtlClass: 'owl-rtl',
35469		responsiveClass: 'owl-responsive',
35470		dragClass: 'owl-drag',
35471		itemClass: 'owl-item',
35472		stageClass: 'owl-stage',
35473		stageOuterClass: 'owl-stage-outer',
35474		grabClass: 'owl-grab'
35475	};
35476
35477	/**
35478	 * Enumeration for width.
35479	 * @public
35480	 * @readonly
35481	 * @enum {String}
35482	 */
35483	Owl.Width = {
35484		Default: 'default',
35485		Inner: 'inner',
35486		Outer: 'outer'
35487	};
35488
35489	/**
35490	 * Enumeration for types.
35491	 * @public
35492	 * @readonly
35493	 * @enum {String}
35494	 */
35495	Owl.Type = {
35496		Event: 'event',
35497		State: 'state'
35498	};
35499
35500	/**
35501	 * Contains all registered plugins.
35502	 * @public
35503	 */
35504	Owl.Plugins = {};
35505
35506	/**
35507	 * List of workers involved in the update process.
35508	 */
35509	Owl.Workers = [ {
35510		filter: [ 'width', 'settings' ],
35511		run: function() {
35512			this._width = (this.$element.closest('.px-gutter').length) ? 12 * Math.ceil(this.$element.width() / 12) : this.$element.width();
35513			//this._width = (UNCODE.isMobile) ? this.$element.width() : 12 * Math.ceil(this.$element.width() / 12);
35514		}
35515	}, {
35516		filter: [ 'width', 'items', 'settings' ],
35517		run: function(cache) {
35518			cache.current = this._items && this._items[this.relative(this._current)];
35519		}
35520	}, {
35521		filter: [ 'items', 'settings' ],
35522		run: function() {
35523			this.$stage.children('.cloned').remove();
35524		}
35525	}, {
35526		filter: [ 'width', 'items', 'settings' ],
35527		run: function(cache) {
35528			var margin = this.settings.margin || '',
35529				grid = !this.settings.autoWidth,
35530				rtl = this.settings.rtl,
35531				css = {
35532					'width': 'auto',
35533					'margin-left': rtl ? margin : '',
35534					'margin-right': rtl ? '' : margin
35535				};
35536
35537			!grid && this.$stage.children().css(css);
35538
35539			cache.css = css;
35540		}
35541	}, {
35542		filter: [ 'width', 'items', 'settings' ],
35543		run: function(cache) {
35544			//UNCODE edit to fix Chrome stage padding issue
35545			var width = Math.round((this.width() / this.settings.items).toFixed(3) - this.settings.margin),
35546				merge = null,
35547				iterator = this._items.length,
35548				grid = !this.settings.autoWidth,
35549				widths = [];
35550
35551			cache.items = {
35552				merge: false,
35553				width: width
35554			};
35555
35556			while (iterator--) {
35557				merge = this._mergers[iterator];
35558				merge = this.settings.mergeFit && Math.min(merge, this.settings.items) || merge;
35559
35560				cache.items.merge = merge > 1 || cache.items.merge;
35561
35562				widths[iterator] = !grid ? this._items[iterator].width() : width * merge;
35563			}
35564
35565			this._widths = widths;
35566		}
35567	}, {
35568		filter: [ 'items', 'settings' ],
35569		run: function() {
35570			var clones = [],
35571				items = this._items,
35572				settings = this.settings,
35573				view = Math.max(settings.items * 2, 4),
vendor: 4,968 bytes, lines 35574-35726
35574				size = Math.ceil(items.length / 2) * 2,
35575				repeat = settings.loop && items.length ? settings.rewind ? view : Math.max(view, size) : 0,
35576				append = '',
35577				prepend = '';
35578
35579			repeat /= 2;
35580
35581			while (repeat--) {
35582				clones.push(this.normalize(clones.length / 2, true));
35583				append = append + items[clones[clones.length - 1]][0].outerHTML;
35584				clones.push(this.normalize(items.length - 1 - (clones.length - 1) / 2, true));
35585				prepend = items[clones[clones.length - 1]][0].outerHTML + prepend;
35586			}
35587
35588			this._clones = clones;
35589
35590			// var appendVideo = $(append).find('.uncode-video-container');
35591			// if (appendVideo.length) {
35592			// 	appendVideo.attr('data-id', Math.round(Math.random() * 100000));
35593			// }
35594			// var prependVideo = $(prepend).find('.uncode-video-container');
35595			// if (prependVideo.length) {
35596			// 	prependVideo.attr('data-id', Math.round(Math.random() * 100000));
35597			// }
35598			$(append).addClass('cloned').appendTo(this.$stage);
35599			$(prepend).addClass('cloned').prependTo(this.$stage);
35600		}
35601	}, {
35602		filter: [ 'width', 'items', 'settings' ],
35603		run: function() {
35604			var rtl = this.settings.rtl ? 1 : -1,
35605				size = this._clones.length + this._items.length,
35606				iterator = -1,
35607				previous = 0,
35608				current = 0,
35609				coordinates = [];
35610
35611			while (++iterator < size) {
35612				previous = coordinates[iterator - 1] || 0;
35613				current = this._widths[this.relative(iterator)] + this.settings.margin;
35614				coordinates.push(previous + current * rtl);
35615			}
35616
35617			this._coordinates = coordinates;
35618		}
35619	}, {
35620		filter: [ 'width', 'items', 'settings' ],
35621		run: function() {
35622			var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200,
35623				padding = stagePadding,
35624				coordinates = this._coordinates,
35625				css = {
35626					'width': Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2,
35627					'padding-left': padding || '',
35628					'padding-right': padding || ''
35629				};
35630
35631			this.$stage.css(css);
35632		}
35633	}, {
35634		filter: [ 'width', 'items', 'settings' ],
35635		run: function(cache) {
35636			var iterator = this._coordinates.length,
35637				grid = !this.settings.autoWidth,
35638				items = this.$stage.children();
35639
35640			if (grid && cache.items.merge) {
35641				while (iterator--) {
35642					cache.css.width = this._widths[this.relative(iterator)];
35643					items.eq(iterator).css(cache.css);
35644				}
35645			} else if (grid) {
35646				cache.css.width = cache.items.width;
35647				items.css(cache.css);
35648			}
35649		}
35650	}, {
35651		filter: [ 'items' ],
35652		run: function() {
35653			this._coordinates.length < 1 && this.$stage.removeAttr('style');
35654		}
35655	}, {
35656		filter: [ 'width', 'items', 'settings' ],
35657		run: function(cache) {
35658			cache.current = cache.current ? this.$stage.children().index(cache.current) : 0;
35659			cache.current = Math.max(this.minimum(), Math.min(this.maximum(), cache.current));
35660			this.reset(cache.current);
35661		}
35662	}, {
35663		filter: [ 'position' ],
35664		run: function() {
35665			this.animate(this.coordinates(this._current));
35666		}
35667	}, {
35668		filter: [ 'width', 'position', 'items', 'settings' ],
35669		run: function() {
35670			var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200,
35671				rtl = this.settings.rtl ? 1 : -1,
35672				padding = this.settings.stagePadding * 2,
35673				begin = this.coordinates(this.current()) + padding,
35674				end = begin + this.width() * rtl,
35675				inner, outer, matches = [], i, n;
35676
35677			for (i = 0, n = this._coordinates.length; i < n; i++) {
35678				inner = this._coordinates[i - 1] || 0;
35679				outer = Math.abs(this._coordinates[i]) + padding * rtl;
35680
35681				if ((this.op(inner, '<=', begin) && (this.op(inner, '>', end)))
35682					|| (this.op(outer, '<', begin) && this.op(outer, '>', end))) {
35683					matches.push(i);
35684				}
35685			}
35686
35687			this.$stage.children('.active').removeClass('active');
35688			this.$stage.children(':eq(' + matches.join('), :eq(') + ')').addClass('active');
35689
35690			if (this.settings.center) {
35691				this.$stage.children('.center').removeClass('center');
35692				this.$stage.children().eq(this.current()).addClass('center');
35693			}
35694		}
35695	} ];
35696
35697	/**
35698	 * Initializes the carousel.
35699	 * @protected
35700	 */
35701	Owl.prototype.initialize = function() {
35702		this.enter('initializing');
35703		this.trigger('initialize');
35704
35705		this.$element.toggleClass(this.settings.rtlClass, this.settings.rtl);
35706
35707		if (this.settings.autoWidth && !this.is('pre-loading')) {
35708			var imgs, nestedSelector, width;
35709			imgs = this.$element.find('img');
35710			nestedSelector = this.settings.nestedItemSelector ? '.' + this.settings.nestedItemSelector : undefined;
35711			width = this.$element.children(nestedSelector).width();
35712
35713			if (imgs.length && width <= 0) {
35714				this.preloadAutoWidthImages(imgs);
35715			}
35716		}
35717
35718		this.$element.addClass(this.options.loadingClass);
35719
35720		// create stage
35721		this.$stage = $('<' + this.settings.stageElement + ' class="' + this.settings.stageClass + '"/>')
35722			.wrap('<div class="' + this.settings.stageOuterClass + '"/>');
35723
35724		//UNCODE edit to exclude hidden items
35725		if ( this.settings.itemSelector ) {
35726			// append stage
35727			this.$element.prepend(this.$stage.parent());
35728			// append content
35729			this.replace(this.$element.find(' > ' + this.settings.itemSelector).not(this.$stage.parent()));
35730		} else {
35731			// append stage
35732			this.$element.append(this.$stage.parent());
35733			// append content
35734			this.replace(this.$element.children().not(this.$stage.parent()));
35735		}
35736
35737		// check visibility
35738		if (this.$element.is(':visible')) {
35739			// update view
35740			this.refresh();
35741		} else {
35742			// invalidate width
35743			this.invalidate('width');
35744		}
35745
35746		this.$element
35747			.removeClass(this.options.loadingClass)
35748			.addClass(this.options.loadedClass);
35749
35750		// register event handlers
35751		this.registerEventHandlers();
35752
35753		this.leave('initializing');
35754		this.trigger('initialized');
35755	};
35756
35757	/**
35758	 * Setups the current settings.
35759	 * @todo Remove responsive classes. Why should adaptive designs be brought into IE8?
35760	 * @todo Support for media queries by using `matchMedia` would be nice.
35761	 * @public
35762	 */
35763	Owl.prototype.setup = function() {
35764		var viewport = this.viewport(),
35765			overwrites = this.options.responsive,
35766			match = -1,
35767			settings = null;
35768
35769		if (!overwrites) {
35770			settings = $.extend({}, this.options);
35771		} else {
35772			$.each(overwrites, function(breakpoint) {
35773				if (breakpoint <= viewport && breakpoint > match) {
35774					match = Number(breakpoint);
35775				}
35776			});
35777
35778			settings = $.extend({}, this.options, overwrites[match]);
35779			delete settings.responsive;
35780
35781			// responsive class
35782			if (settings.responsiveClass) {
35783				this.$element.attr('class',
35784					this.$element.attr('class').replace(new RegExp('(' + this.options.responsiveClass + '-)\\S+\\s', 'g'), '$1' + match)
35785				);
35786			}
35787		}
35788
35789		if (this.settings === null || this._breakpoint !== match) {
35790			this.trigger('change', { property: { name: 'settings', value: settings } });
35791			this._breakpoint = match;
35792			this.settings = settings;
35793			this.invalidate('settings');
35794			this.trigger('changed', { property: { name: 'settings', value: this.settings } });
35795		}
35796	};
35797
35798	/**
35799	 * Updates option logic if necessery.
35800	 * @protected
35801	 */
35802	Owl.prototype.optionsLogic = function() {
35803		if (this.settings.autoWidth) {
35804			this.settings.stagePadding = false;
35805			this.settings.merge = false;
35806		}
35807	};
35808
35809	/**
35810	 * Prepares an item before add.
35811	 * @todo Rename event parameter `content` to `item`.
35812	 * @protected
35813	 * @returns {jQuery|HTMLElement} - The item container.
35814	 */
35815	Owl.prototype.prepare = function(item, index) {
35816		var event = this.trigger('prepare', { content: item });
35817		if (!event.data) {
35818			event.data = $('<' + this.settings.itemElement + '/>')
35819				.addClass(this.options.itemClass).attr('data-index', index + 1).append(item)
35820		}
35821
35822		this.trigger('prepared', { content: event.data });
35823
35824		return event.data;
35825	};
35826
35827	/**
35828	 * Updates the view.
35829	 * @public
35830	 */
35831	Owl.prototype.update = function() {
35832		var i = 0,
35833			n = this._pipe.length,
35834			filter = $.proxy(function(p) { return this[p] }, this._invalidated),
35835			cache = {};
35836
35837		while (i < n) {
35838			if (this._invalidated.all || $.grep(this._pipe[i].filter, filter).length > 0) {
35839				this._pipe[i].run(cache);
35840			}
35841			i++;
35842		}
35843
35844		this._invalidated = {};
35845
35846		!this.is('valid') && this.enter('valid');
35847	};
35848
35849	/**
35850	 * Gets the width of the view.
35851	 * @public
35852	 * @param {Owl.Width} [dimension=Owl.Width.Default] - The dimension to return.
35853	 * @returns {Number} - The width of the view in pixel.
35854	 */
35855	Owl.prototype.width = function(dimension) {
35856		dimension = dimension || Owl.Width.Default;
35857		var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200;
35858		switch (dimension) {
35859			case Owl.Width.Inner:
35860			case Owl.Width.Outer:
35861				return this._width;
35862			default:
35863				return this._width - stagePadding * 2 + this.settings.margin;
35864		}
35865	};
35866
35867	/**
35868	 * Refreshes the carousel primarily for adaptive purposes.
35869	 * @public
35870	 */
35871	Owl.prototype.refresh = function() {
35872		this.enter('refreshing');
35873		this.trigger('refresh');
35874
35875		this.setup();
35876
35877		this.optionsLogic();
35878
35879		this.$element.addClass(this.options.refreshClass);
35880
35881		this.update();
35882
35883		this.$element.removeClass(this.options.refreshClass);
35884
35885		this.leave('refreshing');
35886		this.trigger('refreshed');
35887	};
35888
35889	/**
35890	 * Checks window `resize` event.
35891	 * @protected
35892	 */
35893	Owl.prototype.onThrottledResize = function() {
35894		window.clearTimeout(this.resizeTimer);
35895		this.resizeTimer = window.setTimeout(this._handlers.onResize, this.settings.responsiveRefreshRate);
35896	};
35897
35898	/**
35899	 * Checks window `resize` event.
35900	 * @protected
35901	 */
35902	Owl.prototype.onResize = function() {
35903		if (!this._items.length) {
35904			return false;
vendor: 15,850 bytes, lines 35905-36461
35905		}
35906
35907		if (this._width === this.$element.width()) {
35908			return false;
35909		}
35910
35911		if (!this.$element.is(':visible')) {
35912			return false;
35913		}
35914
35915		this.enter('resizing');
35916
35917		if (this.trigger('resize').isDefaultPrevented()) {
35918			this.leave('resizing');
35919			return false;
35920		}
35921
35922		this.invalidate('width');
35923
35924		this.refresh();
35925
35926		this.leave('resizing');
35927		this.trigger('resized');
35928	};
35929
35930	/**
35931	 * Registers event handlers.
35932	 * @todo Check `msPointerEnabled`
35933	 * @todo #261
35934	 * @protected
35935	 */
35936	Owl.prototype.registerEventHandlers = function() {
35937		if ($.support.transition) {
35938			this.$stage.on($.support.transition.end + '.owl.core', $.proxy(this.onTransitionEnd, this));
35939		}
35940
35941		if (this.settings.responsive !== false) {
35942			this.on(window, 'resize', this._handlers.onThrottledResize);
35943		}
35944
35945		if (this.settings.mouseDrag) {
35946			this.$element.addClass(this.options.dragClass);
35947			this.$stage.on('mousedown.owl.core', $.proxy(this.onDragStart, this));
35948			this.$stage.on('dragstart.owl.core selectstart.owl.core', function() { return false });
35949		}
35950
35951		if (this.settings.touchDrag){
35952			this.$stage.on('touchstart.owl.core', $.proxy(this.onDragStart, this));
35953			this.$stage.on('touchcancel.owl.core', $.proxy(this.onDragEnd, this));
35954		}
35955	};
35956
35957	/**
35958	 * Handles `touchstart` and `mousedown` events.
35959	 * @todo Horizontal swipe threshold as option
35960	 * @todo #261
35961	 * @protected
35962	 * @param {Event} event - The event arguments.
35963	 */
35964	Owl.prototype.onDragStart = function(event) {
35965		var stage = null;
35966
35967		if (event.which === 3) {
35968			return;
35969		}
35970
35971		if ($.support.transform) {
35972			stage = this.$stage.css('transform').replace(/.*\(|\)| /g, '').split(',');
35973			stage = {
35974				x: stage[stage.length === 16 ? 12 : 4],
35975				y: stage[stage.length === 16 ? 13 : 5]
35976			};
35977		} else {
35978			stage = this.$stage.position();
35979			stage = {
35980				x: this.settings.rtl ?
35981					stage.left + this.$stage.width() - this.width() + this.settings.margin :
35982					stage.left,
35983				y: stage.top
35984			};
35985		}
35986
35987		if (this.is('animating')) {
35988			$.support.transform ? this.animate(stage.x) : this.$stage.stop()
35989			this.invalidate('position');
35990		}
35991
35992		this.$element.toggleClass(this.options.grabClass, event.type === 'mousedown');
35993
35994		this.speed(0);
35995
35996		this._drag.time = new Date().getTime();
35997		this._drag.target = $(event.target);
35998		this._drag.stage.start = stage;
35999		this._drag.stage.current = stage;
36000		this._drag.pointer = this.pointer(event);
36001
36002		$(document).on('mouseup.owl.core touchend.owl.core', $.proxy(this.onDragEnd, this));
36003
36004		$(document).one('mousemove.owl.core touchmove.owl.core', $.proxy(function(event) {
36005			var delta = this.difference(this._drag.pointer, this.pointer(event));
36006
36007			$(document).on('mousemove.owl.core touchmove.owl.core', $.proxy(this.onDragMove, this));
36008
36009			if (Math.abs(delta.x) < Math.abs(delta.y) && this.is('valid')) {
36010				return;
36011			}
36012
36013			event.preventDefault();
36014
36015			this.enter('dragging');
36016			this.trigger('drag');
36017		}, this));
36018	};
36019
36020	/**
36021	 * Handles the `touchmove` and `mousemove` events.
36022	 * @todo #261
36023	 * @protected
36024	 * @param {Event} event - The event arguments.
36025	 */
36026	Owl.prototype.onDragMove = function(event) {
36027		var minimum = null,
36028			maximum = null,
36029			pull = null,
36030			delta = this.difference(this._drag.pointer, this.pointer(event)),
36031			stage = this.difference(this._drag.stage.start, delta);
36032
36033		if (!this.is('dragging')) {
36034			return;
36035		}
36036
36037		event.preventDefault();
36038
36039		if (this.settings.loop) {
36040			minimum = this.coordinates(this.minimum());
36041			maximum = this.coordinates(this.maximum() + 1) - minimum;
36042			stage.x = (((stage.x - minimum) % maximum + maximum) % maximum) + minimum;
36043		} else {
36044			minimum = this.settings.rtl ? this.coordinates(this.maximum()) : this.coordinates(this.minimum());
36045			maximum = this.settings.rtl ? this.coordinates(this.minimum()) : this.coordinates(this.maximum());
36046			pull = this.settings.pullDrag ? -1 * delta.x / 5 : 0;
36047			stage.x = Math.max(Math.min(stage.x, minimum + pull), maximum + pull);
36048		}
36049
36050		this._drag.stage.current = stage;
36051
36052		this.animate(stage.x);
36053	};
36054
36055	/**
36056	 * Handles the `touchend` and `mouseup` events.
36057	 * @todo #261
36058	 * @todo Threshold for click event
36059	 * @protected
36060	 * @param {Event} event - The event arguments.
36061	 */
36062	Owl.prototype.onDragEnd = function(event) {
36063		var delta = this.difference(this._drag.pointer, this.pointer(event)),
36064			stage = this._drag.stage.current,
36065			direction = delta.x > 0 ^ this.settings.rtl ? 'left' : 'right';
36066
36067		$(document).off('.owl.core');
36068
36069		this.$element.removeClass(this.options.grabClass);
36070
36071		if (delta.x !== 0 && this.is('dragging') || !this.is('valid')) {
36072			this.speed(this.settings.dragEndSpeed || this.settings.smartSpeed);
36073			this.current(this.closest(stage.x, delta.x !== 0 ? direction : this._drag.direction));
36074			this.invalidate('position');
36075			this.update();
36076
36077			this._drag.direction = direction;
36078
36079			if (Math.abs(delta.x) > 3 || new Date().getTime() - this._drag.time > 300) {
36080				this._drag.target.one('click.owl.core', function() { return false; });
36081			}
36082		}
36083
36084		if (!this.is('dragging')) {
36085			return;
36086		}
36087
36088		this.leave('dragging');
36089		this.trigger('dragged');
36090	};
36091
36092	/**
36093	 * Gets absolute position of the closest item for a coordinate.
36094	 * @todo Setting `freeDrag` makes `closest` not reusable. See #165.
36095	 * @protected
36096	 * @param {Number} coordinate - The coordinate in pixel.
36097	 * @param {String} direction - The direction to check for the closest item. Ether `left` or `right`.
36098	 * @return {Number} - The absolute position of the closest item.
36099	 */
36100	Owl.prototype.closest = function(coordinate, direction) {
36101		var position = -1,
36102			pull = 30,
36103			width = this.width(),
36104			coordinates = this.coordinates();
36105
36106		if (!this.settings.freeDrag) {
36107			// check closest item
36108			$.each(coordinates, $.proxy(function(index, value) {
36109				if (coordinate > value - pull && coordinate < value + pull) {
36110					position = index;
36111				} else if (this.op(coordinate, '<', value)
36112					&& this.op(coordinate, '>', coordinates[index + 1] || value - width)) {
36113					position = direction === 'left' ? index + 1 : index;
36114				}
36115				return position === -1;
36116			}, this));
36117		}
36118
36119		if (!this.settings.loop) {
36120			// non loop boundries
36121			if (this.op(coordinate, '>', coordinates[this.minimum()])) {
36122				position = coordinate = this.minimum();
36123			} else if (this.op(coordinate, '<', coordinates[this.maximum()])) {
36124				position = coordinate = this.maximum();
36125			}
36126		}
36127
36128		return position;
36129	};
36130
36131	/**
36132	 * Animates the stage.
36133	 * @todo #270
36134	 * @public
36135	 * @param {Number} coordinate - The coordinate in pixels.
36136	 */
36137	Owl.prototype.animate = function(coordinate) {
36138		var animate = this.speed() > 0;
36139
36140		this.is('animating') && this.onTransitionEnd();
36141
36142		if (animate) {
36143			this.enter('animating');
36144			this.trigger('translate');
36145		}
36146
36147		if ($.support.transform3d && $.support.transition) {
36148			this.$stage.css({
36149				transform: 'translate3d(' + coordinate + 'px,0px,0px)',
36150				transition: (this.speed() / 1000) + 's'
36151			});
36152		} else if (animate) {
36153			this.$stage.animate({
36154				left: coordinate + 'px'
36155			}, this.speed(), this.settings.fallbackEasing, $.proxy(this.onTransitionEnd, this));
36156		} else {
36157			this.$stage.css({
36158				left: coordinate + 'px'
36159			});
36160		}
36161	};
36162
36163	/**
36164	 * Checks whether the carousel is in a specific state or not.
36165	 * @param {String} state - The state to check.
36166	 * @returns {Boolean} - The flag which indicates if the carousel is busy.
36167	 */
36168	Owl.prototype.is = function(state) {
36169		return this._states.current[state] && this._states.current[state] > 0;
36170	};
36171
36172	/**
36173	 * Sets the absolute position of the current item.
36174	 * @public
36175	 * @param {Number} [position] - The new absolute position or nothing to leave it unchanged.
36176	 * @returns {Number} - The absolute position of the current item.
36177	 */
36178	Owl.prototype.current = function(position) {
36179		if (position === undefined) {
36180			return this._current;
36181		}
36182
36183		if (this._items.length === 0) {
36184			return undefined;
36185		}
36186
36187		position = this.normalize(position);
36188
36189		if (this._current !== position) {
36190			var event = this.trigger('change', { property: { name: 'position', value: position } });
36191
36192			if (event.data !== undefined) {
36193				position = this.normalize(event.data);
36194			}
36195
36196			this._current = position;
36197
36198			this.invalidate('position');
36199
36200			this.trigger('changed', { property: { name: 'position', value: this._current } });
36201		}
36202
36203		return this._current;
36204	};
36205
36206	/**
36207	 * Invalidates the given part of the update routine.
36208	 * @param {String} [part] - The part to invalidate.
36209	 * @returns {Array.<String>} - The invalidated parts.
36210	 */
36211	Owl.prototype.invalidate = function(part) {
36212		if ($.type(part) === 'string') {
36213			this._invalidated[part] = true;
36214			this.is('valid') && this.leave('valid');
36215		}
36216		return $.map(this._invalidated, function(v, i) { return i });
36217	};
36218
36219	/**
36220	 * Resets the absolute position of the current item.
36221	 * @public
36222	 * @param {Number} position - The absolute position of the new item.
36223	 */
36224	Owl.prototype.reset = function(position) {
36225		position = this.normalize(position);
36226
36227		if (position === undefined) {
36228			return;
36229		}
36230
36231		this._speed = 0;
36232		this._current = position;
36233
36234		this.suppress([ 'translate', 'translated' ]);
36235
36236		this.animate(this.coordinates(position));
36237
36238		this.release([ 'translate', 'translated' ]);
36239	};
36240
36241	/**
36242	 * Normalizes an absolute or a relative position of an item.
36243	 * @public
36244	 * @param {Number} position - The absolute or relative position to normalize.
36245	 * @param {Boolean} [relative=false] - Whether the given position is relative or not.
36246	 * @returns {Number} - The normalized position.
36247	 */
36248	Owl.prototype.normalize = function(position, relative) {
36249		var n = this._items.length,
36250			m = relative ? 0 : this._clones.length;
36251
36252		if (!$.isNumeric(position) || n < 1) {
36253			position = undefined;
36254		} else if (position < 0 || position >= n + m) {
36255			position = ((position - m / 2) % n + n) % n + m / 2;
36256		}
36257
36258		return position;
36259	};
36260
36261	/**
36262	 * Converts an absolute position of an item into a relative one.
36263	 * @public
36264	 * @param {Number} position - The absolute position to convert.
36265	 * @returns {Number} - The converted position.
36266	 */
36267	Owl.prototype.relative = function(position) {
36268		position -= this._clones.length / 2;
36269		return this.normalize(position, true);
36270	};
36271
36272	/**
36273	 * Gets the maximum position for the current item.
36274	 * @public
36275	 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
36276	 * @returns {Number}
36277	 */
36278	Owl.prototype.maximum = function(relative) {
36279		var settings = this.settings,
36280			maximum = this._coordinates.length,
36281			boundary = Math.abs(this._coordinates[maximum - 1]) - this._width,
36282			i = -1, j;
36283
36284		if (settings.loop) {
36285			maximum = this._clones.length / 2 + this._items.length - 1;
36286		} else if (settings.autoWidth || settings.merge) {
36287			// binary search
36288			while (maximum - i > 1) {
36289				Math.abs(this._coordinates[j = maximum + i >> 1]) < boundary
36290					? i = j : maximum = j;
36291			}
36292		} else if (settings.center) {
36293			maximum = this._items.length - 1;
36294		} else {
36295			maximum = this._items.length - settings.items;
36296		}
36297
36298		if (relative) {
36299			maximum -= this._clones.length / 2;
36300		}
36301
36302		return Math.max(maximum, 0);
36303	};
36304
36305	/**
36306	 * Gets the minimum position for the current item.
36307	 * @public
36308	 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
36309	 * @returns {Number}
36310	 */
36311	Owl.prototype.minimum = function(relative) {
36312		return relative ? 0 : this._clones.length / 2;
36313	};
36314
36315	/**
36316	 * Gets an item at the specified relative position.
36317	 * @public
36318	 * @param {Number} [position] - The relative position of the item.
36319	 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
36320	 */
36321	Owl.prototype.items = function(position) {
36322		if (position === undefined) {
36323			return this._items.slice();
36324		}
36325
36326		position = this.normalize(position, true);
36327		return this._items[position];
36328	};
36329
36330	/**
36331	 * Gets an item at the specified relative position.
36332	 * @public
36333	 * @param {Number} [position] - The relative position of the item.
36334	 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
36335	 */
36336	Owl.prototype.mergers = function(position) {
36337		if (position === undefined) {
36338			return this._mergers.slice();
36339		}
36340
36341		position = this.normalize(position, true);
36342		return this._mergers[position];
36343	};
36344
36345	/**
36346	 * Gets the absolute positions of clones for an item.
36347	 * @public
36348	 * @param {Number} [position] - The relative position of the item.
36349	 * @returns {Array.<Number>} - The absolute positions of clones for the item or all if no position was given.
36350	 */
36351	Owl.prototype.clones = function(position) {
36352		var odd = this._clones.length / 2,
36353			even = odd + this._items.length,
36354			map = function(index) { return index % 2 === 0 ? even + index / 2 : odd - (index + 1) / 2 };
36355
36356		if (position === undefined) {
36357			return $.map(this._clones, function(v, i) { return map(i) });
36358		}
36359
36360		return $.map(this._clones, function(v, i) { return v === position ? map(i) : null });
36361	};
36362
36363	/**
36364	 * Sets the current animation speed.
36365	 * @public
36366	 * @param {Number} [speed] - The animation speed in milliseconds or nothing to leave it unchanged.
36367	 * @returns {Number} - The current animation speed in milliseconds.
36368	 */
36369	Owl.prototype.speed = function(speed) {
36370		if (speed !== undefined) {
36371			this._speed = speed;
36372		}
36373
36374		return this._speed;
36375	};
36376
36377	/**
36378	 * Gets the coordinate of an item.
36379	 * @todo The name of this method is missleanding.
36380	 * @public
36381	 * @param {Number} position - The absolute position of the item within `minimum()` and `maximum()`.
36382	 * @returns {Number|Array.<Number>} - The coordinate of the item in pixel or all coordinates.
36383	 */
36384	Owl.prototype.coordinates = function(position) {
36385		var coordinate = null;
36386
36387		if (position === undefined) {
36388			return $.map(this._coordinates, $.proxy(function(coordinate, index) {
36389				return this.coordinates(index);
36390			}, this));
36391		}
36392
36393		if (this.settings.center) {
36394			coordinate = this._coordinates[position];
36395			coordinate += (this.width() - coordinate + (this._coordinates[position - 1] || 0)) / 2 * (this.settings.rtl ? -1 : 1);
36396		} else {
36397			coordinate = this._coordinates[position - 1] || 0;
36398		}
36399
36400		return coordinate;
36401	};
36402
36403	/**
36404	 * Calculates the speed for a translation.
36405	 * @protected
36406	 * @param {Number} from - The absolute position of the start item.
36407	 * @param {Number} to - The absolute position of the target item.
36408	 * @param {Number} [factor=undefined] - The time factor in milliseconds.
36409	 * @returns {Number} - The time in milliseconds for the translation.
36410	 */
36411	Owl.prototype.duration = function(from, to, factor) {
36412		return Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((factor || this.settings.smartSpeed));
36413	};
36414
36415	/**
36416	 * Slides to the specified item.
36417	 * @public
36418	 * @param {Number} position - The position of the item.
36419	 * @param {Number} [speed] - The time in milliseconds for the transition.
36420	 */
36421	Owl.prototype.to = function(position, speed) {
36422		var current = this.current(),
36423			revert = null,
36424			distance = position - this.relative(current),
36425			direction = (distance > 0) - (distance < 0),
36426			items = this._items.length,
36427			minimum = this.minimum(),
36428			maximum = this.maximum();
36429
36430		if (this.settings.loop) {
36431			if (!this.settings.rewind && Math.abs(distance) > items / 2) {
36432				distance += direction * -1 * items;
36433			}
36434
36435			position = current + distance;
36436			revert = ((position - minimum) % items + items) % items + minimum;
36437
36438			if (revert !== position && revert - distance <= maximum && revert - distance > 0) {
36439				current = revert - distance;
36440				position = revert;
36441				this.reset(current);
36442			}
36443		} else if (this.settings.rewind) {
36444			maximum += 1;
36445			position = (position % maximum + maximum) % maximum;
36446		} else {
36447			position = Math.max(minimum, Math.min(maximum, position));
36448		}
36449
36450		this.speed(this.duration(current, position, speed));
36451		this.current(position);
36452
36453		if (this.$element.is(':visible')) {
36454			this.update();
36455		}
36456	};
36457
36458	/**
36459	 * Slides to the next item.
36460	 * @public
36461	 * @param {Number}
vendor: 12,284 bytes, lines 36461-36881
36461 [speed] - The time in milliseconds for the transition.
36462	 */
36463	Owl.prototype.next = function(speed) {
36464		speed = speed || false;
36465		this.to(this.relative(this.current()) + 1, speed);
36466	};
36467
36468	/**
36469	 * Slides to the previous item.
36470	 * @public
36471	 * @param {Number} [speed] - The time in milliseconds for the transition.
36472	 */
36473	Owl.prototype.prev = function(speed) {
36474		speed = speed || false;
36475		this.to(this.relative(this.current()) - 1, speed);
36476	};
36477
36478	/**
36479	 * Handles the end of an animation.
36480	 * @protected
36481	 * @param {Event} event - The event arguments.
36482	 */
36483	Owl.prototype.onTransitionEnd = function(event) {
36484
36485		// if css2 animation then event object is undefined
36486		if (event !== undefined) {
36487			event.stopPropagation();
36488
36489			// Catch only owl-stage transitionEnd event
36490			if ((event.target || event.srcElement || event.originalTarget) !== this.$stage.get(0)) {
36491				return false;
36492			}
36493		}
36494
36495		this.leave('animating');
36496		this.trigger('translated');
36497	};
36498
36499	/**
36500	 * Gets viewport width.
36501	 * @protected
36502	 * @return {Number} - The width in pixel.
36503	 */
36504	Owl.prototype.viewport = function() {
36505		var width;
36506		if (this.options.responsiveBaseElement !== window) {
36507			width = $(this.options.responsiveBaseElement).width();
36508		} else if (window.innerWidth) {
36509			width = window.innerWidth;
36510		} else if (document.documentElement && document.documentElement.clientWidth) {
36511			width = document.documentElement.clientWidth;
36512		} else {
36513			throw 'Can not detect viewport width.';
36514		}
36515
36516		return width;
36517	};
36518
36519	/**
36520	 * Replaces the current content.
36521	 * @public
36522	 * @param {HTMLElement|jQuery|String} content - The new content.
36523	 */
36524	Owl.prototype.replace = function(content) {
36525		this.$stage.empty();
36526		this._items = [];
36527
36528		if (content) {
36529			content = (content instanceof jQuery) ? content : $(content);
36530		}
36531
36532		if (this.settings.nestedItemSelector) {
36533			content = content.find('.' + this.settings.nestedItemSelector);
36534		}
36535
36536		content.filter(function() {
36537			return this.nodeType === 1;
36538		}).each($.proxy(function(index, item) {
36539			item = this.prepare(item, index);
36540			this.$stage.append(item);
36541			this._items.push(item);
36542			this._mergers.push(item.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1);
36543		}, this));
36544
36545		this.reset($.isNumeric(this.settings.startPosition) ? this.settings.startPosition : 0);
36546
36547		this.invalidate('items');
36548	};
36549
36550	/**
36551	 * Adds an item.
36552	 * @todo Use `item` instead of `content` for the event arguments.
36553	 * @public
36554	 * @param {HTMLElement|jQuery|String} content - The item content to add.
36555	 * @param {Number} [position] - The relative position at which to insert the item otherwise the item will be added to the end.
36556	 */
36557	Owl.prototype.add = function(content, position) {
36558		var current = this.relative(this._current);
36559
36560		position = position === undefined ? this._items.length : this.normalize(position, true);
36561		content = content instanceof jQuery ? content : $(content);
36562
36563		this.trigger('add', { content: content, position: position });
36564
36565		content = this.prepare(content, this._items[current].index());
36566
36567		if (this._items.length === 0 || position === this._items.length) {
36568			this._items.length === 0 && this.$stage.append(content);
36569			this._items.length !== 0 && this._items[position - 1].after(content);
36570			this._items.push(content);
36571			this._mergers.push(content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1);
36572		} else {
36573			this._items[position].before(content);
36574			this._items.splice(position, 0, content);
36575			this._mergers.splice(position, 0, content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1);
36576		}
36577
36578		this._items[current] && this.reset(this._items[current].index());
36579
36580		this.invalidate('items');
36581
36582		this.trigger('added', { content: content, position: position });
36583	};
36584
36585	/**
36586	 * Removes an item by its position.
36587	 * @todo Use `item` instead of `content` for the event arguments.
36588	 * @public
36589	 * @param {Number} position - The relative position of the item to remove.
36590	 */
36591	Owl.prototype.remove = function(position) {
36592		position = this.normalize(position, true);
36593
36594		if (position === undefined) {
36595			return;
36596		}
36597
36598		this.trigger('remove', { content: this._items[position], position: position });
36599
36600		this._items[position].remove();
36601		this._items.splice(position, 1);
36602		this._mergers.splice(position, 1);
36603
36604		this.invalidate('items');
36605
36606		this.trigger('removed', { content: null, position: position });
36607	};
36608
36609	/**
36610	 * Preloads images with auto width.
36611	 * @todo Replace by a more generic approach
36612	 * @protected
36613	 */
36614	Owl.prototype.preloadAutoWidthImages = function(images) {
36615		images.each($.proxy(function(i, element) {
36616			this.enter('pre-loading');
36617			element = $(element);
36618			$(new Image()).one('load', $.proxy(function(e) {
36619				element.attr('src', e.target.src);
36620				element.css('opacity', 1);
36621				this.leave('pre-loading');
36622				!this.is('pre-loading') && !this.is('initializing') && this.refresh();
36623			}, this)).attr('src', element.attr('src') || element.attr('data-src') || element.attr('data-src-retina'));
36624		}, this));
36625	};
36626
36627	/**
36628	 * Destroys the carousel.
36629	 * @public
36630	 */
36631	Owl.prototype.destroy = function() {
36632
36633		this.$element.off('.owl.core');
36634		this.$stage.off('.owl.core');
36635		$(document).off('.owl.core');
36636
36637		if (this.settings.responsive !== false) {
36638			window.clearTimeout(this.resizeTimer);
36639			this.off(window, 'resize', this._handlers.onThrottledResize);
36640		}
36641
36642		for (var i in this._plugins) {
36643			this._plugins[i].destroy();
36644		}
36645
36646		this.$stage.children('.cloned').remove();
36647
36648		this.$stage.unwrap();
36649		this.$stage.children().contents().unwrap();
36650		this.$stage.children().unwrap();
36651
36652		this.$element
36653			.removeClass(this.options.refreshClass)
36654			.removeClass(this.options.loadingClass)
36655			.removeClass(this.options.loadedClass)
36656			.removeClass(this.options.rtlClass)
36657			.removeClass(this.options.dragClass)
36658			.removeClass(this.options.grabClass)
36659			.attr('class', this.$element.attr('class').replace(new RegExp(this.options.responsiveClass + '-\\S+\\s', 'g'), ''))
36660			.removeData('owl.carousel');
36661	};
36662
36663	/**
36664	 * Operators to calculate right-to-left and left-to-right.
36665	 * @protected
36666	 * @param {Number} [a] - The left side operand.
36667	 * @param {String} [o] - The operator.
36668	 * @param {Number} [b] - The right side operand.
36669	 */
36670	Owl.prototype.op = function(a, o, b) {
36671		var rtl = this.settings.rtl;
36672		switch (o) {
36673			case '<':
36674				return rtl ? a > b : a < b;
36675			case '>':
36676				return rtl ? a < b : a > b;
36677			case '>=':
36678				return rtl ? a <= b : a >= b;
36679			case '<=':
36680				return rtl ? a >= b : a <= b;
36681			default:
36682				break;
36683		}
36684	};
36685
36686	/**
36687	 * Attaches to an internal event.
36688	 * @protected
36689	 * @param {HTMLElement} element - The event source.
36690	 * @param {String} event - The event name.
36691	 * @param {Function} listener - The event handler to attach.
36692	 * @param {Boolean} capture - Wether the event should be handled at the capturing phase or not.
36693	 */
36694	Owl.prototype.on = function(element, event, listener, capture) {
36695		if (element.addEventListener) {
36696			element.addEventListener(event, listener, capture);
36697		} else if (element.attachEvent) {
36698			element.attachEvent('on' + event, listener);
36699		}
36700	};
36701
36702	/**
36703	 * Detaches from an internal event.
36704	 * @protected
36705	 * @param {HTMLElement} element - The event source.
36706	 * @param {String} event - The event name.
36707	 * @param {Function} listener - The attached event handler to detach.
36708	 * @param {Boolean} capture - Wether the attached event handler was registered as a capturing listener or not.
36709	 */
36710	Owl.prototype.off = function(element, event, listener, capture) {
36711		if (element.removeEventListener) {
36712			element.removeEventListener(event, listener, capture);
36713		} else if (element.detachEvent) {
36714			element.detachEvent('on' + event, listener);
36715		}
36716	};
36717
36718	/**
36719	 * Triggers a public event.
36720	 * @todo Remove `status`, `relatedTarget` should be used instead.
36721	 * @protected
36722	 * @param {String} name - The event name.
36723	 * @param {*} [data=null] - The event data.
36724	 * @param {String} [namespace=carousel] - The event namespace.
36725	 * @param {String} [state] - The state which is associated with the event.
36726	 * @param {Boolean} [enter=false] - Indicates if the call enters the specified state or not.
36727	 * @returns {Event} - The event arguments.
36728	 */
36729	Owl.prototype.trigger = function(name, data, namespace, state, enter) {
36730		var status = {
36731			item: { count: this._items.length, index: this.current() }
36732		}, handler = $.camelCase(
36733			$.grep([ 'on', name, namespace ], function(v) { return v })
36734				.join('-').toLowerCase()
36735		), event = $.Event(
36736			[ name, 'owl', namespace || 'carousel' ].join('.').toLowerCase(),
36737			$.extend({ relatedTarget: this }, status, data)
36738		);
36739
36740		if (!this._supress[name]) {
36741			$.each(this._plugins, function(name, plugin) {
36742				if (plugin.onTrigger) {
36743					plugin.onTrigger(event);
36744				}
36745			});
36746
36747			this.register({ type: Owl.Type.Event, name: name });
36748			this.$element.trigger(event);
36749
36750			if (this.settings && typeof this.settings[handler] === 'function') {
36751				this.settings[handler].call(this, event);
36752			}
36753		}
36754
36755		return event;
36756	};
36757
36758	/**
36759	 * Enters a state.
36760	 * @param name - The state name.
36761	 */
36762	Owl.prototype.enter = function(name) {
36763		$.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
36764			if (this._states.current[name] === undefined) {
36765				this._states.current[name] = 0;
36766			}
36767
36768			this._states.current[name]++;
36769		}, this));
36770	};
36771
36772	/**
36773	 * Leaves a state.
36774	 * @param name - The state name.
36775	 */
36776	Owl.prototype.leave = function(name) {
36777		$.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
36778			this._states.current[name]--;
36779		}, this));
36780	};
36781
36782	/**
36783	 * Registers an event or state.
36784	 * @public
36785	 * @param {Object} object - The event or state to register.
36786	 */
36787	Owl.prototype.register = function(object) {
36788		if (object.type === Owl.Type.Event) {
36789			if (!$.event.special[object.name]) {
36790				$.event.special[object.name] = {};
36791			}
36792
36793			if (!$.event.special[object.name].owl) {
36794				var _default = $.event.special[object.name]._default;
36795				$.event.special[object.name]._default = function(e) {
36796					if (_default && _default.apply && (!e.namespace || e.namespace.indexOf('owl') === -1)) {
36797						return _default.apply(this, arguments);
36798					}
36799					return e.namespace && e.namespace.indexOf('owl') > -1;
36800				};
36801				$.event.special[object.name].owl = true;
36802			}
36803		} else if (object.type === Owl.Type.State) {
36804			if (!this._states.tags[object.name]) {
36805				this._states.tags[object.name] = object.tags;
36806			} else {
36807				this._states.tags[object.name] = this._states.tags[object.name].concat(object.tags);
36808			}
36809
36810			this._states.tags[object.name] = $.grep(this._states.tags[object.name], $.proxy(function(tag, i) {
36811				return $.inArray(tag, this._states.tags[object.name]) === i;
36812			}, this));
36813		}
36814	};
36815
36816	/**
36817	 * Suppresses events.
36818	 * @protected
36819	 * @param {Array.<String>} events - The events to suppress.
36820	 */
36821	Owl.prototype.suppress = function(events) {
36822		$.each(events, $.proxy(function(index, event) {
36823			this._supress[event] = true;
36824		}, this));
36825	};
36826
36827	/**
36828	 * Releases suppressed events.
36829	 * @protected
36830	 * @param {Array.<String>} events - The events to release.
36831	 */
36832	Owl.prototype.release = function(events) {
36833		$.each(events, $.proxy(function(index, event) {
36834			delete this._supress[event];
36835		}, this));
36836	};
36837
36838	/**
36839	 * Gets unified pointer coordinates from event.
36840	 * @todo #261
36841	 * @protected
36842	 * @param {Event} - The `mousedown` or `touchstart` event.
36843	 * @returns {Object} - Contains `x` and `y` coordinates of current pointer position.
36844	 */
36845	Owl.prototype.pointer = function(event) {
36846		var result = { x: null, y: null };
36847
36848		event = event.originalEvent || event || window.event;
36849
36850		event = event.touches && event.touches.length ?
36851			event.touches[0] : event.changedTouches && event.changedTouches.length ?
36852				event.changedTouches[0] : event;
36853
36854		if (event.pageX) {
36855			result.x = event.pageX;
36856			result.y = event.pageY;
36857		} else {
36858			result.x = event.clientX;
36859			result.y = event.clientY;
36860		}
36861
36862		return result;
36863	};
36864
36865	/**
36866	 * Gets the difference of two vectors.
36867	 * @todo #261
36868	 * @protected
36869	 * @param {Object} - The first vector.
36870	 * @param {Object} - The second vector.
36871	 * @returns {Object} - The difference.
36872	 */
36873	Owl.prototype.difference = function(first, second) {
36874		return {
36875			x: first.x - second.x,
36876			y: first.y - second.y
36877		};
36878	};
36879
36880	/**
36881	 * The jQuery Plugin for the Owl Carousel
vendor: 32,302 bytes, lines 36882-38164
36882	 * @todo Navigation plugin `next` and `prev`
36883	 * @public
36884	 */
36885	$.fn.owlCarousel = function(option) {
36886		var args = Array.prototype.slice.call(arguments, 1);
36887
36888		return this.each(function() {
36889			var $this = $(this),
36890				data = $this.data('owl.carousel');
36891
36892			if (!data) {
36893				data = new Owl(this, typeof option == 'object' && option);
36894				$this.data('owl.carousel', data);
36895
36896				$.each([
36897					'next', 'prev', 'to', 'destroy', 'refresh', 'replace', 'add', 'remove'
36898				], function(i, event) {
36899					data.register({ type: Owl.Type.Event, name: event });
36900					data.$element.on(event + '.owl.carousel.core', $.proxy(function(e) {
36901						if (e.namespace && e.relatedTarget !== this) {
36902							this.suppress([ event ]);
36903							data[event].apply(this, [].slice.call(arguments, 1));
36904							this.release([ event ]);
36905						}
36906					}, data));
36907				});
36908			}
36909
36910			if (typeof option == 'string' && option.charAt(0) !== '_') {
36911				data[option].apply(data, args);
36912			}
36913		});
36914	};
36915
36916	/**
36917	 * The constructor for the jQuery Plugin
36918	 * @public
36919	 */
36920	$.fn.owlCarousel.Constructor = Owl;
36921
36922})(window.Zepto || window.jQuery, window, document);
36923
36924/**
36925 * AutoRefresh Plugin
36926 * @version 2.0.0-beta.3
36927 * @author Artus Kolanowski
36928 * @license The MIT License (MIT)
36929 */
36930;(function($, window, document, undefined) {
36931
36932	/**
36933	 * Creates the auto refresh plugin.
36934	 * @class The Auto Refresh Plugin
36935	 * @param {Owl} carousel - The Owl Carousel
36936	 */
36937	var AutoRefresh = function(carousel) {
36938		/**
36939		 * Reference to the core.
36940		 * @protected
36941		 * @type {Owl}
36942		 */
36943		this._core = carousel;
36944
36945		/**
36946		 * Refresh interval.
36947		 * @protected
36948		 * @type {number}
36949		 */
36950		this._interval = null;
36951
36952		/**
36953		 * Whether the element is currently visible or not.
36954		 * @protected
36955		 * @type {Boolean}
36956		 */
36957		this._visible = null;
36958
36959		/**
36960		 * All event handlers.
36961		 * @protected
36962		 * @type {Object}
36963		 */
36964		this._handlers = {
36965			'initialized.owl.carousel': $.proxy(function(e) {
36966				if (e.namespace && this._core.settings.autoRefresh) {
36967					this.watch();
36968				}
36969			}, this)
36970		};
36971
36972		// set default options
36973		this._core.options = $.extend({}, AutoRefresh.Defaults, this._core.options);
36974
36975		// register event handlers
36976		this._core.$element.on(this._handlers);
36977	};
36978
36979	/**
36980	 * Default options.
36981	 * @public
36982	 */
36983	AutoRefresh.Defaults = {
36984		autoRefresh: true,
36985		autoRefreshInterval: 500
36986	};
36987
36988	/**
36989	 * Watches the element.
36990	 */
36991	AutoRefresh.prototype.watch = function() {
36992		if (this._interval) {
36993			return;
36994		}
36995
36996		this._visible = this._core.$element.is(':visible');
36997		this._interval = window.setInterval($.proxy(this.refresh, this), this._core.settings.autoRefreshInterval);
36998	};
36999
37000	/**
37001	 * Refreshes the element.
37002	 */
37003	AutoRefresh.prototype.refresh = function() {
37004		if (this._core.$element.is(':visible') === this._visible || this._core.$element.closest('.drop-menu').length) {
37005			return;
37006		}
37007
37008		this._visible = !this._visible;
37009
37010		this._core.$element.toggleClass('owl-hidden', !this._visible);
37011
37012		this._visible && (this._core.invalidate('width') && this._core.refresh());
37013	};
37014
37015	/**
37016	 * Destroys the plugin.
37017	 */
37018	AutoRefresh.prototype.destroy = function() {
37019		var handler, property;
37020
37021		window.clearInterval(this._interval);
37022
37023		for (handler in this._handlers) {
37024			this._core.$element.off(handler, this._handlers[handler]);
37025		}
37026		for (property in Object.getOwnPropertyNames(this)) {
37027			typeof this[property] != 'function' && (this[property] = null);
37028		}
37029	};
37030
37031	$.fn.owlCarousel.Constructor.Plugins.AutoRefresh = AutoRefresh;
37032
37033})(window.Zepto || window.jQuery, window, document);
37034
37035/**
37036 * Lazy Plugin
37037 * @version 2.0.0-beta.3
37038 * @author Bartosz Wojciechowski
37039 * @license The MIT License (MIT)
37040 */
37041;(function($, window, document, undefined) {
37042
37043	/**
37044	 * Creates the lazy plugin.
37045	 * @class The Lazy Plugin
37046	 * @param {Owl} carousel - The Owl Carousel
37047	 */
37048	var Lazy = function(carousel) {
37049
37050		/**
37051		 * Reference to the core.
37052		 * @protected
37053		 * @type {Owl}
37054		 */
37055		this._core = carousel;
37056
37057		/**
37058		 * Already loaded items.
37059		 * @protected
37060		 * @type {Array.<jQuery>}
37061		 */
37062		this._loaded = [];
37063
37064		/**
37065		 * Event handlers.
37066		 * @protected
37067		 * @type {Object}
37068		 */
37069		this._handlers = {
37070			'initialized.owl.carousel change.owl.carousel': $.proxy(function(e) {
37071				if (!e.namespace) {
37072					return;
37073				}
37074
37075				if (!this._core.settings || !this._core.settings.lazyLoad) {
37076					return;
37077				}
37078
37079				if ((e.property && e.property.name == 'position') || e.type == 'initialized') {
37080					var settings = this._core.settings,
37081						n = (settings.center && Math.ceil(settings.items / 2) || settings.items),
37082						i = ((settings.center && n * -1) || 0),
37083						position = ((e.property && e.property.value) || this._core.current()) + i,
37084						clones = this._core.clones().length,
37085						load = $.proxy(function(i, v) { this.load(v) }, this);
37086
37087					while (i++ < n) {
37088						this.load(clones / 2 + this._core.relative(position));
37089						clones && $.each(this._core.clones(this._core.relative(position)), load);
37090						position++;
37091					}
37092				}
37093			}, this)
37094		};
37095
37096		// set the default options
37097		this._core.options = $.extend({}, Lazy.Defaults, this._core.options);
37098
37099		// register event handler
37100		this._core.$element.on(this._handlers);
37101	}
37102
37103	/**
37104	 * Default options.
37105	 * @public
37106	 */
37107	Lazy.Defaults = {
37108		lazyLoad: false
37109	}
37110
37111	/**
37112	 * Loads all resources of an item at the specified position.
37113	 * @param {Number} position - The absolute position of the item.
37114	 * @protected
37115	 */
37116	Lazy.prototype.load = function(position) {
37117		var $item = this._core.$stage.children().eq(position),
37118			$elements = $item && $item.find('.owl-lazy');
37119
37120		if (!$elements || $.inArray($item.get(0), this._loaded) > -1) {
37121			return;
37122		}
37123
37124		$elements.each($.proxy(function(index, element) {
37125			var $element = $(element), image,
37126				url = (window.devicePixelRatio > 1 && $element.attr('data-src-retina')) || $element.attr('data-src');
37127
37128			this._core.trigger('load', { element: $element, url: url }, 'lazy');
37129
37130			if ($element.is('img')) {
37131				$element.one('load.owl.lazy', $.proxy(function() {
37132					$element.css('opacity', 1);
37133					this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
37134				}, this)).attr('src', url);
37135			} else {
37136				image = new Image();
37137				image.onload = $.proxy(function() {
37138					$element.css({
37139						'background-image': 'url(' + url + ')',
37140						'opacity': '1'
37141					});
37142					this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
37143				}, this);
37144				image.src = url;
37145			}
37146		}, this));
37147
37148		this._loaded.push($item.get(0));
37149	}
37150
37151	/**
37152	 * Destroys the plugin.
37153	 * @public
37154	 */
37155	Lazy.prototype.destroy = function() {
37156		var handler, property;
37157
37158		for (handler in this.handlers) {
37159			this._core.$element.off(handler, this.handlers[handler]);
37160		}
37161		for (property in Object.getOwnPropertyNames(this)) {
37162			typeof this[property] != 'function' && (this[property] = null);
37163		}
37164	};
37165
37166	$.fn.owlCarousel.Constructor.Plugins.Lazy = Lazy;
37167
37168})(window.Zepto || window.jQuery, window, document);
37169
37170/**
37171 * AutoHeight Plugin
37172 * @version 2.0.0-beta.3
37173 * @author Bartosz Wojciechowski
37174 * @license The MIT License (MIT)
37175 */
37176;(function($, window, document, undefined) {
37177
37178	/**
37179	 * Creates the auto height plugin.
37180	 * @class The Auto Height Plugin
37181	 * @param {Owl} carousel - The Owl Carousel
37182	 */
37183	var AutoHeight = function(carousel) {
37184		/**
37185		 * Reference to the core.
37186		 * @protected
37187		 * @type {Owl}
37188		 */
37189		this._core = carousel;
37190
37191		/**
37192		 * All event handlers.
37193		 * @protected
37194		 * @type {Object}
37195		 */
37196		this._handlers = {
37197			'initialized.owl.carousel refreshed.owl.carousel': $.proxy(function(e) {
37198				if (e.namespace && this._core.settings.autoHeight) {
37199					this.update();
37200				}
37201			}, this),
37202			'changed.owl.carousel': $.proxy(function(e) {
37203				if (e.namespace && this._core.settings.autoHeight && e.property.name == 'position'){
37204					this.update();
37205				}
37206			}, this),
37207			'loaded.owl.lazy': $.proxy(function(e) {
37208				if (e.namespace && this._core.settings.autoHeight
37209					&& e.element.closest('.' + this._core.settings.itemClass).index() === this._core.current()) {
37210					this.update();
37211				}
37212			}, this)
37213		};
37214
37215		// set default options
37216		this._core.options = $.extend({}, AutoHeight.Defaults, this._core.options);
37217
37218		// register event handlers
37219		this._core.$element.on(this._handlers);
37220	};
37221
37222	/**
37223	 * Default options.
37224	 * @public
37225	 */
37226	AutoHeight.Defaults = {
37227		autoHeight: false,
37228		autoHeightClass: 'owl-height'
37229	};
37230
37231	/**
37232	 * Updates the view.
37233	 */
37234	AutoHeight.prototype.update = function() {
37235		var start = this._core._current,
37236			end = start + this._core.settings.items,
37237			visible = this._core.$stage.children().toArray().slice(start, end);
37238			heights = [],
37239			maxheight = 0;
37240
37241		$.each(visible, function(index, item) {
37242			heights.push($(item).height());
37243		});
37244
37245		maxheight = Math.max.apply(null, heights);
37246
37247		this._core.$stage.parent()
37248			.height(maxheight)
37249			.addClass(this._core.settings.autoHeightClass);
37250	};
37251
37252	AutoHeight.prototype.destroy = function() {
37253		var handler, property;
37254
37255		for (handler in this._handlers) {
37256			this._core.$element.off(handler, this._handlers[handler]);
37257		}
37258		for (property in Object.getOwnPropertyNames(this)) {
37259			typeof this[property] != 'function' && (this[property] = null);
37260		}
37261	};
37262
37263	$.fn.owlCarousel.Constructor.Plugins.AutoHeight = AutoHeight;
37264
37265})(window.Zepto || window.jQuery, window, document);
37266
37267/**
37268 * Video Plugin
37269 * @version 2.0.0-beta.3
37270 * @author Bartosz Wojciechowski
37271 * @license The MIT License (MIT)
37272 */
37273;(function($, window, document, undefined) {
37274
37275	/**
37276	 * Creates the video plugin.
37277	 * @class The Video Plugin
37278	 * @param {Owl} carousel - The Owl Carousel
37279	 */
37280	var Video = function(carousel) {
37281		/**
37282		 * Reference to the core.
37283		 * @protected
37284		 * @type {Owl}
37285		 */
37286		this._core = carousel;
37287
37288		/**
37289		 * Cache all video URLs.
37290		 * @protected
37291		 * @type {Object}
37292		 */
37293		this._videos = {};
37294
37295		/**
37296		 * Current playing item.
37297		 * @protected
37298		 * @type {jQuery}
37299		 */
37300		this._playing = null;
37301
37302		/**
37303		 * All event handlers.
37304		 * @todo The cloned content removale is too late
37305		 * @protected
37306		 * @type {Object}
37307		 */
37308		this._handlers = {
37309			'initialized.owl.carousel': $.proxy(function(e) {
37310				if (e.namespace) {
37311					this._core.register({ type: 'state', name: 'playing', tags: [ 'interacting' ] });
37312				}
37313			}, this),
37314			'resize.owl.carousel': $.proxy(function(e) {
37315				if (e.namespace && this._core.settings.video && this.isInFullScreen()) {
37316					e.preventDefault();
37317				}
37318			}, this),
37319			'refreshed.owl.carousel': $.proxy(function(e) {
37320				if (e.namespace && this._core.is('resizing')) {
37321					this._core.$stage.find('.cloned .owl-video-frame').remove();
37322				}
37323			}, this),
37324			'changed.owl.carousel': $.proxy(function(e) {
37325				if (e.namespace && e.property.name === 'position' && this._playing) {
37326					this.stop();
37327				}
37328			}, this),
37329			'prepared.owl.carousel': $.proxy(function(e) {
37330				if (!e.namespace) {
37331					return;
37332				}
37333
37334				var $element = $(e.content).find('.owl-video');
37335
37336				if ($element.length) {
37337					$element.css('display', 'none');
37338					this.fetch($element, $(e.content));
37339				}
37340			}, this)
37341		};
37342
37343		// set default options
37344		this._core.options = $.extend({}, Video.Defaults, this._core.options);
37345
37346		// register event handlers
37347		this._core.$element.on(this._handlers);
37348
37349		this._core.$element.on('click.owl.video', '.owl-video-play-icon', $.proxy(function(e) {
37350			this.play(e);
37351		}, this));
37352	};
37353
37354	/**
37355	 * Default options.
37356	 * @public
37357	 */
37358	Video.Defaults = {
37359		video: false,
37360		videoHeight: false,
37361		videoWidth: false
37362	};
37363
37364	/**
37365	 * Gets the video ID and the type (YouTube/Vimeo only).
37366	 * @protected
37367	 * @param {jQuery} target - The target containing the video data.
37368	 * @param {jQuery} item - The item containing the video.
37369	 */
37370	Video.prototype.fetch = function(target, item) {
37371		var type = target.attr('data-vimeo-id') ? 'vimeo' : 'youtube',
37372			id = target.attr('data-vimeo-id') || target.attr('data-youtube-id'),
37373			width = target.attr('data-width') || this._core.settings.videoWidth,
37374			height = target.attr('data-height') || this._core.settings.videoHeight,
37375			url = target.attr('href');
37376
37377		if (url) {
37378			id = url.match(/(http:|https:|)\/\/(player.|www.)?(vimeo\.com|youtu(be\.com|\.be|be\.googleapis\.com))\/(video\/|embed\/|watch\?v=|v\/)?([A-Za-z0-9._%-]*)(\&\S+)?/);
37379
37380			if (id[3].indexOf('youtu') > -1) {
37381				type = 'youtube';
37382			} else if (id[3].indexOf('vimeo') > -1) {
37383				type = 'vimeo';
37384			} else {
37385				throw new Error('Video URL not supported.');
37386			}
37387			id = id[6];
37388		} else {
37389			throw new Error('Missing video URL.');
37390		}
37391
37392		this._videos[url] = {
37393			type: type,
37394			id: id,
37395			width: width,
37396			height: height
37397		};
37398
37399		item.attr('data-video', url);
37400
37401		this.thumbnail(target, this._videos[url]);
37402	};
37403
37404	/**
37405	 * Creates video thumbnail.
37406	 * @protected
37407	 * @param {jQuery} target - The target containing the video data.
37408	 * @param {Object} info - The video info object.
37409	 * @see `fetch`
37410	 */
37411	Video.prototype.thumbnail = function(target, video) {
37412		var tnLink,
37413			icon,
37414			path,
37415			dimensions = video.width && video.height ? 'style="width:' + video.width + 'px;height:' + video.height + 'px;"' : '',
37416			customTn = target.find('img'),
37417			srcType = 'src',
37418			lazyClass = '',
37419			settings = this._core.settings,
37420			create = function(path) {
37421				icon = '<div class="owl-video-play-icon"></div>';
37422
37423				if (settings.lazyLoad) {
37424					tnLink = '<div class="owl-video-tn ' + lazyClass + '" ' + srcType + '="' + path + '"></div>';
37425				} else {
37426					tnLink = '<div class="owl-video-tn" style="opacity:1;background-image:url(' + path + ')"></div>';
37427				}
37428				target.after(tnLink);
37429				target.after(icon);
37430			};
37431
37432		// wrap video content into owl-video-wrapper div
37433		target.wrap('<div class="owl-video-wrapper"' + dimensions + '></div>');
37434
37435		if (this._core.settings.lazyLoad) {
37436			srcType = 'data-src';
37437			lazyClass = 'owl-lazy';
37438		}
37439
37440		// custom thumbnail
37441		if (customTn.length) {
37442			create(customTn.attr(srcType));
37443			customTn.remove();
37444			return false;
37445		}
37446
37447		if (video.type === 'youtube') {
37448			path = "//img.youtube.com/vi/" + video.id + "/hqdefault.jpg";
37449			create(path);
37450		} else if (video.type === 'vimeo') {
37451			$.ajax({
37452				type: 'GET',
37453				url: '//vimeo.com/api/v2/video/' + video.id + '.json',
37454				jsonp: 'callback',
37455				dataType: 'jsonp',
37456				success: function(data) {
37457					path = data[0].thumbnail_large;
37458					create(path);
37459				}
37460			});
37461		}
37462	};
37463
37464	/**
37465	 * Stops the current video.
37466	 * @public
37467	 */
37468	Video.prototype.stop = function() {
37469		this._core.trigger('stop', null, 'video');
37470		this._playing.find('.owl-video-frame').remove();
37471		this._playing.removeClass('owl-video-playing');
37472		this._playing = null;
37473		this._core.leave('playing');
37474		this._core.trigger('stopped', null, 'video');
37475	};
37476
37477	/**
37478	 * Starts the current video.
37479	 * @public
37480	 * @param {Event} event - The event arguments.
37481	 */
37482	Video.prototype.play = function(event) {
37483		var target = $(event.target),
37484			item = target.closest('.' + this._core.settings.itemClass),
37485			video = this._videos[item.attr('data-video')],
37486			width = video.width || '100%',
37487			height = video.height || this._core.$stage.height(),
37488			html;
37489
37490		if (this._playing) {
37491			return;
37492		}
37493
37494		this._core.enter('playing');
37495		this._core.trigger('play', null, 'video');
37496
37497		item = this._core.items(this._core.relative(item.index()));
37498
37499		this._core.reset(item.index());
37500
37501		if (video.type === 'youtube') {
37502			html = '<iframe width="' + width + '" height="' + height + '" src="//www.youtube.com/embed/' +
37503				video.id + '?autoplay=1&v=' + video.id + '" frameborder="0" allowfullscreen></iframe>';
37504		} else if (video.type === 'vimeo') {
37505			html = '<iframe src="//player.vimeo.com/video/' + video.id +
37506				'?autoplay=1" width="' + width + '" height="' + height +
37507				'" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>';
37508		}
37509
37510		$('<div class="owl-video-frame">' + html + '</div>').insertAfter(item.find('.owl-video'));
37511
37512		this._playing = item.addClass('owl-video-playing');
37513	};
37514
37515	/**
37516	 * Checks whether an video is currently in full screen mode or not.
37517	 * @todo Bad style because looks like a readonly method but changes members.
37518	 * @protected
37519	 * @returns {Boolean}
37520	 */
37521	Video.prototype.isInFullScreen = function() {
37522		var element = document.fullscreenElement || document.mozFullScreenElement ||
37523				document.webkitFullscreenElement;
37524
37525		return element && $(element).parent().hasClass('owl-video-frame');
37526	};
37527
37528	/**
37529	 * Destroys the plugin.
37530	 */
37531	Video.prototype.destroy = function() {
37532		var handler, property;
37533
37534		this._core.$element.off('click.owl.video');
37535
37536		for (handler in this._handlers) {
37537			this._core.$element.off(handler, this._handlers[handler]);
37538		}
37539		for (property in Object.getOwnPropertyNames(this)) {
37540			typeof this[property] != 'function' && (this[property] = null);
37541		}
37542	};
37543
37544	$.fn.owlCarousel.Constructor.Plugins.Video = Video;
37545
37546})(window.Zepto || window.jQuery, window, document);
37547
37548/**
37549 * Animate Plugin
37550 * @version 2.0.0-beta.3
37551 * @author Bartosz Wojciechowski
37552 * @license The MIT License (MIT)
37553 */
37554;(function($, window, document, undefined) {
37555
37556	/**
37557	 * Creates the animate plugin.
37558	 * @class The Navigation Plugin
37559	 * @param {Owl} scope - The Owl Carousel
37560	 */
37561	var Animate = function(scope) {
37562		this.core = scope;
37563		this.core.options = $.extend({}, Animate.Defaults, this.core.options);
37564		this.swapping = true;
37565		this.previous = undefined;
37566		this.next = undefined;
37567
37568		this.handlers = {
37569			'change.owl.carousel': $.proxy(function(e) {
37570				if (e.namespace && e.property.name == 'position') {
37571					this.previous = this.core.current();
37572					this.next = e.property.value;
37573				}
37574			}, this),
37575			'drag.owl.carousel dragged.owl.carousel translated.owl.carousel': $.proxy(function(e) {
37576				if (e.namespace) {
37577					this.swapping = e.type == 'translated';
37578				}
37579			}, this),
37580			'translate.owl.carousel': $.proxy(function(e) {
37581				if (e.namespace && this.swapping && (this.core.options.animateOut || this.core.options.animateIn)) {
37582					this.swap();
37583				}
37584			}, this)
37585		};
37586
37587		this.core.$element.on(this.handlers);
37588	};
37589
37590	/**
37591	 * Default options.
37592	 * @public
37593	 */
37594	Animate.Defaults = {
37595		animateOut: false,
37596		animateIn: false
37597	};
37598
37599	/**
37600	 * Toggles the animation classes whenever an translations starts.
37601	 * @protected
37602	 * @returns {Boolean|undefined}
37603	 */
37604	Animate.prototype.swap = function() {
37605
37606		if (this.core.settings.items !== 1) {
37607			return;
37608		}
37609
37610		if (!$.support.animation || !$.support.transition) {
37611			return;
37612		}
37613
37614		this.core.speed(0);
37615
37616		var left,
37617			clear = $.proxy(this.clear, this),
37618			previous = this.core.$stage.children().eq(this.previous),
37619			next = this.core.$stage.children().eq(this.next),
37620			incoming = this.core.settings.animateIn,
37621			outgoing = this.core.settings.animateOut;
37622
37623		if (this.core.current() === this.previous) {
37624			return;
37625		}
37626
37627		if (outgoing) {
37628			left = this.core.coordinates(this.previous) - this.core.coordinates(this.next);
37629			previous.css( { 'left': left + 'px' } )
37630				.addClass('animated owl-animated-out')
37631				.addClass(outgoing)
37632				.on($.support.animation.end, clear);
37633		}
37634
37635		if (incoming) {
37636			next.addClass('animated owl-animated-in')
37637				.addClass(incoming)
37638				.on($.support.animation.end, clear);
37639		}
37640	};
37641
37642	Animate.prototype.clear = function(e) {
37643		if ($(e.target).hasClass('animated')) {
37644			$(e.target).css( { 'left': '' } )
37645				.removeClass('animated owl-animated-out owl-animated-in')
37646				.removeClass(this.core.settings.animateIn)
37647				.removeClass(this.core.settings.animateOut);
37648			this.core.onTransitionEnd();
37649		}
37650	};
37651
37652	/**
37653	 * Destroys the plugin.
37654	 * @public
37655	 */
37656	Animate.prototype.destroy = function() {
37657		var handler, property;
37658
37659		for (handler in this.handlers) {
37660			this.core.$element.off(handler, this.handlers[handler]);
37661		}
37662		for (property in Object.getOwnPropertyNames(this)) {
37663			typeof this[property] != 'function' && (this[property] = null);
37664		}
37665	};
37666
37667	$.fn.owlCarousel.Constructor.Plugins.Animate = Animate;
37668
37669})(window.Zepto || window.jQuery, window, document);
37670
37671/**
37672 * Autoplay Plugin
37673 * @version 2.0.0-beta.3
37674 * @author Bartosz Wojciechowski
37675 * @author Artus Kolanowski
37676 * @license The MIT License (MIT)
37677 */
37678;(function($, window, document, undefined) {
37679
37680	/**
37681	 * Creates the autoplay plugin.
37682	 * @class The Autoplay Plugin
37683	 * @param {Owl} scope - The Owl Carousel
37684	 */
37685	var Autoplay = function(carousel) {
37686		/**
37687		 * Reference to the core.
37688		 * @protected
37689		 * @type {Owl}
37690		 */
37691		this._core = carousel;
37692
37693		/**
37694		 * The autoplay interval.
37695		 * @type {Number}
37696		 */
37697		this._interval = null;
37698
37699		/**
37700		 * Indicates whenever the autoplay is paused.
37701		 * @type {Boolean}
37702		 */
37703		this._paused = false;
37704
37705		/**
37706		 * All event handlers.
37707		 * @protected
37708		 * @type {Object}
37709		 */
37710		this._handlers = {
37711			'changed.owl.carousel': $.proxy(function(e) {
37712				if (e.namespace && e.property.name === 'settings') {
37713					if (this._core.settings.autoplay) {
37714						this.play();
37715					} else {
37716						this.stop();
37717					}
37718				}
37719			}, this),
37720			'initialized.owl.carousel': $.proxy(function(e) {
37721				if (e.namespace && this._core.settings.autoplay) {
37722					this.play();
37723				}
37724			}, this),
37725			'play.owl.autoplay': $.proxy(function(e, t, s) {
37726				if (e.namespace) {
37727					this.play(t, s);
37728				}
37729			}, this),
37730			'stop.owl.autoplay': $.proxy(function(e) {
37731				if (e.namespace) {
37732					this.stop();
37733				}
37734			}, this),
37735			'mouseover.owl.autoplay': $.proxy(function() {
37736				if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
37737					this.pause();
37738				}
37739			}, this),
37740			'mouseleave.owl.autoplay': $.proxy(function() {
37741				if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
37742					this.play();
37743				}
37744			}, this)
37745		};
37746
37747		// register event handlers
37748		this._core.$element.on(this._handlers);
37749
37750		// set default options
37751		this._core.options = $.extend({}, Autoplay.Defaults, this._core.options);
37752	};
37753
37754	/**
37755	 * Default options.
37756	 * @public
37757	 */
37758	Autoplay.Defaults = {
37759		autoplay: false,
37760		autoplayTimeout: 5000,
37761		autoplayHoverPause: false,
37762		autoplaySpeed: false
37763	};
37764
37765	/**
37766	 * Starts the autoplay.
37767	 * @public
37768	 * @param {Number} [timeout] - The interval before the next animation starts.
37769	 * @param {Number} [speed] - The animation speed for the animations.
37770	 */
37771	Autoplay.prototype.play = function(timeout, speed) {
37772		this._paused = false;
37773
37774		if (this._core.is('rotating')) {
37775			return;
37776		}
37777
37778		this._core.enter('rotating');
37779
37780		this._interval = window.setInterval($.proxy(function() {
37781			if (this._paused || this._core.is('busy') || this._core.is('interacting') || document.hidden) {
37782				return;
37783			}
37784			this._core.next(speed || this._core.settings.autoplaySpeed);
37785		}, this), timeout || this._core.settings.autoplayTimeout);
37786	};
37787
37788	/**
37789	 * Stops the autoplay.
37790	 * @public
37791	 */
37792	Autoplay.prototype.stop = function() {
37793		if (!this._core.is('rotating')) {
37794			return;
37795		}
37796
37797		window.clearInterval(this._interval);
37798		this._core.leave('rotating');
37799	};
37800
37801	/**
37802	 * Stops the autoplay.
37803	 * @public
37804	 */
37805	Autoplay.prototype.pause = function() {
37806		if (!this._core.is('rotating')) {
37807			return;
37808		}
37809
37810		this._paused = true;
37811	};
37812
37813	/**
37814	 * Destroys the plugin.
37815	 */
37816	Autoplay.prototype.destroy = function() {
37817		var handler, property;
37818
37819		this.stop();
37820
37821		for (handler in this._handlers) {
37822			this._core.$element.off(handler, this._handlers[handler]);
37823		}
37824		for (property in Object.getOwnPropertyNames(this)) {
37825			typeof this[property] != 'function' && (this[property] = null);
37826		}
37827	};
37828
37829	$.fn.owlCarousel.Constructor.Plugins.autoplay = Autoplay;
37830
37831})(window.Zepto || window.jQuery, window, document);
37832
37833/**
37834 * Navigation Plugin
37835 * @version 2.0.0-beta.3
37836 * @author Artus Kolanowski
37837 * @license The MIT License (MIT)
37838 */
37839;(function($, window, document, undefined) {
37840	'use strict';
37841
37842	/**
37843	 * Creates the navigation plugin.
37844	 * @class The Navigation Plugin
37845	 * @param {Owl} carousel - The Owl Carousel.
37846	 */
37847	var Navigation = function(carousel) {
37848		/**
37849		 * Reference to the core.
37850		 * @protected
37851		 * @type {Owl}
37852		 */
37853		this._core = carousel;
37854
37855		/**
37856		 * Indicates whether the plugin is initialized or not.
37857		 * @protected
37858		 * @type {Boolean}
37859		 */
37860		this._initialized = false;
37861
37862		/**
37863		 * The current paging indexes.
37864		 * @protected
37865		 * @type {Array}
37866		 */
37867		this._pages = [];
37868
37869		/**
37870		 * All DOM elements of the user interface.
37871		 * @protected
37872		 * @type {Object}
37873		 */
37874		this._controls = {};
37875
37876		/**
37877		 * Markup for an indicator.
37878		 * @protected
37879		 * @type {Array.<String>}
37880		 */
37881		this._templates = [];
37882
37883		/**
37884		 * The carousel element.
37885		 * @type {jQuery}
37886		 */
37887		this.$element = this._core.$element;
37888
37889		/**
37890		 * Overridden methods of the carousel.
37891		 * @protected
37892		 * @type {Object}
37893		 */
37894		this._overrides = {
37895			next: this._core.next,
37896			prev: this._core.prev,
37897			to: this._core.to
37898		};
37899
37900		/**
37901		 * All event handlers.
37902		 * @protected
37903		 * @type {Object}
37904		 */
37905		this._handlers = {
37906			'prepared.owl.carousel': $.proxy(function(e) {
37907				if (e.namespace && this._core.settings.dotsData) {
37908					this._templates.push('<div class="' + this._core.settings.dotClass + '">' +
37909						$(e.content).find('[data-dot]').andSelf('[data-dot]').attr('data-dot') + '</div>');
37910				}
37911			}, this),
37912			'added.owl.carousel': $.proxy(function(e) {
37913				if (e.namespace && this._core.settings.dotsData) {
37914					this._templates.splice(e.position, 0, this._templates.pop());
37915				}
37916			}, this),
37917			'remove.owl.carousel': $.proxy(function(e) {
37918				if (e.namespace && this._core.settings.dotsData) {
37919					this._templates.splice(e.position, 1);
37920				}
37921			}, this),
37922			'changed.owl.carousel': $.proxy(function(e) {
37923				if (e.namespace && e.property.name == 'position') {
37924					this.draw();
37925				}
37926			}, this),
37927			'initialized.owl.carousel': $.proxy(function(e) {
37928				if (e.namespace && !this._initialized) {
37929					this._core.trigger('initialize', null, 'navigation');
37930					this.initialize();
37931					this.update();
37932					this.draw();
37933					this._initialized = true;
37934					this._core.trigger('initialized', null, 'navigation');
37935				}
37936			}, this),
37937			'refreshed.owl.carousel': $.proxy(function(e) {
37938				if (e.namespace && this._initialized) {
37939					this._core.trigger('refresh', null, 'navigation');
37940					this.update();
37941					this.draw();
37942					this._core.trigger('refreshed', null, 'navigation');
37943				}
37944			}, this)
37945		};
37946
37947		// set default options
37948		this._core.options = $.extend({}, Navigation.Defaults, this._core.options);
37949
37950		// register event handlers
37951		this.$element.on(this._handlers);
37952	};
37953
37954	/**
37955	 * Default options.
37956	 * @public
37957	 * @todo Rename `slideBy` to `navBy`
37958	 */
37959	Navigation.Defaults = {
37960		nav: false,
37961		navText: [ 'prev', 'next' ],
37962		navSpeed: false,
37963		navElement: 'button type="button"',
37964		navContainer: false,
37965		navContainerClass: 'owl-nav',
37966		navClass: [ 'owl-prev', 'owl-next' ],
37967		slideBy: 1,
37968		dotClass: 'owl-dot',
37969		dotsClass: 'owl-dots',
37970		dots: true,
37971		dotsEach: false,
37972		dotsData: false,
37973		dotsSpeed: false,
37974		dotsContainer: false
37975	};
37976
37977	/**
37978	 * Initializes the layout of the plugin and extends the carousel.
37979	 * @protected
37980	 */
37981	Navigation.prototype.initialize = function() {
37982		var override,
37983			settings = this._core.settings;
37984
37985		// create DOM structure for relative navigation
37986		this._controls.$relative = (settings.navContainer ? $(settings.navContainer)
37987			: $('<div>').addClass(settings.navContainerClass).appendTo(this.$element)).addClass('disabled');
37988
37989		this._controls.$previous = $('<' + settings.navElement[0] + '>')
37990			.addClass(settings.navClass[0])
37991			.html(settings.navText[0])
37992			.prependTo(this._controls.$relative)
37993			.on('click', $.proxy(function(e) {
37994				this.prev(settings.navSpeed);
37995			}, this));
37996		this._controls.$next = $('<' + settings.navElement[1] + '>')
37997			.addClass(settings.navClass[1])
37998			.html(settings.navText[1])
37999			.appendTo(this._controls.$relative)
38000			.on('click', $.proxy(function(e) {
38001				this.next(settings.navSpeed);
38002			}, this));
38003
38004		// create DOM structure for absolute navigation
38005		if (!settings.dotsData) {
38006			this._templates = [ $('<button>')
38007				.addClass(settings.dotClass)
38008				.append($('<span>'))
38009				.prop('outerHTML') ];
38010		}
38011
38012		this._controls.$absolute = (settings.dotsContainer ? $(settings.dotsContainer)
38013			: $('<div>').addClass(settings.dotsClass).appendTo(this.$element)).addClass('disabled');
38014
38015		this._controls.$absolute.on('click', 'div, button', $.proxy(function(e) {
38016			var index = $(e.target).parent().is(this._controls.$absolute)
38017				? $(e.target).index() : $(e.target).parent().index();
38018
38019			e.preventDefault();
38020
38021			this.to(index, settings.dotsSpeed);
38022		}, this));
38023
38024		// override public methods of the carousel
38025		for (override in this._overrides) {
38026			this._core[override] = $.proxy(this[override], this);
38027		}
38028	};
38029
38030	/**
38031	 * Destroys the plugin.
38032	 * @protected
38033	 */
38034	Navigation.prototype.destroy = function() {
38035		var handler, control, property, override;
38036
38037		for (handler in this._handlers) {
38038			this.$element.off(handler, this._handlers[handler]);
38039		}
38040		for (control in this._controls) {
38041			this._controls[control].remove();
38042		}
38043		for (override in this.overides) {
38044			this._core[override] = this._overrides[override];
38045		}
38046		for (property in Object.getOwnPropertyNames(this)) {
38047			typeof this[property] != 'function' && (this[property] = null);
38048		}
38049	};
38050
38051	/**
38052	 * Updates the internal state.
38053	 * @protected
38054	 */
38055	Navigation.prototype.update = function() {
38056		var i, j, k,
38057			lower = this._core.clones().length / 2,
38058			upper = lower + this._core.items().length,
38059			maximum = this._core.maximum(true),
38060			settings = this._core.settings,
38061			size = settings.center || settings.autoWidth || settings.dotsData
38062				? 1 : settings.dotsEach || settings.items;
38063
38064		if (settings.slideBy !== 'page') {
38065			settings.slideBy = Math.min(settings.slideBy, settings.items);
38066		}
38067
38068		if (settings.dots || settings.slideBy == 'page') {
38069			this._pages = [];
38070
38071			for (i = lower, j = 0, k = 0; i < upper; i++) {
38072				if (j >= size || j === 0) {
38073					this._pages.push({
38074						start: Math.min(maximum, i - lower),
38075						end: i - lower + size - 1
38076					});
38077					if (Math.min(maximum, i - lower) === maximum) {
38078						break;
38079					}
38080					j = 0, ++k;
38081				}
38082				j += this._core.mergers(this._core.relative(i));
38083			}
38084		}
38085	};
38086
38087	/**
38088	 * Draws the user interface.
38089	 * @todo The option `dotsData` wont work.
38090	 * @protected
38091	 */
38092	Navigation.prototype.draw = function() {
38093		var difference,
38094			settings = this._core.settings,
38095			disabled = this._core.items().length <= settings.items,
38096			index = this._core.relative(this._core.current()),
38097			loop = settings.loop || settings.rewind;
38098
38099		this._controls.$relative.toggleClass('disabled', !settings.nav || disabled);
38100
38101		if (settings.nav) {
38102			this._controls.$previous.toggleClass('disabled', !loop && index <= this._core.minimum(true));
38103			this._controls.$next.toggleClass('disabled', !loop && index >= this._core.maximum(true));
38104		}
38105
38106		this._controls.$absolute.toggleClass('disabled', !settings.dots || disabled);
38107
38108		if (settings.dots) {
38109			difference = this._pages.length - this._controls.$absolute.children().length;
38110
38111			if (settings.dotsData && difference !== 0) {
38112				this._controls.$absolute.html(this._templates.join(''));
38113			} else if (difference > 0) {
38114				this._controls.$absolute.append(new Array(difference + 1).join(this._templates[0]));
38115			} else if (difference < 0) {
38116				this._controls.$absolute.children().slice(difference).remove();
38117			}
38118
38119			this._controls.$absolute.find('.active').removeClass('active');
38120			this._controls.$absolute.children().eq($.inArray(this.current(), this._pages)).addClass('active');
38121		}
38122	};
38123
38124	/**
38125	 * Extends event data.
38126	 * @protected
38127	 * @param {Event} event - The event object which gets thrown.
38128	 */
38129	Navigation.prototype.onTrigger = function(event) {
38130		var settings = this._core.settings;
38131
38132		event.page = {
38133			index: $.inArray(this.current(), this._pages),
38134			count: this._pages.length,
38135			size: settings && (settings.center || settings.autoWidth || settings.dotsData
38136				? 1 : settings.dotsEach || settings.items)
38137		};
38138	};
38139
38140	/**
38141	 * Gets the current page position of the carousel.
38142	 * @protected
38143	 * @returns {Number}
38144	 */
38145	Navigation.prototype.current = function() {
38146		var current = this._core.relative(this._core.current());
38147		return $.grep(this._pages, $.proxy(function(page, index) {
38148			return page.start <= current && page.end >= current;
38149		}, this)).pop();
38150	};
38151
38152	/**
38153	 * Gets the current succesor/predecessor position.
38154	 * @protected
38155	 * @returns {Number}
38156	 */
38157	Navigation.prototype.getPosition = function(successor) {
38158		var position, length,
38159			settings = this._core.settings;
38160
38161		if (settings.slideBy == 'page') {
38162			position = $.inArray(this.current(), this._pages);
38163			length = this._pages.length;
38164			successor ? ++position : --position;
vendor: 5,674 bytes, lines 38165-38389
38165			position = this._pages[((position % length) + length) % length].start;
38166		} else {
38167			position = this._core.relative(this._core.current());
38168			length = this._core.items().length;
38169			successor ? position += settings.slideBy : position -= settings.slideBy;
38170		}
38171
38172		return position;
38173	};
38174
38175	/**
38176	 * Slides to the next item or page.
38177	 * @public
38178	 * @param {Number} [speed=false] - The time in milliseconds for the transition.
38179	 */
38180	Navigation.prototype.next = function(speed) {
38181		$.proxy(this._overrides.to, this._core)(this.getPosition(true), speed);
38182	};
38183
38184	/**
38185	 * Slides to the previous item or page.
38186	 * @public
38187	 * @param {Number} [speed=false] - The time in milliseconds for the transition.
38188	 */
38189	Navigation.prototype.prev = function(speed) {
38190		$.proxy(this._overrides.to, this._core)(this.getPosition(false), speed);
38191	};
38192
38193	/**
38194	 * Slides to the specified item or page.
38195	 * @public
38196	 * @param {Number} position - The position of the item or page.
38197	 * @param {Number} [speed] - The time in milliseconds for the transition.
38198	 * @param {Boolean} [standard=false] - Whether to use the standard behaviour or not.
38199	 */
38200	Navigation.prototype.to = function(position, speed, standard) {
38201		var length;
38202
38203		if (!standard) {
38204			length = this._pages.length;
38205			$.proxy(this._overrides.to, this._core)(this._pages[((position % length) + length) % length].start, speed);
38206		} else {
38207			$.proxy(this._overrides.to, this._core)(position, speed);
38208		}
38209	};
38210
38211	$.fn.owlCarousel.Constructor.Plugins.Navigation = Navigation;
38212
38213})(window.Zepto || window.jQuery, window, document);
38214
38215/**
38216 * Hash Plugin
38217 * @version 2.0.0-beta.3
38218 * @author Artus Kolanowski
38219 * @license The MIT License (MIT)
38220 */
38221;(function($, window, document, undefined) {
38222	'use strict';
38223
38224	/**
38225	 * Creates the hash plugin.
38226	 * @class The Hash Plugin
38227	 * @param {Owl} carousel - The Owl Carousel
38228	 */
38229	var Hash = function(carousel) {
38230		/**
38231		 * Reference to the core.
38232		 * @protected
38233		 * @type {Owl}
38234		 */
38235		this._core = carousel;
38236
38237		/**
38238		 * Hash index for the items.
38239		 * @protected
38240		 * @type {Object}
38241		 */
38242		this._hashes = {};
38243
38244		/**
38245		 * The carousel element.
38246		 * @type {jQuery}
38247		 */
38248		this.$element = this._core.$element;
38249
38250		/**
38251		 * All event handlers.
38252		 * @protected
38253		 * @type {Object}
38254		 */
38255		this._handlers = {
38256			'initialized.owl.carousel': $.proxy(function(e) {
38257				if (e.namespace && this._core.settings.startPosition === 'URLHash') {
38258					$(window).trigger('hashchange.owl.navigation');
38259				}
38260			}, this),
38261			'prepared.owl.carousel': $.proxy(function(e) {
38262				if (e.namespace) {
38263					var hash = $(e.content).find('[data-hash]').addBack('[data-hash]').attr('data-hash');
38264
38265					if (!hash) {
38266						return;
38267					}
38268
38269					this._hashes[hash] = e.content;
38270				}
38271			}, this),
38272			'changed.owl.carousel': $.proxy(function(e) {
38273				if (e.namespace && e.property.name === 'position') {
38274					var current = this._core.items(this._core.relative(this._core.current())),
38275						hash = $.map(this._hashes, function(item, hash) {
38276							return item === current ? hash : null;
38277						}).join();
38278
38279					if (!hash || window.location.hash.slice(1) === hash) {
38280						return;
38281					}
38282
38283					window.location.hash = hash;
38284				}
38285			}, this)
38286		};
38287
38288		// set default options
38289		this._core.options = $.extend({}, Hash.Defaults, this._core.options);
38290
38291		// register the event handlers
38292		this.$element.on(this._handlers);
38293
38294		// register event listener for hash navigation
38295		/*$(window).on('hashchange.owl.navigation', $.proxy(function(e) {
38296			var hash = window.location.hash.substring(1),
38297				items = this._core.$stage.children(),
38298				position = this._hashes[hash] && items.index(this._hashes[hash]);
38299
38300			if (position === undefined || position === this._core.current()) {
38301				return;
38302			}
38303
38304			this._core.to(this._core.relative(position), false, true);
38305		}, this));*/
38306	};
38307
38308	/**
38309	 * Default options.
38310	 * @public
38311	 */
38312	Hash.Defaults = {
38313		URLhashListener: false
38314	};
38315
38316	/**
38317	 * Destroys the plugin.
38318	 * @public
38319	 */
38320	Hash.prototype.destroy = function() {
38321		var handler, property;
38322
38323		$(window).off('hashchange.owl.navigation');
38324
38325		for (handler in this._handlers) {
38326			this._core.$element.off(handler, this._handlers[handler]);
38327		}
38328		for (property in Object.getOwnPropertyNames(this)) {
38329			typeof this[property] != 'function' && (this[property] = null);
38330		}
38331	};
38332
38333	$.fn.owlCarousel.Constructor.Plugins.Hash = Hash;
38334
38335})(window.Zepto || window.jQuery, window, document);
38336
38337/**
38338 * Support Plugin
38339 *
38340 * @version 2.0.0-beta.3
38341 * @author Vivid Planet Software GmbH
38342 * @author Artus Kolanowski
38343 * @license The MIT License (MIT)
38344 */
38345;(function($, window, document, undefined) {
38346
38347	var style = $('<support>').get(0).style,
38348		prefixes = 'Webkit Moz O ms'.split(' '),
38349		events = {
38350			transition: {
38351				end: {
38352					WebkitTransition: 'webkitTransitionEnd',
38353					MozTransition: 'transitionend',
38354					OTransition: 'oTransitionEnd',
38355					transition: 'transitionend'
38356				}
38357			},
38358			animation: {
38359				end: {
38360					WebkitAnimation: 'webkitAnimationEnd',
38361					MozAnimation: 'animationend',
38362					OAnimation: 'oAnimationEnd',
38363					animation: 'animationend'
38364				}
38365			}
38366		},
38367		tests = {
38368			csstransforms: function() {
38369				return !!test('transform');
38370			},
38371			csstransforms3d: function() {
38372				return !!test('perspective');
38373			},
38374			csstransitions: function() {
38375				return !!test('transition');
38376			},
38377			cssanimations: function() {
38378				return !!test('animation');
38379			}
38380		};
38381
38382	function test(property, prefixed) {
38383		var result = false,
38384			upper = property.charAt(0).toUpperCase() + property.slice(1);
38385
38386		$.each((property + ' ' + prefixes.join(upper + ' ') + upper).split(' '), function(i, property) {
38387			if (style[property] !== undefined) {
38388				result = prefixed ? property : true;
38389				return false;
38390			}
38391		});
38392
38393		return result;
38394	}
38395
38396	function prefixed(property) {
38397		return test(property, true);
38398	}
38399
38400	if (tests.csstransitions()) {
38401		/* jshint -W053 */
38402		$.support.transition = new String(prefixed('transition'))
38403		$.support.transition.end = events.transition.end[ $.support.transition ];
38404	}
38405
38406	if (tests.cssanimations()) {
38407		/* jshint -W053 */
38408		$.support.animation = new String(prefixed('animation'))
38409		$.support.animation.end = events.animation.end[ $.support.animation ];
38410	}
38411
38412	if (tests.csstransforms()) {
38413		/* jshint -W053 */
38414		$.support.transform = new String(prefixed('transform'));
38415		$.support.transform3d = tests.csstransforms3d();
38416	}
38417
38418})(window.Zepto || window.jQuery, window, document);
38419
38420(function(window, document, undefined) {
38421
38422	/**
38423	 * Find the absolute position of an element
38424	 */
38425	var absPos = function(element) {
38426		var offsetLeft, offsetTop;
38427		offsetLeft = offsetTop = 0;
38428		if (element.offsetParent) {
38429			do {
38430				offsetLeft += element.offsetLeft;
38431				offsetTop += element.offsetTop;
38432			} while (element = element.offsetParent);
38433		}
38434		return [offsetLeft, offsetTop];
38435	};
38436
38437	/**
38438	 * @constructor Progress Circle class
38439	 * @param params.canvas Canvas on which the circles will be drawn.
38440	 * @param params.minRadius Inner radius of the innermost circle, in px.
38441	 * @param params.arcWidth Width of each circle(to be more accurate, ring).
38442	 * @param params.gapWidth Space between each circle.
38443	 * @param params.centerX X coordinate of the center of circles.
38444	 * @param params.centerY Y coordinate of the center of circles.
38445	 * @param params.infoLineBaseAngle Base angle of the info line.
38446	 * @param params.infoLineAngleInterval Angles between the info lines.
38447	 */
38448	var ProgressCircle = function(params) {
38449		this.canvas = params.canvas;
38450		this.minRadius = params.minRadius || 15;
38451		this.arcWidth = params.arcWidth || 5;
38452		this.gapWidth = params.gapWidth || 3;
38453		this.centerX = params.centerX || this.canvas.width / 2;
38454		this.centerY = params.centerY || this.canvas.height / 2;
38455		this.infoLineLength = params.infoLineLength || 60;
38456		this.horizLineLength = params.horizLineLength || 10;
38457		this.infoLineAngleInterval = params.infoLineAngleInterval || Math.PI / 8;
38458		this.infoLineBaseAngle = params.infoLineBaseAngle || Math.PI / 6;
38459
38460		this.context = this.canvas.getContext('2d');
38461
38462		this.width = this.canvas.width;
38463		this.height = this.canvas.height;
38464
38465		this.circles = [];
38466		this.runningCount = 0;
38467	};
38468
38469	ProgressCircle.prototype = {
38470		constructor: ProgressCircle,
38471
38472		/**
38473		 * @method Adds an progress monitor entry.
38474		 * @param params.fillColor Color to fill in the circle.
38475		 * @param params.outlineColor Color to outline the circle.
38476		 * @param params.progressListener Callback function to fetch the progress.
38477		 * @param params.infoListener Callback function to fetch the info.
38478		 * @returns this
38479		 */
38480		addEntry: function(params) {
38481			this.circles.push(new Circle({
38482				canvas: this.canvas,
38483				context: this.context,
38484				centerX: this.centerX,
38485				centerY: this.centerY,
38486				innerRadius: this.minRadius + this.circles.length *
38487					(this.gapWidth + this.arcWidth),
38488				arcWidth: this.arcWidth,
38489				infoLineLength: this.infoLineLength,
38490				horizLineLength: this.horizLineLength,
38491
38492				id: this.circles.length,
38493				fillColor: params.fillColor,
38494				outlineColor: params.outlineColor,
38495				progressListener: params.progressListener,
38496				infoListener: params.infoListener,
38497				infoLineAngle: this.infoLineBaseAngle +
38498					this.circles.length * this.infoLineAngleInterval,
38499			}));
38500
38501			return this;
38502		},
38503
38504		/**
38505		 * @method Starts the monitor and updates with the given interval.
38506		 * @param interval Interval between updates, in millisecond.
38507		 * @returns this
38508		 */
38509		start: function(interval) {
38510			var self = this;
38511			this.timer = setInterval(function() {
38512				self._update();
38513			}, interval || 33);
38514
38515			return this;
38516		},
38517
38518		/**
38519		 * @method Stop the animation.
38520		 */
38521		stop: function() {
38522			clearTimeout(this.timer);
38523		},
38524
38525		/**
38526		 * @private
38527		 * @method Call update on each circle and redraw them.
38528		 * @returns this
38529		 */
38530		_update: function() {
38531			this._clear();
38532			this.circles.forEach(function(circle, idx, array) {
38533				circle.update();
38534			});
38535
38536			return this;
38537		},
38538
38539		/**
38540		 * @private
38541		 * @method Clear the canvas.
38542		 * @returns this
38543		 */
38544		_clear: function() {
38545			this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
38546
38547			return this;
38548		},
38549
38550	};
38551
38552	/**
38553	 * @private
38554	 * @class Individual progress circle.
38555	 * @param params.canvas Canvas on which the circle will be drawn.
38556	 * @param params.context Context of the canvas.
38557	 * @param params.innerRadius Inner radius of the circle, in px.
38558	 * @param params.arcWidth Width of each arc(circle).
38559	 * @param params.gapWidth Distance between each arc.
38560	 * @param params.centerX X coordinate of the center of circles.
38561	 * @param params.centerY Y coordinate of the center of circles.
38562	 * @param params.fillColor Color to fill in the circle.
38563	 * @param params.outlineColor Color to outline the circle.
38564	 * @param params.progressListener Callback function to fetch the progress.
38565	 * @param params.infoListener Callback function to fetch the info.
38566	 * @param params.infoLineAngle Angle of info line.
38567	 */
38568	var Circle = function(params) {
38569		this.id = params.id;
38570		this.canvas = params.canvas;
38571		this.context = params.context;
38572		this.centerX = params.centerX;
38573		this.centerY = params.centerY;
38574		this.arcWidth = params.arcWidth;
38575		this.innerRadius = params.innerRadius || 0;
38576		this.fillColor = params.fillColor || '#fff';
38577		this.outlineColor = params.outlineColor || this.fillColor;
38578		this.progressListener = params.progressListener;
38579		this.infoLineLength = params.infoLineLength || 250;
38580		this.horizLineLength = params.horizLineLength || 50;
38581		this.infoListener = params.infoListener;
38582		this.infoLineAngle = params.infoLineAngle;
38583
38584		this.outerRadius = this.innerRadius + this.arcWidth;
38585
38586		// If the info listener is not registered, then don't calculate
38587		// the related coordinates
38588		if (!this.infoListener) return;
38589
38590		// calculate the info-line turning points
38591		var angle = this.infoLineAngle,
38592			arcDistance = (this.innerRadius + this.outerRadius) / 2,
38593
38594			sinA = Math.sin(angle),
38595			cosA = Math.cos(angle);
38596
38597		this.infoLineStartX = this.centerX + sinA * arcDistance;
38598		this.infoLineStartY = this.centerY - cosA * arcDistance;
38599
38600		this.infoLineMidX = this.centerX + sinA * this.infoLineLength;
38601		this.infoLineMidY = this.centerY - cosA * this.infoLineLength;
38602
38603		this.infoLineEndX = this.infoLineMidX +
38604			 (sinA < 0 ? -this.horizLineLength : this.horizLineLength);
38605		this.infoLineEndY = this.infoLineMidY;
38606
38607		var infoText = document.createElement('div'),
38608			style = infoText.style;
38609
38610		style.color = this.fillColor;
38611		style.position = 'absolute';
38612		style.left = this.infoLineEndX + absPos(this.canvas)[0] + 'px';
38613		// style.top will be calculated in the `drawInfo` method. Since
38614		// user may want to change the size of the font, so the top offset
38615		// must be updated in each loop.
38616		infoText.className = 'ProgressCircleInfo'; // For css styling
38617		infoText.id = 'progress_circle_info_' + this.id;
38618		document.body.appendChild(infoText);
38619		this.infoText = infoText;
38620	};
38621
38622	Circle.prototype = {
38623		constructor: Circle,
38624
38625		update: function() {
38626			this.progress = this.progressListener();
38627			this._draw();
38628
38629			if (this.infoListener) {
38630				this.info = this.infoListener();
38631				this._drawInfo();
38632			}
38633		},
38634
38635		/**
38636		 * @private
38637		 * @method Draw the circle on the canvas.
38638		 * @returns this
38639		 */
38640		_draw: function() {
38641			var ctx = this.context,
38642
38643				ANGLE_OFFSET = -Math.PI / 2,
38644
38645				startAngle = 0 + ANGLE_OFFSET,
38646				endAngle= startAngle + this.progress * Math.PI * 2,
38647
38648				x = this.centerX,
38649				y = this.centerY,
38650
38651				innerRadius = this.innerRadius - this.arcWidth - 1,
38652				outerRadius = this.outerRadius - this.arcWidth - 1;
38653
38654			if ( innerRadius < 0 )
38655				return;
38656
38657			ctx.fillStyle = this.fillColor;
38658			ctx.strokeStyle = this.outlineColor;
38659
38660			ctx.beginPath();
38661			ctx.arc(x, y, innerRadius, startAngle, endAngle, false);
38662			ctx.arc(x, y, outerRadius, endAngle, startAngle, true);
38663			ctx.closePath();
38664			ctx.stroke();
38665			ctx.fill();
38666
38667			return this;
38668		},
38669
38670		/**
38671		 * @private
38672		 * @method Draw the info lines and info text.
38673		 * @returns this
38674		 */
38675		_drawInfo: function() {
38676
38677			var pointList, lineHeight;
38678
38679			pointList = [
38680				[this.infoLineStartX, this.infoLineStartY],
38681				[this.infoLineMidX, this.infoLineMidY],
38682				[this.infoLineEndX, this.infoLineEndY],
38683			];
38684			this._drawSegments(pointList, false);
38685
38686			this.infoText.innerHTML = this.info;
38687
38688			lineHeight = this.infoText.offsetHeight;
38689			this.infoText.style.top = this.infoLineEndY +
38690				absPos(this.canvas)[1] - lineHeight / 2 + 'px';
38691
38692			return this;
38693		},
38694
38695		/**
38696		 * @private
38697		 * @method Helper function to draw the segments
38698		 * @param pointList An array of points in the form of [x, y].
38699		 * @param close Whether to connect the first and last point.
38700		 */
38701		_drawSegments: function(pointList, close) {
38702			var ctx = this.context;
38703
38704			ctx.beginPath();
38705			ctx.moveTo(pointList[0][0], pointList[0][1]);
38706			for (var i = 1; i < pointList.length; ++i) {
38707				ctx.lineTo(pointList[i][0], pointList[i][1]);
38708			}
38709
38710			if (close) {
38711				ctx.closePath();
38712			}
38713			ctx.stroke();
38714		},
38715	};
38716
38717	window.ProgressCircle = ProgressCircle;
38718
38719})(window, document);
38720
38721
38722
38723
38724/* =========================================================
38725 * jquery.vc_chart.js v1.0
38726 * =========================================================
38727 * Copyright 2013 Wpbakery
38728 *
38729 * Jquery chart plugin for the Visual Composer.
38730 * ========================================================= */
38731(function($){
38732	/**
38733	 * Pie chart animated.
38734	 * @param element - DOM element
38735	 * @param options - settings object.
38736	 * @constructor
38737	 */
38738	var VcChart = function(element, options) {
38739		this.el = element;
38740		this.$el = $(this.el);
38741		var $this = this;
38742		$this.options = $.extend({
38743			color: 'wpb_button',
38744			units: '',
38745			width: '',
38746			label_selector: '.vc_pie_chart_value',
38747			back_selector: '.vc_pie_chart_back',
38748			responsive: true
38749		}, options);
38750		$this.init();
38751	};
38752	VcChart.prototype = {
38753		constructor: VcChart,
38754		_progress_v: 0,
38755		animated: false,
38756		colors: {
38757			'wpb_button': 'rgba(247, 247, 247, 1)',
38758			'btn-primary': 'rgba(0, 136, 204, 1)',
38759			'btn-info': 'rgba(88, 185, 218, 1)',
38760			'btn-success': 'rgba(106, 177, 101, 1)',
38761			'btn-warning': 'rgba(255, 153, 0, 1)',
38762			'btn-danger': 'rgba(255, 103, 91, 1)',
38763			'btn-inverse': 'rgba(85, 85, 85, 1)'
38764		},
38765		init: function() {
38766			this.setupColor();
38767			this.value = this.$el.data('pie-value')/100;
38768			this.label_value = this.$el.data('pie-label-value') || this.$el.data('pie-value');
38769			this.$wrapper = $('.vc_pie_wrapper', this.$el);
38770			this.$label = $(this.options.label_selector, this.$el);
38771			this.$back = $(this.options.back_selector, this.$el);
38772			this.$canvas = this.$el.find('canvas');
38773			this.arcWidth = this.$el.data('pie-width') * 2;
38774			this.draw();
38775			this.setWayPoint();
38776			if(this.options.responsive === true) this.setResponsive();
38777			if (UNCODE.isMobile) this._progress_v = this.value;
38778		},
38779		setupColor: function() {
38780			// if(typeof this.colors[this.options.color] !== 'undefined') {
38781			//     this.color = this.colors[this.options.color];
38782			// } else if(typeof this.options.color === 'string' && this.options.color.match(/^rgba?\([^\)]+\)/)) {
38783			//     this.color = this.options.color;
38784			// } else {
38785			//     this.color = 'rgba(247, 247, 247, 0.2)';
38786			// }
38787			if(typeof this.options.color !== 'undefined') {
38788				this.color = this.options.color;
38789			} else this.color = 'rgba(247, 247, 247, 0.2)';
38790
38791		},
38792		setResponsive: function() {
38793			var that = this;
38794			if (!UNCODE.isMobile) {
38795				$(window).resize(function(){
38796					if(that.animated === true) that.circle.stop();
38797					that.draw(true);
38798				});
38799			}
38800		},
38801		draw: function(redraw) {
38802			var w = this.$el.addClass('vc_ready').width() * 2,
38803				border_w = this.arcWidth,
38804				radius;
38805			if(!w) w = this.$el.parents(':visible').first().width()-2;
38806			//w = Math.round(w/100*80);
38807			//if (w < 250) w = 250;
38808			radius = w/2;
38809			this.$wrapper.css({"width" : (w / 2) + "px"});
38810			this.$label.css({"width" : (w / 2), "height" : (w / 2), "line-height" : (w / 2)+"px"});
38811			this.$back.css({"width" : (w / 2), "height" : (w / 2)});
38812			this.$canvas.attr({"width" : w + "px", "height" : w + "px"});
38813			this.$el.addClass('vc_ready');
38814			this.circle = new ProgressCircle({
38815				canvas: this.$canvas.get(0),
38816				minRadius: radius,
38817				arcWidth: border_w
38818			});
38819			if(redraw === true && this.animated === true) {
38820				this._progress_v = this.value;
38821				this.circle.addEntry({
38822					fillColor: this.color,
38823					progressListener: $.proxy(this.setProgress, this)
38824				}).start();
38825			}
38826		},
38827		setProgress: function() {
38828			if (this._progress_v >= this.value) {
38829				this.circle.stop();
38830				this.animated = true;
38831				this.$label.html(this.label_value + this.options.units);
38832				return this._progress_v;
38833			}
38834			this._progress_v += 0.01;
38835			if (!isNaN(this.label_value)) {
38836				var label_value = this._progress_v/this.value*this.label_value;
38837				var val = Math.round(label_value) + this.options.units;
38838				this.$label.html(val);
38839			} else this.$label.html(this.label_value + this.options.units);
38840			return this._progress_v;
38841		},
38842		animate: function() {
38843			if(this.animated !== true) {
38844				this.circle.addEntry({
38845					fillColor: this.color,
38846					progressListener: $.proxy(this.setProgress, this)
38847				}).start(10);
38848			}
38849		},
38850		setWayPoint: function() {
38851			if (typeof $.fn.waypoint !== 'undefined' && !UNCODE.isMobile) {
38852				this.$el.waypoint($.proxy(this.animate, this), { offset: '85%' });
38853			} else {
38854				this.animate();
38855			}
38856		}
38857	};
38858	/**
38859	 * jQuery plugin
38860	 * @param option - object with settings
38861	 * @return {*}
38862	 */
38863	$.fn.vcChat = function(option, value) {
38864		return this.each(function () {
38865			var $this = $(this),
38866				data = $this.data('vc_chart'),
38867				options = typeof option === 'object' ? option : {
38868					color: $this.data('pie-color'),
38869					units: $this.data('pie-units')
38870				};
38871			if (typeof option == 'undefined') $this.data('vc_chart', (data = new VcChart(this, options)));
38872			if (typeof option == 'string') data[option](value);
38873		});
38874	};
38875	/**
38876	 * Allows users to rewrite function inside theme.
38877	 */
38878	if ( typeof window['vc_pieChart'] !== 'function' ) {
38879		window.vc_pieChart = function() {
38880			$('.vc_pie_chart:visible:not(.vc_ready)').vcChat();
38881		}
38882	}
38883	$(document).ready(function(){
38884		!window.vc_iframe && vc_pieChart();
38885
38886		/**
38887		* Tab and collapse integration.
38888		*/
38889		$('.nav-tabs a').on('shown.bs.tab', function(e){
38890			var $cont = $(e.target).closest('.tab-container'),
38891				$active = $('.tab-pane.active', $cont);
38892			$('.vc_pie_chart:not(.vc_ready)', $active).vcChat();
38893		});
38894
38895		$('.panel-collapse').on('shown.bs.collapse', function (e) {
38896			$('.vc_pie_chart:not(.vc_ready)', e.target).vcChat();
38897		})
38898	});
38899
38900})(window.jQuery);
38901
38902/* Progress bar
38903 ---------------------------------------------------------- */
38904function uncode_progress_bar() {
38905	jQuery.each(jQuery('.vc_progress_bar'), function(index, val) {
38906		if (UNCODE.isUnmodalOpen && !val.closest('#unmodal-content')) {
38907			return;
38908		}
38909		if (!UNCODE.isMobile) {
38910			new Waypoint({
38911				context: UNCODE.isUnmodalOpen ? document.getElementById('unmodal-content') : window,
38912				element: val,
38913				handler: function() {
38914					var element = jQuery(this.element);
38915					element.find('.vc_single_bar').each(function(index) {
38916						var $this = jQuery(this),
38917							bar = $this.find('.vc_bar'),
38918							val = bar.data('percentage-value');
38919						setTimeout(function() {
38920							bar.css({
38921								"width": val + '%'
38922							});
38923						}, index * 200);
38924					});
38925				},
38926				offset: '80%'
38927			});
38928		} else {
38929			var element = jQuery(val);
38930			element.find('.vc_single_bar').each(function(index) {
38931				var $this = jQuery(this),
38932					bar = $this.find('.vc_bar'),
38933					val = bar.data('percentage-value');
38934				setTimeout(function() {
38935					bar.css({
38936						"width": val + '%'
38937					});
38938				}, index * 200);
38939			});
38940		}
38941	});
38942};
38943uncode_progress_bar();
38944
38945/*!
38946 * jquery.counterup.js 1.0
38947 *
38948 * Copyright 2013, Benjamin Intal http://gambit.ph @bfintal
38949 * Released under the GPL v2 License
38950 *
38951 * Date: Nov 26, 2013
38952 */
38953(function($) {
38954	"use strict";
38955	$.fn.counterUp = function(options) {
38956		// Defaults
38957		var settings = $.extend({
38958			'time': 400,
38959			'delay': 10
38960		}, options);
38961		return this.each(function() {
38962			// Store the object
38963			var $this = $(this);
38964			var $settings = settings;
38965			var counterUpper = function() {
38966				var nums = [];
38967				var divisions = $settings.time / $settings.delay;
38968				var numReal = $this.attr('data-val'),
38969				num = numReal;
38970				var isComma = /[0-9]+,[0-9]+/.test(num);
38971				num = num.replace(/,/g, '');
38972				var isInt = /^[0-9]+$/.test(num);
38973				var isFloat = /^[0-9]+\.[0-9]+$/.test(num);
38974				var decimalPlaces = isFloat ? (num.split('.')[1] || []).length : 0;
38975				// Generate list of incremental numbers to display
38976				for (var i = divisions; i >= 1; i--) {
38977					// Preserve as int if input was int
38978					var newNum = parseInt(num / divisions * i);
38979					// Preserve float if input was float
38980					if (isFloat) {
38981						newNum = parseFloat(num / divisions * i).toFixed(decimalPlaces);
38982					}
38983					// Preserve commas if input had commas
38984					if (isComma) {
38985						while (/(\d+)(\d{3})/.test(newNum.toString())) {
38986							newNum = newNum.toString().replace(/(\d+)(\d{3})/, '$1' + ',' + '$2');
38987						}
38988					}
38989					nums.unshift(newNum);
38990				}
38991				nums.push(numReal);
38992				$this.data('counterup-nums', nums);
38993				$this.text('0');
38994				// Updates the number until we're done
38995				var f = function() {
38996					if ($this.data('counterup-nums') != null) {
38997						$this.text($this.data('counterup-nums').shift());
38998						if ($this.data('counterup-nums').length) {
38999							setTimeout($this.data('counterup-func'), $settings.delay);
39000						} else {
39001							delete $this.data('counterup-nums');
39002							$this.data('counterup-nums', null);
39003							$this.data('counterup-func', null);
39004						}
39005					}
39006				};
39007				$this.data('counterup-func', f);
39008				// Start the count up
39009				setTimeout($this.data('counterup-func'), $settings.delay);
39010			};
39011			// Perform counts when the element gets into view
39012			new Waypoint({
39013				context: UNCODE.isUnmodalOpen ? document.getElementById('unmodal-content') : window,
39014				element: this,
39015				handler: function() {
39016					counterUpper();
39017					if (!UNCODE.isUnmodalOpen) {
39018						this.destroy();
39019					}
39020				},
39021				offset: '100%'
39022			});
39023		});
39024	};
39025})(jQuery);
39026
39027/*!
39028 * The Final Countdown for jQuery v2.2.0 (http://hilios.github.io/jQuery.countdown/)
39029 * Copyright (c) 2016 Edson Hilios
39030 *
39031 * Permission is hereby granted, free of charge, to any person obtaining a copy of
39032 * this software and associated documentation files (the "Software"), to deal in
39033 * the Software without restriction, including without limitation the rights to
39034 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
39035 * the Software, and to permit persons to whom the Software is furnished to do so,
39036 * subject to the following conditions:
39037 *
39038 * The above copyright notice and this permission notice shall be included in all
39039 * copies or substantial portions of the Software.
39040 *
39041 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39042 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
39043 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
39044 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
39045 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
39046 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
39047 */
39048(function(factory) {
39049	"use strict";
39050	if (typeof define === "function" && define.amd) {
39051		define([ "jquery" ], factory);
39052	} else {
39053		factory(jQuery);
39054	}
39055})(function($) {
39056	"use strict";
39057	var instances = [], matchers = [], defaultOptions = {
39058		precision: 100,
39059		elapse: false,
39060		defer: false
39061	};
39062	matchers.push(/^[0-9]*$/.source);
39063	matchers.push(/([0-9]{1,2}\/){2}[0-9]{4}( [0-9]{1,2}(:[0-9]{2}){2})?/.source);
39064	matchers.push(/[0-9]{4}([\/\-][0-9]{1,2}){2}( [0-9]{1,2}(:[0-9]{2}){2})?/.source);
39065	matchers = new RegExp(matchers.join("|"));
39066	function parseDateString(dateString) {
39067		if (dateString instanceof Date) {
39068			return dateString;
39069		}
39070		if (String(dateString).match(matchers)) {
39071			if (String(dateString).match(/^[0-9]*$/)) {
39072				dateString = Number(dateString);
39073			}
39074			if (String(dateString).match(/\-/)) {
39075				dateString = String(dateString).replace(/\-/g, "/");
39076			}
39077			return new Date(dateString);
39078		} else {
39079			throw new Error("Couldn't cast `" + dateString + "` to a date object.");
39080		}
39081	}
39082	var DIRECTIVE_KEY_MAP = {
39083		Y: "years",
39084		m: "months",
39085		n: "daysToMonth",
39086		d: "daysToWeek",
39087		w: "weeks",
39088		W: "weeksToMonth",
39089		H: "hours",
39090		M: "minutes",
39091		S: "seconds",
39092		D: "totalDays",
39093		I: "totalHours",
39094		N: "totalMinutes",
39095		T: "totalSeconds"
39096	};
39097	function escapedRegExp(str) {
39098		var sanitize = str.toString().replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
39099		return new RegExp(sanitize);
39100	}
39101	function strftime(offsetObject) {
39102		return function(format) {
39103			var directives = format.match(/%(-|!)?[A-Z]{1}(:[^;]+;)?/gi);
39104			if (directives) {
39105				for (var i = 0, len = directives.length; i < len; ++i) {
39106					var directive = directives[i].match(/%(-|!)?([a-zA-Z]{1})(:[^;]+;)?/), regexp = escapedRegExp(directive[0]), modifier = directive[1] || "", plural = directive[3] || "", value = null;
39107					directive = directive[2];
39108					if (DIRECTIVE_KEY_MAP.hasOwnProperty(directive)) {
39109						value = DIRECTIVE_KEY_MAP[directive];
39110						value = Number(offsetObject[value]);
39111					}
39112					if (value !== null) {
39113						if (modifier === "!") {
39114							value = pluralize(plural, value);
39115						}
39116						if (modifier === "") {
39117							if (value < 10) {
39118								value = "0" + value.toString();
39119							}
39120						}
39121						format = format.replace(regexp, value.toString());
39122					}
39123				}
39124			}
39125			format = format.replace(/%%/, "%");
39126			return format;
39127		};
39128	}
39129	function pluralize(format, count) {
39130		var plural = "s", singular = "";
39131		if (format) {
39132			format = format.rep
vendor: 8,618 bytes, lines 39132-39276
39132lace(/(:|;|\s)/gi, "").split(/\,/);
39133			if (format.length === 1) {
39134				plural = format[0];
39135			} else {
39136				singular = format[0];
39137				plural = format[1];
39138			}
39139		}
39140		if (Math.abs(count) > 1) {
39141			return plural;
39142		} else {
39143			return singular;
39144		}
39145	}
39146	var Countdown = function(el, finalDate, options) {
39147		this.el = el;
39148		this.$el = $(el);
39149		this.interval = null;
39150		this.offset = {};
39151		this.options = $.extend({}, defaultOptions);
39152		this.instanceNumber = instances.length;
39153		instances.push(this);
39154		this.$el.data("countdown-instance", this.instanceNumber);
39155		if (options) {
39156			if (typeof options === "function") {
39157				this.$el.on("update.countdown", options);
39158				this.$el.on("stoped.countdown", options);
39159				this.$el.on("finish.countdown", options);
39160			} else {
39161				this.options = $.extend({}, defaultOptions, options);
39162			}
39163		}
39164		this.setFinalDate(finalDate);
39165		if (this.options.defer === false) {
39166			this.start();
39167		}
39168	};
39169	$.extend(Countdown.prototype, {
39170		start: function() {
39171			if (this.interval !== null) {
39172				clearInterval(this.interval);
39173			}
39174			var self = this;
39175			this.update();
39176			this.interval = setInterval(function() {
39177				self.update.call(self);
39178			}, this.options.precision);
39179		},
39180		stop: function() {
39181			clearInterval(this.interval);
39182			this.interval = null;
39183			this.dispatchEvent("stoped");
39184		},
39185		toggle: function() {
39186			if (this.interval) {
39187				this.stop();
39188			} else {
39189				this.start();
39190			}
39191		},
39192		pause: function() {
39193			this.stop();
39194		},
39195		resume: function() {
39196			this.start();
39197		},
39198		remove: function() {
39199			this.stop.call(this);
39200			instances[this.instanceNumber] = null;
39201			delete this.$el.data().countdownInstance;
39202		},
39203		setFinalDate: function(value) {
39204			this.finalDate = parseDateString(value);
39205		},
39206		update: function() {
39207			if (this.$el.closest("html").length === 0) {
39208				this.remove();
39209				return;
39210			}
39211			var hasEventsAttached = $._data(this.el, "events") !== undefined, now = new Date(), newTotalSecsLeft;
39212			newTotalSecsLeft = this.finalDate.getTime() - now.getTime();
39213			newTotalSecsLeft = Math.ceil(newTotalSecsLeft / 1e3);
39214			newTotalSecsLeft = !this.options.elapse && newTotalSecsLeft < 0 ? 0 : Math.abs(newTotalSecsLeft);
39215			if (this.totalSecsLeft === newTotalSecsLeft || !hasEventsAttached) {
39216				return;
39217			} else {
39218				this.totalSecsLeft = newTotalSecsLeft;
39219			}
39220			this.elapsed = now >= this.finalDate;
39221			this.offset = {
39222				seconds: this.totalSecsLeft % 60,
39223				minutes: Math.floor(this.totalSecsLeft / 60) % 60,
39224				hours: Math.floor(this.totalSecsLeft / 60 / 60) % 24,
39225				days: Math.floor(this.totalSecsLeft / 60 / 60 / 24) % 7,
39226				daysToWeek: Math.floor(this.totalSecsLeft / 60 / 60 / 24) % 7,
39227				daysToMonth: Math.floor(this.totalSecsLeft / 60 / 60 / 24 % 30.4368),
39228				weeks: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 7),
39229				weeksToMonth: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 7) % 4,
39230				months: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 30.4368),
39231				years: Math.abs(this.finalDate.getFullYear() - now.getFullYear()),
39232				totalDays: Math.floor(this.totalSecsLeft / 60 / 60 / 24),
39233				totalHours: Math.floor(this.totalSecsLeft / 60 / 60),
39234				totalMinutes: Math.floor(this.totalSecsLeft / 60),
39235				totalSeconds: this.totalSecsLeft
39236			};
39237			if (!this.options.elapse && this.totalSecsLeft === 0) {
39238				this.stop();
39239				this.dispatchEvent("finish");
39240			} else {
39241				this.dispatchEvent("update");
39242			}
39243		},
39244		dispatchEvent: function(eventName) {
39245			var event = $.Event(eventName + ".countdown");
39246			event.finalDate = this.finalDate;
39247			event.elapsed = this.elapsed;
39248			event.offset = $.extend({}, this.offset);
39249			event.strftime = strftime(this.offset);
39250			this.$el.trigger(event);
39251		}
39252	});
39253	$.fn.countdown = function() {
39254		var argumentsArray = Array.prototype.slice.call(arguments, 0);
39255		return this.each(function() {
39256			var instanceNumber = $(this).data("countdown-instance");
39257			if (instanceNumber !== undefined) {
39258				var instance = instances[instanceNumber], method = argumentsArray[0];
39259				if (Countdown.prototype.hasOwnProperty(method)) {
39260					instance[method].apply(instance, argumentsArray.slice(1));
39261				} else if (String(method).match(/^[$A-Z_][0-9A-Z_$]*$/i) === null) {
39262					instance.setFinalDate.call(instance, method);
39263					instance.start();
39264				} else {
39265					$.error("Method %s does not exist on jQuery.countdown".replace(/\%s/gi, method));
39266				}
39267			} else {
39268				new Countdown(this, argumentsArray[0], argumentsArray[1]);
39269			}
39270		});
39271	};
39272});
39273
39274!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.Share=e()}}(function(){var define,module,exports;
39275function getStyles(config){
39276  // return ""+config.selector+"{width:92px;height:20px;-webkit-touch-callout:none;-khtml-user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}"+config.selector+" [class*=social-]:before{font-family:'uncodeicon'}"+config.selector+" label{font-size:16px;cursor:pointer;margin:0;padding:5px 10px;border-radius:5px;background:#a29baa;-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out}"+config.selector+" label:hover{opacity:.8}"+config.selector+" label span{text-transform:uppercase;font-size:.9em;font-family:Lato,sans-serif;font-weight:700;-webkit-font-smoothing:antialiased;padding-left:6px}"+config.selector+" .social{opacity:0;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;margin-left:-15px;visibility:hidden}"+config.selector+" .social.top{-webkit-transform-origin:0 0;-ms-transform-origin:0 0;transform-origin:0 0;margin-top:-80px}"+config.selector+" .social.bottom{-webkit-transform-origin:0 0;-ms-transform-origin:0 0;transform-origin:0 0;margin-top:5px}"+config.selector+" .social.middle{margin-top:-34px}"+config.selector+" .social.middle.right{-webkit-transform-origin:5% 50%;-ms-transform-origin:5% 50%;transform-origin:5% 50%;margin-left:105px}"+config.selector+" .social.middle.left{-webkit-transform-origin:5% 50%;-ms-transform-origin:5% 50%;transform-origin:5% 50%}"+config.selector+" .social.right{margin-left:14px}"+config.selector+" .social.load{-webkit-transition:none!important;transition:none!important}"+config.selector+" .social.networks-1{width:60px}"+config.selector+" .social.networks-1.center,"+config.selector+" .social.networks-1.left{margin-left:14px}"+config.selector+" .social.networks-1.middle.left{margin-left:-70px}"+config.selector+" .social.networks-1 ul{width:60px}"+config.selector+" .social.networks-2{width:120px}"+config.selector+" .social.networks-2.center{margin-left:-13px}"+config.selector+" .social.networks-2.left{margin-left:-44px}"+config.selector+" .social.networks-2.middle.left{margin-left:-130px}"+config.selector+" .social.networks-2 ul{width:120px}"+config.selector+" .social.networks-3{width:180px}"+config.selector+" .social.networks-3.center{margin-left:-45px}"+config.selector+" .social.networks-3.left{margin-left:-102px}"+config.selector+" .social.networks-3.middle.left{margin-left:-190px}"+config.selector+" .social.networks-3 ul{width:180px}"+config.selector+" .social.networks-4{width:240px}"+config.selector+" .social.networks-4.center{margin-left:-75px}"+config.selector+" .social.networks-4.left{margin-left:162px}"+config.selector+" .social.networks-4.middle.left{margin-left:-250px}"+config.selector+" .social.networks-4 ul{width:240px}"+config.selector+" .social.networks-5{width:300px}"+config.selector+" .social.networks-5.center{margin-left:-105px}"+config.selector+" .social.networks-5.left{margin-left:-225px}"+config.selector+" .social.networks-5.middle.left{margin-left:-320px}"+config.selector+" .social.networks-5 ul{width:300px}"+config.selector+" .social.active{opacity:1;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;visibility:visible}"+config.selector+" .social.active.top{-webkit-transform:scale(1) translateY(-20px);-ms-transform:scale(1) translateY(-20px);transform:scale(1) translateY(-20px)}"+config.selector+" .social.active.bottom{-webkit-transform:scale(1) translateY(15px);-ms-transform:scale(1) translateY(15px);transform:scale(1) translateY(15px)}"+config.selector+" .social.active.middle.right{-webkit-transform:scale(1) translateX(10px);-ms-transform:scale(1) translateX(10px);transform:scale(1) translateX(10px)}"+config.selector+" .social.active.middle.left{-webkit-transform:scale(1) translateX(-20px);-ms-transform:scale(1) translateX(-20px);transform:scale(1) translateX(-20px)}"+config.selector+" .social ul{position:relative;
39276left:0;right:0;height:46px;color:#fff;margin:auto;padding:0;list-style:none}"+config.selector+" .social ul li{font-size:20px;cursor:pointer;width:60px;margin:0;padding:12px 0;text-align:center;float:left;display:none;height:22px;position:relative;z-index:2;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out}"+config.selector+" .social ul li:hover{}"+config.selector+" .social li[class*=facebook]{display:"+config.networks.facebook.display+"}"+config.selector+" .social li[class*=twitter]{display:"+config.networks.twitter.display+"}"+config.selector+" .social li[class*=gplus]{display:"+config.networks.google_plus.display+"}"+config.selector+" .social li[class*=pinterest]{display:"+config.networks.pinterest.display+"}"+config.selector+" .social li[class*=paper-plane]{display:"+config.networks.email.display+"}"
39277};
39278  var ShareUtils;
39279
39280if ((!("classList" in document.documentElement)) && Object.defineProperty && typeof HTMLElement !== "undefined") {
39281  Object.defineProperty(HTMLElement.prototype, "classList", {
39282    get: function() {
39283      var ret, self, update;
39284      update = function(fn) {
39285        return function(value) {
39286          var classes, index;
39287          classes = self.className.split(/\s+/);
39288          index = classes.indexOf(value);
39289          fn(classes, index, value);
39290          self.className = classes.join(" ");
39291        };
39292      };
39293      self = this;
39294      ret = {
39295        add: update(function(classes, index, value) {
39296          ~index || classes.push(value);
39297        }),
39298        remove: update(function(classes, index) {
39299          ~index && classes.splice(index, 1);
39300        }),
39301        toggle: update(function(classes, index, value) {
39302          if (~index) {
39303            classes.splice(index, 1);
39304          } else {
39305            classes.push(value);
39306          }
39307        }),
39308        contains: function(value) {
39309          return !!~self.className.split(/\s+/).indexOf(value);
39310        },
39311        item: function(i) {
39312          return self.className.split(/\s+/)[i] || null;
39313        }
39314      };
39315      Object.defineProperty(ret, "length", {
39316        get: function() {
39317          return self.className.split(/\s+/).length;
39318        }
39319      });
39320      return ret;
39321    }
39322  });
39323}
39324
39325String.prototype.to_rfc3986 = function() {
39326  var tmp;
39327  tmp = encodeURIComponent(this);
39328  return tmp.replace(/[!'()*]/g, function(c) {
39329    return "%" + c.charCodeAt(0).toString(16);
39330  });
39331};
39332
39333ShareUtils = (function() {
39334  function ShareUtils() {}
39335
39336  ShareUtils.prototype.extend = function(to, from, overwrite) {
39337    var hasProp, prop;
39338    for (prop in from) {
39339      hasProp = to[prop] !== undefined;
39340      if (hasProp && typeof from[prop] === "object") {
39341        this.extend(to[prop], from[prop], overwrite);
39342      } else {
39343        if (overwrite || !hasProp) {
39344          to[prop] = from[prop];
39345        }
39346      }
39347    }
39348  };
39349
39350  ShareUtils.prototype.hide = function(el) {
39351    return el.style.display = "none";
39352  };
39353
39354  ShareUtils.prototype.show = function(el) {
39355    return el.style.display = "block";
39356  };
39357
39358  ShareUtils.prototype.has_class = function(el, class_name) {
39359    return el.classList.contains(class_name);
39360  };
39361
39362  ShareUtils.prototype.add_class = function(el, class_name) {
39363    return el.classList.add(class_name);
39364  };
39365
39366  ShareUtils.prototype.remove_class = function(el, class_name) {
39367    return el.classList.remove(class_name);
39368  };
39369
39370  ShareUtils.prototype.is_encoded = function(str) {
39371    str = str.to_rfc3986();
39372    return decodeURIComponent(str) !== str;
39373  };
39374
39375  ShareUtils.prototype.encode = function(str) {
39376    if (typeof str === "undefined" || this.is_encoded(str)) {
39377      return str;
39378    } else {
39379      return str.to_rfc3986();
39380    }
39381  };
39382
39383  ShareUtils.prototype.popup = function(url, params) {
39384    var k, popup, qs, v;
39385    if (params == null) {
39386      params = {};
39387    }
39388    popup = {
39389      width: 500,
39390      height: 350
39391    };
39392    popup.top = (screen.height / 2) - (popup.height / 2);
39393    popup.left = (screen.width / 2) - (popup.width / 2);
39394    qs = ((function() {
39395      var _results;
39396      _results = [];
39397      for (k in params) {
39398        v = params[k];
39399        _results.push("" + k + "=" + (this.encode(v)));
39400      }
39401      return _results;
39402    }).call(this)).join('&');
39403    if (qs) {
39404      qs = "?" + qs;
39405    }
39406    return window.open(url + qs, 'targetWindow', "toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes,left=" + popup.left + ",top=" + popup.top + ",width=" 
39406+ popup.width + ",height=" + popup.height);
39407  };
39408
39409  return ShareUtils;
39410
39411})();
39412var Share,
39413  __hasProp = {}.hasOwnProperty,
39414  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
39415
39416Share = (function(_super) {
39417  __extends(Share, _super);
39418
39419  function Share(element, options) {
39420    this.element = element;
39421    this.el = {
39422      head: document.getElementsByTagName('head')[0],
39423      body: document.getElementsByTagName('body')[0]
39424    };
39425    this.config = {
39426      enabled_networks: 0,
39427      protocol: ['http', 'https'].indexOf(window.location.href.split(':')[0]) === -1 ? 'https://' : '//',
39428      url: window.location.href.replace("&", "%26"),
39429      caption: null,
39430      title: this.default_title(),
39431      image: this.default_image(),
39432      description: this.default_description(),
39433      ui: {
39434        flyout: 'top center',
39435        button_text: 'Share',
39436        button_font: true,
39437        icon_font: true
39438      },
39439      networks: {
39440        twitter: {
39441          enabled: true,
39442          url: null,
39443          title: null,
39444          description: null
39445        },
39446        facebook: {
39447          enabled: true,
39448          load_sdk: true,
39449          url: null,
39450          app_id: null,
39451          title: null,
39452          caption: null,
39453          description: null,
39454          image: null
39455        },
39456        threads: {
39457          enabled: true,
39458          url: null,
39459          title: null,
39460          description: null
39461        },
39462        bluesky: {
39463          enabled: true,
39464          url: null,
39465          title: null,
39466          description: null
39467        },
39468        pinterest: {
39469          enabled: true,
39470          url: null,
39471          image: null,
39472          description: null
39473        },
39474        reddit: {
39475          enabled: true,
39476          url: null,
39477          title: null
39478        },
39479        linkedin: {
39480          enabled: true,
39481          url: null,
39482          title: null,
39483          description: null
39484        },
39485        xing: {
39486          enabled: true,
39487          url: null,
39488          title: null,
39489          image: null,
39490          description: null
39491        },
39492        whatsapp: {
39493          enabled: true,
39494          title: null,
39495          url: null
39496        },
39497        email: {
39498          enabled: true,
39499          title: null,
39500          description: null,
39501          url: null
39502        }
39503      }
39504    };
39505    this.setup(element, options);
39506    return this;
39507  }
39508
39509  Share.prototype.setup = function(element, opts) {
39510    var index, instance, instances, _i, _len;
39511    instances = document.querySelectorAll(element);
39512    this.extend(this.config, opts, true);
39513    this.set_global_configuration();
39514    this.normalize_network_configuration();
39515    if (this.config.ui.icon_font) {
39516      this.inject_icons();
39517    }
39518    if (this.config.ui.button_font) {
39519      this.inject_fonts();
39520    }
39521    if (this.config.networks.facebook.enabled && this.config.networks.facebook.load_sdk) {
39522      this.inject_facebook_sdk();
39523    }
39524    for (index = _i = 0, _len = instances.length; _i < _len; index = ++_i) {
39525      instance = instances[index];
39526      this.setup_instance(element, index);
39527    }
39528  };
39529
39530  Share.prototype.setup_instance = function(element, index) {
39531    var button, instance, label, network, networks, _i, _len, _results,
39532      _this = this;
39533    instance = document.querySelectorAll(element)[index];
39534    this.hide(instance);
39535    this.add_class(instance, "sharer-" + index);
39536    instance = document.querySelectorAll(element)[index];
39537    this.inject_css(instance);
39538    this.inject_html(instance);
39539    this.show(instance);
39540    label = instance.getElementsByTagName("label")[0];
39541    button = instance.getElementsByClassName("social")[0];
39542    networks = instance.getElementsByTagName('li');
39543    this.add_class(button, "networks-" + this.config.enabled_networks);
39544    label.addEventListener("click", function() {
39545      return _this.event_toggle(button);
39546    });
39547    _this = this;
39548    _results = [];
39549    for (index = _i = 0, _len = networks.length; _i < _len; index = ++_i) {
39550      network = networks[index];
39551      _results.push(network.addEventListener("click", function() {
39552        _this.event_network(instance, this);
39553        return _this.event_close(button);
39554      }));
39555    }
39556    return _results;
39557  };
39558
39559  Share.prototype.event_toggle = function(button) {
39560    if (this.has_class(button, "active")) {
39561      return this.event_close(button);
39562    } else {
39563      return this.event_open(button);
39564    }
39565  };
39566
39567  Share.prototype.event_open = function(button) {
39568    if (this.has_class(button, "load")) {
39569      this.remove_class(button, "load");
39570    }
39571    return this.add_class(button, "active");
39572  };
39573
39574  Share.prototype.event_close = function(button) {
39575    return this.remove_class(button, "active");
39576  };
39577
39578  Share.prototype.event_network = function(instance, network) {
39579    var name;
39580    name = network.getAttribute("data-network");
39581    this.hook("before", name, instance);
39582    this["network_" + name]();
39583    return this.hook("after", name, instance);
39584  };
39585
39586  Share.prototype.open = function() {
39587    return this["public"]("open");
39588  };
39589
39590  Share.prototype.close = function() {
39591    return this["public"]("close");
39592  };
39593
39594  Share.prototype.toggle = function() {
39595    return this["public"]("toggle");
39596  };
39597
39598  Share.prototype["public"] = function(action) {
39599    var button, index, instance, _i, _len, _ref, _results;
39600    _ref = document.querySelectorAll(this.element);
39601    _results = [];
39602    for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) {
39603      instance = _ref[index];
39604      button = instance.getElementsByClassName("social")[0];
39605      _results.push(this["event_" + action](button));
39606    }
39607    return _results;
39608  };
39609
39610  Share.prototype.network_facebook = function() {
39611    if (this.config.networks.facebook.load_sdk) {
39612      if (!window.FB) {
39613        return console.error("The Facebook JS SDK hasn't loaded yet.");
39614      }
39615      return FB.ui({
39616        method: 'feed',
39617        name: this.config.networks.facebook.title,
39618        link: this.config.networks.facebook.url,
39619        picture: this.config.networks.facebook.image,
39620        caption: this.config.networks.facebook.caption,
39621        description: this.config.networks.facebook.description
39622      });
39623    } else {
39624      return this.popup('https://www.facebook.com/sharer/sharer.php', {
39625        u: this.config.networks.facebook.url
39626      });
39627    }
39628  };
39629
39630  Share.prototype.network_threads = function() {
39631    return this.popup('https://threads.net/intent/post', {
39632      text: this.config.networks.threads.title,
39633      url: this.config.networks.threads.url
39634    });
39635  };
39636
39637  Share.prototype.network_bluesky = function() {
39638    return this.popup('https://bsky.app/intent/compose', {
39639      text: this.config.networks.bluesky.title + ' ' + this.config.networks.bluesky.url
39640    });
39641  };
39642
39643  Share.prototype.network_twitter = function() {
39644    return this.popup('https://twitter.com/intent/tweet', {
39645      text: this.config.networks.twitter.title,
39646      url: this.config.networks.twitter.url
39647    });
39648  };
39649
39650  Share.prototype.network_pinterest = function() {
39651    return this.popup('https://www.pinterest.com/pin/create/button', {
39652      url: this.config.networks.pinterest.url,
39653      media: this.config.networks.pinterest.image,
39654      description: this.config.networks.pinterest.description
39655    });
39656  };
39657
39658  Share.prototype.network_linkedin = function() {
39659    return this.popup('https://www.linkedin.com/shareArticle', {
39660      url: this.config.networks.linkedin.url,
39661      title: this.config.networks.linkedin.title,
39662      summary: this.config.networks.linkedin.description
39663    });
39664  }
39665
39666  Share.prototype.network_xing = function() {
39667    return this.popup('https://www.xing.com/spi/shares/new', {
39668      url: this.config.networks.xing.url,
39669      image: this.config.networks.xing.image,
39670      title: this.config.networks.xing.title,
39671      summary: this.config.networks.xing.description
39672    });
39673  }
39674
39675  Share.prototype.network_whatsapp = function() {
39676    return this.popup('https://api.whatsapp.com/send', {
39677      text: this.config.networks.whatsapp.title + '%20' + this.config.networks.whatsapp.url,
39678    });
39679  }
39680
39681  Share.prototype.network_email = function() {
39682    return this.popup('mailto:', {
39683      subject: this.config.networks.email.title,
39684      body: this.config.networks.email.url + '%0A%0A' + this.config.networks.email.description,
39685    });
39686  };
39687
39688  Share.prototype.inject_icons = function() {
39689  //  return this.inject_stylesheet("https://www.sharebutton.co/fonts/v2/entypo.min.css");
39690  };
39691
39692  Share.prototype.inject_fonts = function() {
39693   // return this.inject_stylesheet("http://fonts.googleapis.com/css?family=Lato:900&text=" + this.config.ui.button_text);
39694  };
39695
39696  Share.prototype.inject_stylesheet = function(url) {
39697    var link;
39698    if (!this.el.head.querySelector("link[href=\"" + url + "\"]")) {
39699      link = document.createElement("link");
39700      link.setAttribute("rel", "stylesheet");
39701      link.setAttribute("href", url);
39702      return this.el.head.appendChild(link);
39703    }
39704  };
39705
39706  Share.prototype.inject_css = function(instance) {
39707    var css, meta, selector, style;
39708    selector = "." + (instance.getAttribute('class').split(" ").join("."));
39709    if (!this.el.head.querySelector("meta[name='sharer" + selector + "']")) {
39710      this.config.selector = selector;
39711      css = getStyles(this.config);
39712      style = document.createElement("style");
39713      style.type = "text/css";
39714      if (style.styleSheet) {
39715        style.styleSheet.cssText = css;
39716      } else {
39717        style.appendChild(document.createTextNode(css));
39718      }
39719      this.el.head.appendChild(style);
39720      delete this.config.selector;
39721      meta = document.createElement("meta");
39722      meta.setAttribute("name", "sharer" + selector);
39723      return this.el.head.appendChild(meta);
39724    }
39725  };
39726
39727  Share.prototype.inject_html = function(instance) {
39728    // return instance.innerHTML = "<label class='social-export'><span>" + this.config.ui.button_text + "</span></label><div class='social load " + this.config.ui.flyout + "'><ul><li class='social-facebook' data-network='facebook' tabindex='0'></li><li class='social-twitter' data-network='twitter' tabindex='0'></li><li class='social-gplus' data-network='google_plus' tabindex='0'></li><li class='social-pinterest' data-network='pinterest' tabindex='0'></li><li class='social-linkedin' data-network='linkedin' tabindex='0'></li><li class='social-xing' data-network='xing' tabindex='0'></li><li class='social-paper-plane' data-network='email' tabindex='0'></li></ul></div>";
39729    return instance.innerHTML = "<label class='social-export'><span>" + this.config.ui.button_text + "</span></label><div class='social load " + this.config.ui.flyout + "'><ul><li class='social-facebook' data-network='facebook' tabindex='0'></li><li class='social-twitter' data-network='twitter' tabindex='0'></li><li class='social-threads' data-network='threads' tabindex='0'></li><li class='social-pinterest' data-network='pinterest' tabindex='0'></li><li class='social-linkedin' data-network='linkedin' tabindex='0'></li><li class='social-whatsapp' data-network='whatsapp' tabindex='0'></li><li class='social-bluesky' data-network='bluesky' tabindex='0'></li><li class='social-xing' data-network='xing' tabindex='0'></li><li class='social-paper-plane' data-network='email' tabindex='0'></li></ul></div>";
39730  };
39731
39732  Share.prototype.inject_facebook_sdk = function() {
39733    var fb_root, script;
39734    if (!window.FB && this.config.networks.facebook.app_id && !this.el.body.querySelector('#fb-root')) {
39735      script = document.createElement("script");
39736      script.text = "window.fbAsyncInit=function(){FB.init({appId:'" + this.config.networks.facebook.app_id + "',status:true,xfbml:true})};(function(e,t,n){var r,i=e.getElementsByTagName(t)[0];if(e.getElementById(n)){return}r=e.createElement(t);r.id=n;r.src='" + this.config.protocol + "connect.facebook.net/en_US/all.js';i.parentNode.insertBefore(r,i)})(document,'script','facebook-jssdk')";
39737      fb_root = document.createElement("div");
39738      fb_root.id = "fb-root";
39739      this.el.body.appendChild(fb_root);
39740      return this.el.body.appendChild(script);
39741    }
39742  };
39743
39744  Share.prototype.hook = function(type, network, instance) {
39745    var fn, opts;
39746    fn = this.config.networks[network][type];
39747    if (typeof fn === "function") {
39748      opts = fn.call(this.config.networks[network], instance);
39749      if (opts !== void 0) {
39750        opts = this.normalize_filter_config_updates(opts);
39751        this.extend(this.config.networks[network], opts, true);
39752        this.normalize_network_configuration();
39753      }
39754    }
39755  };
39756
39757  Share.prototype.default_title = function() {
39758    var content;
39759    if (content = document.querySelector('meta[property="og:title"]') || document.querySelector('meta[name="twitter:title"]')) {
39760      return encodeURIComponent(content.getAttribute('content'));
39761    } else if (content = document.querySelector('title')) {
39762      return encodeURIComponent(content.innerText);
39763    }
39764  };
39765
39766  Share.prototype.default_image = function() {
39767    var content;
39768    if (content = document.querySelector('meta[property="og:image"]') || document.querySelector('meta[name="twitter:image"]')) {
39769      return content.getAttribute('content');
39770    }
39771  };
39772
39773  Share.prototype.default_description = function() {
39774    var content;
39775    if (content = document.querySelector('meta[property="og:description"]') || document.querySelector('meta[name="twitter:description"]') || document.querySelector('meta[name="description"]')) {
39776      return encodeURIComponent(content.getAttribute('content'));
39777    } else {
39778      return '';
39779    }
39780  };
39781
39782  Share.prototype.set_global_configuration = function() {
39783    var display, network, option, options, _ref, _results;
39784    _ref = this.config.networks;
39785    _results = [];
39786    for (network in _ref) {
39787      options = _ref[network];
39788      for (option in options) {
39789        if (this.config.networks[network][option] == null) {
39790          this.config.networks[network][option] = this.config[option];
39791        }
39792      }
39793      if (this.config.networks[network].enabled) {
39794        display = 'block';
39795        this.config.enabled_networks += 1;
39796      } else {
39797        display = 'none';
39798      }
39799      _results.push(this.config.networks[network].display = display);
39800    }
39801    return _results;
39802  };
39803
39804  Share.prototype.normalize_network_configuration = function() {
39805    if (!this.config.networks.facebook.app_id) {
39806      this.config.networks.facebook.load_sdk = false;
39807    }
39808    if (!this.is_encoded(this.config.networks.twitter.description)) {
39809      this.config.networks.twitter.description = encodeURIComponent(this.config.networks.twitter.description);
39810    }
39811    if (typeof this.config.networks.facebook.app_id === 'number') {
39812      return this.config.networks.facebook.app_id = this.config.networks.facebook.app_id.toString();
39813    }
39814  };
39815
39816  Share.prototype.normalize_filter_config_updates = function(opts) {
39817    if (this.config.networks.facebook.app_id !== opts.app_id) {
39818      console.warn("You are unable to change the Facebook app_id after the button has been initialized. Please-in-out update your Facebook filters accordingly.");
39819      delete opts.app_id;
39820    }
39821    if (this.config.networks.facebook.load_sdk !== opts.load_sdk) {
39822      console.warn("You are unable to change the Facebook load_sdk option after the button has been initialized. Please-in-out update your Facebook filters accordingly.");
39823      delete opts.app_id;
39824    }
39825    return opts;
39826  };
39827
39828  return Share;
39829
39830})(ShareUtils);
39831 return Share;
39832});
39833
39834// Generated by CoffeeScript 1.9.2
39835
39836// @license Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net
39837
39838(function() {
39839  var $, win;
39840
39841  $ = this.jQuery || window.jQuery;
39842
39843  win = $(window);
39844
39845  $.fn.stick_in_parent = function(opts) {
39846    var doc, elm, enable_bottoming, fn, i, inner_scrolling, len, manual_spacer, offset_top, outer_width, parent_selector, recalc_every, sticky_class;
39847    if (opts == null) {
39848      opts = {};
39849    }
39850    sticky_class = opts.sticky_class, inner_scrolling = opts.inner_scrolling, recalc_every = opts.recalc_every, parent_selector = opts.parent, offset_top = opts.offset_top, manual_spacer = opts.spacer, enable_bottoming = opts.bottoming;
39851    if (offset_top == null) {
39852      offset_top = 0;
39853    }
39854    if (parent_selector == null) {
39855      parent_selector = void 0;
39856    }
39857    if (inner_scrolling == null) {
39858      inner_scrolling = true;
39859    }
39860    if (sticky_class == null) {
39861      sticky_class = "is_stuck";
39862    }
39863    doc = $(document);
39864    if (enable_bottoming == null) {
39865      enable_bottoming = true;
39866    }
39867    outer_width = function(el) {
39868      var _el, computed, w;
39869      if (window.getComputedStyle) {
39870        _el = el[0];
39871        computed = window.getComputedStyle(el[0]);
39872        w = parseFloat(computed.getPropertyValue("width")) + parseFloat(computed.getPropertyValue("margin-left")) + parseFloat(computed.getPropertyValue("margin-right"));
39873        if (computed.getPropertyValue("box-sizing") !== "border-box") {
39874          w += parseFloat(computed.getPropertyValue("border-left-width")) + parseFloat(computed.getPropertyValue("border-right-width")) + parseFloat(computed.getPropertyValue("padding-left")) + parseFloat(computed.getPropertyValue("padding-right"));
39875        }
39876        return w;
39877      } else {
39878        return el.outerWidth(true);
39879      }
39880    };
39881    fn = function(elm, padding_bottom, parent_top, parent_height, top, height, el_float, detached) {
39882      var bottomed, detach, fixed, last_pos, last_scroll_height, offset, parent, recalc, recalc_and_tick, recalc_counter, spacer, tick;
39883      if (elm.data("sticky_kit")) {
39884        return;
39885      }
39886      elm.data("sticky_kit", true);
39887      last_scroll_height = doc.height();
39888      parent = elm.parent();
39889      if (parent_selector != null) {
39890        parent = parent.closest(parent_selector);
39891      }
39892      if (!parent.length) {
39893        throw "failed to find stick parent";
39894      }
39895      fixed = false;
39896      bottomed = false;
39897      spacer = manual_spacer != null ? manual_spacer && elm.closest(manual_spacer) : $("<div />");
39898      if (spacer) {
39899        spacer.css('position', elm.css('position'));
39900      }
39901      recalc = function() {
39902        var border_top, padding_top, restore;
39903        if (detached) {
39904          return;
39905        }
39906        last_scroll_height = doc.height();
39907        border_top = parseInt(parent.css("border-top-width"), 10);
39908        padding_top = parseInt(parent.css("padding-top"), 10);
39909        padding_bottom = parseInt(parent.css("padding-bottom"), 10);
39910        parent_top = parent.offset().top + border_top + padding_top;
39911        parent_height = parent.height();
39912        if (fixed) {
39913          fixed = false;
vendor: 6,068 bytes, lines 39914-40108
39914          bottomed = false;
39915          if (manual_spacer == null) {
39916            elm.insertAfter(spacer);
39917            spacer.detach();
39918          }
39919          elm.css({
39920            position: "",
39921            top: "",
39922            width: "",
39923            bottom: ""
39924          }).removeClass(sticky_class);
39925          restore = true;
39926        }
39927        top = elm.offset().top - (parseInt(elm.css("margin-top"), 10) || 0) - offset_top;
39928        height = elm.outerHeight(true);
39929        el_float = elm.css("float");
39930        if (spacer) {
39931          spacer.css({
39932            width: outer_width(elm),
39933            height: height,
39934            display: elm.css("display"),
39935            "vertical-align": elm.css("vertical-align"),
39936            "float": el_float
39937          });
39938        }
39939        if (restore) {
39940          return tick();
39941        }
39942      };
39943      recalc();
39944      if (height === parent_height) {
39945        return;
39946      }
39947      last_pos = void 0;
39948      offset = offset_top;
39949      recalc_counter = recalc_every;
39950      tick = function() {
39951        var css, delta, recalced, scroll, will_bottom, win_height;
39952        if (detached) {
39953          return;
39954        }
39955        recalced = false;
39956        if (recalc_counter != null) {
39957          recalc_counter -= 1;
39958          if (recalc_counter <= 0) {
39959            recalc_counter = recalc_every;
39960            recalc();
39961            recalced = true;
39962          }
39963        }
39964        if (!recalced && doc.height() !== last_scroll_height) {
39965          recalc();
39966          recalced = true;
39967        }
39968        scroll = win.scrollTop();
39969        if (last_pos != null) {
39970          delta = scroll - last_pos;
39971        }
39972        last_pos = scroll;
39973        if (fixed) {
39974          if (enable_bottoming) {
39975            will_bottom = scroll + height + offset > parent_height + parent_top;
39976            if (bottomed && !will_bottom) {
39977              bottomed = false;
39978              elm.css({
39979                position: "fixed",
39980                bottom: "",
39981                top: offset
39982              }).trigger("sticky_kit:unbottom");
39983            }
39984          }
39985          if (scroll < top) {
39986            fixed = false;
39987            offset = offset_top;
39988            if (manual_spacer == null) {
39989              if (el_float === "left" || el_float === "right") {
39990                elm.insertAfter(spacer);
39991              }
39992              spacer.detach();
39993            }
39994            css = {
39995              position: "",
39996              width: "",
39997              top: ""
39998            };
39999            elm.css(css).removeClass(sticky_class).trigger("sticky_kit:unstick");
40000          }
40001          if (inner_scrolling) {
40002            win_height = win.height();
40003            if (height + offset_top > win_height) {
40004              if (!bottomed) {
40005                offset -= delta;
40006                offset = Math.max(win_height - height, offset);
40007                offset = Math.min(offset_top, offset);
40008                if (fixed) {
40009                  elm.css({
40010                    top: offset + "px"
40011                  });
40012                }
40013              }
40014            }
40015          }
40016        } else {
40017          if (scroll > top) {
40018            fixed = true;
40019            css = {
40020              position: "fixed",
40021              top: offset
40022            };
40023            css.width = elm.css("box-sizing") === "border-box" ? elm.outerWidth() + "px" : elm.width() + "px";
40024            elm.css(css).addClass(sticky_class);
40025            if (manual_spacer == null) {
40026              elm.after(spacer);
40027              if (el_float === "left" || el_float === "right") {
40028                spacer.append(elm);
40029              }
40030            }
40031            elm.trigger("sticky_kit:stick");
40032          }
40033        }
40034        if (fixed && enable_bottoming) {
40035          if (will_bottom == null) {
40036            will_bottom = scroll + height + offset > parent_height + parent_top;
40037          }
40038          if (!bottomed && will_bottom) {
40039            bottomed = true;
40040            if (parent.css("position") === "static") {
40041              parent.css({
40042                position: "relative"
40043              });
40044            }
40045            return elm.css({
40046              position: "absolute",
40047              bottom: padding_bottom,
40048              top: "auto"
40049            }).trigger("sticky_kit:bottom");
40050          }
40051        }
40052      };
40053      recalc_and_tick = function() {
40054        recalc();
40055        return tick();
40056      };
40057      detach = function() {
40058        detached = true;
40059        win.off("touchmove", tick);
40060        win.off("scroll", tick);
40061        win.off("resize", recalc_and_tick);
40062        $(document.body).off("sticky_kit:recalc", recalc_and_tick);
40063        elm.off("sticky_kit:detach", detach);
40064        elm.removeData("sticky_kit");
40065        elm.css({
40066          position: "",
40067          bottom: "",
40068          top: "",
40069          width: ""
40070        });
40071        parent.position("position", "");
40072        if (fixed) {
40073          if (manual_spacer == null) {
40074            if (el_float === "left" || el_float === "right") {
40075              elm.insertAfter(spacer);
40076            }
40077            spacer.remove();
40078          }
40079          return elm.removeClass(sticky_class);
40080        }
40081      };
40082      win.on("touchmove", tick);
40083      win.on("scroll", tick);
40084      win.on("resize", recalc_and_tick);
40085      $(document.body).on("sticky_kit:recalc", recalc_and_tick);
40086      elm.on("sticky_kit:detach", detach);
40087      return setTimeout(tick, 0);
40088    };
40089    for (i = 0, len = this.length; i < len; i++) {
40090      elm = this[i];
40091      fn($(elm));
40092    }
40093    return this;
40094  };
40095
40096}).call(this);
40097/* ==========================================================================
40098 * bootstrap-tab-history.js
40099 * Author: Michael Narayan <[email protected]>
40100 * Repository: https://github.com/mnarayan01/bootstrap-tab-history/
40101 * ==========================================================================
40102 * Licensed under the Apache License, Version 2.0 (the "License"); you may
40103 * not use this file except in compliance with the License. You may obtain a
40104 * copy of the License at
40105 *
40106 * http://www.apache.org/licenses/LICENSE-2.0
40107 *
40108 * Unless required by applicable law or agreed to in writing, softw
40108are
40109 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
40110 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
40111 * License for the specific language governing permissions and limitations
40112 * under the License.
40113 * ========================================================================== */
40114
40115/* ========================================================================== */
40116/* JSHint directives                                                          */
40117/*                                                                            */
40118/* global BootstrapTabHistory: true                                           */
40119/*                                                                            */
40120/* global document                                                            */
40121/* global jQuery                                                              */
40122/* global history                                                             */
40123/* global window                                                              */
40124/* ========================================================================== */
40125
40126/**
40127 * Integrate [HTML5 history state tracking](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history)
40128 * with [`bootstrap/tab.js`](http://getbootstrap.com/javascript/#tabs). To enable tracking on a tab element, simply set
40129 * the `data-tab-history` attribute to true (or a string denoting a tab grouping).
40130 *
40131 * See the README for additional information.
40132 *
40133 * Functionality based upon bootstrap/tab.js v3.1.0; reference it when making any changes.
40134 */
40135
40136BootstrapTabHistory = {
40137  options: {
40138    /**
40139     * When the anchor portion of the URI is used to activate a tab, scroll down to the given offset, rather than the
40140     * element with the given `id` attribute. Set to null to disable. Only relevant if showTabsBasedOnAnchor is true.
40141     *
40142     * May be overriden on a per-element basis by the attribute `data-tab-history-anchor-y-offset`.
40143     *
40144     * @public
40145     * @type {?number}
40146     */
40147    defaultAnchorYOffset: 0,
40148    /**
40149     * Either 'push' or 'replace', for whether to use `history.pushState` or `history.replaceState`, resp.
40150     *
40151     * May be overriden on a per-element basis by the attribute `data-tab-history-changer`.
40152     *
40153     * @public
40154     * @type {string}
40155     */
40156    defaultChanger: 'replace',
40157    /**
40158     * If true, update the URL in onShownTab in the calls to `history.pushState` and `history.replaceState`. Otherwise,
40159     * `null` is passed as the third parameter to these calls.
40160     *
40161     * May be overriden on a per-element basis by the attribute `data-tab-history-update-url`.
40162     *
40163     * @public
40164     * @type {boolean}
40165     */
40166    defaultUpdateURL: false,
40167    /**
40168     * Should the anchor portion of the loaded URI be used to activate a single tab if no history was present on page
40169     * load.
40170     *
40171     * @public
40172     * @type {boolean}
40173     */
40174    showTabsBasedOnAnchor: true
40175  }
40176};
40177
40178(function () {
40179  'use strict';
40180
40181  jQuery(function () {
40182    if(history && history.pushState && history.replaceState) {
40183      var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory;
40184
40185      if(bootstrapTabHistory) {
40186        showTabsBasedOnState(bootstrapTabHistory);
40187      } else {
40188        showTabsBasedOnAnchor();
40189      }
40190
40191      backfillHistoryState();
40192
40193      jQuery(document).on('shown.bs.tab show.bs.collapse', onShownTab);
40194      jQuery(window).on('popstate', onPopState);
40195    } else {
40196      showTabsBasedOnAnchor();
40197    }
40198  });
40199
40200  /**
40201   * Used to prevent onShownTab from registering shown events that we triggered via showTabsBasedOnState.
40202   *
40203   * @type {boolean}
40204   */
40205  var showingTabsBasedOnState = false;
40206
40207  /**
40208   * Used to update `history.state` to reflect the default active tabs on initial page load. This supports proper
40209   * `history.back` handling when `data-tab-history-update-url` is true.
40210   */
40211  function backfillHistoryState() {
40212    var newState = null;
40213
40214    jQuery('li.active > [data-tab-history], .panel-title.active [data-tab-history]').each(function () {//edited by Uncode
40215      var $activeTabElement = jQuery(this);
40216      var selector = getTabSelector($activeTabElement);
40217
40218      if(selector) {
40219        var tabGroup = getTabGroup($activeTabElement);
40220
40221        if(tabGroup) {
40222          newState = createNewHistoryState(newState || history.state, tabGroup, selector);
40223        }
40224      }
40225    });
40226
40227    if(newState) {
40228      history.replaceState(newState, '', null);
40229    }
40230  }
40231
40232  /**
40233   * Clone the existing state, ensure its bootstrapTabHistory attribute is an Object, and add the provided tabGroup to
40234   * said bootstrapTabHistory attribute.
40235   *
40236   * @param {?object} existingState
40237   * @param {!string} tabGroup
40238   * @param {!string} selector
40239   * @returns {!object}
40240   */
40241  function createNewHistoryState(existingState, tabGroup, selector) {
40242    // Clone history.state and ensure it has a bootstrapTabHistory entry.
40243    var newState = jQuery.extend(true, {}, existingState, {
40244      bootstrapTabHistory: {}
40245    });
40246
40247    newState.bootstrapTabHistory[tabGroup] = selector;
40248
40249    return newState;
40250  }
40251
40252  /**
40253   * @param {jQuery} $tab
40254   * @returns {?string}
40255   */
40256  function getTabGroup($tab) {
40257    return parseTruthyAttributeValue($tab.data('tab-history'));
40258  }
40259
40260  /**
40261   * @param {jQuery} $tab
40262   * @returns {?string}
40263   */
40264  function getTabSelector($tab) {
40265    return $tab.data('target') || $tab.attr('href');
40266  }
40267
40268  /**
40269   * Receives the `shown.bs.tab` event. Updates `history.state` as appropriate.
40270   *
40271   * @param {jQuery.Event} shownEvt
40272   */
40273  function onShownTab(shownEvt) {
40274    if(!showingTabsBasedOnState) {
40275      var $activatedTab = jQuery(shownEvt.target);
40276      if ( $activatedTab.hasClass('panel-collapse') )
40277        $activatedTab = $activatedTab.closest('.panel').find('a');
40278      var selector = getTabSelector($activatedTab);
40279
40280      if(selector) {
40281        var tabGroup = getTabGroup($activatedTab);
40282
40283        if(tabGroup) {
40284          var historyChanger = $activatedTab.data('tab-history-changer') || BootstrapTabHistory.options.defaultChanger;
40285          var newState = createNewHistoryState(history.state, tabGroup, selector);
40286          var updateURL = (function ($activatedTab) {
40287            if(selector[0] === '#') {
40288              var elementUpdateURLOption = parseTruthyAttributeValue($activatedTab.data('tab-history-update-url'));
40289
40290              if(elementUpdateURLOption === undefined) {
40291                return BootstrapTabHistory.options.defaultUpdateURL;
40292              } else {
40293                return elementUpdateURLOption;
40294              }
40295            } else {
40296              return false;
40297            }
40298          })($activatedTab);
40299
40300          switch(historyChanger) {
40301            case 'push':
40302              history.pushState(newState, '', updateURL ? selector : null);
40303              break;
40304            case 'replace':
40305              history.replaceState(newState, '', updateURL ? selector : null);
40306              break;
40307            default:
40308              throw new Error('Unknown tab-history-changer: ' + historyChanger);
40309          }
40310        }
40311      }
40312    }
40313  }
40314
40315  /**
40316   * Receives the `popstate` event. Shows tabs based on the value of `history.state` as appropriate.
40317   */
40318  function onPopState() {
40319    var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory;
40320
40321    if(bootstrapTabHistory) {
40322      showTabsBasedOnState(bootstrapTabHistory);
40323    }
40324  }
40325
40326  /**
40327   * Returns the given value, _unless_ that value is an empty string, in which case `true` is returned.
40328   *
40329   * Rationale: HAML data attributes which are set to `true` are rendered as a blank string.
40330   *
40331   * @param {*} value
40332   * @returns {*}
40333   */
40334  function parseTruthyAttributeValue(value) {
40335    if(value) {
40336      return value;
40337    } else if(value === '') {
40338      return true;
40339    } else {
40340      return value;
40341    }
40342  }
40343
40344  /**
40345   * Show tabs based upon the anchor component of `window.location`.
40346   */
40347  function showTabsBasedOnAnchor() {
40348    if(BootstrapTabHistory.options.showTabsBasedOnAnchor) {
40349      var anchor = window.location && window.location.hash;
40350
40351      if(anchor) {
40352        var $tabElement = showTabForSelector(anchor);
40353
40354        if($tabElement && window.addEventListener && window.removeEventListener) {
40355          var anchorYOffset = (function ($tabElement) {
40356            var elementSetting = $tabElement.data('tab-history-anchor-y-offset');
40357
40358            if(elementSetting === undefined) {
40359              return BootstrapTabHistory.options.defaultAnchorYOffset;
40360            } else {
40361              return elementSetting;
40362            }
40363          })($tabElement);
40364
40365          // HACK: This prevents scrolling to the tab on page load. This relies on the fact that we should never get
40366          //   here on `history.forward`, `history.back`, or `location.reload`, since in all those situations the
40367          //   `history.state` object should have been used (unless the browser did not support the modern History API).
40368          if(anchorYOffset || anchorYOffset === 0) {
40369            var scrollListener = function resetAnchorScroll () {
40370              window.removeEventListener('scroll', scrollListener);
40371              window.scrollTo(0, anchorYOffset);
40372            };
40373
40374            window.addEventListener('scroll', scrollListener);
40375          }
40376        }
40377      }
40378    }
40379  }
40380
40381  /**
40382   * Show a tab which corresponds to the provided selector.
40383   *
40384   * @param {string} selector - A CSS selector.
40385   * @returns {?jQuery} - The tab which was found to show (even if said tab was already active).
40386   */
40387  function showTabForSelector(selector) {
40388    var $tabElement = (function (selector) {
40389      var $ret = null;
40390
40391      jQuery('[data-toggle="tab"], [data-toggle="pill"], [data-toggle="collapse"]').each(function () {
40392        var $potentialTab = jQuery(this);
40393
40394        if(($potentialTab.attr('href') === selector || $potentialTab.data('target') === selector ) && getTabGroup($potentialTab)) {
40395          $ret = $potentialTab;
40396          return false;
vendor: 43,483 bytes, lines 40397-41613
40397        } else {
40398         return null;
40399        }
40400      });
40401
40402      return $ret;
40403    })(selector);
40404
40405    if($tabElement) {
40406      if ( !$tabElement.parent().hasClass('active') ) {
40407        $tabElement.trigger('click');
40408      }
40409      //$tabElement.tab('show');
40410    }
40411
40412    return $tabElement;
40413  }
40414
40415  /**
40416   * Iterate through the provided set of tab tab groups, showing the tabs based on the stored selectors.
40417   *
40418   * @param {object} bootstrapTabHistory - Each of the values is passed to showTabForSelector; the keys are actually irrelevant.
40419   */
40420  function showTabsBasedOnState(bootstrapTabHistory) {
40421    showingTabsBasedOnState = true;
40422
40423    try {
40424      for(var k in bootstrapTabHistory) {
40425        if(bootstrapTabHistory.hasOwnProperty(k)) {
40426          showTabForSelector(bootstrapTabHistory[k]);
40427        }
40428      }
40429    } finally {
40430      showingTabsBasedOnState = false;
40431    }
40432  }
40433})();
40434
40435/*!
40436 * justifiedGallery - v3.8.1
40437 * http://miromannino.github.io/Justified-Gallery/
40438 * Copyright (c) 2020 Miro Mannino
40439 * Licensed under the MIT license.
40440 */
40441(function (factory) {
40442  if (typeof define === 'function' && define.amd) {
40443    // AMD. Register as an anonymous module.
40444    define(['jquery'], factory);
40445  } else if (typeof module === 'object' && module.exports) {
40446    // Node/CommonJS
40447    module.exports = function (root, jQuery) {
40448      if (jQuery === undefined) {
40449        // require('jQuery') returns a factory that requires window to
40450        // build a jQuery instance, we normalize how we use modules
40451        // that require this pattern but the window provided is a noop
40452        // if it's defined (how jquery works)
40453        if (typeof window !== 'undefined') {
40454          jQuery = require('jquery');
40455        }
40456        else {
40457          jQuery = require('jquery')(root);
40458        }
40459      }
40460      factory(jQuery);
40461      return jQuery;
40462    };
40463  } else {
40464    // Browser globals
40465    factory(jQuery);
40466  }
40467}(function ($) {
40468
40469  /**
40470   * Justified Gallery controller constructor
40471   *
40472   * @param $gallery the gallery to build
40473   * @param settings the settings (the defaults are in JustifiedGallery.defaults)
40474   * @constructor
40475   */
40476  var JustifiedGallery = function ($gallery, settings) {
40477
40478    this.settings = settings;
40479    this.checkSettings();
40480
40481    this.imgAnalyzerTimeout = null;
40482    this.entries = null;
40483    this.buildingRow = {
40484      entriesBuff: [],
40485      width: 0,
40486      height: 0,
40487      aspectRatio: 0
40488    };
40489    this.lastFetchedEntry = null;
40490    this.lastAnalyzedIndex = -1;
40491    this.yield = {
40492      every: 2, // do a flush every n flushes (must be greater than 1)
40493      flushed: 0 // flushed rows without a yield
40494    };
40495    this.border = settings.border >= 0 ? settings.border : settings.margins;
40496    this.maxRowHeight = this.retrieveMaxRowHeight();
40497    this.suffixRanges = this.retrieveSuffixRanges();
40498    this.offY = this.border;
40499    this.rows = 0;
40500    this.spinner = {
40501      phase: 0,
40502      timeSlot: 150,
40503      $el: $('<div class="jg-spinner"><span></span><span></span><span></span></div>'),
40504      intervalId: null
40505    };
40506    this.scrollBarOn = false;
40507    this.checkWidthIntervalId = null;
40508    this.galleryWidth = $gallery.width();
40509    this.$gallery = $gallery;
40510
40511  };
40512
40513  /** @returns {String} the best suffix given the width and the height */
40514  JustifiedGallery.prototype.getSuffix = function (width, height) {
40515    var longestSide, i;
40516    longestSide = (width > height) ? width : height;
40517    for (i = 0; i < this.suffixRanges.length; i++) {
40518      if (longestSide <= this.suffixRanges[i]) {
40519        return this.settings.sizeRangeSuffixes[this.suffixRanges[i]];
40520      }
40521    }
40522    return this.settings.sizeRangeSuffixes[this.suffixRanges[i - 1]];
40523  };
40524
40525  /**
40526   * Remove the suffix from the string
40527   *
40528   * @returns {string} a new string without the suffix
40529   */
40530  JustifiedGallery.prototype.removeSuffix = function (str, suffix) {
40531    return str.substring(0, str.length - suffix.length);
40532  };
40533
40534  /**
40535   * @returns {boolean} a boolean to say if the suffix is contained in the str or not
40536   */
40537  JustifiedGallery.prototype.endsWith = function (str, suffix) {
40538    return str.indexOf(suffix, str.length - suffix.length) !== -1;
40539  };
40540
40541  /**
40542   * Get the used suffix of a particular url
40543   *
40544   * @param str
40545   * @returns {String} return the used suffix
40546   */
40547  JustifiedGallery.prototype.getUsedSuffix = function (str) {
40548    for (var si in this.settings.sizeRangeSuffixes) {
40549      if (this.settings.sizeRangeSuffixes.hasOwnProperty(si)) {
40550        if (this.settings.sizeRangeSuffixes[si].length === 0) continue;
40551        if (this.endsWith(str, this.settings.sizeRangeSuffixes[si])) return this.settings.sizeRangeSuffixes[si];
40552      }
40553    }
40554    return '';
40555  };
40556
40557  /**
40558   * Given an image src, with the width and the height, returns the new image src with the
40559   * best suffix to show the best quality thumbnail.
40560   *
40561   * @returns {String} the suffix to use
40562   */
40563  JustifiedGallery.prototype.newSrc = function (imageSrc, imgWidth, imgHeight, image) {
40564    var newImageSrc;
40565
40566    if (this.settings.thumbnailPath) {
40567      newImageSrc = this.settings.thumbnailPath(imageSrc, imgWidth, imgHeight, image);
40568    } else {
40569      var matchRes = imageSrc.match(this.settings.extension);
40570      var ext = (matchRes !== null) ? matchRes[0] : '';
40571      newImageSrc = imageSrc.replace(this.settings.extension, '');
40572      newImageSrc = this.removeSuffix(newImageSrc, this.getUsedSuffix(newImageSrc));
40573      newImageSrc += this.getSuffix(imgWidth, imgHeight) + ext;
40574    }
40575
40576    return newImageSrc;
40577  };
40578
40579  /**
40580   * Shows the images that is in the given entry
40581   *
40582   * @param $entry the entry
40583   * @param callback the callback that is called when the show animation is finished
40584   */
40585  JustifiedGallery.prototype.showImg = function ($entry, callback) {
40586    if (this.settings.cssAnimation) {
40587      $entry.addClass('jg-entry-visible');
40588      if (callback) callback();
40589    } else {
40590      $entry.stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback);
40591      $entry.find(this.settings.imgSelector).stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback);
40592    }
40593  };
40594
40595  /**
40596   * Extract the image src form the image, looking from the 'safe-src', and if it can't be found, from the
40597   * 'src' attribute. It saves in the image data the 'jg.originalSrc' field, with the extracted src.
40598   *
40599   * @param $image the image to analyze
40600   * @returns {String} the extracted src
40601   */
40602  JustifiedGallery.prototype.extractImgSrcFromImage = function ($image) {
40603    var imageSrc = $image.data('safe-src');
40604    var imageSrcLoc = 'data-safe-src';
40605    // Begin Uncode edit
40606    if (typeof imageSrc === 'undefined') {
40607    	var imageCurrentSrc = $image[0].currentSrc;
40608    	if (imageCurrentSrc) {
40609    		imageSrc = imageCurrentSrc;
40610    	} else {
40611    		imageSrc = $image.attr('src');
40612    	}
40613		imageSrcLoc = 'src';
40614    }
40615    // End Uncode edit
40616    $image.data('jg.originalSrc', imageSrc); // this is saved for the destroy method
40617    $image.data('jg.src', imageSrc); // this will change overtime
40618    $image.data('jg.originalSrcLoc', imageSrcLoc); // this is saved for the destroy method
40619    return imageSrc;
40620  };
40621
40622  /** @returns {jQuery} the image in the given entry */
40623  JustifiedGallery.prototype.imgFromEntry = function ($entry) {
40624    var $img = $entry.find(this.settings.imgSelector);
40625    if ($img.length === 0) $img = $entry.find('.t-entry-visual-cont img');//hacked by Uncode
40626    return $img.length === 0 ? null : $img;
40627  };
40628
40629  /** @returns {jQuery} the caption in the given entry */
40630  JustifiedGallery.prototype.captionFromEntry = function ($entry) {
40631    var $caption = $entry.find('> .jg-caption');
40632    return $caption.length === 0 ? null : $caption;
40633  };
40634
40635  /**
40636   * Display the entry
40637   *
40638   * @param {jQuery} $entry the entry to display
40639   * @param {int} x the x position where the entry must be positioned
40640   * @param y the y position where the entry must be positioned
40641   * @param imgWidth the image width
40642   * @param imgHeight the image height
40643   * @param rowHeight the row height of the row that owns the entry
40644   */
40645  JustifiedGallery.prototype.displayEntry = function ($entry, x, y, imgWidth, imgHeight, rowHeight) {
40646    $entry.width(imgWidth);
40647    $entry.height(Math.floor(rowHeight));//hacked by Uncode
40648    $entry.css('top', Math.floor(y));//hacked by Uncode
40649    $entry.css('left', x);
40650
40651    var $image = this.imgFromEntry($entry);
40652    if ($image !== null) {
40653      $image.css('width', imgWidth);
40654      $image.css('height', imgHeight);
40655      $image.css('margin-left', - imgWidth / 2);
40656      $image.css('margin-top', - imgHeight / 2);
40657
40658      // Image reloading for an high quality of thumbnails
40659      var imageSrc = $image.data('jg.src');
40660      if (imageSrc) {
40661        imageSrc = this.newSrc(imageSrc, imgWidth, imgHeight, $image[0]);
40662
40663        $image.one('error', function () {
40664           this.resetImgSrc($image); //revert to the original thumbnail
40665        });
40666
40667        var loadNewImage = function () {
40668          // if (imageSrc !== newImageSrc) {
40669            $image.attr('src', imageSrc);
40670          // }
40671        };
40672
40673        if ($entry.data('jg.loaded') === 'skipped' && imageSrc) {
40674          this.onImageEvent(imageSrc, (function() {
40675            this.showImg($entry, loadNewImage); //load the new image after the fadeIn
40676            $entry.data('jg.loaded', true);
40677          }).bind(this));
40678        } else {
40679          this.showImg($entry, loadNewImage); //load the new image after the fadeIn
40680        }
40681
40682      }
40683
40684    } else {
40685      this.showImg($entry);
40686    }
40687
40688    this.displayEntryCaption($entry);
40689  };
40690
40691  /**
40692   * Display the entry caption. If the caption element doesn't exists, it creates the caption using the 'alt'
40693   * or the 'title' attributes.
40694   *
40695   * @param {jQuery} $entry the entry to process
40696   */
40697  JustifiedGallery.prototype.displayEntryCaption = function ($entry) {
40698    var $image = this.imgFromEntry($entry);
40699    if ($image !== null && this.settings.captions) {
40700      var $imgCaption = this.captionFromEntry($entry);
40701
40702      // Create it if it doesn't exists
40703      if ($imgCaption === null) {
40704        var caption = $image.attr('alt');
40705        if (!this.isValidCaption(caption)) caption = $entry.attr('title');
40706        if (this.isValidCaption(caption)) { // Create only we found something
40707          $imgCaption = $('<div class="jg-caption">' + caption + '</div>');
40708          $entry.append($imgCaption);
40709          $entry.data('jg.createdCaption', true);
40710        }
40711      }
40712
40713      // Create events (we check again the $imgCaption because it can be still inexistent)
40714      if ($imgCaption !== null) {
40715        if (!this.settings.cssAnimation) $imgCaption.stop().fadeTo(0, this.settings.captionSettings.nonVisibleOpacity);
40716        this.addCaptionEventsHandlers($entry);
40717      }
40718    } else {
40719      this.removeCaptionEventsHandlers($entry);
40720    }
40721  };
40722
40723  /**
40724   * Validates the caption
40725   *
40726   * @param caption The caption that should be validated
40727   * @return {boolean} Validation result
40728   */
40729  JustifiedGallery.prototype.isValidCaption = function (caption) {
40730    return (typeof caption !== 'undefined' && caption.length > 0);
40731  };
40732
40733  /**
40734   * The callback for the event 'mouseenter'. It assumes that the event currentTarget is an entry.
40735   * It shows the caption using jQuery (or using CSS if it is configured so)
40736   *
40737   * @param {Event} eventObject the event object
40738   */
40739  JustifiedGallery.prototype.onEntryMouseEnterForCaption = function (eventObject) {
40740    var $caption = this.captionFromEntry($(eventObject.currentTarget));
40741    if (this.settings.cssAnimation) {
40742      $caption.addClass('jg-caption-visible').removeClass('jg-caption-hidden');
40743    } else {
40744      $caption.stop().fadeTo(this.settings.captionSettings.animationDuration,
40745        this.settings.captionSettings.visibleOpacity);
40746    }
40747  };
40748
40749  /**
40750   * The callback for the event 'mouseleave'. It assumes that the event currentTarget is an entry.
40751   * It hides the caption using jQuery (or using CSS if it is configured so)
40752   *
40753   * @param {Event} eventObject the event object
40754   */
40755  JustifiedGallery.prototype.onEntryMouseLeaveForCaption = function (eventObject) {
40756    var $caption = this.captionFromEntry($(eventObject.currentTarget));
40757    if (this.settings.cssAnimation) {
40758      $caption.removeClass('jg-caption-visible').removeClass('jg-caption-hidden');
40759    } else {
40760      $caption.stop().fadeTo(this.settings.captionSettings.animationDuration,
40761        this.settings.captionSettings.nonVisibleOpacity);
40762    }
40763  };
40764
40765  /**
40766   * Add the handlers of the entry for the caption
40767   *
40768   * @param $entry the entry to modify
40769   */
40770  JustifiedGallery.prototype.addCaptionEventsHandlers = function ($entry) {
40771    var captionMouseEvents = $entry.data('jg.captionMouseEvents');
40772    if (typeof captionMouseEvents === 'undefined') {
40773      captionMouseEvents = {
40774        mouseenter: $.proxy(this.onEntryMouseEnterForCaption, this),
40775        mouseleave: $.proxy(this.onEntryMouseLeaveForCaption, this)
40776      };
40777      $entry.on('mouseenter', undefined, undefined, captionMouseEvents.mouseenter);
40778      $entry.on('mouseleave', undefined, undefined, captionMouseEvents.mouseleave);
40779      $entry.data('jg.captionMouseEvents', captionMouseEvents);
40780    }
40781  };
40782
40783  /**
40784   * Remove the handlers of the entry for the caption
40785   *
40786   * @param $entry the entry to modify
40787   */
40788  JustifiedGallery.prototype.removeCaptionEventsHandlers = function ($entry) {
40789    var captionMouseEvents = $entry.data('jg.captionMouseEvents');
40790    if (typeof captionMouseEvents !== 'undefined') {
40791      $entry.off('mouseenter', undefined, captionMouseEvents.mouseenter);
40792      $entry.off('mouseleave', undefined, captionMouseEvents.mouseleave);
40793      $entry.removeData('jg.captionMouseEvents');
40794    }
40795  };
40796
40797  /**
40798   * Clear the building row data to be used for a new row
40799   */
40800  JustifiedGallery.prototype.clearBuildingRow = function () {
40801    this.buildingRow.entriesBuff = [];
40802    this.buildingRow.aspectRatio = 0;
40803    this.buildingRow.width = 0;
40804  };
40805
40806  /**
40807   * Justify the building row, preparing it to
40808   *
40809   * @param isLastRow
40810   * @param hiddenRow undefined or false for normal behavior. hiddenRow = true to hide the row.
40811   * @returns a boolean to know if the row has been justified or not
40812   */
40813  JustifiedGallery.prototype.prepareBuildingRow = function (isLastRow, hiddenRow) {
40814    var i, $entry, imgAspectRatio, newImgW, newImgH, justify = true;
40815    var minHeight = 0;
40816    var availableWidth = this.galleryWidth - 2 * this.border - (
40817      (this.buildingRow.entriesBuff.length - 1) * this.settings.margins);
40818    var rowHeight = Math.floor( availableWidth / this.buildingRow.aspectRatio );//hacked by Uncode
40819    var defaultRowHeight = this.settings.rowHeight;
40820    var justifiable = this.buildingRow.width / availableWidth > this.settings.justifyThreshold;
40821
40822    //Skip the last row if we can't justify it and the lastRow == 'hide'
40823    if (hiddenRow || (isLastRow && this.settings.lastRow === 'hide' && !justifiable)) {
40824      for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
40825        $entry = this.buildingRow.entriesBuff[i];
40826        if (this.settings.cssAnimation)
40827          $entry.removeClass('jg-entry-visible');
40828        else {
40829          $entry.stop().fadeTo(0, 0.1);
40830          $entry.find('> img, > a > img').fadeTo(0, 0);
40831        }
40832      }
40833      return -1;
40834    }
40835
40836    // With lastRow = nojustify, justify if is justificable (the images will not become too big)
40837    if (isLastRow && !justifiable && this.settings.lastRow !== 'justify' && this.settings.lastRow !== 'hide') {
40838      justify = false;
40839
40840      if (this.rows > 0) {
40841        defaultRowHeight = (this.offY - this.border - this.settings.margins * this.rows) / this.rows;
40842        justify = defaultRowHeight * this.buildingRow.aspectRatio / availableWidth > this.settings.justifyThreshold;
40843      }
40844    }
40845
40846    for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
40847      $entry = this.buildingRow.entriesBuff[i];
40848      imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height');
40849
40850      if (justify) {
40851        newImgW = (i === this.buildingRow.entriesBuff.length - 1) ? availableWidth : rowHeight * imgAspectRatio;
40852        newImgH = rowHeight;
40853      } else {
40854        newImgW = defaultRowHeight * imgAspectRatio;
40855        newImgH = defaultRowHeight;
40856      }
40857
40858      availableWidth -= Math.round(newImgW);
40859      $entry.data('jg.jwidth', Math.round(newImgW));
40860      $entry.data('jg.jheight', Math.ceil(newImgH));
40861      if (i === 0 || minHeight > newImgH) minHeight = newImgH;
40862    }
40863
40864    this.buildingRow.height = minHeight;
40865    return justify;
40866  };
40867
40868  /**
40869   * Flush a row: justify it, modify the gallery height accordingly to the row height
40870   *
40871   * @param isLastRow
40872   * @param hiddenRow undefined or false for normal behavior. hiddenRow = true to hide the row.
40873   */
40874  JustifiedGallery.prototype.flushRow = function (isLastRow, hiddenRow) {
40875    var settings = this.settings;
40876    var $entry, buildingRowRes, offX = this.border, i;
40877
40878    buildingRowRes = this.prepareBuildingRow(isLastRow, hiddenRow);
40879    if (hiddenRow || (isLastRow && settings.lastRow === 'hide' && buildingRowRes === -1)) {
40880      this.clearBuildingRow();
40881      return;
40882    }
40883
40884    if (this.maxRowHeight) {
40885      if (this.maxRowHeight < this.buildingRow.height) this.buildingRow.height = this.maxRowHeight;
40886    }
40887
40888    //Align last (unjustified) row
40889    if (isLastRow && (settings.lastRow === 'center' || settings.lastRow === 'right')) {
40890      var availableWidth = this.galleryWidth - 2 * this.border - (this.buildingRow.entriesBuff.length - 1) * settings.margins;
40891
40892      for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
40893        $entry = this.buildingRow.entriesBuff[i];
40894        availableWidth -= $entry.data('jg.jwidth');
40895      }
40896
40897      if (settings.lastRow === 'center')
40898        offX += Math.round(availableWidth / 2);
40899      else if (settings.lastRow === 'right')
40900        offX += availableWidth;
40901    }
40902
40903    var lastEntryIdx = this.buildingRow.entriesBuff.length - 1;
40904    for (i = 0; i <= lastEntryIdx; i++) {
40905      $entry = this.buildingRow.entriesBuff[this.settings.rtl ? lastEntryIdx - i : i];
40906      this.displayEntry($entry, offX, this.offY, $entry.data('jg.jwidth'), $entry.data('jg.jheight'), this.buildingRow.height);
40907      offX += $entry.data('jg.jwidth') + settings.margins;
40908    }
40909
40910    //Gallery Height
40911    this.galleryHeightToSet = this.offY + this.buildingRow.height + this.border;
40912    this.setGalleryTempHeight(this.galleryHeightToSet + this.getSpinnerHeight());
40913
40914    if (!isLastRow || (this.buildingRow.height <= settings.rowHeight && buildingRowRes)) {
40915      //Ready for a new row
40916      this.offY += this.buildingRow.height + settings.margins;
40917      this.rows += 1;
40918      this.clearBuildingRow();
40919      this.settings.triggerEvent.call(this, 'jg.rowflush');
40920    }
40921  };
40922
40923
40924  // Scroll position not restoring: https://github.com/miromannino/Justified-Gallery/issues/221
40925  var galleryPrevStaticHeight = 0;
40926
40927  JustifiedGallery.prototype.rememberGalleryHeight = function () {
40928    galleryPrevStaticHeight = this.$gallery.height();
40929    this.$gallery.height(galleryPrevStaticHeight);
40930  };
40931
40932  // grow only
40933  JustifiedGallery.prototype.setGalleryTempHeight = function (height) {
40934    galleryPrevStaticHeight = Math.max(height, galleryPrevStaticHeight);
40935    this.$gallery.height(galleryPrevStaticHeight);
40936  };
40937
40938  JustifiedGallery.prototype.setGalleryFinalHeight = function (height) {
40939    galleryPrevStaticHeight = height;
40940    this.$gallery.height(height);
40941  };
40942
40943  /**
40944   * Checks the width of the gallery container, to know if a new justification is needed
40945   */
40946  JustifiedGallery.prototype.checkWidth = function () {
40947    this.checkWidthIntervalId = setInterval($.proxy(function () {
40948
40949      // if the gallery is not currently visible, abort.
40950      if (!this.$gallery.is(":visible")) return;
40951
40952      var galleryWidth = parseFloat(this.$gallery.width());
40953      if (Math.abs(galleryWidth - this.galleryWidth) > this.settings.refreshSensitivity) {
40954        this.galleryWidth = galleryWidth;
40955        this.rewind();
40956
40957        this.rememberGalleryHeight();
40958
40959        // Restart to analyze
40960        this.startImgAnalyzer(true);
40961      }
40962    }, this), this.settings.refreshTime);
40963  };
40964
40965  /**
40966   * @returns {boolean} a boolean saying if the spinner is active or not
40967   */
40968  JustifiedGallery.prototype.isSpinnerActive = function () {
40969    return this.spinner.intervalId !== null;
40970  };
40971
40972  /**
40973   * @returns {int} the spinner height
40974   */
40975  JustifiedGallery.prototype.getSpinnerHeight = function () {
40976    return this.spinner.$el.innerHeight();
40977  };
40978
40979  /**
40980   * Stops the spinner animation and modify the gallery height to exclude the spinner
40981   */
40982  JustifiedGallery.prototype.stopLoadingSpinnerAnimation = function () {
40983    clearInterval(this.spinner.intervalId);
40984    this.spinner.intervalId = null;
40985    this.setGalleryTempHeight(this.$gallery.height() - this.getSpinnerHeight());
40986    this.spinner.$el.detach();
40987  };
40988
40989  /**
40990   * Starts the spinner animation
40991   */
40992  JustifiedGallery.prototype.startLoadingSpinnerAnimation = function () {
40993    var spinnerContext = this.spinner;
40994    var $spinnerPoints = spinnerContext.$el.find('span');
40995    clearInterval(spinnerContext.intervalId);
40996    this.$gallery.append(spinnerContext.$el);
40997    this.setGalleryTempHeight(this.offY + this.buildingRow.height + this.getSpinnerHeight());
40998    spinnerContext.intervalId = setInterval(function () {
40999      if (spinnerContext.phase < $spinnerPoints.length) {
41000        $spinnerPoints.eq(spinnerContext.phase).fadeTo(spinnerContext.timeSlot, 1);
41001      } else {
41002        $spinnerPoints.eq(spinnerContext.phase - $spinnerPoints.length).fadeTo(spinnerContext.timeSlot, 0);
41003      }
41004      spinnerContext.phase = (spinnerContext.phase + 1) % ($spinnerPoints.length * 2);
41005    }, spinnerContext.timeSlot);
41006  };
41007
41008  /**
41009   * Rewind the image analysis to start from the first entry.
41010   */
41011  JustifiedGallery.prototype.rewind = function () {
41012    this.lastFetchedEntry = null;
41013    this.lastAnalyzedIndex = -1;
41014    this.offY = this.border;
41015    this.rows = 0;
41016    this.clearBuildingRow();
41017  };
41018
41019  /**
41020   * @returns {String} `settings.selector` rejecting spinner element
41021   */
41022  JustifiedGallery.prototype.getSelectorWithoutSpinner = function () {
41023    return this.settings.selector + ', div:not(.jg-spinner)';
41024  };
41025
41026  /**
41027   * @returns {Array} all entries matched by `settings.selector`
41028   */
41029  JustifiedGallery.prototype.getAllEntries = function () {
41030    var selector = this.getSelectorWithoutSpinner();
41031    return this.$gallery.children(selector).toArray();
41032  };
41033
41034  /**
41035   * Update the entries searching it from the justified gallery HTML element
41036   *
41037   * @param norewind if norewind only the new entries will be changed (i.e. randomized, sorted or filtered)
41038   * @returns {boolean} true if some entries has been founded
41039   */
41040  JustifiedGallery.prototype.updateEntries = function (norewind) {
41041    var newEntries;
41042
41043    if (norewind && this.lastFetchedEntry != null) {
41044      var selector = this.getSelectorWithoutSpinner();
41045      newEntries = $(this.lastFetchedEntry).nextAll(selector).toArray();
41046    } else {
41047      this.entries = [];
41048      newEntries = this.getAllEntries();
41049    }
41050
41051    if (newEntries.length > 0) {
41052
41053      // Sort or randomize
41054      if ($.isFunction(this.settings.sort)) {
41055        newEntries = this.sortArray(newEntries);
41056      } else if (this.settings.randomize) {
41057        newEntries = this.shuffleArray(newEntries);
41058      }
41059      this.lastFetchedEntry = newEntries[newEntries.length - 1];
41060
41061      // Filter
41062      if (this.settings.filter) {
41063        newEntries = this.filterArray(newEntries);
41064      } else {
41065        this.resetFilters(newEntries);
41066      }
41067
41068    }
41069
41070    this.entries = this.entries.concat(newEntries);
41071    return true;
41072  };
41073
41074  /**
41075   * Apply the entries order to the DOM, iterating the entries and appending the images
41076   *
41077   * @param entries the entries that has been modified and that must be re-ordered in the DOM
41078   */
41079  JustifiedGallery.prototype.insertToGallery = function (entries) {
41080    var that = this;
41081    $.each(entries, function () {
41082      $(this).appendTo(that.$gallery);
41083    });
41084  };
41085
41086  /**
41087   * Shuffle the array using the Fisher-Yates shuffle algorithm
41088   *
41089   * @param a the array to shuffle
41090   * @return the shuffled array
41091   */
41092  JustifiedGallery.prototype.shuffleArray = function (a) {
41093    var i, j, temp;
41094    for (i = a.length - 1; i > 0; i--) {
41095      j = Math.floor(Math.random() * (i + 1));
41096      temp = a[i];
41097      a[i] = a[j];
41098      a[j] = temp;
41099    }
41100    this.insertToGallery(a);
41101    return a;
41102  };
41103
41104  /**
41105   * Sort the array using settings.comparator as comparator
41106   *
41107   * @param a the array to sort (it is sorted)
41108   * @return the sorted array
41109   */
41110  JustifiedGallery.prototype.sortArray = function (a) {
41111    a.sort(this.settings.sort);
41112    this.insertToGallery(a);
41113    return a;
41114  };
41115
41116  /**
41117   * Reset the filters removing the 'jg-filtered' class from all the entries
41118   *
41119   * @param a the array to reset
41120   */
41121  JustifiedGallery.prototype.resetFilters = function (a) {
41122    for (var i = 0; i < a.length; i++) $(a[i]).removeClass('jg-filtered');
41123  };
41124
41125  /**
41126   * Filter the entries considering theirs classes (if a string has been passed) or using a function for filtering.
41127   *
41128   * @param a the array to filter
41129   * @return the filtered array
41130   */
41131  JustifiedGallery.prototype.filterArray = function (a) {
41132    var settings = this.settings;
41133    if ($.type(settings.filter) === 'string') {
41134      // Filter only keeping the entries passed in the string
41135      return a.filter(function (el) {
41136        var $el = $(el);
41137        if ($el.is(settings.filter)) {
41138          $el.removeClass('jg-filtered');
41139          return true;
41140        } else {
41141          $el.addClass('jg-filtered').removeClass('jg-visible');
41142          return false;
41143        }
41144      });
41145    } else if ($.isFunction(settings.filter)) {
41146      // Filter using the passed function
41147      var filteredArr = a.filter(settings.filter);
41148      for (var i = 0; i < a.length; i++) {
41149        if (filteredArr.indexOf(a[i]) === -1) {
41150          $(a[i]).addClass('jg-filtered').removeClass('jg-visible');
41151        } else {
41152          $(a[i]).removeClass('jg-filtered');
41153        }
41154      }
41155      return filteredArr;
41156    }
41157  };
41158
41159  /**
41160   * Revert the image src to the default value.
41161   */
41162  JustifiedGallery.prototype.resetImgSrc = function ($img) {
41163    if ($img.data('jg.originalSrcLoc') === 'src') {
41164      $img.attr('src', $img.data('jg.originalSrc'));
41165    } else {
41166      $img.attr('src', '');
41167    }
41168  };
41169
41170  /**
41171   * Destroy the Justified Gallery instance.
41172   *
41173   * It clears all the css properties added in the style attributes. We doesn't backup the original
41174   * values for those css attributes, because it costs (performance) and because in general one
41175   * shouldn't use the style attribute for an uniform set of images (where we suppose the use of
41176   * classes). Creating a backup is also difficult because JG could be called multiple times and
41177   * with different style attributes.
41178   */
41179  JustifiedGallery.prototype.destroy = function () {
41180    clearInterval(this.checkWidthIntervalId);
41181    this.stopImgAnalyzerStarter();
41182
41183    // Get fresh entries list since filtered entries are absent in `this.entries`
41184    $.each(this.getAllEntries(), $.proxy(function (_, entry) {
41185      var $entry = $(entry);
41186
41187      // Reset entry style
41188      $entry.css('width', '');
41189      $entry.css('height', '');
41190      $entry.css('top', '');
41191      $entry.css('left', '');
41192      $entry.data('jg.loaded', undefined);
41193      $entry.removeClass('jg-entry jg-filtered jg-entry-visible');
41194
41195      // Reset image style
41196      var $img = this.imgFromEntry($entry);
41197      if ($img) {
41198        $img.css('width', '');
41199        $img.css('height', '');
41200        $img.css('margin-left', '');
41201        $img.css('margin-top', '');
41202        this.resetImgSrc($img);
41203        $img.data('jg.originalSrc', undefined);
41204        $img.data('jg.originalSrcLoc', undefined);
41205        $img.data('jg.src', undefined);
41206      }
41207
41208      // Remove caption
41209      this.removeCaptionEventsHandlers($entry);
41210      var $caption = this.captionFromEntry($entry);
41211      if ($entry.data('jg.createdCaption')) {
41212        // remove also the caption element (if created by jg)
41213        $entry.data('jg.createdCaption', undefined);
41214        if ($caption !== null) $caption.remove();
41215      } else {
41216        if ($caption !== null) $caption.fadeTo(0, 1);
41217      }
41218
41219    }, this));
41220
41221    this.$gallery.css('height', '');
41222    this.$gallery.removeClass('justified-gallery');
41223    this.$gallery.data('jg.controller', undefined);
41224    this.settings.triggerEvent.call(this, 'jg.destroy');
41225  };
41226
41227  /**
41228   * Analyze the images and builds the rows. It returns if it found an image that is not loaded.
41229   *
41230   * @param isForResize if the image analyzer is called for resizing or not, to call a different callback at the end
41231   */
41232  JustifiedGallery.prototype.analyzeImages = function (isForResize) {
41233    for (var i = this.lastAnalyzedIndex + 1; i < this.entries.length; i++) {
41234      var $entry = $(this.entries[i]);
41235      if ($entry.data('jg.loaded') === true || $entry.data('jg.loaded') === 'skipped') {
41236        var availableWidth = this.galleryWidth - 2 * this.border - (
41237          (this.buildingRow.entriesBuff.length - 1) * this.settings.margins);
41238        var imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height');
41239
41240        this.buildingRow.entriesBuff.push($entry);
41241        this.buildingRow.aspectRatio += imgAspectRatio;
41242        this.buildingRow.width += imgAspectRatio * this.settings.rowHeight;
41243        this.lastAnalyzedIndex = i;
41244
41245        if (availableWidth / (this.buildingRow.aspectRatio + imgAspectRatio) < this.settings.rowHeight) {
41246          this.flushRow(false, this.settings.maxRowsCount > 0 && this.rows === this.settings.maxRowsCount);
41247
41248          if (++this.yield.flushed >= this.yield.every) {
41249            this.startImgAnalyzer(isForResize);
41250            return;
41251          }
41252        }
41253      } else if ($entry.data('jg.loaded') !== 'error') {
41254        return;
41255      }
41256    }
41257
41258    // Last row flush (the row is not full)
41259    if (this.buildingRow.entriesBuff.length > 0) {
41260      this.flushRow(true, this.settings.maxRowsCount > 0 && this.rows === this.settings.maxRowsCount);
41261    }
41262
41263    if (this.isSpinnerActive()) {
41264      this.stopLoadingSpinnerAnimation();
41265    }
41266
41267    /* Stop, if there is, the timeout to start the analyzeImages.
41268     This is because an image can be set loaded, and the timeout can be set,
41269     but this image can be analyzed yet.
41270     */
41271    this.stopImgAnalyzerStarter();
41272
41273    this.setGalleryFinalHeight(this.galleryHeightToSet);
41274
41275    //On complete callback
41276    this.settings.triggerEvent.call(this, isForResize ? 'jg.resize' : 'jg.complete');
41277  };
41278
41279  /**
41280   * Stops any ImgAnalyzer starter (that has an assigned timeout)
41281   */
41282  JustifiedGallery.prototype.stopImgAnalyzerStarter = function () {
41283    this.yield.flushed = 0;
41284    if (this.imgAnalyzerTimeout !== null) {
41285      clearTimeout(this.imgAnalyzerTimeout);
41286      this.imgAnalyzerTimeout = null;
41287    }
41288  };
41289
41290  /**
41291   * Starts the image analyzer. It is not immediately called to let the browser to update the view
41292   *
41293   * @param isForResize specifies if the image analyzer must be called for resizing or not
41294   */
41295  JustifiedGallery.prototype.startImgAnalyzer = function (isForResize) {
41296    var that = this;
41297    this.stopImgAnalyzerStarter();
41298    this.imgAnalyzerTimeout = setTimeout(function () {
41299      that.analyzeImages(isForResize);
41300    }, 0.001); // we can't start it immediately due to a IE different behaviour
41301  };
41302
41303  /**
41304   * Checks if the image is loaded or not using another image object. We cannot use the 'complete' image property,
41305   * because some browsers, with a 404 set complete = true.
41306   *
41307   * @param imageSrc the image src to load
41308   * @param onLoad callback that is called when the image has been loaded
41309   * @param onError callback that is called in case of an error
41310   */
41311  JustifiedGallery.prototype.onImageEvent = function (imageSrc, onLoad, onError) {
41312    if (!onLoad && !onError) return;
41313
41314    var memImage = new Image();
41315    var $memImage = $(memImage);
41316    if (onLoad) {
41317      $memImage.one('load', function () {
41318        $memImage.off('load error');
41319        onLoad(memImage);
41320      });
41321    }
41322    if (onError) {
41323      $memImage.one('error', function () {
41324        $memImage.off('load error');
41325        onError(memImage);
41326      });
41327    }
41328    memImage.src = imageSrc;
41329  };
41330
41331  /**
41332   * Init of Justified Gallery controlled
41333   * It analyzes all the entries starting theirs loading and calling the image analyzer (that works with loaded images)
41334   */
41335  JustifiedGallery.prototype.init = function () {
41336    var imagesToLoad = false, skippedImages = false, that = this;
41337    $.each(this.entries, function (index, entry) {
41338      var $entry = $(entry);
41339      var $image = that.imgFromEntry($entry);
41340
41341      $entry.addClass('jg-entry');
41342
41343      if ($entry.data('jg.loaded') !== true && $entry.data('jg.loaded') !== 'skipped') {
41344
41345        // Link Rel global overwrite
41346        if (that.settings.rel !== null) $entry.attr('rel', that.settings.rel);
41347
41348        // Link Target global overwrite
41349        if (that.settings.target !== null) $entry.attr('target', that.settings.target);
41350
41351        if ($image !== null) {
41352
41353          // Image src
41354          var imageSrc = that.extractImgSrcFromImage($image);
41355
41356          /* If we have the height and the width, we don't wait that the image is loaded,
41357             but we start directly with the justification */
41358          if (that.settings.waitThumbnailsLoad === false || !imageSrc) {
41359            var width = parseFloat($image.attr('width'));
41360            var height = parseFloat($image.attr('height'));
41361            if ($image.prop('tagName') === 'svg') {
41362              width = parseFloat($image[0].getBBox().width);
41363              height = parseFloat($image[0].getBBox().height);
41364            }
41365            if (!isNaN(width) && !isNaN(height)) {
41366              $entry.data('jg.width', width);
41367              $entry.data('jg.height', height);
41368              $entry.data('jg.loaded', 'skipped');
41369              skippedImages = true;
41370              that.startImgAnalyzer(false);
41371              return true; // continue
41372            }
41373          }
41374
41375          $entry.data('jg.loaded', false);
41376          imagesToLoad = true;
41377
41378          // Spinner start
41379          if (!that.isSpinnerActive()) that.startLoadingSpinnerAnimation();
41380
41381          that.onImageEvent(imageSrc, function (loadImg) { // image loaded
41382            $entry.data('jg.width', loadImg.width);
41383            $entry.data('jg.height', loadImg.height);
41384            $entry.data('jg.loaded', true);
41385            that.startImgAnalyzer(false);
41386          }, function () { // image load error
41387            $entry.data('jg.loaded', 'error');
41388            that.startImgAnalyzer(false);
41389          });
41390
41391        } else {
41392          $entry.data('jg.loaded', true);
41393          $entry.data('jg.width', $entry.width() | parseFloat($entry.css('width')) | 1);
41394          $entry.data('jg.height', $entry.height() | parseFloat($entry.css('height')) | 1);
41395        }
41396
41397      }
41398
41399    });
41400
41401    if (!imagesToLoad && !skippedImages) this.startImgAnalyzer(false);
41402    this.checkWidth();
41403  };
41404
41405  /**
41406   * Checks that it is a valid number. If a string is passed it is converted to a number
41407   *
41408   * @param settingContainer the object that contains the setting (to allow the conversion)
41409   * @param settingName the setting name
41410   */
41411  JustifiedGallery.prototype.checkOrConvertNumber = function (settingContainer, settingName) {
41412    if ($.type(settingContainer[settingName]) === 'string') {
41413      settingContainer[settingName] = parseFloat(settingContainer[settingName]);
41414    }
41415
41416    if ($.type(settingContainer[settingName]) === 'number') {
41417      if (isNaN(settingContainer[settingName])) throw 'invalid number for ' + settingName;
41418    } else {
41419      throw settingName + ' must be a number';
41420    }
41421  };
41422
41423  /**
41424   * Checks the sizeRangeSuffixes and, if necessary, converts
41425   * its keys from string (e.g. old settings with 'lt100') to int.
41426   */
41427  JustifiedGallery.prototype.checkSizeRangesSuffixes = function () {
41428    if ($.type(this.settings.sizeRangeSuffixes) !== 'object') {
41429      throw 'sizeRangeSuffixes must be defined and must be an object';
41430    }
41431
41432    var suffixRanges = [];
41433    for (var rangeIdx in this.settings.sizeRangeSuffixes) {
41434      if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(rangeIdx);
41435    }
41436
41437    var newSizeRngSuffixes = { 0: '' };
41438    for (var i = 0; i < suffixRanges.length; i++) {
41439      if ($.type(suffixRanges[i]) === 'string') {
41440        try {
41441          var numIdx = parseInt(suffixRanges[i].replace(/^[a-z]+/, ''), 10);
41442          newSizeRngSuffixes[numIdx] = this.settings.sizeRangeSuffixes[suffixRanges[i]];
41443        } catch (e) {
41444          throw 'sizeRangeSuffixes keys must contains correct numbers (' + e + ')';
41445        }
41446      } else {
41447        newSizeRngSuffixes[suffixRanges[i]] = this.settings.sizeRangeSuffixes[suffixRanges[i]];
41448      }
41449    }
41450
41451    this.settings.sizeRangeSuffixes = newSizeRngSuffixes;
41452  };
41453
41454  /**
41455   * check and convert the maxRowHeight setting
41456   * requires rowHeight to be already set
41457   * TODO: should be always called when only rowHeight is changed
41458   * @return number or null
41459   */
41460  JustifiedGallery.prototype.retrieveMaxRowHeight = function () {
41461    var newMaxRowHeight = null;
41462    var rowHeight = this.settings.rowHeight;
41463
41464    if ($.type(this.settings.maxRowHeight) === 'string') {
41465      if (this.settings.maxRowHeight.match(/^[0-9]+%$/)) {
41466        newMaxRowHeight = rowHeight * parseFloat(this.settings.maxRowHeight.match(/^([0-9]+)%$/)[1]) / 100;
41467      } else {
41468        newMaxRowHeight = parseFloat(this.settings.maxRowHeight);
41469      }
41470    } else if ($.type(this.settings.maxRowHeight) === 'number') {
41471      newMaxRowHeight = this.settings.maxRowHeight;
41472    } else if (this.settings.maxRowHeight === false || this.settings.maxRowHeight == null) {
41473      return null;
41474    } else {
41475      throw 'maxRowHeight must be a number or a percentage';
41476    }
41477
41478    // check if the converted value is not a number
41479    if (isNaN(newMaxRowHeight)) throw 'invalid number for maxRowHeight';
41480
41481    // check values, maxRowHeight must be >= rowHeight
41482    if (newMaxRowHeight < rowHeight) newMaxRowHeight = rowHeight;
41483
41484    return newMaxRowHeight;
41485  };
41486
41487  /**
41488   * Checks the settings
41489   */
41490  JustifiedGallery.prototype.checkSettings = function () {
41491    this.checkSizeRangesSuffixes();
41492
41493    this.checkOrConvertNumber(this.settings, 'rowHeight');
41494    this.checkOrConvertNumber(this.settings, 'margins');
41495    this.checkOrConvertNumber(this.settings, 'border');
41496    this.checkOrConvertNumber(this.settings, 'maxRowsCount');
41497
41498    var lastRowModes = [
41499      'justify',
41500      'nojustify',
41501      'left',
41502      'center',
41503      'right',
41504      'hide'
41505    ];
41506    if (lastRowModes.indexOf(this.settings.lastRow) === -1) {
41507      throw 'lastRow must be one of: ' + lastRowModes.join(', ');
41508    }
41509
41510    this.checkOrConvertNumber(this.settings, 'justifyThreshold');
41511    if (this.settings.justifyThreshold < 0 || this.settings.justifyThreshold > 1) {
41512      throw 'justifyThreshold must be in the interval [0,1]';
41513    }
41514    if ($.type(this.settings.cssAnimation) !== 'boolean') {
41515      throw 'cssAnimation must be a boolean';
41516    }
41517
41518    if ($.type(this.settings.captions) !== 'boolean') throw 'captions must be a boolean';
41519    this.checkOrConvertNumber(this.settings.captionSettings, 'animationDuration');
41520
41521    this.checkOrConvertNumber(this.settings.captionSettings, 'visibleOpacity');
41522    if (this.settings.captionSettings.visibleOpacity < 0 ||
41523      this.settings.captionSettings.visibleOpacity > 1) {
41524      throw 'captionSettings.visibleOpacity must be in the interval [0, 1]';
41525    }
41526
41527    this.checkOrConvertNumber(this.settings.captionSettings, 'nonVisibleOpacity');
41528    if (this.settings.captionSettings.nonVisibleOpacity < 0 ||
41529      this.settings.captionSettings.nonVisibleOpacity > 1) {
41530      throw 'captionSettings.nonVisibleOpacity must be in the interval [0, 1]';
41531    }
41532
41533    this.checkOrConvertNumber(this.settings, 'imagesAnimationDuration');
41534    this.checkOrConvertNumber(this.settings, 'refreshTime');
41535    this.checkOrConvertNumber(this.settings, 'refreshSensitivity');
41536    if ($.type(this.settings.randomize) !== 'boolean') throw 'randomize must be a boolean';
41537    if ($.type(this.settings.selector) !== 'string') throw 'selector must be a string';
41538
41539    if (this.settings.sort !== false && !$.isFunction(this.settings.sort)) {
41540      throw 'sort must be false or a comparison function';
41541    }
41542
41543    if (this.settings.filter !== false && !$.isFunction(this.settings.filter) &&
41544      $.type(this.settings.filter) !== 'string') {
41545      throw 'filter must be false, a string or a filter function';
41546    }
41547  };
41548
41549  /**
41550   * It brings all the indexes from the sizeRangeSuffixes and it orders them. They are then sorted and returned.
41551   * @returns {Array} sorted suffix ranges
41552   */
41553  JustifiedGallery.prototype.retrieveSuffixRanges = function () {
41554    var suffixRanges = [];
41555    for (var rangeIdx in this.settings.sizeRangeSuffixes) {
41556      if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(parseInt(rangeIdx, 10));
41557    }
41558    suffixRanges.sort(function (a, b) { return a > b ? 1 : a < b ? -1 : 0; });
41559    return suffixRanges;
41560  };
41561
41562  /**
41563   * Update the existing settings only changing some of them
41564   *
41565   * @param newSettings the new settings (or a subgroup of them)
41566   */
41567  JustifiedGallery.prototype.updateSettings = function (newSettings) {
41568    // In this case Justified Gallery has been called again changing only some options
41569    this.settings = $.extend({}, this.settings, newSettings);
41570    this.checkSettings();
41571
41572    // As reported in the settings: negative value = same as margins, 0 = disabled
41573    this.border = this.settings.border >= 0 ? this.settings.border : this.settings.margins;
41574
41575    this.maxRowHeight = this.retrieveMaxRowHeight();
41576    this.suffixRanges = this.retrieveSuffixRanges();
41577  };
41578
41579  JustifiedGallery.prototype.defaults = {
41580    sizeRangeSuffixes: {}, /* e.g. Flickr configuration
41581        {
41582          100: '_t',  // used when longest is less than 100px
41583          240: '_m',  // used when longest is between 101px and 240px
41584          320: '_n',  // ...
41585          500: '',
41586          640: '_z',
41587          1024: '_b'  // used as else case because it is the last
41588        }
41589    */
41590    thumbnailPath: undefined, /* If defined, sizeRangeSuffixes is not used, and this function is used to determine the
41591    path relative to a specific thumbnail size. The function should accept respectively three arguments:
41592    current path, width and height */
41593    rowHeight: 120, // required? required to be > 0?
41594    maxRowHeight: false, // false or negative value to deactivate. Positive number to express the value in pixels,
41595    // A string '[0-9]+%' to express in percentage (e.g. 300% means that the row height
41596    // can't exceed 3 * rowHeight)
41597    maxRowsCount: 0, // maximum number of rows to be displayed (0 = disabled)
41598    margins: 1,
41599    border: -1, // negative value = same as margins, 0 = disabled, any other value to set the border
41600
41601    lastRow: 'nojustify', // … which is the same as 'left', or can be 'justify', 'center', 'right' or 'hide'
41602
41603    justifyThreshold: 0.90, /* if row width / available space > 0.90 it will be always justified
41604                             * (i.e. lastRow setting is not considered) */
41605    waitThumbnailsLoad: true,
41606    captions: true,
41607    cssAnimation: true,
41608    imagesAnimationDuration: 500, // ignored with css animations
41609    captionSettings: { // ignored with css animations
41610      animationDuration: 500,
41611      visibleOpacity: 0.7,
41612      nonVisibleOpacity: 0.0
41613    },
41614    rel: null, // rewrite the rel of each analyzed links
41615    target: null, // rewrite the target of all links
41616    extension: /\.[^.\\/]+$/, // regexp to capture the extension of an image
41617    refreshTime: 200, // time interval (in ms) to check if the page changes its width
41618    refreshSensitivity: 0, // change in width allowed (in px) without re-building the gallery
41619    randomize: false,
41620    rtl: false, // right-to-left mode
41621    sort: false, /*
41622      - false: to do not sort
41623      - function: to sort them using the function as comparator (see Array.prototype.sort())
41624    */
41625    filter: false, /*
41626      - false, null or undefined: for a disabled filter
41627      - a string: an entry is kept if entry.is(filter string) returns true
41628                  see jQuery's .is() function for further information
41629      - a function: invoked with arguments (entry, index, array). Return true to keep the entry, false otherwise.
41630                    It follows the specifications of the Array.prototype.filter() function of JavaScript.
41631    */
41632    selector: 'a', // The selector that is used to know what are the entries of the gallery
41633    imgSelector: '> img, > a > img, > svg, > a > svg', // The selector that is used to know what are the images of each entry
41634    triggerEvent: function (event) { // This is called to trigger events, the default behavior is to call $.trigger
41635      this.$gallery.trigger(event);  // Consider that 'this' is this set to the JustifiedGallery object, so it can
41636    }                                // access to fields such as $gallery, useful to trigger events with jQuery.
41637  };
41638
41639
41640  /**
41641   * Justified Gallery plugin for jQuery
41642   *
41643   * Events
41644   *  - jg.complete : called when all the gallery has been created
41645   *  - jg.resize : called when the gallery has been resized
41646   *  - jg.rowflush : when a new row appears
41647   *
41648   * @param arg the action (or the settings) passed when the plugin is called
41649   * @returns {*} the object itself
41650   */
41651  $.fn.justifiedGallery = function (arg) {
41652    return this.each(function (index, gallery) {
41653
41654      var $gallery = $(gallery);
41655      $gallery.addClass('justified-gallery');
41656
41657      var controller = $gallery.data('jg.controller');
41658      if (typeof controller === 'undefined') {
41659        // Create controller and assign it to the object data
41660        if (typeof arg !== 'undefined' && arg !== null && $.type(arg) !== 'object') {
41661          if (arg === 'destroy') return; // Just a call to an unexisting object
41662          throw 'The argument must be an object';
41663        }
41664        controller = new JustifiedGallery($gallery, $.extend({}, JustifiedGallery.prototype.defaults, arg));
41665        $gallery.data('jg.controller', controller);
41666      } else if (arg === 'norewind') {
41667        // In this case we don't rewind: we analyze only the latest images (e.g. to complete the last unfinished row
41668        // ... left to be more readable
41669      } else if (arg === 'destroy') {
41670        controller.destroy();
41671        return;
41672      } else {
41673        // In this case Justified Gallery has been called again changing only some options
41674        controller.updateSettings(arg);
41675        controller.rewind();
41676      }
41677
41678      // Update the entries list
41679      if (!controller.updateEntries(arg === 'norewind')) return;
41680
41681      // Init justified gallery
41682      controller.init();
41683
41684    });
41685  };
41686
41687}));
41688
41689/*!
41690* Customized version of iScroll.js 0.0.1
41691* It fixes bugs affecting its integration with fullpage.js
41692*/
41693/*! iScroll v5.2.0 ~ (c) 2008-2016 Matteo Spinelli ~ http://cubiq.org/license */
41694(function (window, document, Math) {
41695var rAF = window.requestAnimationFrame  ||
41696    window.webkitRequestAnimationFrame  ||
41697    window.mozRequestAnimationFrame     ||
41698    window.oRequestAnimationFrame       ||
41699    window.msRequestAnimationFrame      ||
41700    function (callback) { window.setTimeout(callback, 1000 / 60); };
41701
41702var utils = (function () {
41703    var me = {};
41704
41705    var _elementStyle = document.createElement('div').style;
41706    var _vendor = (function () {
41707        var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'],
41708            transform,
41709            i = 0,
41710            l = vendors.length;
41711
41712        for ( ; i < l; i++ ) {
41713            transform = vendors[i] + 'ransform';
41714            if ( transform in _elementStyle ) return vendors[i].substr(0, vendors[i].length-1);
41715        }
41716
41717        return false;
vendor: 5,154 bytes, lines 41718-41870
41718    })();
41719
41720    function _prefixStyle (style) {
41721        if ( _vendor === false ) return false;
41722        if ( _vendor === '' ) return style;
41723        return _vendor + style.charAt(0).toUpperCase() + style.substr(1);
41724    }
41725
41726    me.getTime = Date.now || function getTime () { return new Date().getTime(); };
41727
41728    me.extend = function (target, obj) {
41729        for ( var i in obj ) {
41730            target[i] = obj[i];
41731        }
41732    };
41733
41734    me.addEvent = function (el, type, fn, capture) {
41735        el.addEventListener(type, fn, !!capture);
41736    };
41737
41738    me.removeEvent = function (el, type, fn, capture) {
41739        el.removeEventListener(type, fn, !!capture);
41740    };
41741
41742    me.prefixPointerEvent = function (pointerEvent) {
41743        return window.MSPointerEvent ?
41744            'MSPointer' + pointerEvent.charAt(7).toUpperCase() + pointerEvent.substr(8):
41745            pointerEvent;
41746    };
41747
41748    me.momentum = function (current, start, time, lowerMargin, wrapperSize, deceleration) {
41749        var distance = current - start,
41750            speed = Math.abs(distance) / time,
41751            destination,
41752            duration;
41753
41754        deceleration = deceleration === undefined ? 0.0006 : deceleration;
41755
41756        destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 );
41757        duration = speed / deceleration;
41758
41759        if ( destination < lowerMargin ) {
41760            destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin;
41761            distance = Math.abs(destination - current);
41762            duration = distance / speed;
41763        } else if ( destination > 0 ) {
41764            destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0;
41765            distance = Math.abs(current) + destination;
41766            duration = distance / speed;
41767        }
41768
41769        return {
41770            destination: Math.round(destination),
41771            duration: duration
41772        };
41773    };
41774
41775    var _transform = _prefixStyle('transform');
41776
41777    me.extend(me, {
41778        hasTransform: _transform !== false,
41779        hasPerspective: _prefixStyle('perspective') in _elementStyle,
41780        hasTouch: 'ontouchstart' in window,
41781        hasPointer: !!(window.PointerEvent || window.MSPointerEvent), // IE10 is prefixed
41782        hasTransition: _prefixStyle('transition') in _elementStyle
41783    });
41784
41785    /*
41786    This should find all Android browsers lower than build 535.19 (both stock browser and webview)
41787    - galaxy S2 is ok
41788    - 2.3.6 : `AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1`
41789    - 4.0.4 : `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
41790   - galaxy S3 is badAndroid (stock brower, webview)
41791     `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
41792   - galaxy S4 is badAndroid (stock brower, webview)
41793     `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
41794   - galaxy S5 is OK
41795     `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`
41796   - galaxy S6 is OK
41797     `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`
41798  */
41799    me.isBadAndroid = (function() {
41800        var appVersion = window.navigator.appVersion;
41801        // Android browser is not a chrome browser.
41802        if (/Android/.test(appVersion) && !(/Chrome\/\d/.test(appVersion))) {
41803            var safariVersion = appVersion.match(/Safari\/(\d+.\d)/);
41804            if(safariVersion && typeof safariVersion === "object" && safariVersion.length >= 2) {
41805                return parseFloat(safariVersion[1]) < 535.19;
41806            } else {
41807                return true;
41808            }
41809        } else {
41810            return false;
41811        }
41812    })();
41813
41814    me.extend(me.style = {}, {
41815        transform: _transform,
41816        transitionTimingFunction: _prefixStyle('transitionTimingFunction'),
41817        transitionDuration: _prefixStyle('transitionDuration'),
41818        transitionDelay: _prefixStyle('transitionDelay'),
41819        transformOrigin: _prefixStyle('transformOrigin')
41820    });
41821
41822    me.hasClass = function (e, c) {
41823        var re = new RegExp("(^|\\s)" + c + "(\\s|$)");
41824        return re.test(e.className);
41825    };
41826
41827    me.addClass = function (e, c) {
41828        if ( me.hasClass(e, c) ) {
41829            return;
41830        }
41831
41832        var newclass = e.className.split(' ');
41833        newclass.push(c);
41834        e.className = newclass.join(' ');
41835    };
41836
41837    me.removeClass = function (e, c) {
41838        if ( !me.hasClass(e, c) ) {
41839            return;
41840        }
41841
41842        var re = new RegExp("(^|\\s)" + c + "(\\s|$)", 'g');
41843        e.className = e.className.replace(re, ' ');
41844    };
41845
41846    me.offset = function (el) {
41847        var left = -el.offsetLeft,
41848            top = -el.offsetTop;
41849
41850        // jshint -W084
41851        while (el = el.offsetParent) {
41852            left -= el.offsetLeft;
41853            top -= el.offsetTop;
41854        }
41855        // jshint +W084
41856
41857        return {
41858            left: left,
41859            top: top
41860        };
41861    };
41862
41863    me.preventDefaultException = function (el, exceptions) {
41864        for ( var i in exceptions ) {
41865            if ( exceptions[i].test(el[i]) ) {
41866                return true;
41867            }
41868        }
41869
41870        return false;
vendor: 5,660 bytes, lines 41871-42036
41871    };
41872
41873    me.extend(me.eventType = {}, {
41874        touchstart: 1,
41875        touchmove: 1,
41876        touchend: 1,
41877
41878        mousedown: 2,
41879        mousemove: 2,
41880        mouseup: 2,
41881
41882        pointerdown: 3,
41883        pointermove: 3,
41884        pointerup: 3,
41885
41886        MSPointerDown: 3,
41887        MSPointerMove: 3,
41888        MSPointerUp: 3
41889    });
41890
41891    me.extend(me.ease = {}, {
41892        quadratic: {
41893            style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
41894            fn: function (k) {
41895                return k * ( 2 - k );
41896            }
41897        },
41898        circular: {
41899            style: 'cubic-bezier(0.1, 0.57, 0.1, 1)',   // Not properly "circular" but this looks better, it should be (0.075, 0.82, 0.165, 1)
41900            fn: function (k) {
41901                return Math.sqrt( 1 - ( --k * k ) );
41902            }
41903        },
41904        back: {
41905            style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)',
41906            fn: function (k) {
41907                var b = 4;
41908                return ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1;
41909            }
41910        },
41911        bounce: {
41912            style: '',
41913            fn: function (k) {
41914                if ( ( k /= 1 ) < ( 1 / 2.75 ) ) {
41915                    return 7.5625 * k * k;
41916                } else if ( k < ( 2 / 2.75 ) ) {
41917                    return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75;
41918                } else if ( k < ( 2.5 / 2.75 ) ) {
41919                    return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375;
41920                } else {
41921                    return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375;
41922                }
41923            }
41924        },
41925        elastic: {
41926            style: '',
41927            fn: function (k) {
41928                var f = 0.22,
41929                    e = 0.4;
41930
41931                if ( k === 0 ) { return 0; }
41932                if ( k == 1 ) { return 1; }
41933
41934                return ( e * Math.pow( 2, - 10 * k ) * Math.sin( ( k - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 );
41935            }
41936        }
41937    });
41938
41939    me.tap = function (e, eventName) {
41940        var ev = document.createEvent('Event');
41941        ev.initEvent(eventName, true, true);
41942        ev.pageX = e.pageX;
41943        ev.pageY = e.pageY;
41944        e.target.dispatchEvent(ev);
41945    };
41946
41947    me.click = function (e) {
41948        var target = e.target,
41949            ev;
41950
41951        if ( !(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName) ) {
41952            // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent
41953            // initMouseEvent is deprecated.
41954            ev = document.createEvent(window.MouseEvent ? 'MouseEvents' : 'Event');
41955            ev.initEvent('click', true, true);
41956            ev.view = e.view || window;
41957            ev.detail = 1;
41958            ev.screenX = target.screenX || 0;
41959            ev.screenY = target.screenY || 0;
41960            ev.clientX = target.clientX || 0;
41961            ev.clientY = target.clientY || 0;
41962            ev.ctrlKey = !!e.ctrlKey;
41963            ev.altKey = !!e.altKey;
41964            ev.shiftKey = !!e.shiftKey;
41965            ev.metaKey = !!e.metaKey;
41966            ev.button = 0;
41967            ev.relatedTarget = null;
41968            ev._constructed = true;
41969            target.dispatchEvent(ev);
41970        }
41971    };
41972
41973    return me;
41974})();
41975function IScroll (el, options) {
41976    this.wrapper = typeof el == 'string' ? document.querySelector(el) : el;
41977    this.scroller = this.wrapper.children[0];
41978    this.scrollerStyle = this.scroller.style;       // cache style for better performance
41979
41980    this.options = {
41981
41982        resizeScrollbars: true,
41983
41984        mouseWheelSpeed: 20,
41985
41986        snapThreshold: 0.334,
41987
41988// INSERT POINT: OPTIONS
41989        disablePointer : !utils.hasPointer,
41990        disableTouch : utils.hasPointer || !utils.hasTouch,
41991        disableMouse : utils.hasPointer || utils.hasTouch,
41992        startX: 0,
41993        startY: 0,
41994        scrollY: true,
41995        directionLockThreshold: 5,
41996        momentum: true,
41997
41998        bounce: true,
41999        bounceTime: 600,
42000        bounceEasing: '',
42001
42002        preventDefault: true,
42003        preventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT|LABEL)$/ },
42004
42005        HWCompositing: true,
42006        useTransition: true,
42007        useTransform: true,
42008        bindToWrapper: typeof window.onmousedown === "undefined"
42009    };
42010
42011    for ( var i in options ) {
42012        this.options[i] = options[i];
42013    }
42014
42015    // Normalize options
42016    this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : '';
42017
42018    this.options.useTransition = utils.hasTransition && this.options.useTransition;
42019    this.options.useTransform = utils.hasTransform && this.options.useTransform;
42020
42021    this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough;
42022    this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault;
42023
42024    // If you want eventPassthrough I have to lock one of the axes
42025    this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY;
42026    this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX;
42027
42028    // With eventPassthrough we also need lockDirection mechanism
42029    this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough;
42030    this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold;
42031
42032    this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing;
42033
42034    this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling;
42035
42036    if ( this.options.tap === true ) {
vendor: 4,893 bytes, lines 42037-42208
42037        this.options.tap = 'tap';
42038    }
42039
42040    // https://github.com/cubiq/iscroll/issues/1029
42041    if (!this.options.useTransition && !this.options.useTransform) {
42042        if(!(/relative|absolute/i).test(this.scrollerStyle.position)) {
42043            this.scrollerStyle.position = "relative";
42044        }
42045    }
42046
42047    if ( this.options.shrinkScrollbars == 'scale' ) {
42048        this.options.useTransition = false;
42049    }
42050
42051    this.options.invertWheelDirection = this.options.invertWheelDirection ? -1 : 1;
42052
42053// INSERT POINT: NORMALIZATION
42054
42055    // Some defaults
42056    this.x = 0;
42057    this.y = 0;
42058    this.directionX = 0;
42059    this.directionY = 0;
42060    this._events = {};
42061
42062// INSERT POINT: DEFAULTS
42063
42064    this._init();
42065    this.refresh();
42066
42067    this.scrollTo(this.options.startX, this.options.startY);
42068    this.enable();
42069}
42070
42071IScroll.prototype = {
42072    version: '5.2.0',
42073
42074    _init: function () {
42075        this._initEvents();
42076
42077        if ( this.options.scrollbars || this.options.indicators ) {
42078            this._initIndicators();
42079        }
42080
42081        if ( this.options.mouseWheel ) {
42082            this._initWheel();
42083        }
42084
42085        if ( this.options.snap ) {
42086            this._initSnap();
42087        }
42088
42089        if ( this.options.keyBindings ) {
42090            this._initKeys();
42091        }
42092
42093// INSERT POINT: _init
42094
42095    },
42096
42097    destroy: function () {
42098        this._initEvents(true);
42099        clearTimeout(this.resizeTimeout);
42100        this.resizeTimeout = null;
42101        this._execEvent('destroy');
42102    },
42103
42104    _transitionEnd: function (e) {
42105        if ( e.target != this.scroller || !this.isInTransition ) {
42106            return;
42107        }
42108
42109        this._transitionTime();
42110        if ( !this.resetPosition(this.options.bounceTime) ) {
42111            this.isInTransition = false;
42112            this._execEvent('scrollEnd');
42113        }
42114    },
42115
42116    _start: function (e) {
42117        // React to left mouse button only
42118        if ( utils.eventType[e.type] != 1 ) {
42119          // for button property
42120          // http://unixpapa.com/js/mouse.html
42121          var button;
42122        if (!e.which) {
42123          /* IE case */
42124          button = (e.button < 2) ? 0 :
42125                   ((e.button == 4) ? 1 : 2);
42126        } else {
42127          /* All others */
42128          button = e.button;
42129        }
42130            if ( button !== 0 ) {
42131                return;
42132            }
42133        }
42134
42135        if ( !this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated) ) {
42136            return;
42137        }
42138
42139        if ( this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {
42140            e.preventDefault();
42141        }
42142
42143        var point = e.touches ? e.touches[0] : e,
42144            pos;
42145
42146        this.initiated  = utils.eventType[e.type];
42147        this.moved      = false;
42148        this.distX      = 0;
42149        this.distY      = 0;
42150        this.directionX = 0;
42151        this.directionY = 0;
42152        this.directionLocked = 0;
42153
42154        this.startTime = utils.getTime();
42155
42156        if ( this.options.useTransition && this.isInTransition ) {
42157            this._transitionTime();
42158            this.isInTransition = false;
42159            pos = this.getComputedPosition();
42160            this._translate(Math.round(pos.x), Math.round(pos.y));
42161            this._execEvent('scrollEnd');
42162        } else if ( !this.options.useTransition && this.isAnimating ) {
42163            this.isAnimating = false;
42164            this._execEvent('scrollEnd');
42165        }
42166
42167        this.startX    = this.x;
42168        this.startY    = this.y;
42169        this.absStartX = this.x;
42170        this.absStartY = this.y;
42171        this.pointX    = point.pageX;
42172        this.pointY    = point.pageY;
42173
42174        this._execEvent('beforeScrollStart');
42175    },
42176
42177    _move: function (e) {
42178        if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
42179            return;
42180        }
42181
42182        if ( this.options.preventDefault ) {    // increases performance on Android? TODO: check!
42183            e.preventDefault();
42184        }
42185
42186        var point       = e.touches ? e.touches[0] : e,
42187            deltaX      = point.pageX - this.pointX,
42188            deltaY      = point.pageY - this.pointY,
42189            timestamp   = utils.getTime(),
42190            newX, newY,
42191            absDistX, absDistY;
42192
42193        this.pointX     = point.pageX;
42194        this.pointY     = point.pageY;
42195
42196        this.distX      += deltaX;
42197        this.distY      += deltaY;
42198        absDistX        = Math.abs(this.distX);
42199        absDistY        = Math.abs(this.distY);
42200
42201        // We need to move at least 10 pixels for the scrolling to initiate
42202        if ( timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10) ) {
42203            return;
42204        }
42205
42206        // If you are scrolling in one direction lock the other
42207        if ( !this.directionLocked && !this.options.freeScroll ) {
42208            if ( absDistX > absDistY + this.options.directionLockThreshold ) {
vendor: 6,057 bytes, lines 42209-42395
42209                this.directionLocked = 'h';     // lock horizontally
42210            } else if ( absDistY >= absDistX + this.options.directionLockThreshold ) {
42211                this.directionLocked = 'v';     // lock vertically
42212            } else {
42213                this.directionLocked = 'n';     // no lock
42214            }
42215        }
42216
42217        if ( this.directionLocked == 'h' ) {
42218            if ( this.options.eventPassthrough == 'vertical' ) {
42219                e.preventDefault();
42220            } else if ( this.options.eventPassthrough == 'horizontal' ) {
42221                this.initiated = false;
42222                return;
42223            }
42224
42225            deltaY = 0;
42226        } else if ( this.directionLocked == 'v' ) {
42227            if ( this.options.eventPassthrough == 'horizontal' ) {
42228                e.preventDefault();
42229            } else if ( this.options.eventPassthrough == 'vertical' ) {
42230                this.initiated = false;
42231                return;
42232            }
42233
42234            deltaX = 0;
42235        }
42236
42237        deltaX = this.hasHorizontalScroll ? deltaX : 0;
42238        deltaY = this.hasVerticalScroll ? deltaY : 0;
42239
42240        newX = this.x + deltaX;
42241        newY = this.y + deltaY;
42242
42243        // Slow down if outside of the boundaries
42244        if ( newX > 0 || newX < this.maxScrollX ) {
42245            newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX;
42246        }
42247        if ( newY > 0 || newY < this.maxScrollY ) {
42248            newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY;
42249        }
42250
42251        this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0;
42252        this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0;
42253
42254        if ( !this.moved ) {
42255            this._execEvent('scrollStart');
42256        }
42257
42258        this.moved = true;
42259
42260        this._translate(newX, newY);
42261
42262/* REPLACE START: _move */
42263
42264        if ( timestamp - this.startTime > 300 ) {
42265            this.startTime = timestamp;
42266            this.startX = this.x;
42267            this.startY = this.y;
42268        }
42269
42270/* REPLACE END: _move */
42271
42272    },
42273
42274    _end: function (e) {
42275        if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
42276            return;
42277        }
42278
42279        if ( this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {
42280            e.preventDefault();
42281        }
42282
42283        var point = e.changedTouches ? e.changedTouches[0] : e,
42284            momentumX,
42285            momentumY,
42286            duration = utils.getTime() - this.startTime,
42287            newX = Math.round(this.x),
42288            newY = Math.round(this.y),
42289            distanceX = Math.abs(newX - this.startX),
42290            distanceY = Math.abs(newY - this.startY),
42291            time = 0,
42292            easing = '';
42293
42294        this.isInTransition = 0;
42295        this.initiated = 0;
42296        this.endTime = utils.getTime();
42297
42298        // reset if we are outside of the boundaries
42299        if ( this.resetPosition(this.options.bounceTime) ) {
42300            return;
42301        }
42302
42303        this.scrollTo(newX, newY);  // ensures that the last position is rounded
42304
42305        // we scrolled less than 10 pixels
42306        if ( !this.moved ) {
42307            if ( this.options.tap ) {
42308                utils.tap(e, this.options.tap);
42309            }
42310
42311            if ( this.options.click ) {
42312                utils.click(e);
42313            }
42314
42315            this._execEvent('scrollCancel');
42316            return;
42317        }
42318
42319        if ( this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100 ) {
42320            this._execEvent('flick');
42321            return;
42322        }
42323
42324        // start momentum animation if needed
42325        if ( this.options.momentum && duration < 300 ) {
42326            momentumX = this.hasHorizontalScroll ? utils.momentum(this.x, this.startX, duration, this.maxScrollX, this.options.bounce ? this.wrapperWidth : 0, this.options.deceleration) : { destination: newX, duration: 0 };
42327            momentumY = this.hasVerticalScroll ? utils.momentum(this.y, this.startY, duration, this.maxScrollY, this.options.bounce ? this.wrapperHeight : 0, this.options.deceleration) : { destination: newY, duration: 0 };
42328            newX = momentumX.destination;
42329            newY = momentumY.destination;
42330            time = Math.max(momentumX.duration, momentumY.duration);
42331            this.isInTransition = 1;
42332        }
42333
42334
42335        if ( this.options.snap ) {
42336            var snap = this._nearestSnap(newX, newY);
42337            this.currentPage = snap;
42338            time = this.options.snapSpeed || Math.max(
42339                    Math.max(
42340                        Math.min(Math.abs(newX - snap.x), 1000),
42341                        Math.min(Math.abs(newY - snap.y), 1000)
42342                    ), 300);
42343            newX = snap.x;
42344            newY = snap.y;
42345
42346            this.directionX = 0;
42347            this.directionY = 0;
42348            easing = this.options.bounceEasing;
42349        }
42350
42351// INSERT POINT: _end
42352
42353        if ( newX != this.x || newY != this.y ) {
42354            // change easing function when scroller goes out of the boundaries
42355            if ( newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY ) {
42356                easing = utils.ease.quadratic;
42357            }
42358
42359            this.scrollTo(newX, newY, time, easing);
42360            return;
42361        }
42362
42363        this._execEvent('scrollEnd');
42364    },
42365
42366    _resize: function () {
42367        var that = this;
42368
42369        clearTimeout(this.resizeTimeout);
42370
42371        this.resizeTimeout = setTimeout(function () {
42372            that.refresh();
42373        }, this.options.resizePolling);
42374    },
42375
42376    resetPosition: function (time) {
42377        var x = this.x,
42378            y = this.y;
42379
42380        time = time || 0;
42381
42382        if ( !this.hasHorizontalScroll || this.x > 0 ) {
42383            x = 0;
42384        } else if ( this.x < this.maxScrollX ) {
42385            x = this.maxScrollX;
42386        }
42387
42388        if ( !this.hasVerticalScroll || this.y > 0 ) {
42389            y = 0;
42390        } else if ( this.y < this.maxScrollY ) {
42391            y = this.maxScrollY;
42392        }
42393
42394        if ( x == this.x && y == this.y ) {
42395            return false;
vendor: 5,509 bytes, lines 42396-42600
42396        }
42397
42398        this.scrollTo(x, y, time, this.options.bounceEasing);
42399
42400        return true;
42401    },
42402
42403    disable: function () {
42404        this.enabled = false;
42405    },
42406
42407    enable: function () {
42408        this.enabled = true;
42409    },
42410
42411    refresh: function () {
42412        var rf = this.wrapper.offsetHeight;     // Force reflow
42413
42414        this.wrapperWidth   = this.wrapper.clientWidth;
42415        this.wrapperHeight  = this.wrapper.clientHeight;
42416
42417/* REPLACE START: refresh */
42418
42419        this.scrollerWidth  = this.scroller.offsetWidth;
42420        this.scrollerHeight = this.scroller.offsetHeight;
42421
42422        this.maxScrollX     = this.wrapperWidth - this.scrollerWidth;
42423        this.maxScrollY     = this.wrapperHeight - this.scrollerHeight;
42424
42425/* REPLACE END: refresh */
42426
42427        this.hasHorizontalScroll    = this.options.scrollX && this.maxScrollX < 0;
42428        this.hasVerticalScroll      = this.options.scrollY && this.maxScrollY < 0;
42429
42430        if ( !this.hasHorizontalScroll ) {
42431            this.maxScrollX = 0;
42432            this.scrollerWidth = this.wrapperWidth;
42433        }
42434
42435        if ( !this.hasVerticalScroll ) {
42436            this.maxScrollY = 0;
42437            this.scrollerHeight = this.wrapperHeight;
42438        }
42439
42440        this.endTime = 0;
42441        this.directionX = 0;
42442        this.directionY = 0;
42443
42444        this.wrapperOffset = utils.offset(this.wrapper);
42445
42446        this._execEvent('refresh');
42447
42448        this.resetPosition();
42449
42450// INSERT POINT: _refresh
42451
42452    },
42453
42454
42455    on: function (type, fn) {
42456        if ( !this._events[type] ) {
42457            this._events[type] = [];
42458        }
42459
42460        this._events[type].push(fn);
42461    },
42462
42463    off: function (type, fn) {
42464        if ( !this._events[type] ) {
42465            return;
42466        }
42467
42468        var index = this._events[type].indexOf(fn);
42469
42470        if ( index > -1 ) {
42471            this._events[type].splice(index, 1);
42472        }
42473    },
42474
42475    _execEvent: function (type) {
42476        if ( !this._events[type] ) {
42477            return;
42478        }
42479
42480        var i = 0,
42481            l = this._events[type].length;
42482
42483        if ( !l ) {
42484            return;
42485        }
42486
42487        for ( ; i < l; i++ ) {
42488            this._events[type][i].apply(this, [].slice.call(arguments, 1));
42489        }
42490    },
42491
42492    scrollBy: function (x, y, time, easing) {
42493        x = this.x + x;
42494        y = this.y + y;
42495        time = time || 0;
42496
42497        this.scrollTo(x, y, time, easing);
42498    },
42499
42500    scrollTo: function (x, y, time, easing) {
42501        easing = easing || utils.ease.circular;
42502
42503        this.isInTransition = this.options.useTransition && time > 0;
42504        var transitionType = this.options.useTransition && easing.style;
42505        if ( !time || transitionType ) {
42506                if(transitionType) {
42507                    this._transitionTimingFunction(easing.style);
42508                    this._transitionTime(time);
42509                }
42510            this._translate(x, y);
42511        } else {
42512            this._animate(x, y, time, easing.fn);
42513        }
42514    },
42515
42516    scrollToElement: function (el, time, offsetX, offsetY, easing) {
42517        el = el.nodeType ? el : this.scroller.querySelector(el);
42518
42519        if ( !el ) {
42520            return;
42521        }
42522
42523        var pos = utils.offset(el);
42524
42525        pos.left -= this.wrapperOffset.left;
42526        pos.top  -= this.wrapperOffset.top;
42527
42528        // if offsetX/Y are true we center the element to the screen
42529        if ( offsetX === true ) {
42530            offsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2);
42531        }
42532        if ( offsetY === true ) {
42533            offsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2);
42534        }
42535
42536        pos.left -= offsetX || 0;
42537        pos.top  -= offsetY || 0;
42538
42539        pos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left;
42540        pos.top  = pos.top  > 0 ? 0 : pos.top  < this.maxScrollY ? this.maxScrollY : pos.top;
42541
42542        time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x-pos.left), Math.abs(this.y-pos.top)) : time;
42543
42544        this.scrollTo(pos.left, pos.top, time, easing);
42545    },
42546
42547    _transitionTime: function (time) {
42548        if (!this.options.useTransition) {
42549            return;
42550        }
42551        time = time || 0;
42552        var durationProp = utils.style.transitionDuration;
42553        if(!durationProp) {
42554            return;
42555        }
42556
42557        this.scrollerStyle[durationProp] = time + 'ms';
42558
42559        if ( !time && utils.isBadAndroid ) {
42560            this.scrollerStyle[durationProp] = '0.0001ms';
42561            // remove 0.0001ms
42562            var self = this;
42563            rAF(function() {
42564                if(self.scrollerStyle[durationProp] === '0.0001ms') {
42565                    self.scrollerStyle[durationProp] = '0s';
42566                }
42567            });
42568        }
42569
42570
42571        if ( this.indicators ) {
42572            for ( var i = this.indicators.length; i--; ) {
42573                this.indicators[i].transitionTime(time);
42574            }
42575        }
42576
42577
42578// INSERT POINT: _transitionTime
42579
42580    },
42581
42582    _transitionTimingFunction: function (easing) {
42583        this.scrollerStyle[utils.style.transitionTimingFunction] = easing;
42584
42585
42586        if ( this.indicators ) {
42587            for ( var i = this.indicators.length; i--; ) {
42588                this.indicators[i].transitionTimingFunction(easing);
42589            }
42590        }
42591
42592
42593// INSERT POINT: _transitionTimingFunction
42594
42595    },
42596
42597    _translate: function (x, y) {
42598        //Uncode addition
42599        if ( (" " + this.wrapper.className + " ").replace(/[\n\t]/g, " ").indexOf(" no-scrolloverflow ") > -1 )
42600            return false;
vendor: 9,939 bytes, lines 42601-42912
42601
42602        if ( this.options.useTransform ) {
42603
42604/* REPLACE START: _translate */
42605
42606            this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ;
42607
42608/* REPLACE END: _translate */
42609
42610        } else {
42611            x = Math.round(x);
42612            y = Math.round(y);
42613            this.scrollerStyle.left = x + 'px';
42614            this.scrollerStyle.top = y + 'px';
42615        }
42616
42617        this.x = x;
42618        this.y = y;
42619
42620
42621        if ( this.indicators ) {
42622            for ( var i = this.indicators.length; i--; ) {
42623                this.indicators[i].updatePosition();
42624            }
42625        }
42626
42627        //Uncode addition
42628        var uncodevent = new CustomEvent('fp-slide-scroll');
42629        window.dispatchEvent(uncodevent);
42630
42631// INSERT POINT: _translate
42632
42633    },
42634
42635    _initEvents: function (remove) {
42636        var eventType = remove ? utils.removeEvent : utils.addEvent,
42637            target = this.options.bindToWrapper ? this.wrapper : window;
42638
42639        eventType(window, 'orientationchange', this);
42640        eventType(window, 'resize', this);
42641
42642        if ( this.options.click ) {
42643            eventType(this.wrapper, 'click', this, true);
42644        }
42645
42646        if ( !this.options.disableMouse ) {
42647            eventType(this.wrapper, 'mousedown', this);
42648            eventType(target, 'mousemove', this);
42649            eventType(target, 'mousecancel', this);
42650            eventType(target, 'mouseup', this);
42651        }
42652
42653        if ( utils.hasPointer && !this.options.disablePointer ) {
42654            eventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this);
42655            eventType(target, utils.prefixPointerEvent('pointermove'), this);
42656            eventType(target, utils.prefixPointerEvent('pointercancel'), this);
42657            eventType(target, utils.prefixPointerEvent('pointerup'), this);
42658        }
42659
42660        if ( utils.hasTouch && !this.options.disableTouch ) {
42661            eventType(this.wrapper, 'touchstart', this);
42662            eventType(target, 'touchmove', this);
42663            eventType(target, 'touchcancel', this);
42664            eventType(target, 'touchend', this);
42665        }
42666
42667        eventType(this.scroller, 'transitionend', this);
42668        eventType(this.scroller, 'webkitTransitionEnd', this);
42669        eventType(this.scroller, 'oTransitionEnd', this);
42670        eventType(this.scroller, 'MSTransitionEnd', this);
42671    },
42672
42673    getComputedPosition: function () {
42674        var matrix = window.getComputedStyle(this.scroller, null),
42675            x, y;
42676
42677        if ( this.options.useTransform ) {
42678            matrix = matrix[utils.style.transform].split(')')[0].split(', ');
42679            x = +(matrix[12] || matrix[4]);
42680            y = +(matrix[13] || matrix[5]);
42681        } else {
42682            x = +matrix.left.replace(/[^-\d.]/g, '');
42683            y = +matrix.top.replace(/[^-\d.]/g, '');
42684        }
42685
42686        return { x: x, y: y };
42687    },
42688    _initIndicators: function () {
42689        var interactive = this.options.interactiveScrollbars,
42690            customStyle = typeof this.options.scrollbars != 'string',
42691            indicators = [],
42692            indicator;
42693
42694        var that = this;
42695
42696        this.indicators = [];
42697
42698        if ( this.options.scrollbars ) {
42699            // Vertical scrollbar
42700            if ( this.options.scrollY ) {
42701                indicator = {
42702                    el: createDefaultScrollbar('v', interactive, this.options.scrollbars),
42703                    interactive: interactive,
42704                    defaultScrollbars: true,
42705                    customStyle: customStyle,
42706                    resize: this.options.resizeScrollbars,
42707                    shrink: this.options.shrinkScrollbars,
42708                    fade: this.options.fadeScrollbars,
42709                    listenX: false
42710                };
42711
42712                this.wrapper.appendChild(indicator.el);
42713                indicators.push(indicator);
42714            }
42715
42716            // Horizontal scrollbar
42717            if ( this.options.scrollX ) {
42718                indicator = {
42719                    el: createDefaultScrollbar('h', interactive, this.options.scrollbars),
42720                    interactive: interactive,
42721                    defaultScrollbars: true,
42722                    customStyle: customStyle,
42723                    resize: this.options.resizeScrollbars,
42724                    shrink: this.options.shrinkScrollbars,
42725                    fade: this.options.fadeScrollbars,
42726                    listenY: false
42727                };
42728
42729                this.wrapper.appendChild(indicator.el);
42730                indicators.push(indicator);
42731            }
42732        }
42733
42734        if ( this.options.indicators ) {
42735            // TODO: check concat compatibility
42736            indicators = indicators.concat(this.options.indicators);
42737        }
42738
42739        for ( var i = indicators.length; i--; ) {
42740            this.indicators.push( new Indicator(this, indicators[i]) );
42741        }
42742
42743        // TODO: check if we can use array.map (wide compatibility and performance issues)
42744        function _indicatorsMap (fn) {
42745            if (that.indicators) {
42746                for ( var i = that.indicators.length; i--; ) {
42747                    fn.call(that.indicators[i]);
42748                }
42749            }
42750        }
42751
42752        if ( this.options.fadeScrollbars ) {
42753            this.on('scrollEnd', function () {
42754                _indicatorsMap(function () {
42755                    this.fade();
42756                });
42757            });
42758
42759            this.on('scrollCancel', function () {
42760                _indicatorsMap(function () {
42761                    this.fade();
42762                });
42763            });
42764
42765            this.on('scrollStart', function () {
42766                _indicatorsMap(function () {
42767                    this.fade(1);
42768                });
42769            });
42770
42771            this.on('beforeScrollStart', function () {
42772                _indicatorsMap(function () {
42773                    this.fade(1, true);
42774                });
42775            });
42776        }
42777
42778
42779        this.on('refresh', function () {
42780            _indicatorsMap(function () {
42781                this.refresh();
42782            });
42783        });
42784
42785        this.on('destroy', function () {
42786            _indicatorsMap(function () {
42787                this.destroy();
42788            });
42789
42790            delete this.indicators;
42791        });
42792    },
42793
42794    _initWheel: function () {
42795        utils.addEvent(this.wrapper, 'wheel', this);
42796        utils.addEvent(this.wrapper, 'mousewheel', this);
42797        utils.addEvent(this.wrapper, 'DOMMouseScroll', this);
42798
42799        this.on('destroy', function () {
42800            clearTimeout(this.wheelTimeout);
42801            this.wheelTimeout = null;
42802            utils.removeEvent(this.wrapper, 'wheel', this);
42803            utils.removeEvent(this.wrapper, 'mousewheel', this);
42804            utils.removeEvent(this.wrapper, 'DOMMouseScroll', this);
42805        });
42806    },
42807
42808    _wheel: function (e) {
42809        if ( !this.enabled ) {
42810            return;
42811        }
42812
42813        var wheelDeltaX, wheelDeltaY,
42814            newX, newY,
42815            that = this;
42816
42817        if ( this.wheelTimeout === undefined ) {
42818            that._execEvent('scrollStart');
42819        }
42820
42821        // Execute the scrollEnd event after 400ms the wheel stopped scrolling
42822        clearTimeout(this.wheelTimeout);
42823        this.wheelTimeout = setTimeout(function () {
42824            if(!that.options.snap) {
42825                that._execEvent('scrollEnd');
42826            }
42827            that.wheelTimeout = undefined;
42828        }, 400);
42829
42830        if ( 'deltaX' in e ) {
42831            if (e.deltaMode === 1) {
42832                wheelDeltaX = -e.deltaX * this.options.mouseWheelSpeed;
42833                wheelDeltaY = -e.deltaY * this.options.mouseWheelSpeed;
42834            } else {
42835                wheelDeltaX = -e.deltaX;
42836                wheelDeltaY = -e.deltaY;
42837            }
42838        } else if ( 'wheelDeltaX' in e ) {
42839            wheelDeltaX = e.wheelDeltaX / 120 * this.options.mouseWheelSpeed;
42840            wheelDeltaY = e.wheelDeltaY / 120 * this.options.mouseWheelSpeed;
42841        } else if ( 'wheelDelta' in e ) {
42842            wheelDeltaX = wheelDeltaY = e.wheelDelta / 120 * this.options.mouseWheelSpeed;
42843        } else if ( 'detail' in e ) {
42844            wheelDeltaX = wheelDeltaY = -e.detail / 3 * this.options.mouseWheelSpeed;
42845        } else {
42846            return;
42847        }
42848
42849        wheelDeltaX *= this.options.invertWheelDirection;
42850        wheelDeltaY *= this.options.invertWheelDirection;
42851
42852        if ( !this.hasVerticalScroll ) {
42853            wheelDeltaX = wheelDeltaY;
42854            wheelDeltaY = 0;
42855        }
42856
42857        if ( this.options.snap ) {
42858            newX = this.currentPage.pageX;
42859            newY = this.currentPage.pageY;
42860
42861            if ( wheelDeltaX > 0 ) {
42862                newX--;
42863            } else if ( wheelDeltaX < 0 ) {
42864                newX++;
42865            }
42866
42867            if ( wheelDeltaY > 0 ) {
42868                newY--;
42869            } else if ( wheelDeltaY < 0 ) {
42870                newY++;
42871            }
42872
42873            this.goToPage(newX, newY);
42874
42875            return;
42876        }
42877
42878        newX = this.x + Math.round(this.hasHorizontalScroll ? wheelDeltaX : 0);
42879        newY = this.y + Math.round(this.hasVerticalScroll ? wheelDeltaY : 0);
42880
42881        this.directionX = wheelDeltaX > 0 ? -1 : wheelDeltaX < 0 ? 1 : 0;
42882        this.directionY = wheelDeltaY > 0 ? -1 : wheelDeltaY < 0 ? 1 : 0;
42883
42884        if ( newX > 0 ) {
42885            newX = 0;
42886        } else if ( newX < this.maxScrollX ) {
42887            newX = this.maxScrollX;
42888        }
42889
42890        if ( newY > 0 ) {
42891            newY = 0;
42892        } else if ( newY < this.maxScrollY ) {
42893            newY = this.maxScrollY;
42894        }
42895
42896        this.scrollTo(newX, newY, 0);
42897
42898// INSERT POINT: _wheel
42899    },
42900
42901    _initSnap: function () {
42902        this.currentPage = {};
42903
42904        if ( typeof this.options.snap == 'string' ) {
42905            this.options.snap = this.scroller.querySelectorAll(this.options.snap);
42906        }
42907
42908        this.on('refresh', function () {
42909            var i = 0, l,
42910                m = 0, n,
42911                cx, cy,
42912                x = 0, y,
vendor: 7,339 bytes, lines 42913-43166
42913                stepX = this.options.snapStepX || this.wrapperWidth,
42914                stepY = this.options.snapStepY || this.wrapperHeight,
42915                el;
42916
42917            this.pages = [];
42918
42919            if ( !this.wrapperWidth || !this.wrapperHeight || !this.scrollerWidth || !this.scrollerHeight ) {
42920                return;
42921            }
42922
42923            if ( this.options.snap === true ) {
42924                cx = Math.round( stepX / 2 );
42925                cy = Math.round( stepY / 2 );
42926
42927                while ( x > -this.scrollerWidth ) {
42928                    this.pages[i] = [];
42929                    l = 0;
42930                    y = 0;
42931
42932                    while ( y > -this.scrollerHeight ) {
42933                        this.pages[i][l] = {
42934                            x: Math.max(x, this.maxScrollX),
42935                            y: Math.max(y, this.maxScrollY),
42936                            width: stepX,
42937                            height: stepY,
42938                            cx: x - cx,
42939                            cy: y - cy
42940                        };
42941
42942                        y -= stepY;
42943                        l++;
42944                    }
42945
42946                    x -= stepX;
42947                    i++;
42948                }
42949            } else {
42950                el = this.options.snap;
42951                l = el.length;
42952                n = -1;
42953
42954                for ( ; i < l; i++ ) {
42955                    if ( i === 0 || el[i].offsetLeft <= el[i-1].offsetLeft ) {
42956                        m = 0;
42957                        n++;
42958                    }
42959
42960                    if ( !this.pages[m] ) {
42961                        this.pages[m] = [];
42962                    }
42963
42964                    x = Math.max(-el[i].offsetLeft, this.maxScrollX);
42965                    y = Math.max(-el[i].offsetTop, this.maxScrollY);
42966                    cx = x - Math.round(el[i].offsetWidth / 2);
42967                    cy = y - Math.round(el[i].offsetHeight / 2);
42968
42969                    this.pages[m][n] = {
42970                        x: x,
42971                        y: y,
42972                        width: el[i].offsetWidth,
42973                        height: el[i].offsetHeight,
42974                        cx: cx,
42975                        cy: cy
42976                    };
42977
42978                    if ( x > this.maxScrollX ) {
42979                        m++;
42980                    }
42981                }
42982            }
42983
42984            this.goToPage(this.currentPage.pageX || 0, this.currentPage.pageY || 0, 0);
42985
42986            // Update snap threshold if needed
42987            if ( this.options.snapThreshold % 1 === 0 ) {
42988                this.snapThresholdX = this.options.snapThreshold;
42989                this.snapThresholdY = this.options.snapThreshold;
42990            } else {
42991                this.snapThresholdX = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].width * this.options.snapThreshold);
42992                this.snapThresholdY = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].height * this.options.snapThreshold);
42993            }
42994        });
42995
42996        this.on('flick', function () {
42997            var time = this.options.snapSpeed || Math.max(
42998                    Math.max(
42999                        Math.min(Math.abs(this.x - this.startX), 1000),
43000                        Math.min(Math.abs(this.y - this.startY), 1000)
43001                    ), 300);
43002
43003            this.goToPage(
43004                this.currentPage.pageX + this.directionX,
43005                this.currentPage.pageY + this.directionY,
43006                time
43007            );
43008        });
43009    },
43010
43011    _nearestSnap: function (x, y) {
43012        if ( !this.pages.length ) {
43013            return { x: 0, y: 0, pageX: 0, pageY: 0 };
43014        }
43015
43016        var i = 0,
43017            l = this.pages.length,
43018            m = 0;
43019
43020        // Check if we exceeded the snap threshold
43021        if ( Math.abs(x - this.absStartX) < this.snapThresholdX &&
43022            Math.abs(y - this.absStartY) < this.snapThresholdY ) {
43023            return this.currentPage;
43024        }
43025
43026        if ( x > 0 ) {
43027            x = 0;
43028        } else if ( x < this.maxScrollX ) {
43029            x = this.maxScrollX;
43030        }
43031
43032        if ( y > 0 ) {
43033            y = 0;
43034        } else if ( y < this.maxScrollY ) {
43035            y = this.maxScrollY;
43036        }
43037
43038        for ( ; i < l; i++ ) {
43039            if ( x >= this.pages[i][0].cx ) {
43040                x = this.pages[i][0].x;
43041                break;
43042            }
43043        }
43044
43045        l = this.pages[i].length;
43046
43047        for ( ; m < l; m++ ) {
43048            if ( y >= this.pages[0][m].cy ) {
43049                y = this.pages[0][m].y;
43050                break;
43051            }
43052        }
43053
43054        if ( i == this.currentPage.pageX ) {
43055            i += this.directionX;
43056
43057            if ( i < 0 ) {
43058                i = 0;
43059            } else if ( i >= this.pages.length ) {
43060                i = this.pages.length - 1;
43061            }
43062
43063            x = this.pages[i][0].x;
43064        }
43065
43066        if ( m == this.currentPage.pageY ) {
43067            m += this.directionY;
43068
43069            if ( m < 0 ) {
43070                m = 0;
43071            } else if ( m >= this.pages[0].length ) {
43072                m = this.pages[0].length - 1;
43073            }
43074
43075            y = this.pages[0][m].y;
43076        }
43077
43078        return {
43079            x: x,
43080            y: y,
43081            pageX: i,
43082            pageY: m
43083        };
43084    },
43085
43086    goToPage: function (x, y, time, easing) {
43087        easing = easing || this.options.bounceEasing;
43088
43089        if ( x >= this.pages.length ) {
43090            x = this.pages.length - 1;
43091        } else if ( x < 0 ) {
43092            x = 0;
43093        }
43094
43095        if ( y >= this.pages[x].length ) {
43096            y = this.pages[x].length - 1;
43097        } else if ( y < 0 ) {
43098            y = 0;
43099        }
43100
43101        var posX = this.pages[x][y].x,
43102            posY = this.pages[x][y].y;
43103
43104        time = time === undefined ? this.options.snapSpeed || Math.max(
43105            Math.max(
43106                Math.min(Math.abs(posX - this.x), 1000),
43107                Math.min(Math.abs(posY - this.y), 1000)
43108            ), 300) : time;
43109
43110        this.currentPage = {
43111            x: posX,
43112            y: posY,
43113            pageX: x,
43114            pageY: y
43115        };
43116
43117        this.scrollTo(posX, posY, time, easing);
43118    },
43119
43120    next: function (time, easing) {
43121        var x = this.currentPage.pageX,
43122            y = this.currentPage.pageY;
43123
43124        x++;
43125
43126        if ( x >= this.pages.length && this.hasVerticalScroll ) {
43127            x = 0;
43128            y++;
43129        }
43130
43131        this.goToPage(x, y, time, easing);
43132    },
43133
43134    prev: function (time, easing) {
43135        var x = this.currentPage.pageX,
43136            y = this.currentPage.pageY;
43137
43138        x--;
43139
43140        if ( x < 0 && this.hasVerticalScroll ) {
43141            x = 0;
43142            y--;
43143        }
43144
43145        this.goToPage(x, y, time, easing);
43146    },
43147
43148    _initKeys: function (e) {
43149        // default key bindings
43150        var keys = {
43151            pageUp: 33,
43152            pageDown: 34,
43153            end: 35,
43154            home: 36,
43155            left: 37,
43156            up: 38,
43157            right: 39,
43158            down: 40
43159        };
43160        var i;
43161
43162        // if you give me characters I give you keycode
43163        if ( typeof this.options.keyBindings == 'object' ) {
43164            for ( i in this.options.keyBindings ) {
43165                if ( typeof this.options.keyBindings[i] == 'string' ) {
43166                    this.options.keyBindings[i] = this.options.keyBindings[i].toUpperCase().charCo
vendor: 11,097 bytes, lines 43166-43519
43166deAt(0);
43167                }
43168            }
43169        } else {
43170            this.options.keyBindings = {};
43171        }
43172
43173        for ( i in keys ) {
43174            this.options.keyBindings[i] = this.options.keyBindings[i] || keys[i];
43175        }
43176
43177        utils.addEvent(window, 'keydown', this);
43178
43179        this.on('destroy', function () {
43180            utils.removeEvent(window, 'keydown', this);
43181        });
43182    },
43183
43184    _key: function (e) {
43185        if ( !this.enabled ) {
43186            return;
43187        }
43188
43189        var snap = this.options.snap,   // we are using this alot, better to cache it
43190            newX = snap ? this.currentPage.pageX : this.x,
43191            newY = snap ? this.currentPage.pageY : this.y,
43192            now = utils.getTime(),
43193            prevTime = this.keyTime || 0,
43194            acceleration = 0.250,
43195            pos;
43196
43197        if ( this.options.useTransition && this.isInTransition ) {
43198            pos = this.getComputedPosition();
43199
43200            this._translate(Math.round(pos.x), Math.round(pos.y));
43201            this.isInTransition = false;
43202        }
43203
43204        this.keyAcceleration = now - prevTime < 200 ? Math.min(this.keyAcceleration + acceleration, 50) : 0;
43205
43206        switch ( e.keyCode ) {
43207            case this.options.keyBindings.pageUp:
43208                if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {
43209                    newX += snap ? 1 : this.wrapperWidth;
43210                } else {
43211                    newY += snap ? 1 : this.wrapperHeight;
43212                }
43213                break;
43214            case this.options.keyBindings.pageDown:
43215                if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {
43216                    newX -= snap ? 1 : this.wrapperWidth;
43217                } else {
43218                    newY -= snap ? 1 : this.wrapperHeight;
43219                }
43220                break;
43221            case this.options.keyBindings.end:
43222                newX = snap ? this.pages.length-1 : this.maxScrollX;
43223                newY = snap ? this.pages[0].length-1 : this.maxScrollY;
43224                break;
43225            case this.options.keyBindings.home:
43226                newX = 0;
43227                newY = 0;
43228                break;
43229            case this.options.keyBindings.left:
43230                newX += snap ? -1 : 5 + this.keyAcceleration>>0;
43231                break;
43232            case this.options.keyBindings.up:
43233                newY += snap ? 1 : 5 + this.keyAcceleration>>0;
43234                break;
43235            case this.options.keyBindings.right:
43236                newX -= snap ? -1 : 5 + this.keyAcceleration>>0;
43237                break;
43238            case this.options.keyBindings.down:
43239                newY -= snap ? 1 : 5 + this.keyAcceleration>>0;
43240                break;
43241            default:
43242                return;
43243        }
43244
43245        if ( snap ) {
43246            this.goToPage(newX, newY);
43247            return;
43248        }
43249
43250        if ( newX > 0 ) {
43251            newX = 0;
43252            this.keyAcceleration = 0;
43253        } else if ( newX < this.maxScrollX ) {
43254            newX = this.maxScrollX;
43255            this.keyAcceleration = 0;
43256        }
43257
43258        if ( newY > 0 ) {
43259            newY = 0;
43260            this.keyAcceleration = 0;
43261        } else if ( newY < this.maxScrollY ) {
43262            newY = this.maxScrollY;
43263            this.keyAcceleration = 0;
43264        }
43265
43266        this.scrollTo(newX, newY, 0);
43267
43268        this.keyTime = now;
43269    },
43270
43271    _animate: function (destX, destY, duration, easingFn) {
43272        var that = this,
43273            startX = this.x,
43274            startY = this.y,
43275            startTime = utils.getTime(),
43276            destTime = startTime + duration;
43277
43278        function step () {
43279            var now = utils.getTime(),
43280                newX, newY,
43281                easing;
43282
43283            if ( now >= destTime ) {
43284                that.isAnimating = false;
43285                that._translate(destX, destY);
43286
43287                if ( !that.resetPosition(that.options.bounceTime) ) {
43288                    that._execEvent('scrollEnd');
43289                }
43290
43291                return;
43292            }
43293
43294            now = ( now - startTime ) / duration;
43295            easing = easingFn(now);
43296            newX = ( destX - startX ) * easing + startX;
43297            newY = ( destY - startY ) * easing + startY;
43298            that._translate(newX, newY);
43299
43300            if ( that.isAnimating ) {
43301                rAF(step);
43302            }
43303        }
43304
43305        this.isAnimating = true;
43306        step();
43307    },
43308    handleEvent: function (e) {
43309        switch ( e.type ) {
43310            case 'touchstart':
43311            case 'pointerdown':
43312            case 'MSPointerDown':
43313            case 'mousedown':
43314                this._start(e);
43315                break;
43316            case 'touchmove':
43317            case 'pointermove':
43318            case 'MSPointerMove':
43319            case 'mousemove':
43320                this._move(e);
43321                break;
43322            case 'touchend':
43323            case 'pointerup':
43324            case 'MSPointerUp':
43325            case 'mouseup':
43326            case 'touchcancel':
43327            case 'pointercancel':
43328            case 'MSPointerCancel':
43329            case 'mousecancel':
43330                this._end(e);
43331                break;
43332            case 'orientationchange':
43333            case 'resize':
43334                this._resize();
43335                break;
43336            case 'transitionend':
43337            case 'webkitTransitionEnd':
43338            case 'oTransitionEnd':
43339            case 'MSTransitionEnd':
43340                this._transitionEnd(e);
43341                break;
43342            case 'wheel':
43343            case 'DOMMouseScroll':
43344            case 'mousewheel':
43345                this._wheel(e);
43346                break;
43347            case 'keydown':
43348                this._key(e);
43349                break;
43350            case 'click':
43351                if ( this.enabled && !e._constructed ) {
43352                    e.preventDefault();
43353                    e.stopPropagation();
43354                }
43355                break;
43356        }
43357    }
43358};
43359function createDefaultScrollbar (direction, interactive, type) {
43360    var scrollbar = document.createElement('div'),
43361        indicator = document.createElement('div');
43362
43363    if ( type === true ) {
43364        scrollbar.style.cssText = 'position:absolute;z-index:9999';
43365        indicator.style.cssText = '-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;position:absolute;background:rgba(0,0,0,0.5);border:1px solid rgba(255,255,255,0.9);border-radius:3px';
43366    }
43367
43368    indicator.className = 'iScrollIndicator';
43369
43370    if ( direction == 'h' ) {
43371        if ( type === true ) {
43372            scrollbar.style.cssText += ';height:7px;left:2px;right:2px;bottom:0';
43373            indicator.style.height = '100%';
43374        }
43375        scrollbar.className = 'iScrollHorizontalScrollbar';
43376    } else {
43377        if ( type === true ) {
43378            scrollbar.style.cssText += ';width:7px;bottom:2px;top:2px;right:1px';
43379            indicator.style.width = '100%';
43380        }
43381        scrollbar.className = 'iScrollVerticalScrollbar';
43382    }
43383
43384    scrollbar.style.cssText += ';overflow:hidden';
43385
43386    if ( !interactive ) {
43387        scrollbar.style.pointerEvents = 'none';
43388    }
43389
43390    scrollbar.appendChild(indicator);
43391
43392    return scrollbar;
43393}
43394
43395function Indicator (scroller, options) {
43396    this.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el;
43397    this.wrapperStyle = this.wrapper.style;
43398    this.indicator = this.wrapper.children[0];
43399    this.indicatorStyle = this.indicator.style;
43400    this.scroller = scroller;
43401
43402    this.options = {
43403        listenX: true,
43404        listenY: true,
43405        interactive: false,
43406        resize: true,
43407        defaultScrollbars: false,
43408        shrink: false,
43409        fade: false,
43410        speedRatioX: 0,
43411        speedRatioY: 0
43412    };
43413
43414    for ( var i in options ) {
43415        this.options[i] = options[i];
43416    }
43417
43418    this.sizeRatioX = 1;
43419    this.sizeRatioY = 1;
43420    this.maxPosX = 0;
43421    this.maxPosY = 0;
43422
43423    if ( this.options.interactive ) {
43424        if ( !this.options.disableTouch ) {
43425            utils.addEvent(this.indicator, 'touchstart', this);
43426            utils.addEvent(window, 'touchend', this);
43427        }
43428        if ( !this.options.disablePointer ) {
43429            utils.addEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);
43430            utils.addEvent(window, utils.prefixPointerEvent('pointerup'), this);
43431        }
43432        if ( !this.options.disableMouse ) {
43433            utils.addEvent(this.indicator, 'mousedown', this);
43434            utils.addEvent(window, 'mouseup', this);
43435        }
43436    }
43437
43438    if ( this.options.fade ) {
43439        this.wrapperStyle[utils.style.transform] = this.scroller.translateZ;
43440        var durationProp = utils.style.transitionDuration;
43441        if(!durationProp) {
43442            return;
43443        }
43444        this.wrapperStyle[durationProp] = utils.isBadAndroid ? '0.0001ms' : '0ms';
43445        // remove 0.0001ms
43446        var self = this;
43447        if(utils.isBadAndroid) {
43448            rAF(function() {
43449                if(self.wrapperStyle[durationProp] === '0.0001ms') {
43450                    self.wrapperStyle[durationProp] = '0s';
43451                }
43452            });
43453        }
43454        this.wrapperStyle.opacity = '0';
43455    }
43456}
43457
43458Indicator.prototype = {
43459    handleEvent: function (e) {
43460        switch ( e.type ) {
43461            case 'touchstart':
43462            case 'pointerdown':
43463            case 'MSPointerDown':
43464            case 'mousedown':
43465                this._start(e);
43466                break;
43467            case 'touchmove':
43468            case 'pointermove':
43469            case 'MSPointerMove':
43470            case 'mousemove':
43471                this._move(e);
43472                break;
43473            case 'touchend':
43474            case 'pointerup':
43475            case 'MSPointerUp':
43476            case 'mouseup':
43477            case 'touchcancel':
43478            case 'pointercancel':
43479            case 'MSPointerCancel':
43480            case 'mousecancel':
43481                this._end(e);
43482                break;
43483        }
43484    },
43485
43486    destroy: function () {
43487        if ( this.options.fadeScrollbars ) {
43488            clearTimeout(this.fadeTimeout);
43489            this.fadeTimeout = null;
43490        }
43491        if ( this.options.interactive ) {
43492            utils.removeEvent(this.indicator, 'touchstart', this);
43493            utils.removeEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);
43494            utils.removeEvent(this.indicator, 'mousedown', this);
43495
43496            utils.removeEvent(window, 'touchmove', this);
43497            utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);
43498            utils.removeEvent(window, 'mousemove', this);
43499
43500            utils.removeEvent(window, 'touchend', this);
43501            utils.removeEvent(window, utils.prefixPointerEvent('pointerup'), this);
43502            utils.removeEvent(window, 'mouseup', this);
43503        }
43504
43505        if ( this.options.defaultScrollbars ) {
43506            this.wrapper.parentNode.removeChild(this.wrapper);
43507        }
43508    },
43509
43510    _start: function (e) {
43511        var point = e.touches ? e.touches[0] : e;
43512
43513        e.preventDefault();
43514        e.stopPropagation();
43515
43516        this.transitionTime();
43517
43518        this.initiated = true;
43519        this.moved = false;
vendor: 9,615 bytes, lines 43520-43778
43520        this.lastPointX = point.pageX;
43521        this.lastPointY = point.pageY;
43522
43523        this.startTime  = utils.getTime();
43524
43525        if ( !this.options.disableTouch ) {
43526            utils.addEvent(window, 'touchmove', this);
43527        }
43528        if ( !this.options.disablePointer ) {
43529            utils.addEvent(window, utils.prefixPointerEvent('pointermove'), this);
43530        }
43531        if ( !this.options.disableMouse ) {
43532            utils.addEvent(window, 'mousemove', this);
43533        }
43534
43535        this.scroller._execEvent('beforeScrollStart');
43536    },
43537
43538    _move: function (e) {
43539        var point = e.touches ? e.touches[0] : e,
43540            deltaX, deltaY,
43541            newX, newY,
43542            timestamp = utils.getTime();
43543
43544        if ( !this.moved ) {
43545            this.scroller._execEvent('scrollStart');
43546        }
43547
43548        this.moved = true;
43549
43550        deltaX = point.pageX - this.lastPointX;
43551        this.lastPointX = point.pageX;
43552
43553        deltaY = point.pageY - this.lastPointY;
43554        this.lastPointY = point.pageY;
43555
43556        newX = this.x + deltaX;
43557        newY = this.y + deltaY;
43558
43559        this._pos(newX, newY);
43560
43561// INSERT POINT: indicator._move
43562
43563        e.preventDefault();
43564        e.stopPropagation();
43565    },
43566
43567    _end: function (e) {
43568        if ( !this.initiated ) {
43569            return;
43570        }
43571
43572        this.initiated = false;
43573
43574        e.preventDefault();
43575        e.stopPropagation();
43576
43577        utils.removeEvent(window, 'touchmove', this);
43578        utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);
43579        utils.removeEvent(window, 'mousemove', this);
43580
43581        if ( this.scroller.options.snap ) {
43582            var snap = this.scroller._nearestSnap(this.scroller.x, this.scroller.y);
43583
43584            var time = this.options.snapSpeed || Math.max(
43585                    Math.max(
43586                        Math.min(Math.abs(this.scroller.x - snap.x), 1000),
43587                        Math.min(Math.abs(this.scroller.y - snap.y), 1000)
43588                    ), 300);
43589
43590            if ( this.scroller.x != snap.x || this.scroller.y != snap.y ) {
43591                this.scroller.directionX = 0;
43592                this.scroller.directionY = 0;
43593                this.scroller.currentPage = snap;
43594                this.scroller.scrollTo(snap.x, snap.y, time, this.scroller.options.bounceEasing);
43595            }
43596        }
43597
43598        if ( this.moved ) {
43599            this.scroller._execEvent('scrollEnd');
43600        }
43601    },
43602
43603    transitionTime: function (time) {
43604        time = time || 0;
43605        var durationProp = utils.style.transitionDuration;
43606        if(!durationProp) {
43607            return;
43608        }
43609
43610        this.indicatorStyle[durationProp] = time + 'ms';
43611
43612        if ( !time && utils.isBadAndroid ) {
43613            this.indicatorStyle[durationProp] = '0.0001ms';
43614            // remove 0.0001ms
43615            var self = this;
43616            rAF(function() {
43617                if(self.indicatorStyle[durationProp] === '0.0001ms') {
43618                    self.indicatorStyle[durationProp] = '0s';
43619                }
43620            });
43621        }
43622    },
43623
43624    transitionTimingFunction: function (easing) {
43625        this.indicatorStyle[utils.style.transitionTimingFunction] = easing;
43626    },
43627
43628    refresh: function () {
43629        this.transitionTime();
43630
43631        if ( this.options.listenX && !this.options.listenY ) {
43632            this.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none';
43633        } else if ( this.options.listenY && !this.options.listenX ) {
43634            this.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none';
43635        } else {
43636            this.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none';
43637        }
43638
43639        if ( this.scroller.hasHorizontalScroll && this.scroller.hasVerticalScroll ) {
43640            utils.addClass(this.wrapper, 'iScrollBothScrollbars');
43641            utils.removeClass(this.wrapper, 'iScrollLoneScrollbar');
43642
43643            if ( this.options.defaultScrollbars && this.options.customStyle ) {
43644                if ( this.options.listenX ) {
43645                    this.wrapper.style.right = '8px';
43646                } else {
43647                    this.wrapper.style.bottom = '8px';
43648                }
43649            }
43650        } else {
43651            utils.removeClass(this.wrapper, 'iScrollBothScrollbars');
43652            utils.addClass(this.wrapper, 'iScrollLoneScrollbar');
43653
43654            if ( this.options.defaultScrollbars && this.options.customStyle ) {
43655                if ( this.options.listenX ) {
43656                    this.wrapper.style.right = '2px';
43657                } else {
43658                    this.wrapper.style.bottom = '2px';
43659                }
43660            }
43661        }
43662
43663        var r = this.wrapper.offsetHeight;  // force refresh
43664
43665        if ( this.options.listenX ) {
43666            this.wrapperWidth = this.wrapper.clientWidth;
43667            if ( this.options.resize ) {
43668                this.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / (this.scroller.scrollerWidth || this.wrapperWidth || 1)), 8);
43669                this.indicatorStyle.width = this.indicatorWidth + 'px';
43670            } else {
43671                this.indicatorWidth = this.indicator.clientWidth;
43672            }
43673
43674            this.maxPosX = this.wrapperWidth - this.indicatorWidth;
43675
43676            if ( this.options.shrink == 'clip' ) {
43677                this.minBoundaryX = -this.indicatorWidth + 8;
43678                this.maxBoundaryX = this.wrapperWidth - 8;
43679            } else {
43680                this.minBoundaryX = 0;
43681                this.maxBoundaryX = this.maxPosX;
43682            }
43683
43684            this.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX));
43685        }
43686
43687        if ( this.options.listenY ) {
43688            this.wrapperHeight = this.wrapper.clientHeight;
43689            if ( this.options.resize ) {
43690                this.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / (this.scroller.scrollerHeight || this.wrapperHeight || 1)), 8);
43691                this.indicatorStyle.height = this.indicatorHeight + 'px';
43692            } else {
43693                this.indicatorHeight = this.indicator.clientHeight;
43694            }
43695
43696            this.maxPosY = this.wrapperHeight - this.indicatorHeight;
43697
43698            if ( this.options.shrink == 'clip' ) {
43699                this.minBoundaryY = -this.indicatorHeight + 8;
43700                this.maxBoundaryY = this.wrapperHeight - 8;
43701            } else {
43702                this.minBoundaryY = 0;
43703                this.maxBoundaryY = this.maxPosY;
43704            }
43705
43706            this.maxPosY = this.wrapperHeight - this.indicatorHeight;
43707            this.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY));
43708        }
43709
43710        this.updatePosition();
43711    },
43712
43713    updatePosition: function () {
43714        var x = this.options.listenX && Math.round(this.sizeRatioX * this.scroller.x) || 0,
43715            y = this.options.listenY && Math.round(this.sizeRatioY * this.scroller.y) || 0;
43716
43717        if ( !this.options.ignoreBoundaries ) {
43718            if ( x < this.minBoundaryX ) {
43719                if ( this.options.shrink == 'scale' ) {
43720                    this.width = Math.max(this.indicatorWidth + x, 8);
43721                    this.indicatorStyle.width = this.width + 'px';
43722                }
43723                x = this.minBoundaryX;
43724            } else if ( x > this.maxBoundaryX ) {
43725                if ( this.options.shrink == 'scale' ) {
43726                    this.width = Math.max(this.indicatorWidth - (x - this.maxPosX), 8);
43727                    this.indicatorStyle.width = this.width + 'px';
43728                    x = this.maxPosX + this.indicatorWidth - this.width;
43729                } else {
43730                    x = this.maxBoundaryX;
43731                }
43732            } else if ( this.options.shrink == 'scale' && this.width != this.indicatorWidth ) {
43733                this.width = this.indicatorWidth;
43734                this.indicatorStyle.width = this.width + 'px';
43735            }
43736
43737            if ( y < this.minBoundaryY ) {
43738                if ( this.options.shrink == 'scale' ) {
43739                    this.height = Math.max(this.indicatorHeight + y * 3, 8);
43740                    this.indicatorStyle.height = this.height + 'px';
43741                }
43742                y = this.minBoundaryY;
43743            } else if ( y > this.maxBoundaryY ) {
43744                if ( this.options.shrink == 'scale' ) {
43745                    this.height = Math.max(this.indicatorHeight - (y - this.maxPosY) * 3, 8);
43746                    this.indicatorStyle.height = this.height + 'px';
43747                    y = this.maxPosY + this.indicatorHeight - this.height;
43748                } else {
43749                    y = this.maxBoundaryY;
43750                }
43751            } else if ( this.options.shrink == 'scale' && this.height != this.indicatorHeight ) {
43752                this.height = this.indicatorHeight;
43753                this.indicatorStyle.height = this.height + 'px';
43754            }
43755        }
43756
43757        this.x = x;
43758        this.y = y;
43759
43760        if ( this.scroller.options.useTransform ) {
43761            this.indicatorStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.scroller.translateZ;
43762        } else {
43763            this.indicatorStyle.left = x + 'px';
43764            this.indicatorStyle.top = y + 'px';
43765        }
43766    },
43767
43768    _pos: function (x, y) {
43769        if ( x < 0 ) {
43770            x = 0;
43771        } else if ( x > this.maxPosX ) {
43772            x = this.maxPosX;
43773        }
43774
43775        if ( y < 0 ) {
43776            y = 0;
43777        } else if ( y > this.maxPosY ) {
43778            y = this.maxPosY;
43779        }
43780
43781        x = this.options.listenX ? Math.round(x / this.sizeRatioX) : this.scroller.x;
43782        y = this.options.listenY ? Math.round(y / this.sizeRatioY) : this.scroller.y;
43783
43784        this.scroller.scrollTo(x, y);
43785    },
43786
43787    fade: function (val, hold) {
43788        if ( hold && !this.visible ) {
43789            return;
43790        }
43791
43792        clearTimeout(this.fadeTimeout);
43793        this.fadeTimeout = null;
43794
43795        var time = val ? 250 : 500,
43796            delay = val ? 0 : 300;
43797
43798        val = val ? '1' : '0';
43799
43800        this.wrapperStyle[utils.style.transitionDuration] = time + 'ms';
43801
43802        this.fadeTimeout = setTimeout((function (val) {
43803            this.wrapperStyle.opacity = val;
43804            this.visible = +val;
43805        }).bind(this, val), delay);
43806    }
43807};
43808
43809IScroll.utils = utils;
43810
43811if ( typeof module != 'undefined' && module.exports ) {
43812    module.exports = IScroll;
43813} else if ( typeof define == 'function' && define.amd ) {
43814        define( function () { return IScroll; } );
43815} else {
43816    window.IScroll = IScroll;
43817}
43818
43819})(window, document, Math);
43820/*!
43821 * fullPage 2.9.4
43822 * https://github.com/alvarotrigo/fullPage.js
43823 * @license MIT licensed
43824 *
43825 * Copyright (C) 2015 alvarotrigo.com - A project by Alvaro Trigo
43826 */
43827(function(global, factory) {
43828    'use strict';
43829    if (typeof define === 'function' && define.amd) {
43830        define(['jquery'], function($) {
43831          return factory($, global, global.document, global.Math);
43832        });
43833    } else if (typeof exports === "object" && exports) {
43834        module.exports = factory(require('jquery'), global, global.document, global.Math);
43835    } else {
43836        factory(jQuery, global, global.document, global.Math);
43837    }
43838})(typeof window !== 'undefined' ? window : this, function($, window, document, Math, undefined) {
43839    'use strict';
43840
43841    // keeping central set of classnames and selectors
43842    var WRAPPER =               'fullpage-wrapper';
43843    var WRAPPER_SEL =           '.' + WRAPPER;
43844
43845    // slimscroll
43846    var SCROLLABLE =            'fp-scrollable';
43847    var SCROLLABLE_SEL =        '.' + SCROLLABLE;
43848
43849    // util
43850    var RESPONSIVE =            'fp-responsive';
43851    var NO_TRANSITION =         'fp-notransition';
43852    var DESTROYED =             'fp-destroyed';
43853    var ENABLED =               'fp-enabled';
43854    var VIEWING_PREFIX =        'fp-viewing';
43855    var ACTIVE =                'active';
43856    var ACTIVE_SEL =            '.' + ACTIVE;
43857    var COMPLETELY =            'fp-completely';
43858    var COMPLETELY_SEL =        '.' + COMPLETELY;
43859
43860    // section
43861    var SECTION_DEFAULT_SEL =   '.section';
43862    var SECTION =               'fp-section';
43863    var SECTION_SEL =           '.' + SECTION;
43864    var SECTION_ACTIVE_SEL =    SECTION_SEL + ACTIVE_SEL;
43865    var SECTION_FIRST_SEL =     SECTION_SEL + ':first';
43866    var SECTION_LAST_SEL =      SECTION_SEL + ':last';
43867    var TABLE_CELL =            'fp-tableCell';
43868    var TABLE_CELL_SEL =        '.' + TABLE_CELL;
43869    var AUTO_HEIGHT =           'fp-auto-height';
43870    var AUTO_HEIGHT_SEL =       '.fp-auto-height';
43871    var NORMAL_SCROLL =         'fp-normal-scroll';
43872    var NORMAL_SCROLL_SEL =     '.fp-normal-scroll';
43873
43874    // section nav
43875    var SECTION_NAV =           'fp-nav';
43876    var SECTION_NAV_SEL =       '#' + SECTION_NAV;
43877    var SECTION_NAV_TOOLTIP =   'fp-tooltip';
43878    var SECTION_NAV_TOOLTIP_SEL='.'+SECTION_NAV_TOOLTIP;
43879    var SHOW_ACTIVE_TOOLTIP =   'fp-show-active';
43880
43881    // slide
43882    var SLIDE_DEFAULT_SEL =     '.slide';
43883    var SLIDE =                 'fp-slide';
43884    var SLIDE_SEL =             '.' + SLIDE;
43885    var SLIDE_ACTIVE_SEL =      SLIDE_SEL + ACTIVE_SEL;
43886    var SLIDES_WRAPPER =        'fp-slides';
43887    var SLIDES_WRAPPER_SEL =    '.' + SLIDES_WRAPPER;
43888    var SLIDES_CONTAINER =      'fp-slidesContainer';
43889    var SLIDES_CONTAINER_SEL =  '.' + SLIDES_CONTAINER;
43890    var TABLE =                 'fp-table';
43891
43892    // slide nav
43893    var SLIDES_NAV =            'fp-slidesNav';
43894    var SLIDES_NAV_SEL =        '.' + SLIDES_NAV;
43895    var SLIDES_NAV_LINK_SEL =   SLIDES_NAV_SEL + ' a';
43896    var SLIDES_ARROW =          'fp-controlArrow';
43897    var SLIDES_ARROW_SEL =      '.' + SLIDES_ARROW;
43898    var SLIDES_PREV =           'fp-prev';
43899    var SLIDES_PREV_SEL =       '.' + SLIDES_PREV;
43900    var SLIDES_ARROW_PREV =     SLIDES_ARROW + ' ' + SLIDES_PREV;
43901    var SLIDES_ARROW_PREV_SEL = SLIDES_ARROW_SEL + SLIDES_PREV_SEL;
43902    var SLIDES_NEXT =           'fp-next';
43903    var SLIDES_NEXT_SEL =       '.' + SLIDES_NEXT;
43904    var SLIDES_ARROW_NEXT =     SLIDES_ARROW + ' ' + SLIDES_NEXT;
43905    var SLIDES_ARROW_NEXT_SEL = SLIDES_ARROW_SEL + SLIDES_NEXT_SEL;
43906
43907    var $window = $(window);
43908    var $document = $(document);
43909
43910    // Default options for iScroll.js used when using scrollOverflow
43911    var iscrollOptions = {
43912        scrollbars: true,
43913        mouseWheel: true,
43914        hideScrollbars: false,
43915        fadeScrollbars: false,
43916        disableMouse: true,
43917        interactiveScrollbars: true,
43918        bounce: false,
43919    };
43920
43921    $.fn.fullpage = function(options) {
43922        //only once my friend!
43923        if($('html').hasClass(ENABLED)){ displayWarnings(); return; }
43924
43925        // common jQuery objects
43926        var $htmlBody = $('html, body');
43927        var $body = $('body');
43928
43929        var FP = $.fn.fullpage;
43930
43931        // Creating some defaults, extending them with any options that were provided
43932        options = $.extend({
43933            //navigation
43934            menu: false,
43935            anchors:[],
43936            lockAnchors: false,
43937            navigation: false,
43938            navigationPosition: 'right',
43939            navigationTooltips: [],
43940            showActiveTooltip: false,
43941            slidesNavigation: false,
43942            slidesNavPosition: 'bottom',
43943            scrollBar: false,
43944            hybrid: false,
43945
43946            //scrolling
43947            css3: true,
43948            scrollingSpeed: 700,
43949            autoScrolling: true,
43950            fitToSection: true,
43951            fitToSectionDelay: 1000,
43952            easing: 'easeInOutCubic',
43953            easingcss3: 'ease',
43954            loopBottom: false,
43955            loopTop: false,
43956            loopHorizontal: true,
43957            continuousVertical: false,
43958            continuousHorizontal: false,
43959            scrollHorizontally: false,
43960            interlockedSlides: false,
43961            dragAndMove: false,
43962            offsetSections: false,
43963            resetSliders: false,
43964            fadingEffect: false,
43965            normalScrollElements: null,
43966            scrollOverflow: false,
43967            scrollOverflowReset: false,
43968            scrollOverflowHandler: iscrollHandler,
43969            scrollOverflowOptions: null,
43970            touchSensitivity: 5,
43971            normalScrollElementTouchThreshold: 5,
43972            bigSectionsDestination: null,
43973
43974            //Accessibility
43975            keyboardScrolling: true,
43976            animateAnchor: true,
43977            recordHistory: true,
43978
43979            //design
43980            controlArrows: true,
43981            controlArrowColor: '#fff',
43982            verticalCentered: true,
43983            sectionsColor : [],
43984            paddingTop: 0,
43985            paddingBottom: 0,
43986            fixedElements: null,
43987            responsive: 0, //backwards compabitility with responsiveWiddth
43988            responsiveWidth: 0,
43989            responsiveHeight: 0,
43990            responsiveSlides: false,
43991            parallax: false,
43992            parallaxOptions: {
43993                type: 'reveal',
43994                percentage: 62,
43995                property: 'translate'
43996            },
43997
43998            //Custom selectors
43999            sectionSelector: SECTION_DEFAULT_SEL,
44000            slideSelector: SLIDE_DEFAULT_SEL,
44001
44002            //events
44003            afterLoad: null,
44004            onLeave: null,
44005            afterRender: null,
44006            afterResize: null,
44007            afterReBuild: null,
44008            afterSlideLoad: null,
44009            onSlideLeave: null,
44010            afterResponsive: null,
44011
44012            lazyLoading: true
44013        }, options);
44014
44015        //flag to avoid very fast sliding for landscape sliders
44016        var slideMoving = false;
44017
44018        var isTouchDevice = navigator.userAgent.match(/(iPhone|iPod|iPad|Android|playbook|silk|BlackBerry|BB10|Windows Phone|Tizen|Bada|webOS|IEMobile|Opera Mini)/);
44019        var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0) || (navigator.maxTouchPoints));
44020        var container = $(this);
44021        var windowsHeight = $window.height();
44022        var isResizing = false;
44023        var isWindowFocused = true;
44024        var lastScrolledDestiny;
44025        var lastScrolledSlide;
44026        var canScroll = true;
44027        var scrollings = [];
44028        var controlPressed;
44029        var startingSection;
44030        var isScrollAllowed = {};
44031        isScrollAllowed.m = {  'up':true, 'down':true, 'left':true, 'right':true };
44032        isScrollAllowed.k = $.extend(true,{}, isScrollAllowed.m);
44033        var MSPointer = getMSPointer();
44034        var events = {
44035            touchmove: 'ontouchmove' in window ? 'touchmove' :  MSPointer.move,
44036            touchstart: 'ontouchstart' in window ? 'touchstart' :  MSPointer.down
44037        };
44038
44039        //cheks for passive event support
44040        //added by Uncode from new fullPage updates
44041        var g_supportsPassive = false;
44042        try {
44043          var opts = Object.defineProperty({}, 'passive', {
44044            get: function() {
44045              g_supportsPassive = true;
44046            }
44047          });
44048          window.addEventListener("testPassive", null, opts);
44049          window.removeEventListener("testPassive", null, opts);
44050        } catch (e) {}
44051
44052        //timeouts
44053        var resizeId;
44054        var afterSectionLoadsId;
44055        var afterSlideLoadsId;
44056        var scrollId;
44057        var scrollId2;
44058        var keydownId;
44059        var originals = $.extend(true, {}, options); //deep copy
44060
44061        //Uncode addition
44062        var $masthead = $('#masthead');
44063        var hideMenu = !$('body').hasClass('vmenu') && $('body').hasClass('uncode-fp-menu-hide') ? true : false;
44064        var menuHeight = $masthead.hasClass('menu-transparent') || hideMenu ? 0 : UNCODE.menuHeight;
44065        var bodyBorder = UNCODE.bodyBorder;
44066        var adminBarHeight = UNCODE.adminBarHeight;
44067
44068        displayWarnings();
44069
44070        //fixing bug in iScroll with links: https://github.com/cubiq/iscroll/issues/783
44071        iscrollOptions.click = isTouch; // see #2035
44072
44073        //extending iScroll options with the user custom ones
44074        iscrollOptions = $.extend(iscrollOptions, options.scrollOverflowOptions);
44075
44076        //easeInOutCubic animation included in the plugin
44077        $.extend($.easing,{ easeInOutCubic: function (x, t, b, c, d) {if ((t/=d/2) < 1) return c/2*t*t*t + b;return c/2*((t-=2)*t*t + 2) + b;}});
44078
44079        /**
44080        * Sets the autoScroll option.
44081        * It changes the scroll bar visibility and the history of the site as a result.
44082        */
44083        function setAutoScrolling(value, type){
44084            //removing the transformation
44085            if(!value){
44086                silentScroll(0);
44087            }
44088
44089            setVariableState('autoScrolling', value, type);
44090
44091            var element = $(SECTION_ACTIVE_SEL);
44092
44093            if(options.autoScrolling && !options.scrollBar){
44094                $htmlBody.css({
44095                    'overflow' : 'hidden !important',
44096                    'height' : '100%'
44097                });
44098
44099                //Uncode addition
44100                //setRecordHistory(originals.recordHistory, 'internal');
44101
44102                //for IE touch devices
44103                container.css({
44104                    '-ms-touch-action': 'none',
44105                    'touch-action': 'none'
44106                });
44107
44108                if(element.length){
44109                    //moving the container up
44110                    silentScroll(element.position().top);
44111                }
44112
44113            }else{
44114                $htmlBody.css({
44115                    'overflow' : 'visible !important',
44116                    'height' : 'initial'
44117                });
44118
44119                //Uncode addition
44120                //setRecordHistory(false, 'internal');
44121
44122                //for IE touch devices
44123                container.css({
44124                    '-ms-touch-action': '',
44125                    'touch-action': ''
44126                });
44127
44128                //scrolling the page to the section with no animation
44129                if (element.length) {
44130                    $htmlBody.scrollTop(element.position().top);
44131                }
44132            }
44133        }
44134
44135        /**
44136        * Defines wheter to record the history for each hash change in the URL.
44137        */
44138        function setRecordHistory(value, type){
44139            setVariableState('recordHistory', value, type);
44140        }
44141
44142        /**
44143        * Defines the scrolling speed
44144        */
44145        function setScrollingSpeed(value, type){
44146            setVariableState('scrollingSpeed', value, type);
44147        }
44148
44149        /**
44150        * Sets fitToSection
44151        */
44152        function setFitToSection(value, type){
44153            setVariableState('fitToSection', value, type);
44154        }
44155
44156        /**
44157        * Sets lockAnchors
44158        */
44159        function setLockAnchors(value){
44160            options.lockAnchors = value;
44161        }
44162
44163        /**
44164        * Adds or remove the possiblity of scrolling through sections by using the mouse wheel or the trackpad.
44165        */
44166        function setMouseWheelScrolling(value){
44167            if(value){
44168                addMouseWheelHandler();
44169                addMiddleWheelHandler();
44170            }else{
44171                removeMouseWheelHandler();
44172                removeMiddleWheelHandler();
44173            }
44174        }
44175
44176        /**
44177        * Adds or remove the possibility of scrolling through sections by using the mouse wheel/trackpad or touch gestures.
44178        * Optionally a second parameter can be used to specify the direction for which the action will be applied.
44179        *
44180        * @param directions string containing the direction or directions separated by comma.
44181        */
44182        function setAllowScrolling(value, directions){
44183            if(typeof directions !== 'undefined'){
44184                directions = directions.replace(/ /g,'').split(',');
44185
44186                $.each(directions, function (index, direction){
44187                    setIsScrollAllowed(value, direction, 'm');
44188                });
44189            }
44190            else if(value){
44191                setMouseWheelScrolling(true);
44192                addTouchHandler();
44193            }else{
44194                setMouseWheelScrolling(false);
44195                removeTouchHandler();
44196            }
44197        }
44198
44199        /**
44200        * Adds or remove the possibility of scrolling through sections by using the keyboard arrow keys
44201        */
44202        function setKeyboardScrolling(value, directions){
44203            if(typeof directions !== 'undefined'){
44204                directions = directions.replace(/ /g,'').split(',');
44205
44206                $.each(directions, function (index, direction){
44207                    setIsScrollAllowed(value, direction, 'k');
44208                });
44209            }else{
44210                options.keyboardScrolling = value;
44211            }
44212        }
44213
44214        /**
44215        * Moves the page up one section.
44216        */
44217        function moveSectionUp(){
44218            var prev = $(SECTION_ACTIVE_SEL).prev(SECTION_SEL);
44219
44220            //looping to the bottom if there's no more sections above
44221            if (!prev.length && (options.loopTop || options.continuousVertical)) {
44222                prev = $(SECTION_SEL).last();
44223            }
44224
44225            if (prev.length) {
44226                scrollPage(prev, null, true);
44227            }
44228        }
44229
44230        /**
44231        * Moves the page down one section.
44232        */
44233        function moveSectionDown(){
44234            var next = $(SECTION_ACTIVE_SEL).next(SECTION_SEL);
44235
44236            //looping to the top if there's no more sections below
44237            if(!next.length &&
44238                (options.loopBottom || options.continuousVertical)){
44239                next = $(SECTION_SEL).first();
44240            }
44241
44242            if(next.length){
44243                scrollPage(next, null, false);
44244            }
44245        }
44246
44247        /**
44248        * Moves the page to the given section and slide with no animation.
44249        * Anchors or index positions can be used as params.
44250        */
44251        function silentMoveTo(sectionAnchor, slideAnchor){
44252            setScrollingSpeed (0, 'internal');
44253            moveTo(sectionAnchor, slideAnchor);
44254            setScrollingSpeed (originals.scrollingSpeed, 'internal');
44255        }
44256
44257        /**
44258        * Moves the page to the given section and slide.
44259        * Anchors or index positions can be used as params.
44260        */
44261        function moveTo(sectionAnchor, slideAnchor){
44262            var destiny = getSectionByAnchor(sectionAnchor);
44263
44264            if (typeof slideAnchor !== 'undefined'){
44265                scrollPageAndSlide(sectionAnchor, slideAnchor);
44266            }else if(destiny.length > 0){
44267                scrollPage(destiny);
44268            }
44269        }
44270
44271        /**
44272        * Slides right the slider of the active section.
44273        * Optional `section` param.
44274        */
44275        function moveSlideRight(section){
44276            moveSlide('right', section);
44277        }
44278
44279        /**
44280        * Slides left the slider of the active section.
44281        * Optional `section` param.
44282        */
44283        function moveSlideLeft(section){
44284            moveSlide('left', section);
44285        }
44286
44287        /**
44288         * When resizing is finished, we adjust the slides sizes and positions
44289         */
44290        function reBuild(resizing){
44291            if(container.hasClass(DESTROYED)){ return; }  //nothing to do if the plugin was destroyed
44292
44293            isResizing = true;
44294
44295            windowsHeight = $window.height();  //updating global var
44296
44297            $(SECTION_SEL).each(function(){
44298                var slidesWrap = $(this).find(SLIDES_WRAPPER_SEL);
44299                var slides = $(this).find(SLIDE_SEL);
44300
44301                //adjusting the height of the table-cell for IE and Firefox
44302                if(options.verticalCentered){
44303                    $(this).find(TABLE_CELL_SEL).css('height', getTableHeight($(this)) + 'px');
44304                }
44305
44306                $(this).css('height', windowsHeight + 'px');
44307
44308                //resizing the scrolling divs
44309                if(options.scrollOverflow){
44310                    if(slides.length){
44311                        slides.each(function(){
44312                            createScrollBar($(this));
44313                        });
44314                    }else{
44315                        createScrollBar($(this));
44316                    }
44317                }
44318
44319                //adjusting the position fo the FULL WIDTH slides...
44320                if (slides.length > 1) {
44321                    landscapeScroll(slidesWrap, slidesWrap.find(SLIDE_ACTIVE_SEL));
44322                }
44323            });
44324
44325            var activeSection = $(SECTION_ACTIVE_SEL);
44326            var sectionIndex = activeSection.index(SECTION_SEL);
44327
44328            //isn't it the first section?
44329            if(sectionIndex){
44330                //adjusting the position for the current section
44331                silentMoveTo(sectionIndex + 1);
44332            }
44333
44334            isResizing = false;
44335            // Uncode change
44336            // $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container);
44337            $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container, getTableHeight());
44338            $.isFunction( options.afterReBuild ) && !resizing && options.afterReBuild.call(container);
44339        }
44340
44341        /**
44342        * Turns fullPage.js to normal scrolling mode when the viewport `width` or `height`
44343        * are smaller than the set limit values.
44344        */
44345        function setResponsive(active){
44346            var isResponsive = $body.hasClass(RESPONSIVE);
44347
44348            if(active){
44349                if(!isResponsive){
44350                    setAutoScrolling(false, 'internal');
44351                    setFitToSection(false, 'internal');
44352                    $(SECTION_NAV_SEL).hide();
44353                    $body.addClass(RESPONSIVE);
44354                    $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active);
44355                }
44356            }
44357            else if(isResponsive){
44358                setAutoScrolling(originals.autoScrolling, 'internal');
44359                setFitToSection(originals.autoScrolling, 'internal');
44360                $(SECTION_NAV_SEL).show();
44361                $body.removeClass(RESPONSIVE);
44362                $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active);
44363            }
44364        }
44365
44366        if($(this).length){
44367            //public functions
44368            FP.setAutoScrolling = setAutoScrolling;
44369            FP.setRecordHistory = setRecordHistory;
44370            FP.setScrollingSpeed = setScrollingSpeed;
44371            FP.setFitToSection = setFitToSection;
44372            FP.setLockAnchors = setLockAnchors;
44373            FP.setMouseWheelScrolling = setMouseWheelScrolling;
44374            FP.setAllowScrolling = setAllowScrolling;
44375            FP.setKeyboardScrolling = setKeyboardScrolling;
44376            FP.moveSectionUp = moveSectionUp;
44377            FP.moveSectionDown = moveSectionDown;
44378            FP.silentMoveTo = silentMoveTo;
44379            FP.moveTo = moveTo;
44380            FP.moveSlideRight = moveSlideRight;
44381            FP.moveSlideLeft = moveSlideLeft;
44382            FP.fitToSection = fitToSection;
44383            FP.reBuild = reBuild;
44384            FP.setResponsive = setResponsive;
44385            FP.destroy = destroy;
44386
44387            init();
44388
44389            bindEvents();
44390        }
44391
44392        function init(){
44393            //if css3 is not supported, it will use jQuery animations
44394            if(options.css3){
44395                options.css3 = support3d();
44396            }
44397
44398            options.scrollBar = options.scrollBar || options.hybrid;
44399
44400            setOptionsFromDOM();
44401            prepareDom();
44402            setAllowScrolling(true);
44403            setAutoScrolling(options.autoScrolling, 'internal');
44404            responsive();
44405
44406            //setting the class for the body element
44407            setBodyClass();
44408
44409            //Uncode addition
44410            // if(document.readyState === 'complete'){
44411            //     scrollToAnchor();
44412            // }
44413            // $window.on('load', scrollToAnchor);
44414        }
44415
44416        function bindEvents(){
44417            $window
44418                //when scrolling...
44419                //.on('scroll', scrollHandler)
44420
44421                //detecting any change on the URL to scroll to the given anchor link
44422                //(a way to detect back history button as we play with the hashes on the URL)
44423                .on('hashchange', hashChangeHandler)
44424
44425                //when opening a new tab (ctrl + t), `control` won't be pressed when coming back.
44426                .blur(blurHandler)
44427
44428                //when resizing the site, we adjust the heights of the sections, slimScroll...
44429                .resize(resizeHandler);
44430
44431            $document
44432                //Sliding with arrow keys, both, vertical and horizontal
44433                .keydown(keydownHandler)
44434
44435                //to prevent scrolling while zooming
44436                .keyup(keyUpHandler)
44437
44438                //Scrolls to the section when clicking the navigation bullet
44439                .on('click touchstart', SECTION_NAV_SEL + ' a', sectionBulletHandler)
44440
44441                //Scrolls the slider to the given slide destination for the given section
44442                .on('click touchstart', SLIDES_NAV_LINK_SEL, slideBulletHandler)
44443
44444                .on('click', SECTION_NAV_TOOLTIP_SEL, tooltipTextHandler);
44445
44446            //Scrolling horizontally when clicking on the slider controls.
44447            $(SECTION_SEL).on('click touchstart', SLIDES_ARROW_SEL, slideArrowHandler);
44448
44449            /**
44450            * Applying normalScroll elements.
44451            * Ignoring the scrolls over the specified selectors.
44452            */
44453            if(options.normalScrollElements){
44454                $document.on('mouseenter', options.normalScrollElements, function () {
44455                    setMouseWheelScrolling(false);
44456                });
44457
44458                $document.on('mouseleave', options.normalScrollElements, function(){
44459                    setMouseWheelScrolling(true);
44460                });
44461            }
44462        }
44463
44464        /**
44465        * Setting options from DOM elements if they are not provided.
44466        */
44467        function setOptionsFromDOM(){
44468            var sections = container.find(options.sectionSelector);
44469
44470            //no anchors option? Checking for them in the DOM attributes
44471            if(!options.anchors.length){
44472                options.anchors = sections.filter('[data-anchor]').map(function(){
44473                    return $(this).data('anchor').toString();
44474                }).get();
44475            }
44476
44477            //no tooltips option? Checking for them in the DOM attributes
44478            if(!options.navigationTooltips.length){
44479                options.navigationTooltips = sections.filter('[data-tooltip]').map(function(){
44480                    return $(this).data('tooltip').toString();
44481                }).get();
44482            }
44483        }
44484
44485        /**
44486        * Works over the DOM structure to set it up for the current fullpage options.
44487        */
44488        function prepareDom(){
44489            container.css({
44490                'height': '100%',
44491                'position': 'relative'
44492            });
44493
44494            //adding a class to recognize the container internally in the code
44495            container.addClass(WRAPPER);
44496            $('html').addClass(ENABLED);
44497
44498            windowsHeight = $window.height();
44499
44500            container.removeClass(DESTROYED); //in case it was destroyed before initializing it again
44501
44502            addInternalSelectors();
44503
44504             //styling the sections / slides / menu
44505            $(SECTION_SEL).each(function(index){
44506                var section = $(this);
44507                var slides = section.find(SLIDE_SEL);
44508                var numSlides = slides.length;
44509
44510                styleSection(section, index);
44511                styleMenu(section, index);
44512
44513                // if there's any slide
44514                if (numSlides > 0) {
44515                    styleSlides(section, slides, numSlides);
44516                }else{
44517                    if(options.verticalCentered){
44518                        addTableClass(section);
44519                    }
44520                }
44521            });
44522
44523            //fixed elements need to be moved out of the plugin container due to problems with CSS3.
44524            if(options.fixedElements && options.css3){
44525                $(options.fixedElements).appendTo($body);
44526            }
44527
44528            //vertical centered of the navigation + active bullet
44529            if(options.navigation){
44530                addVerticalNavigation();
44531            }
44532
44533            enableYoutubeAPI();
44534
44535            if(options.scrollOverflow){
44536                if(document.readyState === 'complete'){
44537                    createScrollBarHandler();
44538                }
44539                //after DOM and images are loaded
44540                $window.on('load', createScrollBarHandler);
44541            }else{
44542                afterRenderActions();
44543            }
44544        }
44545
44546        /**
44547        * Styles the horizontal slides for a section.
44548        */
44549        function styleSlides(section, slides, numSlides){
44550            var sliderWidth = numSlides * 100;
44551            var slideWidth = 100 / numSlides;
44552
44553            slides.wrapAll('<div class="' + SLIDES_CONTAINER + '" />');
44554            slides.parent().wrap('<div class="' + SLIDES_WRAPPER + '" />');
44555
44556            section.find(SLIDES_CONTAINER_SEL).css('width', sliderWidth + '%');
44557
44558            if(numSlides > 1){
44559                if(options.controlArrows){
44560                    createSlideArrows(section);
44561                }
44562
44563                if(options.slidesNavigation){
44564                    addSlidesNavigation(section, numSlides);
44565                }
44566            }
44567
44568            slides.each(function(index) {
44569                $(this).css('width', slideWidth + '%');
44570
44571                if(options.verticalCentered){
44572                    addTableClass($(this));
44573                }
44574            });
44575
44576            var startingSlide = section.find(SLIDE_ACTIVE_SEL);
44577
44578            //if the slide won't be an starting point, the default will be the first one
44579            //the active section isn't the first one? Is not the first slide of the first section? Then we load that section/sl
44579ide by default.
44580            if( startingSlide.length &&  ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) !== 0 || ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) === 0 && startingSlide.index() !== 0))){
44581                silentLandscapeScroll(startingSlide, 'internal');
44582            }else{
44583                slides.eq(0).addClass(ACTIVE);
44584            }
44585        }
44586
44587        /**
44588        * Styling vertical sections
44589        */
44590        function styleSection(section, index){
44591            //if no active section is defined, the 1st one will be the default one
44592            if(!index && $(SECTION_ACTIVE_SEL).length === 0) {
44593                section.addClass(ACTIVE);
44594            }
44595            startingSection = $(SECTION_ACTIVE_SEL);
44596
44597            section.css('height', windowsHeight + 'px');
44598
44599            if(options.paddingTop){
44600                section.css('padding-top', options.paddingTop);
44601            }
44602
44603            if(options.paddingBottom){
44604                section.css('padding-bottom', options.paddingBottom);
44605            }
44606
44607            if (typeof options.sectionsColor[index] !==  'undefined') {
44608                section.css('background-color', options.sectionsColor[index]);
44609            }
44610
44611            if (typeof options.anchors[index] !== 'undefined') {
44612                section.attr('data-anchor', options.anchors[index]);
44613            }
44614        }
44615
44616        /**
44617        * Sets the data-anchor attributes to the menu elements and activates the current one.
44618        */
44619        function styleMenu(section, index){
44620            if (typeof options.anchors[index] !== 'undefined') {
44621                //activating the menu / nav element on load
44622                if(section.hasClass(ACTIVE)){
44623                    activateMenuAndNav(options.anchors[index], index);
44624                }
44625            }
44626
44627            //moving the menu outside the main container if it is inside (avoid problems with fixed positions when using CSS3 tranforms)
44628            if(options.menu && options.css3 && $(options.menu).closest(WRAPPER_SEL).length){
44629                $(options.menu).appendTo($body);
44630            }
44631        }
44632
44633        /**
44634        * Adds internal classes to be able to provide customizable selectors
44635        * keeping the link with the style sheet.
44636        */
44637        function addInternalSelectors(){
44638            container.find(options.sectionSelector).addClass(SECTION);
44639            container.find(options.slideSelector).addClass(SLIDE);
44640        }
44641
44642        /**
44643        * Creates the control arrows for the given section
44644        */
44645        function createSlideArrows(section){
44646            section.find(SLIDES_WRAPPER_SEL).after('<div class="' + SLIDES_ARROW_PREV + '"></div><div class="' + SLIDES_ARROW_NEXT + '"></div>');
44647
44648            if(options.controlArrowColor!='#fff'){
44649                section.find(SLIDES_ARROW_NEXT_SEL).css('border-color', 'transparent transparent transparent '+options.controlArrowColor);
44650                section.find(SLIDES_ARROW_PREV_SEL).css('border-color', 'transparent '+ options.controlArrowColor + ' transparent transparent');
44651            }
44652
44653            if(!options.loopHorizontal){
44654                section.find(SLIDES_ARROW_PREV_SEL).hide();
44655            }
44656        }
44657
44658        /**
44659        * Creates a vertical navigation bar.
44660        */
44661        function addVerticalNavigation(){
44662            $body.append('<div id="' + SECTION_NAV + '"><ul></ul></div>');
44663            var nav = $(SECTION_NAV_SEL);
44664
44665            nav.addClass(function() {
44666                return options.showActiveTooltip ? SHOW_ACTIVE_TOOLTIP + ' ' + options.navigationPosition : options.navigationPosition;
44667            });
44668
44669            for (var i = 0; i < $(SECTION_SEL).length; i++) {
44670                var link = '';
44671                if (options.anchors.length) {
44672                    link = options.anchors[i];
44673                }
44674
44675                var li = '<li><a href="#' + link + '"><span></span></a>';
44676
44677                // Only add tooltip if needed (defined by user)
44678                var tooltip = options.navigationTooltips[i];
44679
44680                if (typeof tooltip !== 'undefined' && tooltip !== '') {
44681                    li += '<div class="' + SECTION_NAV_TOOLTIP + ' ' + options.navigationPosition + '">' + tooltip + '</div>';
44682                }
44683
44684                li += '</li>';
44685
44686                nav.find('ul').append(li);
44687            }
44688
44689            //centering it vertically
44690            $(SECTION_NAV_SEL).css('margin-top', '-' + ($(SECTION_NAV_SEL).height()/2) + 'px');
44691
44692            //activating the current active section
44693            $(SECTION_NAV_SEL).find('li').eq($(SECTION_ACTIVE_SEL).index(SECTION_SEL)).find('a').addClass(ACTIVE);
44694        }
44695
44696        /**
44697        * Creates the slim scroll scrollbar for the sections and slides inside them.
44698        */
44699        function createScrollBarHandler(){
44700            $(SECTION_SEL).each(function(){
44701                var slides = $(this).find(SLIDE_SEL);
44702
44703                if(slides.length){
44704                    slides.each(function(){
44705                        createScrollBar($(this));
44706                    });
44707                }else{
44708                    createScrollBar($(this));
44709                }
44710
44711            });
44712            afterRenderActions();
44713        }
44714
44715        /*
44716        * Enables the Youtube videos API so we can control their flow if necessary.
44717        */
44718        function enableYoutubeAPI(){
44719            container.find('iframe[src*="youtube.com/embed/"]').each(function(){
44720                addURLParam($(this), 'enablejsapi=1');
44721            });
44722        }
44723
44724        /**
44725        * Adds a new parameter and its value to the `src` of a given element
44726        */
44727        function addURLParam(element, newParam){
44728            var originalSrc = element.attr('src');
44729            element.attr('src', originalSrc + getUrlParamSign(originalSrc) + newParam);
44730        }
44731
44732        /*
44733        * Returns the prefix sign to use for a new parameter in an existen URL.
44734        *
44735        * @return {String}  ? | &
44736        */
44737        function getUrlParamSign(url){
44738            return ( !/\?/.test( url ) ) ? '?' : '&';
44739        }
44740
44741        /**
44742        * Actions and callbacks to fire afterRender
44743        */
44744        function afterRenderActions(){
44745            var section = $(SECTION_ACTIVE_SEL);
44746
44747            section.addClass(COMPLETELY);
44748
44749            if(options.scrollOverflowHandler.afterRender){
44750                options.scrollOverflowHandler.afterRender(section);
44751            }
44752            lazyLoad(section);
44753            playMedia(section);
44754            options.scrollOverflowHandler.afterLoad();
44755
44756            if(isDestinyTheStartingSection()){
44757                $.isFunction( options.afterLoad ) && options.afterLoad.call(section, section.data('anchor'), (section.index(SECTION_SEL) + 1));
44758            }
44759
44760            // Uncode change
44761            // $.isFunction( options.afterRender ) && options.afterRender.call(container);
44762            $.isFunction( options.afterRender ) && options.afterRender.call(container, getTableHeight());
44763        }
44764
44765        /**
44766        * Determines if the URL anchor destiny is the starting section (the one using 'active' class before initialization)
44767        */
44768        function isDestinyTheStartingSection(){
44769            var anchors =  window.location.hash.replace('#', '').split('/');
44770            var destinationSection = getSectionByAnchor(decodeURIComponent(anchors[0]));
44771
44772            return !destinationSection.length || destinationSection.length && destinationSection.index() === startingSection.index();
44773        }
44774
44775
44776        var isScrolling = false;
44777        var lastScroll = 0;
44778
44779        //when scrolling...
44780        function scrollHandler(){
44781            var currentSection;
44782
44783            if(!options.autoScrolling || options.scrollBar){
44784                var currentScroll = $window.scrollTop();
44785                var scrollDirection = getScrollDirection(currentScroll);
44786                var visibleSectionIndex = 0;
44787                var screen_mid = currentScroll + ($window.height() / 2.0);
44788                var isAtBottom = $body.height() - $window.height() === currentScroll;
44789                var sections =  document.querySelectorAll(SECTION_SEL);
44790
44791                //when using `auto-height` for a small last section it won't be centered in the viewport
44792                if(isAtBottom){
44793                    visibleSectionIndex = sections.length - 1;
44794                }
44795                //is at top? when using `auto-height` for a small first section it won't be centered in the viewport
44796                else if(!currentScroll){
44797                    visibleSectionIndex = 0;
44798                }
44799
44800                //taking the section which is showing more content in the viewport
44801                else{
44802                    for (var i = 0; i < sections.length; ++i) {
44803                        var section = sections[i];
44804
44805                        // Pick the the last section which passes the middle line of the screen.
44806                        if (section.offsetTop <= screen_mid)
44807                        {
44808                            visibleSectionIndex = i;
44809                        }
44810                    }
44811                }
44812
44813                if(isCompletelyInViewPort(scrollDirection)){
44814                    if(!$(SECTION_ACTIVE_SEL).hasClass(COMPLETELY)){
44815                        $(SECTION_ACTIVE_SEL).addClass(COMPLETELY).siblings().removeClass(COMPLETELY);
44816                    }
44817                }
44818
44819                //geting the last one, the current one on the screen
44820                currentSection = $(sections).eq(visibleSectionIndex);
44821
44822                //setting the visible section as active when manually scrolling
44823                //executing only once the first time we reach the section
44824                if(!currentSection.hasClass(ACTIVE)){
44825                    isScrolling = true;
44826                    var leavingSection = $(SECTION_ACTIVE_SEL);
44827                    var leavingSectionIndex = leavingSection.index(SECTION_SEL) + 1;
44828                    var yMovement = getYmovement(currentSection);
44829                    var anchorLink  = currentSection.data('anchor');
44830                    var sectionIndex = currentSection.index(SECTION_SEL) + 1;
44831                    var activeSlide = currentSection.find(SLIDE_ACTIVE_SEL);
44832                    var slideIndex;
44833                    var slideAnchorLink;
44834
44835                    if(activeSlide.length){
44836                        slideAnchorLink = activeSlide.data('anchor');
44837                        slideIndex = activeSlide.index();
44838                    }
44839
44840                    if(canScroll){
44841                        currentSection.addClass(ACTIVE).siblings().removeClass(ACTIVE);
44842
44843                        $.isFunction( options.onLeave ) && options.onLeave.call( leavingSection, leavingSectionIndex, sectionIndex, yMovement);
44844                        $.isFunction( options.afterLoad ) && options.afterLoad.call( currentSection, anchorLink, sectionIndex);
44845
44846                        stopMedia(leavingSection);
44847                        lazyLoad(currentSection);
44848                        playMedia(currentSection);
44849
44850                        activateMenuAndNav(anchorLink, sectionIndex - 1);
44851
44852                        if(options.anchors.length){
44853                            //needed to enter in hashChange event when using the menu with anchor links
44854                            lastScrolledDestiny = anchorLink;
44855                        }
44856                        setState(slideIndex, slideAnchorLink, anchorLink, sectionIndex);
44857                    }
44858
44859                    //small timeout in order to avoid entering in hashChange event when scrolling is not finished yet
44860                    clearTimeout(scrollId);
44861                    scrollId = setTimeout(function(){
44862                        isScrolling = false;
44863                    }, 100);
44864                }
44865
44866                if(options.fitToSection){
44867                    //for the auto adjust of the viewport to fit a whole section
44868                    clearTimeout(scrollId2);
44869
44870                    scrollId2 = setTimeout(function(){
44871                        //checking it again in case it changed during the delay
44872                        if(options.fitToSection){
44873                            fitToSection();
44874                        }
44875                    }, options.fitToSectionDelay);
44876                }
44877            }
44878        }
44879
44880        /**
44881        * Fits the site to the nearest active section
44882        */
44883        function fitToSection(){
44884            //checking fitToSection again in case it was set to false before the timeout delay
44885            if(canScroll){
44886                //allows to scroll to an active section and
44887                //if the section is already active, we prevent firing callbacks
44888                isResizing = true;
44889
44890                scrollPage($(SECTION_ACTIVE_SEL));
44891                isResizing = false;
44892            }
44893        }
44894
44895        /**
44896        * Determines whether the active section has seen in its whole or not.
44897        */
44898        function isCompletelyInViewPort(movement){
44899            var top = $(SECTION_ACTIVE_SEL).position().top;
44900            var bottom = top + $window.height();
44901
44902            if(movement == 'up'){
44903                return bottom >= ($window.scrollTop() + $window.height());
44904            }
44905            return top <= $window.scrollTop();
44906        }
44907
44908        /**
44909        * Gets the directon of the the scrolling fired by the scroll event.
44910        */
44911        function getScrollDirection(currentScroll){
44912            var direction = currentScroll > lastScroll ? 'down' : 'up';
44913
44914            lastScroll = currentScroll;
44915
44916            //needed for auto-height sections to determine if we want to scroll to the top or bottom of the destination
44917            previousDestTop = currentScroll;
44918
44919            return direction;
44920        }
44921
44922        /**
44923        * Determines the way of scrolling up or down:
44924        * by 'automatically' scrolling a section or by using the default and normal scrolling.
44925        */
44926        function scrolling(type, scrollable){
44927            if (!isScrollAllowed.m[type]){
44928                return;
44929            }
44930            var check = (type === 'down') ? 'bottom' : 'top';
44931            var scrollSection = (type === 'down') ? moveSectionDown : moveSectionUp;
44932
44933            if(scrollable.length > 0 ){
44934                //is the scrollbar at the start/end of the scroll?
44935                if(options.scrollOverflowHandler.isScrolled(check, scrollable)){
44936                    scrollSection();
44937                }else{
44938                    return true;
44939                }
44940            }else{
44941                // moved up/down
44942                scrollSection();
44943            }
44944        }
44945
44946        /*
44947        * Preventing bouncing in iOS #2285
44948        */
44949        function preventBouncing(event){
44950            var e = event.originalEvent;
44951            if(!checkParentForNormalScrollElement(event.target) && options.autoScrolling && isReallyTouch(e) && isScrollAllowed.m.up){
44952                //preventing the easing on iOS devices
44953                event.preventDefault();
44954            }
44955        }
44956
44957        var touchStartY = 0;
44958        var touchStartX = 0;
44959        var touchEndY = 0;
44960        var touchEndX = 0;
44961
44962        /* Detecting touch events
44963
44964        * As we are changing the top property of the page on scrolling, we can not use the traditional way to detect it.
44965        * This way, the touchstart and the touch moves shows an small difference between them which is the
44966        * used one to determine the direction.
44967        */
44968        function touchMoveHandler(event){
44969            var e = event.originalEvent;
44970            var activeSection = $(e.target).closest(SECTION_SEL);
44971
44972            // additional: if one of the normalScrollElements isn't within options.normalScrollElementTouchThreshold hops up the DOM chain
44973            if (!checkParentForNormalScrollElement(event.target) && isReallyTouch(e) ) {
44974
44975                if(options.autoScrolling){
44976                    //preventing the easing on iOS devices
44977                    event.preventDefault();
44978                }
44979
44980                var scrollable = options.scrollOverflowHandler.scrollable(activeSection);
44981                var touchEvents = getEventsPage(e);
44982
44983                touchEndY = touchEvents.y;
44984                touchEndX = touchEvents.x;
44985
44986                //if movement in the X axys is greater than in the Y and the currect section has slides...
44987                if (activeSection.find(SLIDES_WRAPPER_SEL).length && Math.abs(touchStartX - touchEndX) > (Math.abs(touchStartY - touchEndY))) {
44988
44989                    //is the movement greater than the minimum resistance to scroll?
44990                    if (!slideMoving && Math.abs(touchStartX - touchEndX) > ($window.outerWidth() / 100 * options.touchSensitivity)) {
44991                        if (touchStartX > touchEndX) {
44992                            if(isScrollAllowed.m.right){
44993                                moveSlideRight(activeSection); //next
44994                            }
44995                        } else {
44996                            if(isScrollAllowed.m.left){
44997                                moveSlideLeft(activeSection); //prev
44998                            }
44999                        }
45000                    }
45001                }
45002
45003                //vertical scrolling (only when autoScrolling is enabled)
45004                else if(options.autoScrolling && canScroll){
45005
45006                    //is the movement greater than the minimum resistance to scroll?
45007                    if (Math.abs(touchStartY - touchEndY) > ($window.height() / 100 * options.touchSensitivity)) {
45008                        if (touchStartY > touchEndY) {
45009                            scrolling('down', scrollable);
45010                        } else if (touchEndY > touchStartY) {
45011                            scrolling('up', scrollable);
45012                        }
45013                    }
45014                }
45015            }
45016        }
45017
45018        /**
45019         * recursive function to loop up the parent nodes to check if one of them exists in options.normalScrollElements
45020         * Currently works well for iOS - Android might need some testing
45021         * @param  {Element} el  target element / jquery selector (in subsequent nodes)
45022         * @param  {int}     hop current hop compared to options.normalScrollElementTouchThreshold
45023         * @return {boolean} true if there is a match to options.normalScrollElements
45024         */
45025        function checkParentForNormalScrollElement (el, hop) {
45026            hop = hop || 0;
45027            var parent = $(el).parent();
45028
45029            if (hop < options.normalScrollElementTouchThreshold &&
45030                parent.is(options.normalScrollElements) ) {
45031                return true;
45032            } else if (hop == options.normalScrollElementTouchThreshold) {
45033                return false;
45034            } else {
45035                return checkParentForNormalScrollElement(parent, ++hop);
45036            }
45037        }
45038
45039        /**
45040        * As IE >= 10 fires both touch and mouse events when using a mouse in a touchscreen
45041        * this way we make sure that is really a touch event what IE is detecting.
45042        */
45043        function isReallyTouch(e){
45044            //if is not IE   ||  IE is detecting `touch` or `pen`
45045            return typeof e.pointerType === 'undefined' || e.pointerType != 'mouse';
45046        }
45047
45048        /**
45049        * Handler for the touch start event.
45050        */
45051        function touchStartHandler(event){
45052            var e = event.originalEvent;
45053
45054            //stopping the auto scroll to adjust to a section
45055            if(options.fitToSection){
45056                $htmlBody.stop();
45057            }
45058
45059            if(isReallyTouch(e)){
45060                var touchEvents = getEventsPage(e);
45061                touchStartY = touchEvents.y;
45062                touchStartX = touchEvents.x;
45063            }
45064        }
45065
45066        /**
45067        * Gets the average of the last `number` elements of the given array.
45068        */
45069        function getAverage(elements, number){
45070            var sum = 0;
45071
45072            //taking `number` elements from the end to make the average, if there are not enought, 1
45073            var lastElements = elements.slice(Math.max(elements.length - number, 1));
45074
45075            for(var i = 0; i < lastElements.length; i++){
45076                sum = sum + lastElements[i];
45077            }
45078
45079            return Math.ceil(sum/number);
45080        }
45081
45082        /**
45083         * Detecting mousewheel scrolling
45084         *
45085         * http://blogs.sitepointstatic.com/examples/tech/mouse-wheel/index.html
45086         * http://www.sitepoint.com/html5-javascript-mouse-wheel/
45087         */
45088        var prevTime = new Date().getTime();
45089
45090        function MouseWheelHandler(e) {
45091            var curTime = new Date().getTime();
45092            var isNormalScroll = $(COMPLETELY_SEL).hasClass(NORMAL_SCROLL);
45093
45094            //autoscrolling and not zooming?
45095            if(options.autoScrolling && !controlPressed && !isNormalScroll){
45096                // cross-browser wheel delta
45097                e = e || window.event;
45098                var value = e.wheelDelta || -e.deltaY || -e.detail;
45099                var delta = Math.max(-1, Math.min(1, value));
45100
45101                var horizontalDetection = typeof e.wheelDeltaX !== 'undefined' || typeof e.deltaX !== 'undefined';
45102                var isScrollingVertically = (Math.abs(e.wheelDeltaX) < Math.abs(e.wheelDelta)) || (Math.abs(e.deltaX ) < Math.abs(e.deltaY) || !horizontalDetection);
45103
45104                //Limiting the array to 150 (lets not waste memory!)
45105                if(scrollings.length > 149){
45106                    scrollings.shift();
45107                }
45108
45109                //keeping record of the previous scrollings
45110                scrollings.push(Math.abs(value));
45111
45112                //preventing to scroll the site on mouse wheel when scrollbar is present
45113                if(options.scrollBar){
45114                    e.preventDefault ? e.preventDefault() : e.returnValue = false;
45115                }
45116
45117                var activeSection = $(SECTION_ACTIVE_SEL);
45118                var scrollable = options.scrollOverflowHandler.scrollable(activeSection);
45119
45120                //time difference between the last scroll and the current one
45121                var timeDiff = curTime-prevTime;
45122                prevTime = curTime;
45123
45124                //haven't they scrolled in a while?
45125                //(enough to be consider a different scrolling action to scroll another section)
45126                if(timeDiff > 200){
45127                    //emptying the array, we dont care about old scrollings for our averages
45128                    scrollings = [];
45129                }
45130
45131                if(canScroll){
45132                    var averageEnd = getAverage(scrollings, 10);
45133                    var averageMiddle = getAverage(scrollings, 70);
45134                    var isAccelerating = averageEnd >= averageMiddle;
45135
45136                    //to avoid double swipes...
45137                    if(isAccelerating && isScrollingVertically){
45138                        //scrolling down?
45139                        if (delta < 0) {
45140                            scrolling('down', scrollable);
45141
45142                        //scrolling up?
45143                        }else {
45144                            scrolling('up', scrollable);
45145                        }
45146                    }
45147                }
45148
45149                return false;
45150            }
45151
45152            if(options.fitToSection){
45153                //stopping the auto scroll to adjust to a section
45154                $htmlBody.stop();
45155            }
45156        }
45157
45158        /**
45159        * Slides a slider to the given direction.
45160        * Optional `section` param.
45161        */
45162        function moveSlide(direction, section){
45163            var activeSection = typeof section === 'undefined' ? $(SECTION_ACTIVE_SEL) : section;
45164            var slides = activeSection.find(SLIDES_WRAPPER_SEL);
45165            var numSlides = slides.find(SLIDE_SEL).length;
45166
45167            // more than one slide needed and nothing should be sliding
45168            if (!slides.length || slideMoving || numSlides < 2) {
45169                return;
45170            }
45171
45172            var currentSlide = slides.find(SLIDE_ACTIVE_SEL);
45173            var destiny = null;
45174
45175            if(direction === 'left'){
45176                destiny = currentSlide.prev(SLIDE_SEL);
45177            }else{
45178                destiny = currentSlide.next(SLIDE_SEL);
45179            }
45180
45181            //isn't there a next slide in the secuence?
45182            if(!destiny.length){
45183                //respect loopHorizontal settin
45184                if (!options.loopHorizontal) return;
45185
45186                if(direction === 'left'){
45187                    destiny = currentSlide.siblings(':last');
45188                }else{
45189                    destiny = currentSlide.siblings(':first');
45190                }
45191            }
45192
45193            slideMoving = true;
45194
45195            landscapeScroll(slides, destiny, direction);
45196        }
45197
45198        /**
45199        * Maintains the active slides in the viewport
45200        * (Because the `scroll` animation might get lost with some actions, such as when using continuousVertical)
45201        */
45202        function keepSlidesPosition(){
45203            $(SLIDE_ACTIVE_SEL).each(function(){
45204                silentLandscapeScroll($(this), 'internal');
45205            });
45206        }
45207
45208        var previousDestTop = 0;
45209        /**
45210        * Returns the destination Y position based on the scrolling direction and
45211        * the height of the section.
45212        */
45213        function getDestinationPosition(element){
45214            var elemPosition = element.position();
45215
45216            //top of the desination will be at the top of the viewport
45217            var position = elemPosition.top;
45218            var isScrollingDown =  elemPosition.top > previousDestTop;
45219            var sectionBottom = position - windowsHeight + element.outerHeight();
45220            var bigSectionsDestination = options.bigSectionsDestination;
45221
45222            //Uncode addition
45223            var containerH = container.outerHeight();
45224            var containerPosition = container.offset();
45225
45226            //########### Commented by Uncode - START ###########
45227            //is the destination element bigger than the viewport?
45228            // if(element.outerHeight() > windowsHeight){
45229            //     //scrolling up?
45230            //     if(!isScrollingDown && !bigSectionsDestination || bigSectionsDestination === 'bottom' ){
45231            //         position = sectionBottom;
45232            //     }
45233            // }
45234
45235            // //sections equal or smaller than the viewport height && scrolling down? ||  is resizing and its in the last section
45236            // else if(isScrollingDown || (isResizing && element.is(':last-child')) ){
45237            //     //The bottom of the destination will be at the bottom of the viewport
45238            //     position = sectionBottom;
45239            // }
45240            //########### Commented by Uncode - END ###########
45241
45242            //Uncode addition
45243            if ( !$masthead.hasClass('menu-transparent') && $('body').hasClass('uncode-fp-menu-shrink') && !element.is(':first-child') )
45244                position += 18;
45245            if ( ( containerH + menuHeight + bodyBorder + adminBarHeight - windowsHeight ) < position || ( isResizing && element.is(':last-child') ) ) {
45246                position = sectionBottom + menuHeight + bodyBorder*2 + adminBarHeight;
45247            }
45248
45249            /*
45250            Keeping record of the last scrolled position to determine the scrolling direction.
45251            No conventional methods can be used as the scroll bar might not be present
45252            AND the section might not be active if it is auto-height and didnt reach the middle
45253            of the viewport.
45254            */
45255            previousDestTop = position;
45256            return position;
45257        }
45258
45259        /**
45260        * Scrolls the site to the given element and scrolls to the slide if a callback is given.
45261        */
45262        function scrollPage(element, callback, isMovementUp){
45263            if(typeof element === 'undefined'){ return; } //there's no element to scroll, leaving the function
45264
45265            var dtop = getDestinationPosition(element);
45266            var slideAnchorLink;
45267            var slideIndex;
45268
45269            //local variables
45270            var v = {
45271                element: element,
45272                callback: callback,
45273                isMovementUp: isMovementUp,
45274                dtop: dtop,
45275                yMovement: getYmovement(element),
45276                anchorLink: element.data('anchor'),
45277                sectionIndex: element.index(SECTION_SEL),
45278                activeSlide: element.find(SLIDE_ACTIVE_SEL),
45279                activeSection: $(SECTION_ACTIVE_SEL),
45280                leavingSection: $(SECTION_ACTIVE_SEL).index(SECTION_SEL) + 1,
45281
45282                //caching the value of isResizing at the momment the function is called
45283                //because it will be checked later inside a setTimeout and the value might change
45284                localIsResizing: isResizing
45285            };
45286
45287            //quiting when destination scroll is the same as the current one
45288            if((v.activeSection.is(element) && !isResizing) || (options.scrollBar && $window.scrollTop() === v.dtop && !element.hasClass(AUTO_HEIGHT) )){ return; }
45289
45290            if(v.activeSlide.length){
45291                slideAnchorLink = v.activeSlide.data('anchor');
45292                slideIndex = v.activeSlide.index();
45293            }
45294
45295            // If continuousVertical && we need to wrap around
45296            if (options.autoScrolling && options.continuousVertical && typeof (v.isMovementUp) !== "undefined" &&
45297                ((!v.isMovementUp && v.yMovement == 'up') || // Intending to scroll down but about to go up or
45298                (v.isMovementUp && v.yMovement == 'down'))) { // intending to scroll up but about to go down
45299
45300                v = createInfiniteSections(v);
45301            }
45302
45303            //callback (onLeave) if the site is not just resizing and readjusting the slides
45304            if($.isFunction(options.onLeave) && !v.localIsResizing){
45305                if(options.onLeave.call(v.activeSection, v.leavingSection, (v.sectionIndex + 1), v.yMovement) === false){
45306                    return;
45307                }
45308            }
45309
45310            //pausing media of the leaving section (if we are not just resizing, as destinatino will be the same one)
45311            if(!v.localIsResizing){
45312                stopMedia(v.activeSection);
45313            }
45314
45315            options.scrollOverflowHandler.beforeLeave();
45316            element.addClass(ACTIVE).siblings().removeClass(ACTIVE);
45317            lazyLoad(element);
45318            options.scrollOverflowHandler.onLeave();
45319
45320
45321            //preventing from activating the MouseWheelHandler event
45322            //more than once if the page is scrolling
45323            canScroll = false;
45324
45325            setState(slideIndex, slideAnchorLink, v.anchorLink, v.sectionIndex);
45326
45327            performMovement(v);
45328
45329            //flag to avoid callingn `scrollPage()` twice in case of using anchor links
45330            lastScrolledDestiny = v.anchorLink;
45331
45332            //avoid firing it twice (as it does also on scroll)
45333            activateMenuAndNav(v.anchorLink, v.sectionIndex);
45334        }
45335
45336        /**
45337        * Performs the vertical movement (by CSS3 or by jQuery)
45338        */
45339        function performMovement(v){
45340            // using CSS3 translate functionality
45341            if (options.css3 && options.autoScrolling && !options.scrollBar) {
45342
45343                // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625
45344                // that's why we round it to 0.
45345                var translate3d = 'translate3d(0px, -' + Math.round(v.dtop) + 'px, 0px)';
45346                transformContainer(translate3d, true);
45347
45348                //even when the scrollingSpeed is 0 there's a little delay, which might cause the
45349                //scrollingSpeed to change in case of using silentMoveTo();
45350                if(options.scrollingSpeed){
45351                    clearTimeout(afterSectionLoadsId);
45352                    afterSectionLoadsId = setTimeout(function () {
45353                        afterSectionLoads(v);
45354                    }, options.scrollingSpeed);
45355                }else{
45356                    afterSectionLoads(v);
45357                }
45358            }
45359
45360            // using jQuery animate
45361            else{
45362                var scrollSettings = getScrollSettings(v);
45363
45364                $(scrollSettings.element).animate(
45365                    scrollSettings.options,
45366                options.scrollingSpeed, options.easing).promise().done(function () { //only one single callback in case of animating  `html, body`
45367                    if(options.scrollBar){
45368
45369                        /* Hack!
45370                        The timeout prevents setting the most dominant section in the viewport as "active" when the user
45371                        scrolled to a smaller section by using the mousewheel (auto scrolling) rather than draging the scroll bar.
45372
45373                        When using scrollBar:true It seems like the scroll events still getting propagated even after the scrolling animation has finished.
45374                        */
45375                        setTimeout(function(){
45376                            afterSectionLoads(v);
45377                        },30);
45378                    }else{
45379                        afterSectionLoads(v);
45380                    }
45381                });
45382            }
45383        }
45384
45385        /**
45386        * Gets the scrolling settings depending on the plugin autoScrolling option
45387        */
45388        function getScrollSettings(v){
45389            var scroll = {};
45390
45391            if(options.autoScrolling && !options.scrollBar){
45392                scroll.options = { 'top': -v.dtop};
45393                scroll.element = WRAPPER_SEL;
45394            }else{
45395                scroll.options = { 'scrollTop': v.dtop};
45396                scroll.element = 'html, body';
45397            }
45398
45399            return scroll;
45400        }
45401
45402        /**
45403        * Adds sections before or after the current one to create the infinite effect.
45404        */
45405        function createInfiniteSections(v){
45406            // Scrolling down
45407            if (!v.isMovementUp) {
45408                // Move all previous sections to after the active section
45409                $(SECTION_ACTIVE_SEL).after(v.activeSection.prevAll(SECTION_SEL).get().reverse());
45410            }
45411            else { // Scrolling up
45412                // Move all next sections to before the active section
45413                $(SECTION_ACTIVE_SEL).before(v.activeSection.nextAll(SECTION_SEL));
45414            }
45415
45416            // Maintain the displayed position (now that we changed the element order)
45417            silentScroll($(SECTION_ACTIVE_SEL).position().top);
45418
45419            // Maintain the active slides visible in the viewport
45420            keepSlidesPosition();
45421
45422            // save for later the elements that still need to be reordered
45423            v.wrapAroundElements = v.activeSection;
45424
45425            // Recalculate animation variables
45426            v.dtop = v.element.position().top;
45427            v.yMovement = getYmovement(v.element);
45428
45429            return v;
45430        }
45431
45432        /**
45433        * Fix section order after continuousVertical changes have been animated
45434        */
45435        function continuousVerticalFixSectionOrder (v) {
45436            // If continuousVertical is in effect (and autoScrolling would also be in effect then),
45437            // finish moving the elements around so the direct navigation will function more simply
45438            if (!v.wrapAroundElements || !v.wrapAroundElements.length) {
45439                return;
45440            }
45441
45442            if (v.isMovementUp) {
45443                $(SECTION_FIRST_SEL).before(v.wrapAroundElements);
45444            }
45445            else {
45446                $(SECTION_LAST_SEL).after(v.wrapAroundElements);
45447            }
45448
45449            silentScroll($(SECTION_ACTIVE_SEL).position().top);
45450
45451            // Maintain the active slides visible in the viewport
45452            keepSlidesPosition();
45453        }
45454
45455
45456        /**
45457        * Actions to do once the section is loaded.
45458        */
45459        function afterSectionLoads (v){
45460            continuousVerticalFixSectionOrder(v);
45461
45462            //callback (afterLoad) if the site is not just resizing and readjusting the slides
45463            $.isFunction(options.afterLoad) && !v.localIsResizing && options.afterLoad.call(v.element, v.anchorLink, (v.sectionIndex + 1));
45464            options.scrollOverflowHandler.afterLoad();
45465
45466            if(!v.localIsResizing){
45467                playMedia(v.element);
45468            }
45469
45470            v.element.addClass(COMPLETELY).siblings().removeClass(COMPLETELY);
45471
45472            canScroll = true;
45473
45474            $.isFunction(v.callback) && v.callback.call(this);
45475        }
45476
45477        /**
45478        * Sets the value for the given attribute from the `data-` attribute with the same suffix
45479        * ie: data-srcset ==> srcset  |  data-src ==> src
45480        */
45481        function setSrc(element, attribute){
45482            element
45483                .attr(attribute, element.data(attribute))
45484                .removeAttr('data-' + attribute);
45485        }
45486
45487        /**
45488        * Lazy loads image, video and audio elements.
45489        */
45490        function lazyLoad(destiny){
45491            if (!options.lazyLoading){
45492                return;
45493            }
45494
45495            var panel = getSlideOrSection(destiny);
45496            var element;
45497
45498            panel.find('img[data-src], img[data-srcset], source[data-src], audio[data-src], iframe[data-src]').each(function(){
45499                element = $(this);
45500
45501                $.each(['src', 'srcset'], function(index, type){
45502                    var attribute = element.attr('data-' + type);
45503                    if(typeof attribute !== 'undefined' && attribute){
45504                        setSrc(element, type);
45505                    }
45506                });
45507
45508                if(element.is('source')){
45509                    element.closest('video').get(0).load();
45510                }
45511            });
45512        }
45513
45514        /**
45515        * Plays video and audio elements.
45516        */
45517        function playMedia(destiny){
45518            var panel = getSlideOrSection(destiny);
45519
45520            //playing HTML5 media elements
45521            panel.find('video, audio').each(function(){
45522                var element = $(this).get(0);
45523
45524                if( element.hasAttribute('data-autoplay') && typeof element.play === 'function' ) {
45525                    element.play();
45526                }
45527            });
45528
45529            //youtube videos
45530            panel.find('iframe[src*="youtube.com/embed/"]').each(function(){
45531                var element = $(this).get(0);
45532
45533                if ( element.hasAttribute('data-autoplay') ){
45534                    playYoutube(element);
45535                }
45536
45537                //in case the URL was not loaded yet. On page load we need time for the new URL (with the API string) to load.
45538                element.onload = function() {
45539                    if ( element.hasAttribute('data-autoplay') ){
45540                        playYoutube(element);
45541                    }
45542                };
45543            });
45544        }
45545
45546        /**
45547        * Plays a youtube video
45548        */
45549        function playYoutube(element){
45550            element.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*');
45551        }
45552
45553        /**
45554        * Stops video and audio elements.
45555        */
45556        function stopMedia(destiny){
45557            var panel = getSlideOrSection(destiny);
45558
45559            //stopping HTML5 media elements
45560            panel.find('video, audio').each(function(){
45561                var element = $(this).get(0);
45562
45563                if( !element.hasAttribute('data-keepplaying') && typeof element.pause === 'function' ) {
45564                    element.pause();
45565                }
45566            });
45567
45568            //youtube videos
45569            panel.find('iframe[src*="youtube.com/embed/"]').each(function(){
45570                var element = $(this).get(0);
45571
45572                if( /youtube\.com\/embed\//.test($(this).attr('src')) && !element.hasAttribute('data-keepplaying')){
45573                    $(this).get(0).contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}','*');
45574                }
45575            });
45576        }
45577
45578        /**
45579        * Gets the active slide (or section) for the given section
45580        */
45581        function getSlideOrSection(destiny){
45582            var slide = destiny.find(SLIDE_ACTIVE_SEL);
45583            if( slide.length ) {
45584                destiny = $(slide);
45585            }
45586
45587            return destiny;
45588        }
45589
45590        /**
45591        * Scrolls to the anchor in the URL when loading the site
45592        */
45593        function scrollToAnchor(){
45594            //getting the anchor link in the URL and deleting the `#`
45595            var value =  window.location.hash.replace('#', '').split('/');
45596            var sectionAnchor = decodeURIComponent(value[0]);
45597            var slideAnchor = decodeURIComponent(value[1]);
45598
45599            if(sectionAnchor){  //if theres any #
45600                if(options.animateAnchor){
45601                    scrollPageAndSlide(sectionAnchor, slideAnchor);
45602                }else{
45603                    silentMoveTo(sectionAnchor, slideAnchor);
45604                }
45605            }
45606        }
45607
45608        /**
45609        * Detecting any change on the URL to scroll to the given anchor link
45610        * (a way to detect back history button as we play with the hashes on the URL)
45611        */
45612        function hashChangeHandler(){
45613            if(!isScrolling && !options.lockAnchors){
45614                var value =  window.location.hash.replace('#', '').split('/');
45615                var sectionAnchor = decodeURIComponent(value[0]);
45616                var slideAnchor = decodeURIComponent(value[1]);
45617
45618                    //when moving to a slide in the first section for the first time (first time to add an anchor to the URL)
45619                    var isFirstSlideMove =  (typeof lastScrolledDestiny === 'undefined');
45620                    var isFirstScrollMove = (typeof lastScrolledDestiny === 'undefined' && typeof slideAnchor === 'undefined' && !slideMoving);
45621
45622
45623                if(sectionAnchor.length){
45624                    /*in order to call scrollpage() only once for each destination at a time
45625                    It is called twice for each scroll otherwise, as in case of using anchorlinks `hashChange`
45626                    event is fired on every scroll too.*/
45627                    if ((sectionAnchor && sectionAnchor !== lastScrolledDestiny) && !isFirstSlideMove || isFirstScrollMove || (!slideMoving && lastScrolledSlide != slideAnchor ))  {
45628                        scrollPageAndSlide(sectionAnchor, slideAnchor);
45629                    }
45630                }
45631            }
45632        }
45633
45634        //Sliding with arrow keys, both, vertical and horizontal
45635        function keydownHandler(e) {
45636
45637            clearTimeout(keydownId);
45638
45639            var activeElement = $(':focus');
45640
45641            if(!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select') &&
45642                activeElement.attr('contentEditable') !== "true" && activeElement.attr('contentEditable') !== '' &&
45643                options.keyboardScrolling && options.autoScrolling){
45644                var keyCode = e.which;
45645
45646                //preventing the scroll with arrow keys & spacebar & Page Up & Down keys
45647                var keyControls = [40, 38, 32, 33, 34];
45648                if($.inArray(keyCode, keyControls) > -1){
45649                    e.preventDefault();
45650                }
45651
45652                controlPressed = e.ctrlKey;
45653
45654                keydownId = setTimeout(function(){
45655                    onkeydown(e);
45656                },150);
45657            }
45658        }
45659
45660        function tooltipTextHandler(){
45661            $(this).prev().trigger('click');
45662        }
45663
45664        //to prevent scrolling while zooming
45665        function keyUpHandler(e){
45666            if(isWindowFocused){ //the keyup gets fired on new tab ctrl + t in Firefox
45667                controlPressed = e.ctrlKey;
45668            }
45669        }
45670
45671        //binding the mousemove when the mouse's middle button is released
45672        function mouseDownHandler(e){
45673            //middle button
45674            if (e.which == 2){
45675                oldPageY = e.pageY;
45676                container.on('mousemove', mouseMoveHandler);
45677            }
45678        }
45679
45680        //unbinding the mousemove when the mouse's middle button is released
45681        function mouseUpHandler(e){
45682            //middle button
45683            if (e.which == 2){
45684                container.off('mousemove');
45685            }
45686        }
45687
45688        //Scrolling horizontally when clicking on the slider controls.
45689        function slideArrowHandler(){
45690            var section = $(this).closest(SECTION_SEL);
45691
45692            if ($(this).hasClass(SLIDES_PREV)) {
45693                if(isScrollAllowed.m.left){
45694                    moveSlideLeft(section);
45695                }
45696            } else {
45697                if(isScrollAllowed.m.right){
45698                    moveSlideRight(section);
45699                }
45700            }
45701        }
45702
45703        //when opening a new tab (ctrl + t), `control` won't be pressed when coming back.
45704        function blurHandler(){
45705            isWindowFocused = false;
45706            controlPressed = false;
45707        }
45708
45709        //Scrolls to the section when clicking the navigation bullet
45710        function sectionBulletHandler(e){
45711            e.preventDefault();
45712            var index = $(this).parent().index();
45713            scrollPage($(SECTION_SEL).eq(index));
45714        }
45715
45716        //Scrolls the slider to the given slide destination for the given section
45717        function slideBulletHandler(e){
45718            e.preventDefault();
45719            var slides = $(this).closest(SECTION_SEL).find(SLIDES_WRAPPER_SEL);
45720            var destiny = slides.find(SLIDE_SEL).eq($(this).closest('li').index());
45721
45722            landscapeScroll(slides, destiny);
45723        }
45724
45725        /**
45726        * Keydown event
45727        */
45728        function onkeydown(e){
45729            var shiftPressed = e.shiftKey;
45730
45731            //do nothing if we can not scroll or we are not using horizotnal key arrows.
45732            if(!canScroll && [37,39].indexOf(e.which) < 0){
45733                return;
45734            }
45735
45736            switch (e.which) {
45737                //up
45738                case 38:
45739                case 33:
45740                    if(isScrollAllowed.k.up){
45741                        moveSectionUp();
45742                    }
45743                    break;
45744
45745                //down
45746                case 32: //spacebar
45747                    if(shiftPressed && isScrollAllowed.k.up){
45748                        moveSectionUp();
45749                        break;
45750                    }
45751                /* falls through */
45752                case 40:
45753                case 34:
45754                    if(isScrollAllowed.k.down){
45755                        moveSectionDown();
45756                    }
45757                    break;
45758
45759                //Home
45760                case 36:
45761                    if(isScrollAllowed.k.up){
45762                        moveTo(1);
45763                    }
45764                    break;
45765
45766                //End
45767                case 35:
45768                     if(isScrollAllowed.k.down){
45769                        moveTo( $(SECTION_SEL).length );
45770                    }
45771                    break;
45772
45773                //left
45774                case 37:
45775                    if(isScrollAllowed.k.left){
45776                        moveSlideLeft();
45777                    }
45778                    break;
45779
45780                //right
45781                case 39:
45782                    if(isScrollAllowed.k.right){
45783                        moveSlideRight();
45784                    }
45785                    break;
45786
45787                default:
45788                    return; // exit this handler for other keys
45789            }
45790        }
45791
45792        /**
45793        * Detecting the direction of the mouse movement.
45794        * Used only for the middle button of the mouse.
45795        */
45796        var oldPageY = 0;
45797        function mouseMoveHandler(e){
45798            if(canScroll){
45799                // moving up
45800                if (e.pageY < oldPageY && isScrollAllowed.m.up){
45801                    moveSectionUp();
45802                }
45803
45804                // moving down
45805                else if(e.pageY > oldPageY && isScrollAllowed.m.down){
45806                    moveSectionDown();
45807                }
45808            }
45809            oldPageY = e.pageY;
45810        }
45811
45812        /**
45813        * Scrolls horizontal sliders.
45814        */
45815        function landscapeScroll(slides, destiny, direction){
45816            var section = slides.closest(SECTION_SEL);
45817            var v = {
45818                slides: slides,
45819                destiny: destiny,
45820                direction: direction,
45821                destinyPos: destiny.position(),
45822                slideIndex: destiny.index(),
45823                section: section,
45824                sectionIndex: section.index(SECTION_SEL),
45825                anchorLink: section.data('anchor'),
45826                slidesNav: section.find(SLIDES_NAV_SEL),
45827                slideAnchor:  getAnchor(destiny),
45828                prevSlide: section.find(SLIDE_ACTIVE_SEL),
45829                prevSlideIndex: section.find(SLIDE_ACTIVE_SEL).index(),
45830
45831                //caching the value of isResizing at the momment the function is called
45832                //because it will be checked later inside a setTimeout and the value might change
45833                localIsResizing: isResizing
45834            };
45835            v.xMovement = getXmovement(v.prevSlideIndex, v.slideIndex);
45836            v.direction = v.direction ? v.direction : v.xMovement;
45837
45838            //important!! Only do it when not resizing
45839            if(!v.localIsResizing){
45840                //preventing from scrolling to the next/prev section when using scrollHorizontally
45841                canScroll = false;
45842            }
45843
45844            if(options.onSlideLeave){
45845
45846                //if the site is not just resizing and readjusting the slides
45847                if(!v.localIsResizing && v.xMovement!=='none'){
45848                    if($.isFunction( options.onSlideLeave )){
45849                        if(options.onSlideLeave.call( v.prevSlide, v.anchorLink, (v.sectionIndex + 1), v.prevSlideIndex, v.xMovement, v.slideIndex ) === false){
45850                            slideMoving = false;
45851                            return;
45852                        }
45853                    }
45854                }
45855            }
45856
45857            destiny.addClass(ACTIVE).siblings().removeClass(ACTIVE);
45858
45859            if(!v.localIsResizing){
45860                stopMedia(v.prevSlide);
45861                lazyLoad(destiny);
45862            }
45863
45864            if(!options.loopHorizontal && options.controlArrows){
45865                //hidding it for the fist slide, showing for the rest
45866                section.find(SLIDES_ARROW_PREV_SEL).toggle(v.slideIndex!==0);
45867
45868                //hidding it for the last slide, showing for the rest
45869                section.find(SLIDES_ARROW_NEXT_SEL).toggle(!destiny.is(':last-child'));
45870            }
45871
45872            //only changing the URL if the slides are in the current section (not for resize re-adjusting)
45873            if(section.hasClass(ACTIVE) && !v.localIsResizing){
45874                setState(v.slideIndex, v.slideAnchor, v.anchorLink, v.sectionIndex);
45875            }
45876
45877            performHorizontalMove(slides, v, true);
45878        }
45879
45880
45881        function afterSlideLoads(v){
45882            activeSlidesNavigation(v.slidesNav, v.slideIndex);
45883
45884            //if the site is not just resizing and readjusting the slides
45885            if(!v.localIsResizing){
45886                $.isFunction( options.afterSlideLoad ) && options.afterSlideLoad.call( v.destiny, v.anchorLink, (v.sectionIndex + 1), v.slideAnchor, v.slideIndex);
45887
45888                //needs to be inside the condition to prevent problems with continuousVertical and scrollHorizontally
45889                //and to prevent double scroll right after a windows resize
45890                canScroll = true;
45891
45892                playMedia(v.destiny);
45893            }
45894
45895            //letting them slide again
45896            slideMoving = false;
45897        }
45898
45899        /**
45900        * Performs the horizontal movement. (CSS3 or jQuery)
45901        *
45902        * @param fireCallback {Bool} - determines whether or not to fire the callback
45903        */
45904        function performHorizontalMove(slides, v, fireCallback){
45905            var destinyPos = v.destinyPos;
45906
45907            if(options.css3){
45908                var translate3d = 'translate3d(-' + Math.round(destinyPos.left) + 'px, 0px, 0px)';
45909
45910                addAnimation(slides.find(SLIDES_CONTAINER_SEL)).css(getTransforms(translate3d), v);
45911
45912                afterSlideLoadsId = setTimeout(function(){
45913                    fireCallback && afterSlideLoads(v);
45914                }, options.scrollingSpeed, options.easing);
45915            }else{
45916                slides.animate({
45917                    scrollLeft : Math.round(destinyPos.left)
45918                }, options.scrollingSpeed, options.easing, function() {
45919
45920                    fireCallback && afterSlideLoads(v);
45921                });
45922            }
45923        }
45924
45925        /**
45926        * Sets the state for the horizontal bullet navigations.
45927        */
45928        function activeSlidesNavigation(slidesNav, slideIndex){
45929            slidesNav.find(ACTIVE_SEL).removeClass(ACTIVE);
45930            slidesNav.find('li').eq(slideIndex).find('a').addClass(ACTIVE);
45931        }
45932
45933        var previousHeight = windowsHeight;
45934
45935        //when resizing the site, we adjust the heights of the sections, slimScroll...
45936        function resizeHandler(){
45937            //checking if it needs to get responsive
45938            responsive();
45939
45940            // rebuild immediately on touch devices
45941            if (isTouchDevice) {
45942                var activeElement = $(document.activeElement);
45943
45944                //if the keyboard is NOT visible
45945                if (!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select')) {
45946                    var currentHeight = $window.height();
45947
45948                    //making sure the change in the viewport size is enough to force a rebuild. (20 % of the window to avoid problems when hidding scroll bars)
45949                    if( Math.abs(currentHeight - previousHeight) > (20 * Math.max(previousHeight, currentHeight) / 100) ){
45950                        reBuild(true);
45951                        previousHeight = currentHeight;
45952                    }
45953                }
45954            }else{
45955                //in order to call the functions only when the resize is finished
45956                //http://stackoverflow.com/questions/4298612/jquery-how-to-call-resize-event-only-once-its-finished-resizing
45957                clearTimeout(resizeId);
45958
45959                resizeId = setTimeout(function(){
45960                    reBuild(true);
45961                }, 350);
45962            }
45963        }
45964
45965        /**
45966        * Checks if the site needs to get responsive and disables autoScrolling if so.
45967        * A class `fp-responsive` is added to the plugin's container in case the user wants to use it for his own responsive CSS.
45968        */
45969        function responsive(){
45970            var widthLimit = options.responsive || options.responsiveWidth; //backwards compatiblity
45971            var heightLimit = options.responsiveHeight;
45972
45973            //only calculating what we need. Remember its called on the resize event.
45974            var isBreakingPointWidth = widthLimit && $window.outerWidth() < widthLimit;
45975            var isBreakingPointHeight = heightLimit && $window.height() < heightLimit;
45976
45977            if(widthLimit && heightLimit){
45978                setResponsive(isBreakingPointWidth || isBreakingPointHeight);
45979            }
45980            else if(widthLimit){
45981                setResponsive(isBreakingPointWidth);
45982            }
45983            else if(heightLimit){
45984                setResponsive(isBreakingPointHeight);
45985            }
45986        }
45987
45988        /**
45989        * Adds transition animations for the given element
45990        */
45991        function addAnimation(container, element){
45992            var transition = 'all ' + options.scrollingSpeed + 'ms ' + options.easingcss3;
45993
45994            container.removeClass(NO_TRANSITION);
45995            return container.css({
45996                '-webkit-transition': transition,
45997                'transition': transition
45998            });
45999        }
46000
46001        /**
46002        * Remove transition animations for the given element
46003        */
46004        function removeAnimation(element){
46005            return element.addClass(NO_TRANSITION);
46006        }
46007
46008        /**
46009        * Activating the vertical navigation bullets according to the given slide name.
46010        */
46011        function activateNavDots(name, sectionIndex){
46012            if(options.navigation){
46013                $(SECTION_NAV_SEL).find(ACTIVE_SEL).removeClass(ACTIVE);
46014                if(name){
46015                    $(SECTION_NAV_SEL).find('a[href="#' + name + '"]').addClass(ACTIVE);
46016                }else{
46017                    $(SECTION_NAV_SEL).find('li').eq(sectionIndex).find('a').addClass(ACTIVE);
46018                }
46019            }
46020        }
46021
46022        /**
46023        * Activating the website main menu elements according to the given slide name.
46024        */
46025        function activateMenuElement(name){
46026            if(options.menu){
46027                $(options.menu).find(ACTIVE_SEL).removeClass(ACTIVE);
46028                $(options.menu).find('[data-menuanchor="'+name+'"]').addClass(ACTIVE);
46029            }
46030        }
46031
46032        /**
46033        * Sets to active the current menu and vertical nav items.
46034        */
46035        function activateMenuAndNav(anchor, index){
46036            activateMenuElement(anchor);
46037            activateNavDots(anchor, index);
46038        }
46039
46040        /**
46041        * Retuns `up` or `down` depending on the scrolling movement to reach its destination
46042        * from the current section.
46043        */
46044        function getYmovement(destiny){
46045            var fromIndex = $(SECTION_ACTIVE_SEL).index(SECTION_SEL);
46046            var toIndex = destiny.index(SECTION_SEL);
46047            if( fromIndex == toIndex){
46048                return 'none';
46049            }
46050            if(fromIndex > toIndex){
46051                return 'up';
46052            }
46053            return 'down';
46054        }
46055
46056        /**
46057        * Retuns `right` or `left` depending on the scrolling movement to reach its destination
46058        * from the current slide.
46059        */
46060        function getXmovement(fromIndex, toIndex){
46061            if( fromIndex == toIndex){
46062                return 'none';
46063            }
46064            if(fromIndex > toIndex){
46065                return 'left';
46066            }
46067            return 'right';
46068        }
46069
46070        /**
46071        * Checks if the element needs scrollbar and if the user wants to apply it.
46072        * If so it creates it.
46073        *
46074        * @param {Object} element   jQuery object of the section or slide
46075        */
46076        function createScrollBar(element){
46077            //User doesn't want scrollbar here? Sayonara baby!
46078            if(element.hasClass('fp-noscroll')) return;
46079
46080            //needed to make `scrollHeight` work under Opera 12
46081            element.css('overflow', 'hidden');
46082
46083            var scrollOverflowHandler = options.scrollOverflowHandler;
46084            var wrap = scrollOverflowHandler.wrapContent();
46085            //in case element is a slide
46086            var section = element.closest(SECTION_SEL);
46087            var scrollable = scrollOverflowHandler.scrollable(element);
46088            var contentHeight;
46089
46090            //if there was scroll, the contentHeight will be the one in the scrollable section
46091            if(scrollable.length){
46092                contentHeight = scrollOverflowHandler.scrollHeight(element);
46093            }else{
46094                contentHeight = element.get(0).scrollHeight;
46095                if(options.verticalCentered){
46096                    contentHeight = element.find(TABLE_CELL_SEL).get(0).scrollHeight;
46097                }
46098            }
46099
46100            var scrollHeight = windowsHeight - parseInt(section.css('padding-bottom')) - parseInt(section.css('padding-top'));
46101
46102            //needs scroll?
46103            if ( contentHeight > scrollHeight) {
46104                //did we already have an scrollbar ? Updating it
46105                if(scrollable.length){
46106                    scrollOverflowHandler.update(element, scrollHeight);
46107                }
46108                //creating the scrolling
46109                else{
46110                    if(options.verticalCentered){
46111                        element.find(TABLE_CELL_SEL).wrapInner(wrap);
46112                    }else{
46113                        element.wrapInner(wrap);
46114                    }
46115                    scrollOverflowHandler.create(element, scrollHeight);
46116                }
46117            }
46118            //removing the scrolling when it is not necessary anymore
46119            else{
46120                scrollOverflowHandler.remove(element);
46121            }
46122
46123            //undo
46124            element.css('overflow', '');
46125        }
46126
46127        function addTableClass(element){
46128            //In case we are styling for the 2nd time as in with reponsiveSlides
46129            if(!element.hasClass(TABLE)){
46130                element.addClass(TABLE).wrapInner('<div class="' + TABLE_CELL + '" style="height:' + getTableHeight(element) + 'px;" />');
46131            }
46132        }
46133
46134        function getTableHeight(element){
46135            var sectionHeight = windowsHeight;
46136
46137            if(options.paddingTop || options.paddingBottom){
46138                var section = element;
46139                if(!section.hasClass(SECTION)){
46140                    section = element.closest(SECTION_SEL);
46141                }
46142
46143                var paddings = parseInt(section.css('padding-top')) + parseInt(section.css('padding-bottom'));
46144                sectionHeight = (windowsHeight - paddings);
46145            }
46146
46147            return sectionHeight;
46148        }
46149
46150        /**
46151        * Adds a css3 transform property to the container class with or without animation depending on the animated param.
46152        */
46153        function transformContainer(translate3d, animated){
46154            if(animated){
46155                addAnimation(container);
46156            }else{
46157                removeAnimation(container);
46158            }
46159
46160            container.css(getTransforms(translate3d));
46161
46162            //syncronously removing the class after the animation has been applied.
46163            setTimeout(function(){
46164                container.removeClass(NO_TRANSITION);
46165            },10);
46166        }
46167
46168        /**
46169        * Gets a section by its anchor / index
46170        */
46171        function getSectionByAnchor(sectionAnchor){
46172            if(!sectionAnchor) return [];
46173
46174            var section = container.find(SECTION_SEL + '[data-anchor="'+sectionAnchor+'"]');
46175            if(!section.length){
46176                section = $(SECTION_SEL).eq( sectionAnchor -1);
46177            }
46178
46179            return section;
46180        }
46181
46182        /**
46183        * Gets a slide inside a given section by its anchor / index
46184        */
46185        function getSlideByAnchor(slideAnchor, section){
46186            var slides = section.find(SLIDES_WRAPPER_SEL);
46187            var slide =  slides.find(SLIDE_SEL + '[data-anchor="'+slideAnchor+'"]');
46188
46189            if(!slide.length){
46190                slide = slides.find(SLIDE_SEL).eq(slideAnchor);
46191            }
46192
46193            return slide;
46194        }
46195
46196        /**
46197        * Scrolls to the given section and slide anchors
46198        */
46199        function scrollPageAndSlide(destiny, slide){
46200            var section = getSectionByAnchor(destiny);
46201
46202            //do nothing if there's no section with the given anchor name
46203            if(!section.length) return;
46204
46205            //default slide
46206            if (typeof slide === 'undefined') {
46207                slide = 0;
46208            }
46209
46210            //we need to scroll to the section and then to the slide
46211            if (destiny !== lastScrolledDestiny && !section.hasClass(ACTIVE)){
46212                scrollPage(section, function(){
46213                    scrollSlider(section, slide);
46214                });
46215            }
46216            //if we were already in the section
46217            else{
46218                scrollSlider(section, slide);
46219            }
46220        }
46221
46222        /**
46223        * Scrolls the slider to the given slide destination for the given section
46224        */
46225        function scrollSlider(section, slideAnchor){
46226            if(typeof slideAnchor !== 'undefined'){
46227                var slides = section.find(SLIDES_WRAPPER_SEL);
46228                var destiny =  getSlideByAnchor(slideAnchor, section);
46229
46230                if(destiny.length){
46231                    landscapeScroll(slides, destiny);
46232                }
46233            }
46234        }
46235
46236        /**
46237        * Creates a landscape navigation bar with dots for horizontal sliders.
46238        */
46239        function addSlidesNavigation(section, numSlides){
46240            section.append('<div class="' + SLIDES_NAV + '"><ul></ul></div>');
46241            var nav = section.find(SLIDES_NAV_SEL);
46242
46243            //top or bottom
46244            nav.addClass(options.slidesNavPosition);
46245
46246            for(var i=0; i< numSlides; i++){
46247                nav.find('ul').append('<li><a href="#"><span></span></a></li>');
46248            }
46249
46250            //centering it
46251            nav.css('margin-left', '-' + (nav.width()/2) + 'px');
46252
46253            nav.find('li').first().find('a').addClass(ACTIVE);
46254        }
46255
46256
46257        /**
46258        * Sets the state of the website depending on the active section/slide.
46259        * It changes the URL hash when needed and updates the body class.
46260        */
46261        function setState(slideIndex, slideAnchor, anchorLink, sectionIndex){
46262            var sectionHash = '';
46263
46264            if(options.anchors.length && !options.lockAnchors){
46265
46266                //isn't it the first slide?
46267                if(slideIndex){
46268                    if(typeof anchorLink !== 'undefined'){
46269                        sectionHash = anchorLink;
46270                    }
46271
46272                    //slide without anchor link? We take the index instead.
46273                    if(typeof slideAnchor === 'undefined'){
46274                        slideAnchor = slideIndex;
46275                    }
46276
46277                    lastScrolledSlide = slideAnchor;
46278                    setUrlHash(sectionHash + '/' + slideAnchor);
46279
46280                //first slide won't have slide anchor, just the section one
46281                }else if(typeof slideIndex !== 'undefined'){
46282                    lastScrolledSlide = slideAnchor;
46283                    setUrlHash(anchorLink);
46284                }
46285
46286                //section without slides
46287                else{
46288                    setUrlHash(anchorLink);
46289                }
46290            }
46291
46292            setBodyClass();
46293        }
46294
46295        /**
46296        * Sets the URL hash.
46297        */
46298        function setUrlHash(url){
46299            //Uncode addition
46300            if ( typeof SiteParameters.slide_footer != 'undefined' && url == SiteParameters.slide_footer )
46301                return false;
46302
46303            if(options.recordHistory){
46304                location.hash = url;
46305            }else{
46306                //Uncode addition
46307                //Mobile Chrome doesn't work the normal way, so... lets use HTML5 for phones :)
46308                // if(isTouchDevice || isTouch){
46309                //     window.history.replaceState(undefined, undefined, '#' + url);
46310                // }else{
46311                //     var baseUrl = window.location.href.split('#')[0];
46312                //     window.location.replace( baseUrl + '#' + url );
46313                // }
46314                return false;
46315            }
46316        }
46317
46318        /**
46319        * Gets the anchor for the given slide / section. Its index will be used if there's none.
46320        */
46321        function getAnchor(element){
46322            var anchor = element.data('anchor');
46323            var index = element.index();
46324
46325            //Slide without anchor link? We take the index instead.
46326            if(typeof anchor === 'undefined'){
46327                anchor = index;
46328            }
46329
46330            return anchor;
46331        }
46332
46333        /**
46334        * Sets a class for the body of the page depending on the active section / slide
46335        */
46336        function setBodyClass(){
46337            var section = $(SECTION_ACTIVE_SEL);
46338            var slide = section.find(SLIDE_ACTIVE_SEL);
46339
46340            var sectionAnchor = getAnchor(section);
46341            var slideAnchor = getAnchor(slide);
46342
46343            var text = String(sectionAnchor);
46344
46345            if(slide.length){
46346                text = text + '-' + slideAnchor;
46347            }
46348
46349            //changing slash for dash to make it a valid CSS style
46350            text = text.replace('/', '-').replace('#','');
46351
46352            //removing previous anchor classes
46353            var classRe = new RegExp('\\b\\s?' + VIEWING_PREFIX + '-[^\\s]+\\b', "g");
46354            $body[0].className = $body[0].className.replace(classRe, '');
46355
46356            //adding the current anchor
46357            $body.addClass(VIEWING_PREFIX + '-' + text);
46358        }
46359
46360        /**
46361        * Checks for translate3d support
46362        * @return boolean
46363        * http://stackoverflow.com/questions/5661671/detecting-transform-translate3d-support
46364        */
46365        function support3d() {
46366            var el = document.createElement('p'),
46367                has3d,
46368                transforms = {
46369                    'webkitTransform':'-webkit-transform',
46370                    'OTransform':'-o-transform',
46371                    'msTransform':'-ms-transform',
46372                    'MozTransform':'-moz-transform',
46373                    'transform':'transform'
46374                };
46375
46376            // Add it to the body to get the computed style.
46377            document.body.insertBefore(el, null);
46378
46379            for (var t in transforms) {
46380                if (el.style[t] !== undefined) {
46381                    el.style[t] = 'translate3d(1px,1px,1px)';
46382                    has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]);
46383                }
46384            }
46385
46386            document.body.removeChild(el);
46387
46388            return (has3d !== undefined && has3d.length > 0 && has3d !== 'none');
46389        }
46390
46391        /**
46392        * Removes the auto scrolling action fired by the mouse wheel and trackpad.
46393        * After this function is called, the mousewheel and trackpad movements won't scroll through sections.
46394        */
46395        function removeMouseWheelHandler(){
46396            if (document.addEventListener) {
46397                document.removeEventListener('mousewheel', MouseWheelHandler, false); //IE9, Chrome, Safari, Oper
46398                document.removeEventListener('wheel', MouseWheelHandler, false); //Firefox
46399                document.removeEventListener('MozMousePixelScroll', MouseWheelHandler, false); //old Firefox
46400            } else {
46401                document.detachEvent('onmousewheel', MouseWheelHandler); //IE 6/7/8
46402            }
46403        }
46404
46405        /**
46406        * Adds the auto scrolling action for the mouse wheel and trackpad.
46407        * After this function is called, the mousewheel and trackpad movements will scroll through sections
46408        * https://developer.mozilla.org/en-US/docs/Web/Events/wheel
46409        */
46410        function addMouseWheelHandler(){
46411            var prefix = '';
46412            var _addEventListener;
46413
46414            if (window.addEventListener){
46415                _addEventListener = "addEventListener";
46416            }else{
46417                _addEventListener = "attachEvent";
46418                prefix = 'on';
46419            }
46420
46421             // detect available wheel event
46422            var support = 'onwheel' in document.createElement('div') ? 'wheel' : // Modern browsers support "wheel"
46423                      document.onmousewheel !== undefined ? 'mousewheel' : // Webkit and IE support at least "mousewheel"
46424                      'DOMMouseScroll'; // let's assume that remaining browsers are older Firefox
46425            var passiveEvent = g_supportsPassive ? {passive: false }
46425: false;
46426
46427
46428            if(support == 'DOMMouseScroll'){
46429                document[ _addEventListener ](prefix + 'MozMousePixelScroll', MouseWheelHandler, passiveEvent);
46430            }
46431
46432            //handle MozMousePixelScroll in older Firefox
46433            else{
46434                document[ _addEventListener ](prefix + support, MouseWheelHandler, passiveEvent);
46435            }
46436        }
46437
46438        /**
46439        * Binding the mousemove when the mouse's middle button is pressed
46440        */
46441        function addMiddleWheelHandler(){
46442            container
46443                .on('mousedown', mouseDownHandler)
46444                .on('mouseup', mouseUpHandler);
46445        }
46446
46447        /**
46448        * Unbinding the mousemove when the mouse's middle button is released
46449        */
46450        function removeMiddleWheelHandler(){
46451            container
46452                .off('mousedown', mouseDownHandler)
46453                .off('mouseup', mouseUpHandler);
46454        }
46455
46456        /**
46457        * Adds the possibility to auto scroll through sections on touch devices.
46458        */
46459        function addTouchHandler(){
46460            if(isTouchDevice || isTouch){
46461                if(options.autoScrolling){
46462                    $body.off(events.touchmove).on(events.touchmove, preventBouncing);
46463                }
46464
46465                $(WRAPPER_SEL)
46466                    .off(events.touchstart).on(events.touchstart, touchStartHandler)
46467                    .off(events.touchmove).on(events.touchmove, touchMoveHandler);
46468            }
46469        }
46470
46471        /**
46472        * Removes the auto scrolling for touch devices.
46473        */
46474        function removeTouchHandler(){
46475            if(isTouchDevice || isTouch){
46476                $(WRAPPER_SEL)
46477                    .off(events.touchstart)
46478                    .off(events.touchmove);
46479            }
46480        }
46481
46482        /*
46483        * Returns and object with Microsoft pointers (for IE<11 and for IE >= 11)
46484        * http://msdn.microsoft.com/en-us/library/ie/dn304886(v=vs.85).aspx
46485        */
46486        function getMSPointer(){
46487            var pointer;
46488
46489            //IE >= 11 & rest of browsers
46490            if(window.PointerEvent){
46491                pointer = { down: 'pointerdown', move: 'pointermove'};
46492            }
46493
46494            //IE < 11
46495            else{
46496                pointer = { down: 'MSPointerDown', move: 'MSPointerMove'};
46497            }
46498
46499            return pointer;
46500        }
46501
46502        /**
46503        * Gets the pageX and pageY properties depending on the browser.
46504        * https://github.com/alvarotrigo/fullPage.js/issues/194#issuecomment-34069854
46505        */
46506        function getEventsPage(e){
46507            var events = [];
46508
46509            events.y = (typeof e.pageY !== 'undefined' && (e.pageY || e.pageX) ? e.pageY : e.touches[0].pageY);
46510            events.x = (typeof e.pageX !== 'undefined' && (e.pageY || e.pageX) ? e.pageX : e.touches[0].pageX);
46511
46512            //in touch devices with scrollBar:true, e.pageY is detected, but we have to deal with touch events. #1008
46513            if(isTouch && isReallyTouch(e) && options.scrollBar){
46514                events.y = e.touches[0].pageY;
46515                events.x = e.touches[0].pageX;
46516            }
46517
46518            return events;
46519        }
46520
46521        /**
46522        * Slides silently (with no animation) the active slider to the given slide.
46523        * @param noCallback {bool} true or defined -> no callbacks
46524        */
46525        function silentLandscapeScroll(activeSlide, noCallbacks){
46526            setScrollingSpeed (0, 'internal');
46527
46528            if(typeof noCallbacks !== 'undefined'){
46529                //preventing firing callbacks afterSlideLoad etc.
46530                isResizing = true;
46531            }
46532
46533            landscapeScroll(activeSlide.closest(SLIDES_WRAPPER_SEL), activeSlide);
46534
46535            if(typeof noCallbacks !== 'undefined'){
46536                isResizing = false;
46537            }
46538
46539            setScrollingSpeed(originals.scrollingSpeed, 'internal');
46540        }
46541
46542        /**
46543        * Scrolls silently (with no animation) the page to the given Y position.
46544        */
46545        function silentScroll(top){
46546            // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625
46547            // that's why we round it to 0.
46548            var roundedTop = Math.round(top);
46549
46550            if (options.css3 && options.autoScrolling && !options.scrollBar){
46551                var translate3d = 'translate3d(0px, -' + roundedTop + 'px, 0px)';
46552                transformContainer(translate3d, false);
46553            }
46554            else if(options.autoScrolling && !options.scrollBar){
46555                container.css('top', -roundedTop);
46556            }
46557            else{
46558                $htmlBody.scrollTop(roundedTop);
46559            }
46560        }
46561
46562        /**
46563        * Returns the cross-browser transform string.
46564        */
46565        function getTransforms(translate3d){
46566            return {
46567                '-webkit-transform': translate3d,
46568                '-moz-transform': translate3d,
46569                '-ms-transform':translate3d,
46570                'transform': translate3d
46571            };
46572        }
46573
46574        /**
46575        * Allowing or disallowing the mouse/swipe scroll in a given direction. (not for keyboard)
46576        * @type  m (mouse) or k (keyboard)
46577        */
46578        function setIsScrollAllowed(value, direction, type){
46579            switch (direction){
46580                case 'up': isScrollAllowed[type].up = value; break;
46581                case 'down': isScrollAllowed[type].down = value; break;
46582                case 'left': isScrollAllowed[type].left = value; break;
46583                case 'right': isScrollAllowed[type].right = value; break;
46584                case 'all':
46585                    if(type == 'm'){
46586                        setAllowScrolling(value);
46587                    }else{
46588                        setKeyboardScrolling(value);
46589                    }
46590            }
46591        }
46592
46593        /*
46594        * Destroys fullpage.js plugin events and optinally its html markup and styles
46595        */
46596        function destroy(all){
46597            setAutoScrolling(false, 'internal');
46598            setAllowScrolling(false);
46599            setKeyboardScrolling(false);
46600            container.addClass(DESTROYED);
46601
46602            clearTimeout(afterSlideLoadsId);
46603            clearTimeout(afterSectionLoadsId);
46604            clearTimeout(resizeId);
46605            clearTimeout(scrollId);
46606            clearTimeout(scrollId2);
46607
46608            $window
46609                .off('scroll', scrollHandler)
46610                .off('hashchange', hashChangeHandler)
46611                .off('resize', resizeHandler);
46612
46613            $document
46614                .off('click touchstart', SECTION_NAV_SEL + ' a')
46615                .off('mouseenter', SECTION_NAV_SEL + ' li')
46616                .off('mouseleave', SECTION_NAV_SEL + ' li')
46617                .off('click touchstart', SLIDES_NAV_LINK_SEL)
46618                .off('mouseover', options.normalScrollElements)
46619                .off('mouseout', options.normalScrollElements);
46620
46621            $(SECTION_SEL)
46622                .off('click touchstart', SLIDES_ARROW_SEL);
46623
46624            clearTimeout(afterSlideLoadsId);
46625            clearTimeout(afterSectionLoadsId);
46626
46627            //lets make a mess!
46628            if(all){
46629                destroyStructure();
46630            }
46631        }
46632
46633        /*
46634        * Removes inline styles added by fullpage.js
46635        */
46636        function destroyStructure(){
46637            //reseting the `top` or `translate` properties to 0
46638            silentScroll(0);
46639
46640            //loading all the lazy load content
46641            container.find('img[data-src], source[data-src], audio[data-src], iframe[data-src]').each(function(){
46642                setSrc($(this), 'src');
46643            });
46644
46645            container.find('img[data-srcset]').each(function(){
46646                setSrc($(this), 'srcset');
46647            });
46648
46649            $(SECTION_NAV_SEL + ', ' + SLIDES_NAV_SEL +  ', ' + SLIDES_ARROW_SEL).remove();
46650
46651            //removing inline styles
46652            $(SECTION_SEL).css( {
46653                'height': '',
46654                'background-color' : '',
46655                'padding': ''
46656            });
46657
46658            $(SLIDE_SEL).css( {
46659                'width': ''
46660            });
46661
46662            container.css({
46663                'height': '',
46664                'position': '',
46665                '-ms-touch-action': '',
46666                'touch-action': ''
46667            });
46668
46669            $htmlBody.css({
46670                'overflow': '',
46671                'height': ''
46672            });
46673
46674            // remove .fp-enabled class
46675            $('html').removeClass(ENABLED);
46676
46677            // remove .fp-responsive class
46678            $body.removeClass(RESPONSIVE);
46679
46680            // remove all of the .fp-viewing- classes
46681            $.each($body.get(0).className.split(/\s+/), function (index, className) {
46682                if (className.indexOf(VIEWING_PREFIX) === 0) {
46683                    $body.removeClass(className);
46684                }
46685            });
46686
46687            //removing added classes
46688            $(SECTION_SEL + ', ' + SLIDE_SEL).each(function(){
46689                options.scrollOverflowHandler.remove($(this));
46690                $(this).removeClass(TABLE + ' ' + ACTIVE);
46691            });
46692
46693            removeAnimation(container);
46694
46695            //Unwrapping content
46696            container.find(TABLE_CELL_SEL + ', ' + SLIDES_CONTAINER_SEL + ', ' + SLIDES_WRAPPER_SEL).each(function(){
46697                //unwrap not being use in case there's no child element inside and its just text
46698                $(this).replaceWith(this.childNodes);
46699            });
46700
46701            //removing the applied transition from the fullpage wrapper
46702            container.css({
46703                '-webkit-transition': 'none',
46704                'transition': 'none'
46705            });
46706
46707            //scrolling the page to the top with no animation
46708            $htmlBody.scrollTop(0);
46709
46710            //removing selectors
46711            var usedSelectors = [SECTION, SLIDE, SLIDES_CONTAINER];
46712            $.each(usedSelectors, function(index, value){
46713                $('.' + value).removeClass(value);
46714            });
46715        }
46716
46717        /*
46718        * Sets the state for a variable with multiple states (original, and temporal)
46719        * Some variables such as `autoScrolling` or `recordHistory` might change automatically its state when using `responsive` or `autoScrolling:false`.
46720        * This function is used to keep track of both states, the original and the temporal one.
46721        * If type is not 'internal', then we assume the user is globally changing the variable.
46722        */
46723        function setVariableState(variable, value, type){
46724            options[variable] = value;
46725            if(type !== 'internal'){
46726                originals[variable] = value;
46727            }
46728        }
46729
46730        /**
46731        * Displays warnings
46732        */
46733        function displayWarnings(){
46734            var extensions = ['fadingEffect', 'continuousHorizontal', 'scrollHorizontally', 'interlockedSlides', 'resetSliders', 'responsiveSlides', 'offsetSections', 'dragAndMove', 'scrollOverflowReset', 'parallax'];
46735            //UNCODE.addition
46736            // if($('html').hasClass(ENABLED)){
46737            //     showError('error', 'Fullpage.js can only be initialized once and you are doing it multiple times!');
46738            //     return;
46739            // }
46740
46741            // Disable mutually exclusive settings
46742            //UNCODE.addition
46743            // if (options.continuousVertical &&
46744            //     (options.loopTop || options.loopBottom)) {
46745            //     options.continuousVertical = false;
46746            //     showError('warn', 'Option `loopTop/loopBottom` is mutually exclusive with `continuousVertical`; `continuousVertical` disabled');
46747            // }
46748
46749            // if(options.scrollBar && options.scrollOverflow){
46750            //     showError('warn', 'Option `scrollBar` is mutually exclusive with `scrollOverflow`. Sections with scrollOverflow might not work well in Firefox');
46751            // }
46752
46753            // if(options.continuousVertical && (options.scrollBar || !options.autoScrolling)){
46754            //     options.continuousVertical = false;
46755            //     showError('warn', 'Scroll bars (`scrollBar:true` or `autoScrolling:false`) are mutually exclusive with `continuousVertical`; `continuousVertical` disabled');
46756            // }
46757
46758            //using extensions? Wrong file!
46759            $.each(extensions, function(index, extension){
46760                //is the option set to true?
46761                if(options[extension]){
46762                    showError('warn', 'fullpage.js extensions require jquery.fullpage.extensions.min.js file instead of the usual jquery.fullpage.js. Requested: '+ extension);
46763                }
46764            });
46765
46766            //anchors can not have the same value as any element ID or NAME
46767            $.each(options.anchors, function(index, name){
46768
46769                //case insensitive selectors (http://stackoverflow.com/a/19465187/1081396)
46770                var nameAttr = $document.find('[name]').filter(function() {
46771                    return $(this).attr('name') && $(this).attr('name').toLowerCase() == name.toLowerCase();
46772                });
46773
46774                var idAttr = $document.find('[id]').filter(function() {
46775                    return $(this).attr('id') && $(this).attr('id').toLowerCase() == name.toLowerCase();
46776                });
46777
46778                if(idAttr.length || nameAttr.length ){
46779                    showError('error', 'data-anchor tags can not have the same value as any `id` element on the site (or `name` element for IE).');
46780                    idAttr.length && showError('error', '"' + name + '" is is being used by another element `id` property');
46781                    nameAttr.length && showError('error', '"' + name + '" is is being used by another element `name` property');
46782                }
46783            });
46784        }
46785
46786        /**
46787        * Shows a message in the console of the given type.
46788        */
46789        function showError(type, text){
46790            console && console[type] && console[type]('fullPage: ' + text);
46791        }
46792
46793    }; //end of $.fn.fullpage
46794
46795    if(typeof IScroll !== 'undefined'){
46796        /*
46797        * Turns iScroll `mousewheel` option off dynamically
46798        * https://github.com/cubiq/iscroll/issues/1036
46799        */
46800        IScroll.prototype.wheelOn = function () {
46801            this.wrapper.addEventListener('wheel', this);
46802            this.wrapper.addEventListener('mousewheel', this);
46803            this.wrapper.addEventListener('DOMMouseScroll', this);
46804        };
46805
46806        /*
46807        * Turns iScroll `mousewheel` option on dynamically
46808        * https://github.com/cubiq/iscroll/issues/1036
46809        */
46810        IScroll.prototype.wheelOff = function () {
46811            this.wrapper.removeEventListener('wheel', this);
46812            this.wrapper.removeEventListener('mousewheel', this);
46813            this.wrapper.removeEventListener('DOMMouseScroll', this);
46814        };
46815    }
46816
46817    /**
46818     * An object to handle overflow scrolling.
46819     * This uses jquery.slimScroll to accomplish overflow scrolling.
46820     * It is possible to pass in an alternate scrollOverflowHandler
46821     * to the fullpage.js option that implements the same functions
46822     * as this handler.
46823     *
46824     * @type {Object}
46825     */
46826    var iscrollHandler = {
46827        refreshId: null,
46828        iScrollInstances: [],
46829
46830        // Enables or disables the mouse wheel for the active section or all slides in it
46831        toggleWheel: function(value){
46832            var scrollable = $(SECTION_ACTIVE_SEL).find(SCROLLABLE_SEL);
46833            scrollable.each(function(){
46834                var iScrollInstance = $(this).data('iscrollInstance');
46835                if(typeof iScrollInstance !== 'undefined' && iScrollInstance){
46836                    if(value){
46837                        iScrollInstance.wheelOn();
46838                    }
46839                    else{
46840                        iScrollInstance.wheelOff();
46841                    }
46842                }
46843            });
46844        },
46845
46846        /**
46847        * Turns off iScroll for the destination section.
46848        * When scrolling very fast on some trackpads (and Apple laptops) the inertial scrolling would
46849        * scroll the destination section/slide before the sections animations ends.
46850        */
46851        onLeave: function(){
46852            iscrollHandler.toggleWheel(false);
46853        },
46854
46855        // Turns off iScroll for the leaving section
46856        beforeLeave: function(){
46857            iscrollHandler.onLeave()
46858        },
46859
46860        // Turns on iScroll on section load
46861        afterLoad: function(){
46862            iscrollHandler.toggleWheel(true);
46863        },
46864
46865        /**
46866         * Called when overflow scrolling is needed for a section.
46867         *
46868         * @param  {Object} element      jQuery object containing current section
46869         * @param  {Number} scrollHeight Current window height in pixels
46870         */
46871        create: function(element, scrollHeight) {
46872            var scrollable = element.find(SCROLLABLE_SEL);
46873
46874            scrollable.height(scrollHeight);
46875            scrollable.each(function() {
46876                var $this = $(this);
46877                var iScrollInstance = $this.data('iscrollInstance');
46878                if (iScrollInstance) {
46879                    $.each(iscrollHandler.iScrollInstances, function(){
46880                        $(this).destroy();
46881                    });
46882                }
46883
46884                iScrollInstance = new IScroll($this.get(0), iscrollOptions);
46885                iscrollHandler.iScrollInstances.push(iScrollInstance);
46886
46887                //off by default until the section gets active
46888                iScrollInstance.wheelOff();
46889
46890                $this.data('iscrollInstance', iScrollInstance);
46891            });
46892        },
46893
46894        /**
46895         * Return a boolean depending on whether the scrollable element is a
46896         * the end or at the start of the scrolling depending on the given type.
46897         *
46898         * @param  {String}  type       Either 'top' or 'bottom'
46899         * @param  {Object}  scrollable jQuery object for the scrollable element
46900         * @return {Boolean}
46901         */
46902        isScrolled: function(type, scrollable) {
46903            var scroller = scrollable.data('iscrollInstance');
46904
46905            //no scroller?
46906            if (!scroller) {
46907                return true;
46908            }
46909
46910            //Uncode addition
46911            var uncode_body_borders = parseFloat($('.body-borders').attr('data-border')) || 0;
46912            //End Uncode addition
46913
46914            if (type === 'top') {
46915                return scroller.y >= 0 && !scrollable.scrollTop();
46916            } else if (type === 'bottom') {
46917                //Uncode change
46918                // return (0 - scroller.y) + scrollable.scrollTop() + 1 + scrollable.innerHeight() >= scrollable[0].scrollHeight;
46919                return (0 - scroller.y) + scrollable.scrollTop() + 1 + ( uncode_body_borders * 2 ) + scrollable.innerHeight() >= scrollable[0].scrollHeight;
46920                //End Uncode change
46921            }
46922        },
46923
46924        /**
46925         * Returns the scrollable element for the given section.
46926         * If there are landscape slides, will only return a scrollable element
46927         * if it is in the active slide.
46928         *
46929         * @param  {Object}  activeSection jQuery object containing current section
46930         * @return {Boolean}
46931         */
46932        scrollable: function(activeSection){
46933            // if there are landscape slides, we check if the scrolling bar is in the current one or not
46934            if (activeSection.find(SLIDES_WRAPPER_SEL).length) {
46935                return activeSection.find(SLIDE_ACTIVE_SEL).find(SCROLLABLE_SEL);
46936            }
46937            return activeSection.find(SCROLLABLE_SEL);
46938        },
46939
46940        /**
46941         * Returns the scroll height of the wrapped content.
46942         * If this is larger than the window height minus section padding,
46943         * overflow scrolling is needed.
46944         *
46945         * @param  {Object} element jQuery object containing current section
46946         * @return {Number}
46947         */
46948        scrollHeight: function(element) {
46949            return element.find(SCROLLABLE_SEL).children().first().get(0).scrollHeight;
46950        },
46951
46952        /**
46953         * Called when overflow scrolling is no longer needed for a section.
46954         *
46955         * @param  {Object}
vendor: 5,435 bytes, lines 46955-47106
46955 element      jQuery object containing current section
46956         */
46957        remove: function(element) {
46958            var scrollable = element.find(SCROLLABLE_SEL);
46959            if (scrollable.length) {
46960                var iScrollInstance = scrollable.data('iscrollInstance');
46961                iScrollInstance.destroy();
46962
46963                scrollable.data('iscrollInstance', null);
46964            }
46965            element.find(SCROLLABLE_SEL).children().first().children().first().unwrap().unwrap();
46966        },
46967
46968        /**
46969         * Called when overflow scrolling has already been setup but the
46970         * window height has potentially changed.
46971         *
46972         * @param  {Object} element      jQuery object containing current section
46973         * @param  {Number} scrollHeight Current window height in pixels
46974         */
46975        update: function(element, scrollHeight) {
46976            //using a timeout in order to execute the refresh function only once when `update` is called multiple times in a
46977            //short period of time.
46978            //it also comes on handy because iScroll requires the use of timeout when using `refresh`.
46979            clearTimeout(iscrollHandler.refreshId);
46980            iscrollHandler.refreshId = setTimeout(function(){
46981                $.each(iscrollHandler.iScrollInstances, function(){
46982                    $(this).get(0).refresh();
46983                });
46984            }, 150);
46985
46986            //updating the wrappers height
46987            element.find(SCROLLABLE_SEL).css('height', scrollHeight + 'px').parent().css('height', scrollHeight + 'px');
46988        },
46989
46990        /**
46991         * Called to get any additional elements needed to wrap the section
46992         * content in order to facilitate overflow scrolling.
46993         *
46994         * @return {String|Object} Can be a string containing HTML,
46995         *                         a DOM element, or jQuery object.
46996         */
46997        wrapContent: function() {
46998            return '<div class="' + SCROLLABLE + '"><div class="fp-scroller"></div></div>';
46999        }
47000    };
47001});
47002
47003(function (global, factory) {
47004	typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
47005	typeof define === 'function' && define.amd ? define(['exports'], factory) :
47006	(global = global || self, factory(global.window = global.window || {}));
47007  }(this, (function (exports) { 'use strict';
47008  
47009	function _defineProperties(target, props) {
47010	  for (var i = 0; i < props.length; i++) {
47011		var descriptor = props[i];
47012		descriptor.enumerable = descriptor.enumerable || false;
47013		descriptor.configurable = true;
47014		if ("value" in descriptor) descriptor.writable = true;
47015		Object.defineProperty(target, descriptor.key, descriptor);
47016	  }
47017	}
47018  
47019	function _createClass(Constructor, protoProps, staticProps) {
47020	  if (protoProps) _defineProperties(Constructor.prototype, protoProps);
47021	  if (staticProps) _defineProperties(Constructor, staticProps);
47022	  return Constructor;
47023	}
47024  
47025	/*!
47026	 * Observer 3.12.5
47027	 * https://gsap.com
47028	 *
47029	 * @license Copyright 2008-2024, GreenSock. All rights reserved.
47030	 * Subject to the terms at https://gsap.com/standard-license or for
47031	 * Club GSAP members, the agreement issued with that membership.
47032	 * @author: Jack Doyle, [email protected]
47033	*/
47034	var gsap,
47035		_coreInitted,
47036		_clamp,
47037		_win,
47038		_doc,
47039		_docEl,
47040		_body,
47041		_isTouch,
47042		_pointerType,
47043		ScrollTrigger,
47044		_root,
47045		_normalizer,
47046		_eventTypes,
47047		_context,
47048		_getGSAP = function _getGSAP() {
47049	  return gsap || typeof window !== "undefined" && (gsap = window.gsap) && gsap.registerPlugin && gsap;
47050	},
47051		_startup = 1,
47052		_observers = [],
47053		_scrollers = [],
47054		_proxies = [],
47055		_getTime = Date.now,
47056		_bridge = function _bridge(name, value) {
47057	  return value;
47058	},
47059		_integrate = function _integrate() {
47060	  var core = ScrollTrigger.core,
47061		  data = core.bridge || {},
47062		  scrollers = core._scrollers,
47063		  proxies = core._proxies;
47064	  scrollers.push.apply(scrollers, _scrollers);
47065	  proxies.push.apply(proxies, _proxies);
47066	  _scrollers = scrollers;
47067	  _proxies = proxies;
47068  
47069	  _bridge = function _bridge(name, value) {
47070		return data[name](value);
47071	  };
47072	},
47073		_getProxyProp = function _getProxyProp(element, property) {
47074	  return ~_proxies.indexOf(element) && _proxies[_proxies.indexOf(element) + 1][property];
47075	},
47076		_isViewport = function _isViewport(el) {
47077	  return !!~_root.indexOf(el);
47078	},
47079		_addListener = function _addListener(element, type, func, passive, capture) {
47080	  return element.addEventListener(type, func, {
47081		passive: passive !== false,
47082		capture: !!capture
47083	  });
47084	},
47085		_removeListener = function _removeListener(element, type, func, capture) {
47086	  return element.removeEventListener(type, func, !!capture);
47087	},
47088		_scrollLeft = "scrollLeft",
47089		_scrollTop = "scrollTop",
47090		_onScroll = function _onScroll() {
47091	  return _normalizer && _normalizer.isPressed || _scrollers.cache++;
47092	},
47093		_scrollCacheFunc = function _scrollCacheFunc(f, doNotCache) {
47094	  var cachingFunc = function cachingFunc(value) {
47095		if (value || value === 0) {
47096		  _startup && (_win.history.scrollRestoration = "manual");
47097		  var isNormalizing = _normalizer && _normalizer.isPressed;
47098		  value = cachingFunc.v = Math.round(value) || (_normalizer && _normalizer.iOS ? 1 : 0);
47099		  f(value);
47100		  cachingFunc.cacheID = _scrollers.cache;
47101		  isNormalizing && _bridge("ss", value);
47102		} else if (doNotCache || _scrollers.cache !== cachingFunc.cacheID || _bridge("ref")) {
47103		  cachingFunc.cacheID = _scrollers.cache;
47104		  cachingFunc.v = f();
47105		}
47106  
vendor: 4,462 bytes, lines 47107-47243
47107		return cachingFunc.v + cachingFunc.offset;
47108	  };
47109  
47110	  cachingFunc.offset = 0;
47111	  return f && cachingFunc;
47112	},
47113		_horizontal = {
47114	  s: _scrollLeft,
47115	  p: "left",
47116	  p2: "Left",
47117	  os: "right",
47118	  os2: "Right",
47119	  d: "width",
47120	  d2: "Width",
47121	  a: "x",
47122	  sc: _scrollCacheFunc(function (value) {
47123		return arguments.length ? _win.scrollTo(value, _vertical.sc()) : _win.pageXOffset || _doc[_scrollLeft] || _docEl[_scrollLeft] || _body[_scrollLeft] || 0;
47124	  })
47125	},
47126		_vertical = {
47127	  s: _scrollTop,
47128	  p: "top",
47129	  p2: "Top",
47130	  os: "bottom",
47131	  os2: "Bottom",
47132	  d: "height",
47133	  d2: "Height",
47134	  a: "y",
47135	  op: _horizontal,
47136	  sc: _scrollCacheFunc(function (value) {
47137		return arguments.length ? _win.scrollTo(_horizontal.sc(), value) : _win.pageYOffset || _doc[_scrollTop] || _docEl[_scrollTop] || _body[_scrollTop] || 0;
47138	  })
47139	},
47140		_getTarget = function _getTarget(t, self) {
47141	  return (self && self._ctx && self._ctx.selector || gsap.utils.toArray)(t)[0] || (typeof t === "string" && gsap.config().nullTargetWarn !== false ? console.warn("Element not found:", t) : null);
47142	},
47143		_getScrollFunc = function _getScrollFunc(element, _ref) {
47144	  var s = _ref.s,
47145		  sc = _ref.sc;
47146	  _isViewport(element) && (element = _doc.scrollingElement || _docEl);
47147  
47148	  var i = _scrollers.indexOf(element),
47149		  offset = sc === _vertical.sc ? 1 : 2;
47150  
47151	  !~i && (i = _scrollers.push(element) - 1);
47152	  _scrollers[i + offset] || _addListener(element, "scroll", _onScroll);
47153	  var prev = _scrollers[i + offset],
47154		  func = prev || (_scrollers[i + offset] = _scrollCacheFunc(_getProxyProp(element, s), true) || (_isViewport(element) ? sc : _scrollCacheFunc(function (value) {
47155		return arguments.length ? element[s] = value : element[s];
47156	  })));
47157	  func.target = element;
47158	  prev || (func.smooth = gsap.getProperty(element, "scrollBehavior") === "smooth");
47159	  return func;
47160	},
47161		_getVelocityProp = function _getVelocityProp(value, minTimeRefresh, useDelta) {
47162	  var v1 = value,
47163		  v2 = value,
47164		  t1 = _getTime(),
47165		  t2 = t1,
47166		  min = minTimeRefresh || 50,
47167		  dropToZeroTime = Math.max(500, min * 3),
47168		  update = function update(value, force) {
47169		var t = _getTime();
47170  
47171		if (force || t - t1 > min) {
47172		  v2 = v1;
47173		  v1 = value;
47174		  t2 = t1;
47175		  t1 = t;
47176		} else if (useDelta) {
47177		  v1 += value;
47178		} else {
47179		  v1 = v2 + (value - v2) / (t - t2) * (t1 - t2);
47180		}
47181	  },
47182		  reset = function reset() {
47183		v2 = v1 = useDelta ? 0 : v1;
47184		t2 = t1 = 0;
47185	  },
47186		  getVelocity = function getVelocity(latestValue) {
47187		var tOld = t2,
47188			vOld = v2,
47189			t = _getTime();
47190  
47191		(latestValue || latestValue === 0) && latestValue !== v1 && update(latestValue);
47192		return t1 === t2 || t - t2 > dropToZeroTime ? 0 : (v1 + (useDelta ? vOld : -vOld)) / ((useDelta ? t : t1) - tOld) * 1000;
47193	  };
47194  
47195	  return {
47196		update: update,
47197		reset: reset,
47198		getVelocity: getVelocity
47199	  };
47200	},
47201		_getEvent = function _getEvent(e, preventDefault) {
47202	  preventDefault && !e._gsapAllow && e.preventDefault();
47203	  return e.changedTouches ? e.changedTouches[0] : e;
47204	},
47205		_getAbsoluteMax = function _getAbsoluteMax(a) {
47206	  var max = Math.max.apply(Math, a),
47207		  min = Math.min.apply(Math, a);
47208	  return Math.abs(max) >= Math.abs(min) ? max : min;
47209	},
47210		_setScrollTrigger = function _setScrollTrigger() {
47211	  ScrollTrigger = gsap.core.globals().ScrollTrigger;
47212	  ScrollTrigger && ScrollTrigger.core && _integrate();
47213	},
47214		_initCore = function _initCore(core) {
47215	  gsap = core || _getGSAP();
47216  
47217	  if (!_coreInitted && gsap && typeof document !== "undefined" && document.body) {
47218		_win = window;
47219		_doc = document;
47220		_docEl = _doc.documentElement;
47221		_body = _doc.body;
47222		_root = [_win, _doc, _docEl, _body];
47223		_clamp = gsap.utils.clamp;
47224  
47225		_context = gsap.core.context || function () {};
47226  
47227		_pointerType = "onpointerenter" in _body ? "pointer" : "mouse";
47228		_isTouch = Observer.isTouch = _win.matchMedia && _win.matchMedia("(hover: none), (pointer: coarse)").matches ? 1 : "ontouchstart" in _win || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0 ? 2 : 0;
47229		_eventTypes = Observer.eventTypes = ("ontouchstart" in _docEl ? "touchstart,touchmove,touchcancel,touchend" : !("onpointerdown" in _docEl) ? "mousedown,mousemove,mouseup,mouseup" : "pointerdown,pointermove,pointercancel,pointerup").split(",");
47230		setTimeout(function () {
47231		  return _startup = 0;
47232		}, 500);
47233  
47234		_setScrollTrigger();
47235  
47236		_coreInitted = 1;
47237	  }
47238  
47239	  return _coreInitted;
47240	};
47241  
47242	_horizontal.op = _vertical;
47243	_scrollers.cache = 0;
vendor: 9,292 bytes, lines 47244-47560
47244	var Observer = function () {
47245	  function Observer(vars) {
47246		this.init(vars);
47247	  }
47248  
47249	  var _proto = Observer.prototype;
47250  
47251	  _proto.init = function init(vars) {
47252		_coreInitted || _initCore(gsap) || console.warn("Please gsap.registerPlugin(Observer)");
47253		ScrollTrigger || _setScrollTrigger();
47254		var tolerance = vars.tolerance,
47255			dragMinimum = vars.dragMinimum,
47256			type = vars.type,
47257			target = vars.target,
47258			lineHeight = vars.lineHeight,
47259			debounce = vars.debounce,
47260			preventDefault = vars.preventDefault,
47261			onStop = vars.onStop,
47262			onStopDelay = vars.onStopDelay,
47263			ignore = vars.ignore,
47264			wheelSpeed = vars.wheelSpeed,
47265			event = vars.event,
47266			onDragStart = vars.onDragStart,
47267			onDragEnd = vars.onDragEnd,
47268			onDrag = vars.onDrag,
47269			onPress = vars.onPress,
47270			onRelease = vars.onRelease,
47271			onRight = vars.onRight,
47272			onLeft = vars.onLeft,
47273			onUp = vars.onUp,
47274			onDown = vars.onDown,
47275			onChangeX = vars.onChangeX,
47276			onChangeY = vars.onChangeY,
47277			onChange = vars.onChange,
47278			onToggleX = vars.onToggleX,
47279			onToggleY = vars.onToggleY,
47280			onHover = vars.onHover,
47281			onHoverEnd = vars.onHoverEnd,
47282			onMove = vars.onMove,
47283			ignoreCheck = vars.ignoreCheck,
47284			isNormalizer = vars.isNormalizer,
47285			onGestureStart = vars.onGestureStart,
47286			onGestureEnd = vars.onGestureEnd,
47287			onWheel = vars.onWheel,
47288			onEnable = vars.onEnable,
47289			onDisable = vars.onDisable,
47290			onClick = vars.onClick,
47291			scrollSpeed = vars.scrollSpeed,
47292			capture = vars.capture,
47293			allowClicks = vars.allowClicks,
47294			lockAxis = vars.lockAxis,
47295			onLockAxis = vars.onLockAxis;
47296		this.target = target = _getTarget(target) || _docEl;
47297		this.vars = vars;
47298		ignore && (ignore = gsap.utils.toArray(ignore));
47299		tolerance = tolerance || 1e-9;
47300		dragMinimum = dragMinimum || 0;
47301		wheelSpeed = wheelSpeed || 1;
47302		scrollSpeed = scrollSpeed || 1;
47303		type = type || "wheel,touch,pointer";
47304		debounce = debounce !== false;
47305		lineHeight || (lineHeight = parseFloat(_win.getComputedStyle(_body).lineHeight) || 22);
47306  
47307		var id,
47308			onStopDelayedCall,
47309			dragged,
47310			moved,
47311			wheeled,
47312			locked,
47313			axis,
47314			self = this,
47315			prevDeltaX = 0,
47316			prevDeltaY = 0,
47317			passive = vars.passive || !preventDefault,
47318			scrollFuncX = _getScrollFunc(target, _horizontal),
47319			scrollFuncY = _getScrollFunc(target, _vertical),
47320			scrollX = scrollFuncX(),
47321			scrollY = scrollFuncY(),
47322			limitToTouch = ~type.indexOf("touch") && !~type.indexOf("pointer") && _eventTypes[0] === "pointerdown",
47323			isViewport = _isViewport(target),
47324			ownerDoc = target.ownerDocument || _doc,
47325			deltaX = [0, 0, 0],
47326			deltaY = [0, 0, 0],
47327			onClickTime = 0,
47328			clickCapture = function clickCapture() {
47329		  return onClickTime = _getTime();
47330		},
47331			_ignoreCheck = function _ignoreCheck(e, isPointerOrTouch) {
47332		  return (self.event = e) && ignore && ~ignore.indexOf(e.target) || isPointerOrTouch && limitToTouch && e.pointerType !== "touch" || ignoreCheck && ignoreCheck(e, isPointerOrTouch);
47333		},
47334			onStopFunc = function onStopFunc() {
47335		  self._vx.reset();
47336  
47337		  self._vy.reset();
47338  
47339		  onStopDelayedCall.pause();
47340		  onStop && onStop(self);
47341		},
47342			update = function update() {
47343		  var dx = self.deltaX = _getAbsoluteMax(deltaX),
47344			  dy = self.deltaY = _getAbsoluteMax(deltaY),
47345			  changedX = Math.abs(dx) >= tolerance,
47346			  changedY = Math.abs(dy) >= tolerance;
47347  
47348		  onChange && (changedX || changedY) && onChange(self, dx, dy, deltaX, deltaY);
47349  
47350		  if (changedX) {
47351			onRight && self.deltaX > 0 && onRight(self);
47352			onLeft && self.deltaX < 0 && onLeft(self);
47353			onChangeX && onChangeX(self);
47354			onToggleX && self.deltaX < 0 !== prevDeltaX < 0 && onToggleX(self);
47355			prevDeltaX = self.deltaX;
47356			deltaX[0] = deltaX[1] = deltaX[2] = 0;
47357		  }
47358  
47359		  if (changedY) {
47360			onDown && self.deltaY > 0 && onDown(self);
47361			onUp && self.deltaY < 0 && onUp(self);
47362			onChangeY && onChangeY(self);
47363			onToggleY && self.deltaY < 0 !== prevDeltaY < 0 && onToggleY(self);
47364			prevDeltaY = self.deltaY;
47365			deltaY[0] = deltaY[1] = deltaY[2] = 0;
47366		  }
47367  
47368		  if (moved || dragged) {
47369			onMove && onMove(self);
47370  
47371			if (dragged) {
47372			  onDrag(self);
47373			  dragged = false;
47374			}
47375  
47376			moved = false;
47377		  }
47378  
47379		  locked && !(locked = false) && onLockAxis && onLockAxis(self);
47380  
47381		  if (wheeled) {
47382			onWheel(self);
47383			wheeled = false;
47384		  }
47385  
47386		  id = 0;
47387		},
47388			onDelta = function onDelta(x, y, index) {
47389		  deltaX[index] += x;
47390		  deltaY[index] += y;
47391  
47392		  self._vx.update(x);
47393  
47394		  self._vy.update(y);
47395  
47396		  debounce ? id || (id = requestAnimationFrame(update)) : update();
47397		},
47398			onTouchOrPointerDelta = function onTouchOrPointerDelta(x, y) {
47399		  if (lockAxis && !axis) {
47400			self.axis = axis = Math.abs(x) > Math.abs(y) ? "x" : "y";
47401			locked = true;
47402		  }
47403  
47404		  if (axis !== "y") {
47405			deltaX[2] += x;
47406  
47407			self._vx.update(x, true);
47408		  }
47409  
47410		  if (axis !== "x") {
47411			deltaY[2] += y;
47412  
47413			self._vy.update(y, true);
47414		  }
47415  
47416		  debounce ? id || (id = requestAnimationFrame(update)) : update();
47417		},
47418			_onDrag = function _onDrag(e) {
47419		  if (_ignoreCheck(e, 1)) {
47420			return;
47421		  }
47422  
47423		  e = _getEvent(e, preventDefault);
47424		  var x = e.clientX,
47425			  y = e.clientY,
47426			  dx = x - self.x,
47427			  dy = y - self.y,
47428			  isDragging = self.isDragging;
47429		  self.x = x;
47430		  self.y = y;
47431  
47432		  if (isDragging || Math.abs(self.startX - x) >= dragMinimum || Math.abs(self.startY - y) >= dragMinimum) {
47433			onDrag && (dragged = true);
47434			isDragging || (self.isDragging = true);
47435			onTouchOrPointerDelta(dx, dy);
47436			isDragging || onDragStart && onDragStart(self);
47437		  }
47438		},
47439			_onPress = self.onPress = function (e) {
47440		  if (_ignoreCheck(e, 1) || e && e.button) {
47441			return;
47442		  }
47443  
47444		  self.axis = axis = null;
47445		  onStopDelayedCall.pause();
47446		  self.isPressed = true;
47447		  e = _getEvent(e);
47448		  prevDeltaX = prevDeltaY = 0;
47449		  self.startX = self.x = e.clientX;
47450		  self.startY = self.y = e.clientY;
47451  
47452		  self._vx.reset();
47453  
47454		  self._vy.reset();
47455  
47456		  _addListener(isNormalizer ? target : ownerDoc, _eventTypes[1], _onDrag, passive, true);
47457  
47458		  self.deltaX = self.deltaY = 0;
47459		  onPress && onPress(self);
47460		},
47461			_onRelease = self.onRelease = function (e) {
47462		  if (_ignoreCheck(e, 1)) {
47463			return;
47464		  }
47465  
47466		  _removeListener(isNormalizer ? target : ownerDoc, _eventTypes[1], _onDrag, true);
47467  
47468		  var isTrackingDrag = !isNaN(self.y - self.startY),
47469			  wasDragging = self.isDragging,
47470			  isDragNotClick = wasDragging && (Math.abs(self.x - self.startX) > 3 || Math.abs(self.y - self.startY) > 3),
47471			  eventData = _getEvent(e);
47472  
47473		  if (!isDragNotClick && isTrackingDrag) {
47474			self._vx.reset();
47475  
47476			self._vy.reset();
47477  
47478			if (preventDefault && allowClicks) {
47479			  gsap.delayedCall(0.08, function () {
47480				if (_getTime() - onClickTime > 300 && !e.defaultPrevented) {
47481				  if (e.target.click) {
47482					e.target.click();
47483				  } else if (ownerDoc.createEvent) {
47484					var syntheticEvent = ownerDoc.createEvent("MouseEvents");
47485					syntheticEvent.initMouseEvent("click", true, true, _win, 1, eventData.screenX, eventData.screenY, eventData.clientX, eventData.clientY, false, false, false, false, 0, null);
47486					e.target.dispatchEvent(syntheticEvent);
47487				  }
47488				}
47489			  });
47490			}
47491		  }
47492  
47493		  self.isDragging = self.isGesturing = self.isPressed = false;
47494		  onStop && wasDragging && !isNormalizer && onStopDelayedCall.restart(true);
47495		  onDragEnd && wasDragging && onDragEnd(self);
47496		  onRelease && onRelease(self, isDragNotClick);
47497		},
47498			_onGestureStart = function _onGestureStart(e) {
47499		  return e.touches && e.touches.length > 1 && (self.isGesturing = true) && onGestureStart(e, self.isDragging);
47500		},
47501			_onGestureEnd = function _onGestureEnd() {
47502		  return (self.isGesturing = false) || onGestureEnd(self);
47503		},
47504			onScroll = function onScroll(e) {
47505		  if (_ignoreCheck(e)) {
47506			return;
47507		  }
47508  
47509		  var x = scrollFuncX(),
47510			  y = scrollFuncY();
47511		  onDelta((x - scrollX) * scrollSpeed, (y - scrollY) * scrollSpeed, 1);
47512		  scrollX = x;
47513		  scrollY = y;
47514		  onStop && onStopDelayedCall.restart(true);
47515		},
47516			_onWheel = function _onWheel(e) {
47517		  if (_ignoreCheck(e)) {
47518			return;
47519		  }
47520  
47521		  e = _getEvent(e, preventDefault);
47522		  onWheel && (wheeled = true);
47523		  var multiplier = (e.deltaMode === 1 ? lineHeight : e.deltaMode === 2 ? _win.innerHeight : 1) * wheelSpeed;
47524		  onDelta(e.deltaX * multiplier, e.deltaY * multiplier, 0);
47525		  onStop && !isNormalizer && onStopDelayedCall.restart(true);
47526		},
47527			_onMove = function _onMove(e) {
47528		  if (_ignoreCheck(e)) {
47529			return;
47530		  }
47531  
47532		  var x = e.clientX,
47533			  y = e.clientY,
47534			  dx = x - self.x,
47535			  dy = y - self.y;
47536		  self.x = x;
47537		  self.y = y;
47538		  moved = true;
47539		  onStop && onStopDelayedCall.restart(true);
47540		  (dx || dy) && onTouchOrPointerDelta(dx, dy);
47541		},
47542			_onHover = function _onHover(e) {
47543		  self.event = e;
47544		  onHover(self);
47545		},
47546			_onHoverEnd = function _onHoverEnd(e) {
47547		  self.event = e;
47548		  onHoverEnd(self);
47549		},
47550			_onClick = function _onClick(e) {
47551		  return _ignoreCheck(e) || _getEvent(e, preventDefault) && onClick(self);
47552		};
47553  
47554		onStopDelayedCall = self._dc = gsap.delayedCall(onStopDelay || 0.25, onStopFunc).pause();
47555		self.deltaX = self.deltaY = 0;
47556		self._vx = _getVelocityProp(0, 50, true);
47557		self._vy = _getVelocityProp(0, 50, true);
47558		self.scrollX = scrollFuncX;
47559		self.scrollY = scrollFuncY;
47560		self.isDragging = self.isGesturing = self.isPressed = false;
vendor: 7,173 bytes, lines 47561-47803
47561  
47562		_context(this);
47563  
47564		self.enable = function (e) {
47565		  if (!self.isEnabled) {
47566			_addListener(isViewport ? ownerDoc : target, "scroll", _onScroll);
47567  
47568			type.indexOf("scroll") >= 0 && _addListener(isViewport ? ownerDoc : target, "scroll", onScroll, passive, capture);
47569			type.indexOf("wheel") >= 0 && _addListener(target, "wheel", _onWheel, passive, capture);
47570  
47571			if (type.indexOf("touch") >= 0 && _isTouch || type.indexOf("pointer") >= 0) {
47572			  _addListener(target, _eventTypes[0], _onPress, passive, capture);
47573  
47574			  _addListener(ownerDoc, _eventTypes[2], _onRelease);
47575  
47576			  _addListener(ownerDoc, _eventTypes[3], _onRelease);
47577  
47578			  allowClicks && _addListener(target, "click", clickCapture, true, true);
47579			  onClick && _addListener(target, "click", _onClick);
47580			  onGestureStart && _addListener(ownerDoc, "gesturestart", _onGestureStart);
47581			  onGestureEnd && _addListener(ownerDoc, "gestureend", _onGestureEnd);
47582			  onHover && _addListener(target, _pointerType + "enter", _onHover);
47583			  onHoverEnd && _addListener(target, _pointerType + "leave", _onHoverEnd);
47584			  onMove && _addListener(target, _pointerType + "move", _onMove);
47585			}
47586  
47587			self.isEnabled = true;
47588			e && e.type && _onPress(e);
47589			onEnable && onEnable(self);
47590		  }
47591  
47592		  return self;
47593		};
47594  
47595		self.disable = function () {
47596		  if (self.isEnabled) {
47597			_observers.filter(function (o) {
47598			  return o !== self && _isViewport(o.target);
47599			}).length || _removeListener(isViewport ? ownerDoc : target, "scroll", _onScroll);
47600  
47601			if (self.isPressed) {
47602			  self._vx.reset();
47603  
47604			  self._vy.reset();
47605  
47606			  _removeListener(isNormalizer ? target : ownerDoc, _eventTypes[1], _onDrag, true);
47607			}
47608  
47609			_removeListener(isViewport ? ownerDoc : target, "scroll", onScroll, capture);
47610  
47611			_removeListener(target, "wheel", _onWheel, capture);
47612  
47613			_removeListener(target, _eventTypes[0], _onPress, capture);
47614  
47615			_removeListener(ownerDoc, _eventTypes[2], _onRelease);
47616  
47617			_removeListener(ownerDoc, _eventTypes[3], _onRelease);
47618  
47619			_removeListener(target, "click", clickCapture, true);
47620  
47621			_removeListener(target, "click", _onClick);
47622  
47623			_removeListener(ownerDoc, "gesturestart", _onGestureStart);
47624  
47625			_removeListener(ownerDoc, "gestureend", _onGestureEnd);
47626  
47627			_removeListener(target, _pointerType + "enter", _onHover);
47628  
47629			_removeListener(target, _pointerType + "leave", _onHoverEnd);
47630  
47631			_removeListener(target, _pointerType + "move", _onMove);
47632  
47633			self.isEnabled = self.isPressed = self.isDragging = false;
47634			onDisable && onDisable(self);
47635		  }
47636		};
47637  
47638		self.kill = self.revert = function () {
47639		  self.disable();
47640  
47641		  var i = _observers.indexOf(self);
47642  
47643		  i >= 0 && _observers.splice(i, 1);
47644		  _normalizer === self && (_normalizer = 0);
47645		};
47646  
47647		_observers.push(self);
47648  
47649		isNormalizer && _isViewport(target) && (_normalizer = self);
47650		self.enable(event);
47651	  };
47652  
47653	  _createClass(Observer, [{
47654		key: "velocityX",
47655		get: function get() {
47656		  return this._vx.getVelocity();
47657		}
47658	  }, {
47659		key: "velocityY",
47660		get: function get() {
47661		  return this._vy.getVelocity();
47662		}
47663	  }]);
47664  
47665	  return Observer;
47666	}();
47667	Observer.version = "3.12.5";
47668  
47669	Observer.create = function (vars) {
47670	  return new Observer(vars);
47671	};
47672  
47673	Observer.register = _initCore;
47674  
47675	Observer.getAll = function () {
47676	  return _observers.slice();
47677	};
47678  
47679	Observer.getById = function (id) {
47680	  return _observers.filter(function (o) {
47681		return o.vars.id === id;
47682	  })[0];
47683	};
47684  
47685	_getGSAP() && gsap.registerPlugin(Observer);
47686  
47687	/*!
47688	 * ScrollTrigger 3.12.5
47689	 * https://gsap.com
47690	 *
47691	 * @license Copyright 2008-2024, GreenSock. All rights reserved.
47692	 * Subject to the terms at https://gsap.com/standard-license or for
47693	 * Club GSAP members, the agreement issued with that membership.
47694	 * @author: Jack Doyle, [email protected]
47695	*/
47696  
47697	var gsap$1,
47698		_coreInitted$1,
47699		_win$1,
47700		_doc$1,
47701		_docEl$1,
47702		_body$1,
47703		_root$1,
47704		_resizeDelay,
47705		_toArray,
47706		_clamp$1,
47707		_time2,
47708		_syncInterval,
47709		_refreshing,
47710		_pointerIsDown,
47711		_transformProp,
47712		_i,
47713		_prevWidth,
47714		_prevHeight,
47715		_autoRefresh,
47716		_sort,
47717		_suppressOverwrites,
47718		_ignoreResize,
47719		_normalizer$1,
47720		_ignoreMobileResize,
47721		_baseScreenHeight,
47722		_baseScreenWidth,
47723		_fixIOSBug,
47724		_context$1,
47725		_scrollRestoration,
47726		_div100vh,
47727		_100vh,
47728		_isReverted,
47729		_clampingMax,
47730		_limitCallbacks,
47731		_startup$1 = 1,
47732		_getTime$1 = Date.now,
47733		_time1 = _getTime$1(),
47734		_lastScrollTime = 0,
47735		_enabled = 0,
47736		_parseClamp = function _parseClamp(value, type, self) {
47737	  var clamp = _isString(value) && (value.substr(0, 6) === "clamp(" || value.indexOf("max") > -1);
47738	  self["_" + type + "Clamp"] = clamp;
47739	  return clamp ? value.substr(6, value.length - 7) : value;
47740	},
47741		_keepClamp = function _keepClamp(value, clamp) {
47742	  return clamp && (!_isString(value) || value.substr(0, 6) !== "clamp(") ? "clamp(" + value + ")" : value;
47743	},
47744		_rafBugFix = function _rafBugFix() {
47745	  return _enabled && requestAnimationFrame(_rafBugFix);
47746	},
47747		_pointerDownHandler = function _pointerDownHandler() {
47748	  return _pointerIsDown = 1;
47749	},
47750		_pointerUpHandler = function _pointerUpHandler() {
47751	  return _pointerIsDown = 0;
47752	},
47753		_passThrough = function _passThrough(v) {
47754	  return v;
47755	},
47756		_round = function _round(value) {
47757	  return Math.round(value * 100000) / 100000 || 0;
47758	},
47759		_windowExists = function _windowExists() {
47760	  return typeof window !== "undefined";
47761	},
47762		_getGSAP$1 = function _getGSAP() {
47763	  return gsap$1 || _windowExists() && (gsap$1 = window.gsap) && gsap$1.registerPlugin && gsap$1;
47764	},
47765		_isViewport$1 = function _isViewport(e) {
47766	  return !!~_root$1.indexOf(e);
47767	},
47768		_getViewportDimension = function _getViewportDimension(dimensionProperty) {
47769	  return (dimensionProperty === "Height" ? _100vh : _win$1["inner" + dimensionProperty]) || _docEl$1["client" + dimensionProperty] || _body$1["client" + dimensionProperty];
47770	},
47771		_getBoundsFunc = function _getBoundsFunc(element) {
47772	  return _getProxyProp(element, "getBoundingClientRect") || (_isViewport$1(element) ? function () {
47773		_winOffsets.width = _win$1.innerWidth;
47774		_winOffsets.height = _100vh;
47775		return _winOffsets;
47776	  } : function () {
47777		return _getBounds(element);
47778	  });
47779	},
47780		_getSizeFunc = function _getSizeFunc(scroller, isViewport, _ref) {
47781	  var d = _ref.d,
47782		  d2 = _ref.d2,
47783		  a = _ref.a;
47784	  return (a = _getProxyProp(scroller, "getBoundingClientRect")) ? function () {
47785		return a()[d];
47786	  } : function () {
47787		return (isViewport ? _getViewportDimension(d2) : scroller["client" + d2]) || 0;
47788	  };
47789	},
47790		_getOffsetsFunc = function _getOffsetsFunc(element, isViewport) {
47791	  return !isViewport || ~_proxies.indexOf(element) ? _getBoundsFunc(element) : function () {
47792		return _winOffsets;
47793	  };
47794	},
47795		_maxScroll = function _maxScroll(element, _ref2) {
47796	  var s = _ref2.s,
47797		  d2 = _ref2.d2,
47798		  d = _ref2.d,
47799		  a = _ref2.a;
47800	  return Math.max(0, (s = "scroll" + d2) && (a = _getProxyProp(element, s)) ? a() - _getBoundsFunc(element)()[d] : _isViewport$1(element) ? (_docEl$1[s] || _body$1[s]) - _getViewportDimension(d2) : element[s] - element["offset" + d2]);
47801	},
47802		_iterateAutoRefresh = function _iterateAutoRefresh(func, events) {
47803	  for (var i = 0; i < _autoRefresh.length; i += 3) {
vendor: 14,082 bytes, lines 47804-48275
47804		(!events || ~events.indexOf(_autoRefresh[i + 1])) && func(_autoRefresh[i], _autoRefresh[i + 1], _autoRefresh[i + 2]);
47805	  }
47806	},
47807		_isString = function _isString(value) {
47808	  return typeof value === "string";
47809	},
47810		_isFunction = function _isFunction(value) {
47811	  return typeof value === "function";
47812	},
47813		_isNumber = function _isNumber(value) {
47814	  return typeof value === "number";
47815	},
47816		_isObject = function _isObject(value) {
47817	  return typeof value === "object";
47818	},
47819		_endAnimation = function _endAnimation(animation, reversed, pause) {
47820	  return animation && animation.progress(reversed ? 0 : 1) && pause && animation.pause();
47821	},
47822		_callback = function _callback(self, func) {
47823	  if (self.enabled) {
47824		var result = self._ctx ? self._ctx.add(function () {
47825		  return func(self);
47826		}) : func(self);
47827		result && result.totalTime && (self.callbackAnimation = result);
47828	  }
47829	},
47830		_abs = Math.abs,
47831		_left = "left",
47832		_top = "top",
47833		_right = "right",
47834		_bottom = "bottom",
47835		_width = "width",
47836		_height = "height",
47837		_Right = "Right",
47838		_Left = "Left",
47839		_Top = "Top",
47840		_Bottom = "Bottom",
47841		_padding = "padding",
47842		_margin = "margin",
47843		_Width = "Width",
47844		_Height = "Height",
47845		_px = "px",
47846		_getComputedStyle = function _getComputedStyle(element) {
47847	  return _win$1.getComputedStyle(element);
47848	},
47849		_makePositionable = function _makePositionable(element) {
47850	  var position = _getComputedStyle(element).position;
47851  
47852	  element.style.position = position === "absolute" || position === "fixed" ? position : "relative";
47853	},
47854		_setDefaults = function _setDefaults(obj, defaults) {
47855	  for (var p in defaults) {
47856		p in obj || (obj[p] = defaults[p]);
47857	  }
47858  
47859	  return obj;
47860	},
47861		_getBounds = function _getBounds(element, withoutTransforms) {
47862	  var tween = withoutTransforms && _getComputedStyle(element)[_transformProp] !== "matrix(1, 0, 0, 1, 0, 0)" && gsap$1.to(element, {
47863		x: 0,
47864		y: 0,
47865		xPercent: 0,
47866		yPercent: 0,
47867		rotation: 0,
47868		rotationX: 0,
47869		rotationY: 0,
47870		scale: 1,
47871		skewX: 0,
47872		skewY: 0
47873	  }).progress(1),
47874		  bounds = element.getBoundingClientRect();
47875	  tween && tween.progress(0).kill();
47876	  return bounds;
47877	},
47878		_getSize = function _getSize(element, _ref3) {
47879	  var d2 = _ref3.d2;
47880	  return element["offset" + d2] || element["client" + d2] || 0;
47881	},
47882		_getLabelRatioArray = function _getLabelRatioArray(timeline) {
47883	  var a = [],
47884		  labels = timeline.labels,
47885		  duration = timeline.duration(),
47886		  p;
47887  
47888	  for (p in labels) {
47889		a.push(labels[p] / duration);
47890	  }
47891  
47892	  return a;
47893	},
47894		_getClosestLabel = function _getClosestLabel(animation) {
47895	  return function (value) {
47896		return gsap$1.utils.snap(_getLabelRatioArray(animation), value);
47897	  };
47898	},
47899		_snapDirectional = function _snapDirectional(snapIncrementOrArray) {
47900	  var snap = gsap$1.utils.snap(snapIncrementOrArray),
47901		  a = Array.isArray(snapIncrementOrArray) && snapIncrementOrArray.slice(0).sort(function (a, b) {
47902		return a - b;
47903	  });
47904	  return a ? function (value, direction, threshold) {
47905		if (threshold === void 0) {
47906		  threshold = 1e-3;
47907		}
47908  
47909		var i;
47910  
47911		if (!direction) {
47912		  return snap(value);
47913		}
47914  
47915		if (direction > 0) {
47916		  value -= threshold;
47917  
47918		  for (i = 0; i < a.length; i++) {
47919			if (a[i] >= value) {
47920			  return a[i];
47921			}
47922		  }
47923  
47924		  return a[i - 1];
47925		} else {
47926		  i = a.length;
47927		  value += threshold;
47928  
47929		  while (i--) {
47930			if (a[i] <= value) {
47931			  return a[i];
47932			}
47933		  }
47934		}
47935  
47936		return a[0];
47937	  } : function (value, direction, threshold) {
47938		if (threshold === void 0) {
47939		  threshold = 1e-3;
47940		}
47941  
47942		var snapped = snap(value);
47943		return !direction || Math.abs(snapped - value) < threshold || snapped - value < 0 === direction < 0 ? snapped : snap(direction < 0 ? value - snapIncrementOrArray : value + snapIncrementOrArray);
47944	  };
47945	},
47946		_getLabelAtDirection = function _getLabelAtDirection(timeline) {
47947	  return function (value, st) {
47948		return _snapDirectional(_getLabelRatioArray(timeline))(value, st.direction);
47949	  };
47950	},
47951		_multiListener = function _multiListener(func, element, types, callback) {
47952	  return types.split(",").forEach(function (type) {
47953		return func(element, type, callback);
47954	  });
47955	},
47956		_addListener$1 = function _addListener(element, type, func, nonPassive, capture) {
47957	  return element.addEventListener(type, func, {
47958		passive: !nonPassive,
47959		capture: !!capture
47960	  });
47961	},
47962		_removeListener$1 = function _removeListener(element, type, func, capture) {
47963	  return element.removeEventListener(type, func, !!capture);
47964	},
47965		_wheelListener = function _wheelListener(func, el, scrollFunc) {
47966	  scrollFunc = scrollFunc && scrollFunc.wheelHandler;
47967  
47968	  if (scrollFunc) {
47969		func(el, "wheel", scrollFunc);
47970		func(el, "touchmove", scrollFunc);
47971	  }
47972	},
47973		_markerDefaults = {
47974	  startColor: "green",
47975	  endColor: "red",
47976	  indent: 0,
47977	  fontSize: "16px",
47978	  fontWeight: "normal"
47979	},
47980		_defaults = {
47981	  toggleActions: "play",
47982	  anticipatePin: 0
47983	},
47984		_keywords = {
47985	  top: 0,
47986	  left: 0,
47987	  center: 0.5,
47988	  bottom: 1,
47989	  right: 1
47990	},
47991		_offsetToPx = function _offsetToPx(value, size) {
47992	  if (_isString(value)) {
47993		var eqIndex = value.indexOf("="),
47994			relative = ~eqIndex ? +(value.charAt(eqIndex - 1) + 1) * parseFloat(value.substr(eqIndex + 1)) : 0;
47995  
47996		if (~eqIndex) {
47997		  value.indexOf("%") > eqIndex && (relative *= size / 100);
47998		  value = value.substr(0, eqIndex - 1);
47999		}
48000  
48001		value = relative + (value in _keywords ? _keywords[value] * size : ~value.indexOf("%") ? parseFloat(value) * size / 100 : parseFloat(value) || 0);
48002	  }
48003  
48004	  return value;
48005	},
48006		_createMarker = function _createMarker(type, name, container, direction, _ref4, offset, matchWidthEl, containerAnimation) {
48007	  var startColor = _ref4.startColor,
48008		  endColor = _ref4.endColor,
48009		  fontSize = _ref4.fontSize,
48010		  indent = _ref4.indent,
48011		  fontWeight = _ref4.fontWeight;
48012  
48013	  var e = _doc$1.createElement("div"),
48014		  useFixedPosition = _isViewport$1(container) || _getProxyProp(container, "pinType") === "fixed",
48015		  isScroller = type.indexOf("scroller") !== -1,
48016		  parent = useFixedPosition ? _body$1 : container,
48017		  isStart = type.indexOf("start") !== -1,
48018		  color = isStart ? startColor : endColor,
48019		  css = "border-color:" + color + ";font-size:" + fontSize + ";color:" + color + ";font-weight:" + fontWeight + ";pointer-events:none;white-space:nowrap;font-family:sans-serif,Arial;z-index:1000;padding:4px 8px;border-width:0;border-style:solid;";
48020  
48021	  css += "position:" + ((isScroller || containerAnimation) && useFixedPosition ? "fixed;" : "absolute;");
48022	  (isScroller || containerAnimation || !useFixedPosition) && (css += (direction === _vertical ? _right : _bottom) + ":" + (offset + parseFloat(indent)) + "px;");
48023	  matchWidthEl && (css += "box-sizing:border-box;text-align:left;width:" + matchWidthEl.offsetWidth + "px;");
48024	  e._isStart = isStart;
48025	  e.setAttribute("class", "gsap-marker-" + type + (name ? " marker-" + name : ""));
48026	  e.style.cssText = css;
48027	  e.innerText = name || name === 0 ? type + "-" + name : type;
48028	  parent.children[0] ? parent.insertBefore(e, parent.children[0]) : parent.appendChild(e);
48029	  e._offset = e["offset" + direction.op.d2];
48030  
48031	  _positionMarker(e, 0, direction, isStart);
48032  
48033	  return e;
48034	},
48035		_positionMarker = function _positionMarker(marker, start, direction, flipped) {
48036	  var vars = {
48037		display: "block"
48038	  },
48039		  side = direction[flipped ? "os2" : "p2"],
48040		  oppositeSide = direction[flipped ? "p2" : "os2"];
48041	  marker._isFlipped = flipped;
48042	  vars[direction.a + "Percent"] = flipped ? -100 : 0;
48043	  vars[direction.a] = flipped ? "1px" : 0;
48044	  vars["border" + side + _Width] = 1;
48045	  vars["border" + oppositeSide + _Width] = 0;
48046	  vars[direction.p] = start + "px";
48047	  gsap$1.set(marker, vars);
48048	},
48049		_triggers = [],
48050		_ids = {},
48051		_rafID,
48052		_sync = function _sync() {
48053	  return _getTime$1() - _lastScrollTime > 34 && (_rafID || (_rafID = requestAnimationFrame(_updateAll)));
48054	},
48055		_onScroll$1 = function _onScroll() {
48056	  if (!_normalizer$1 || !_normalizer$1.isPressed || _normalizer$1.startX > _body$1.clientWidth) {
48057		_scrollers.cache++;
48058  
48059		if (_normalizer$1) {
48060		  _rafID || (_rafID = requestAnimationFrame(_updateAll));
48061		} else {
48062		  _updateAll();
48063		}
48064  
48065		_lastScrollTime || _dispatch("scrollStart");
48066		_lastScrollTime = _getTime$1();
48067	  }
48068	},
48069		_setBaseDimensions = function _setBaseDimensions() {
48070	  _baseScreenWidth = _win$1.innerWidth;
48071	  _baseScreenHeight = _win$1.innerHeight;
48072	},
48073		_onResize = function _onResize() {
48074	  _scrollers.cache++;
48075	  !_refreshing && !_ignoreResize && !_doc$1.fullscreenElement && !_doc$1.webkitFullscreenElement && (!_ignoreMobileResize || _baseScreenWidth !== _win$1.innerWidth || Math.abs(_win$1.innerHeight - _baseScreenHeight) > _win$1.innerHeight * 0.25) && _resizeDelay.restart(true);
48076	},
48077		_listeners = {},
48078		_emptyArray = [],
48079		_softRefresh = function _softRefresh() {
48080	  return _removeListener$1(ScrollTrigger$1, "scrollEnd", _softRefresh) || _refreshAll(true);
48081	},
48082		_dispatch = function _dispatch(type) {
48083	  return _listeners[type] && _listeners[type].map(function (f) {
48084		return f();
48085	  }) || _emptyArray;
48086	},
48087		_savedStyles = [],
48088		_revertRecorded = function _revertRecorded(media) {
48089	  for (var i = 0; i < _savedStyles.length; i += 5) {
48090		if (!media || _savedStyles[i + 4] && _savedStyles[i + 4].query === media) {
48091		  _savedStyles[i].style.cssText = _savedStyles[i + 1];
48092		  _savedStyles[i].getBBox && _savedStyles[i].setAttribute("transform", _savedStyles[i + 2] || "");
48093		  _savedStyles[i + 3].uncache = 1;
48094		}
48095	  }
48096	},
48097		_revertAll = function _revertAll(kill, media) {
48098	  var trigger;
48099  
48100	  for (_i = 0; _i < _triggers.length; _i++) {
48101		trigger = _triggers[_i];
48102  
48103		if (trigger && (!media || trigger._ctx === media)) {
48104		  if (kill) {
48105			trigger.kill(1);
48106		  } else {
48107			trigger.revert(true, true);
48108		  }
48109		}
48110	  }
48111  
48112	  _isReverted = true;
48113	  media && _revertRecorded(media);
48114	  media || _dispatch("revert");
48115	},
48116		_clearScrollMemory = function _clearScrollMemory(scrollRestoration, force) {
48117	  _scrollers.cache++;
48118	  (force || !_refreshingAll) && _scrollers.forEach(function (obj) {
48119		return _isFunction(obj) && obj.cacheID++ && (obj.rec = 0);
48120	  });
48121	  _isString(scrollRestoration) && (_win$1.history.scrollRestoration = _scrollRestoration = scrollRestoration);
48122	},
48123		_refreshingAll,
48124		_refreshID = 0,
48125		_queueRefreshID,
48126		_queueRefreshAll = function _queueRefreshAll() {
48127	  if (_queueRefreshID !== _refreshID) {
48128		var id = _queueRefreshID = _refreshID;
48129		requestAnimationFrame(function () {
48130		  return id === _refreshID && _refreshAll(true);
48131		});
48132	  }
48133	},
48134		_refresh100vh = function _refresh100vh() {
48135	  _body$1.appendChild(_div100vh);
48136  
48137	  _100vh = !_normalizer$1 && _div100vh.offsetHeight || _win$1.innerHeight;
48138  
48139	  _body$1.removeChild(_div100vh);
48140	},
48141		_hideAllMarkers = function _hideAllMarkers(hide) {
48142	  return _toArray(".gsap-marker-start, .gsap-marker-end, .gsap-marker-scroller-start, .gsap-marker-scroller-end").forEach(function (el) {
48143		return el.style.display = hide ? "none" : "block";
48144	  });
48145	},
48146		_refreshAll = function _refreshAll(force, skipRevert) {
48147	  if (_lastScrollTime && !force && !_isReverted) {
48148		_addListener$1(ScrollTrigger$1, "scrollEnd", _softRefresh);
48149  
48150		return;
48151	  }
48152  
48153	  _refresh100vh();
48154  
48155	  _refreshingAll = ScrollTrigger$1.isRefreshing = true;
48156  
48157	  _scrollers.forEach(function (obj) {
48158		return _isFunction(obj) && ++obj.cacheID && (obj.rec = obj());
48159	  });
48160  
48161	  var refreshInits = _dispatch("refreshInit");
48162  
48163	  _sort && ScrollTrigger$1.sort();
48164	  skipRevert || _revertAll();
48165  
48166	  _scrollers.forEach(function (obj) {
48167		if (_isFunction(obj)) {
48168		  obj.smooth && (obj.target.style.scrollBehavior = "auto");
48169		  obj(0);
48170		}
48171	  });
48172  
48173	  _triggers.slice(0).forEach(function (t) {
48174		return t.refresh();
48175	  });
48176  
48177	  _isReverted = false;
48178  
48179	  _triggers.forEach(function (t) {
48180		if (t._subPinOffset && t.pin) {
48181		  var prop = t.vars.horizontal ? "offsetWidth" : "offsetHeight",
48182			  original = t.pin[prop];
48183		  t.revert(true, 1);
48184		  t.adjustPinSpacing(t.pin[prop] - original);
48185		  t.refresh();
48186		}
48187	  });
48188  
48189	  _clampingMax = 1;
48190  
48191	  _hideAllMarkers(true);
48192  
48193	  _triggers.forEach(function (t) {
48194		var max = _maxScroll(t.scroller, t._dir),
48195			endClamp = t.vars.end === "max" || t._endClamp && t.end > max,
48196			startClamp = t._startClamp && t.start >= max;
48197  
48198		(endClamp || startClamp) && t.setPositions(startClamp ? max - 1 : t.start, endClamp ? Math.max(startClamp ? max : t.start + 1, max) : t.end, true);
48199	  });
48200  
48201	  _hideAllMarkers(false);
48202  
48203	  _clampingMax = 0;
48204	  refreshInits.forEach(function (result) {
48205		return result && result.render && result.render(-1);
48206	  });
48207  
48208	  _scrollers.forEach(function (obj) {
48209		if (_isFunction(obj)) {
48210		  obj.smooth && requestAnimationFrame(function () {
48211			return obj.target.style.scrollBehavior = "smooth";
48212		  });
48213		  obj.rec && obj(obj.rec);
48214		}
48215	  });
48216  
48217	  _clearScrollMemory(_scrollRestoration, 1);
48218  
48219	  _resizeDelay.pause();
48220  
48221	  _refreshID++;
48222	  _refreshingAll = 2;
48223  
48224	  _updateAll(2);
48225  
48226	  _triggers.forEach(function (t) {
48227		return _isFunction(t.vars.onRefresh) && t.vars.onRefresh(t);
48228	  });
48229  
48230	  _refreshingAll = ScrollTrigger$1.isRefreshing = false;
48231  
48232	  _dispatch("refresh");
48233	},
48234		_lastScroll = 0,
48235		_direction = 1,
48236		_primary,
48237		_updateAll = function _updateAll(force) {
48238	  if (force === 2 || !_refreshingAll && !_isReverted) {
48239		ScrollTrigger$1.isUpdating = true;
48240		_primary && _primary.update(0);
48241  
48242		var l = _triggers.length,
48243			time = _getTime$1(),
48244			recordVelocity = time - _time1 >= 50,
48245			scroll = l && _triggers[0].scroll();
48246  
48247		_direction = _lastScroll > scroll ? -1 : 1;
48248		_refreshingAll || (_lastScroll = scroll);
48249  
48250		if (recordVelocity) {
48251		  if (_lastScrollTime && !_pointerIsDown && time - _lastScrollTime > 200) {
48252			_lastScrollTime = 0;
48253  
48254			_dispatch("scrollEnd");
48255		  }
48256  
48257		  _time2 = _time1;
48258		  _time1 = time;
48259		}
48260  
48261		if (_direction < 0) {
48262		  _i = l;
48263  
48264		  while (_i-- > 0) {
48265			_triggers[_i] && _triggers[_i].update(0, recordVelocity);
48266		  }
48267  
48268		  _direction = 1;
48269		} else {
48270		  for (_i = 0; _i < l; _i++) {
48271			_triggers[_i] && _triggers[_i].update(0, recordVelocity);
48272		  }
48273		}
48274  
48275		ScrollTrigger$1.isUpdating = false;
vendor: 4,937 bytes, lines 48276-48426
48276	  }
48277  
48278	  _rafID = 0;
48279	},
48280		_propNamesToCopy = [_left, _top, _bottom, _right, _margin + _Bottom, _margin + _Right, _margin + _Top, _margin + _Left, "display", "flexShrink", "float", "zIndex", "gridColumnStart", "gridColumnEnd", "gridRowStart", "gridRowEnd", "gridArea", "justifySelf", "alignSelf", "placeSelf", "order"],
48281		_stateProps = _propNamesToCopy.concat([_width, _height, "boxSizing", "max" + _Width, "max" + _Height, "position", _margin, _padding, _padding + _Top, _padding + _Right, _padding + _Bottom, _padding + _Left]),
48282		_swapPinOut = function _swapPinOut(pin, spacer, state) {
48283	  _setState(state);
48284  
48285	  var cache = pin._gsap;
48286  
48287	  if (cache.spacerIsNative) {
48288		_setState(cache.spacerState);
48289	  } else if (pin._gsap.swappedIn) {
48290		var parent = spacer.parentNode;
48291  
48292		if (parent) {
48293		  parent.insertBefore(pin, spacer);
48294		  parent.removeChild(spacer);
48295		}
48296	  }
48297  
48298	  pin._gsap.swappedIn = false;
48299	},
48300		_swapPinIn = function _swapPinIn(pin, spacer, cs, spacerState) {
48301	  if (!pin._gsap.swappedIn) {
48302		var i = _propNamesToCopy.length,
48303			spacerStyle = spacer.style,
48304			pinStyle = pin.style,
48305			p;
48306  
48307		while (i--) {
48308		  p = _propNamesToCopy[i];
48309		  spacerStyle[p] = cs[p];
48310		}
48311  
48312		spacerStyle.position = cs.position === "absolute" ? "absolute" : "relative";
48313		cs.display === "inline" && (spacerStyle.display = "inline-block");
48314		pinStyle[_bottom] = pinStyle[_right] = "auto";
48315		spacerStyle.flexBasis = cs.flexBasis || "auto";
48316		spacerStyle.overflow = "visible";
48317		spacerStyle.boxSizing = "border-box";
48318		spacerStyle[_width] = _getSize(pin, _horizontal) + _px;
48319		spacerStyle[_height] = _getSize(pin, _vertical) + _px;
48320		spacerStyle[_padding] = pinStyle[_margin] = pinStyle[_top] = pinStyle[_left] = "0";
48321  
48322		_setState(spacerState);
48323  
48324		pinStyle[_width] = pinStyle["max" + _Width] = cs[_width];
48325		pinStyle[_height] = pinStyle["max" + _Height] = cs[_height];
48326		pinStyle[_padding] = cs[_padding];
48327  
48328		if (pin.parentNode !== spacer) {
48329		  pin.parentNode.insertBefore(spacer, pin);
48330		  spacer.appendChild(pin);
48331		}
48332  
48333		pin._gsap.swappedIn = true;
48334	  }
48335	},
48336		_capsExp = /([A-Z])/g,
48337		_setState = function _setState(state) {
48338	  if (state) {
48339		var style = state.t.style,
48340			l = state.length,
48341			i = 0,
48342			p,
48343			value;
48344		(state.t._gsap || gsap$1.core.getCache(state.t)).uncache = 1;
48345  
48346		for (; i < l; i += 2) {
48347		  value = state[i + 1];
48348		  p = state[i];
48349  
48350		  if (value) {
48351			style[p] = value;
48352		  } else if (style[p]) {
48353			style.removeProperty(p.replace(_capsExp, "-$1").toLowerCase());
48354		  }
48355		}
48356	  }
48357	},
48358		_getState = function _getState(element) {
48359	  var l = _stateProps.length,
48360		  style = element.style,
48361		  state = [],
48362		  i = 0;
48363  
48364	  for (; i < l; i++) {
48365		state.push(_stateProps[i], style[_stateProps[i]]);
48366	  }
48367  
48368	  state.t = element;
48369	  return state;
48370	},
48371		_copyState = function _copyState(state, override, omitOffsets) {
48372	  var result = [],
48373		  l = state.length,
48374		  i = omitOffsets ? 8 : 0,
48375		  p;
48376  
48377	  for (; i < l; i += 2) {
48378		p = state[i];
48379		result.push(p, p in override ? override[p] : state[i + 1]);
48380	  }
48381  
48382	  result.t = state.t;
48383	  return result;
48384	},
48385		_winOffsets = {
48386	  left: 0,
48387	  top: 0
48388	},
48389		_parsePosition = function _parsePosition(value, trigger, scrollerSize, direction, scroll, marker, markerScroller, self, scrollerBounds, borderWidth, useFixedPosition, scrollerMax, containerAnimation, clampZeroProp) {
48390	  _isFunction(value) && (value = value(self));
48391  
48392	  if (_isString(value) && value.substr(0, 3) === "max") {
48393		value = scrollerMax + (value.charAt(4) === "=" ? _offsetToPx("0" + value.substr(3), scrollerSize) : 0);
48394	  }
48395  
48396	  var time = containerAnimation ? containerAnimation.time() : 0,
48397		  p1,
48398		  p2,
48399		  element;
48400	  containerAnimation && containerAnimation.seek(0);
48401	  isNaN(value) || (value = +value);
48402  
48403	  if (!_isNumber(value)) {
48404		_isFunction(trigger) && (trigger = trigger(self));
48405		var offsets = (value || "0").split(" "),
48406			bounds,
48407			localOffset,
48408			globalOffset,
48409			display;
48410		element = _getTarget(trigger, self) || _body$1;
48411		bounds = _getBounds(element) || {};
48412  
48413		if ((!bounds || !bounds.left && !bounds.top) && _getComputedStyle(element).display === "none") {
48414		  display = element.style.display;
48415		  element.style.display = "block";
48416		  bounds = _getBounds(element);
48417		  display ? element.style.display = display : element.style.removeProperty("display");
48418		}
48419  
48420		localOffset = _offsetToPx(offsets[0], bounds[direction.d]);
48421		globalOffset = _offsetToPx(offsets[1] || "0", scrollerSize);
48422		value = bounds[direction.p] - scrollerBounds[direction.p] - borderWidth + localOffset + scroll - globalOffset;
48423		markerScroller && _positionMarker(markerScroller, globalOffset, direction, scrollerSize - globalOffset < 20 || markerScroller._isStart && globalOffset > 20);
48424		scrollerSize -= scrollerSize - globalOffset;
48425	  } else {
48426		containerAnimation && (value = gsap$1.utils.mapRange(containerAnimation.scrollTrigger.start, containerAnimation.scrollTrigger.end, 0, scrollerMa
vendor: 4,541 bytes, lines 48426-48582
48426x, value));
48427		markerScroller && _positionMarker(markerScroller, scrollerSize, direction, true);
48428	  }
48429  
48430	  if (clampZeroProp) {
48431		self[clampZeroProp] = value || -0.001;
48432		value < 0 && (value = 0);
48433	  }
48434  
48435	  if (marker) {
48436		var position = value + scrollerSize,
48437			isStart = marker._isStart;
48438		p1 = "scroll" + direction.d2;
48439  
48440		_positionMarker(marker, position, direction, isStart && position > 20 || !isStart && (useFixedPosition ? Math.max(_body$1[p1], _docEl$1[p1]) : marker.parentNode[p1]) <= position + 1);
48441  
48442		if (useFixedPosition) {
48443		  scrollerBounds = _getBounds(markerScroller);
48444		  useFixedPosition && (marker.style[direction.op.p] = scrollerBounds[direction.op.p] - direction.op.m - marker._offset + _px);
48445		}
48446	  }
48447  
48448	  if (containerAnimation && element) {
48449		p1 = _getBounds(element);
48450		containerAnimation.seek(scrollerMax);
48451		p2 = _getBounds(element);
48452		containerAnimation._caScrollDist = p1[direction.p] - p2[direction.p];
48453		value = value / containerAnimation._caScrollDist * scrollerMax;
48454	  }
48455  
48456	  containerAnimation && containerAnimation.seek(time);
48457	  return containerAnimation ? value : Math.round(value);
48458	},
48459		_prefixExp = /(webkit|moz|length|cssText|inset)/i,
48460		_reparent = function _reparent(element, parent, top, left) {
48461	  if (element.parentNode !== parent) {
48462		var style = element.style,
48463			p,
48464			cs;
48465  
48466		if (parent === _body$1) {
48467		  element._stOrig = style.cssText;
48468		  cs = _getComputedStyle(element);
48469  
48470		  for (p in cs) {
48471			if (!+p && !_prefixExp.test(p) && cs[p] && typeof style[p] === "string" && p !== "0") {
48472			  style[p] = cs[p];
48473			}
48474		  }
48475  
48476		  style.top = top;
48477		  style.left = left;
48478		} else {
48479		  style.cssText = element._stOrig;
48480		}
48481  
48482		gsap$1.core.getCache(element).uncache = 1;
48483		parent.appendChild(element);
48484	  }
48485	},
48486		_interruptionTracker = function _interruptionTracker(getValueFunc, initialValue, onInterrupt) {
48487	  var last1 = initialValue,
48488		  last2 = last1;
48489	  return function (value) {
48490		var current = Math.round(getValueFunc());
48491  
48492		if (current !== last1 && current !== last2 && Math.abs(current - last1) > 3 && Math.abs(current - last2) > 3) {
48493		  value = current;
48494		  onInterrupt && onInterrupt();
48495		}
48496  
48497		last2 = last1;
48498		last1 = value;
48499		return value;
48500	  };
48501	},
48502		_shiftMarker = function _shiftMarker(marker, direction, value) {
48503	  var vars = {};
48504	  vars[direction.p] = "+=" + value;
48505	  gsap$1.set(marker, vars);
48506	},
48507		_getTweenCreator = function _getTweenCreator(scroller, direction) {
48508	  var getScroll = _getScrollFunc(scroller, direction),
48509		  prop = "_scroll" + direction.p2,
48510		  getTween = function getTween(scrollTo, vars, initialValue, change1, change2) {
48511		var tween = getTween.tween,
48512			onComplete = vars.onComplete,
48513			modifiers = {};
48514		initialValue = initialValue || getScroll();
48515  
48516		var checkForInterruption = _interruptionTracker(getScroll, initialValue, function () {
48517		  tween.kill();
48518		  getTween.tween = 0;
48519		});
48520  
48521		change2 = change1 && change2 || 0;
48522		change1 = change1 || scrollTo - initialValue;
48523		tween && tween.kill();
48524		vars[prop] = scrollTo;
48525		vars.inherit = false;
48526		vars.modifiers = modifiers;
48527  
48528		modifiers[prop] = function () {
48529		  return checkForInterruption(initialValue + change1 * tween.ratio + change2 * tween.ratio * tween.ratio);
48530		};
48531  
48532		vars.onUpdate = function () {
48533		  _scrollers.cache++;
48534		  getTween.tween && _updateAll();
48535		};
48536  
48537		vars.onComplete = function () {
48538		  getTween.tween = 0;
48539		  onComplete && onComplete.call(tween);
48540		};
48541  
48542		tween = getTween.tween = gsap$1.to(scroller, vars);
48543		return tween;
48544	  };
48545  
48546	  scroller[prop] = getScroll;
48547  
48548	  getScroll.wheelHandler = function () {
48549		return getTween.tween && getTween.tween.kill() && (getTween.tween = 0);
48550	  };
48551  
48552	  _addListener$1(scroller, "wheel", getScroll.wheelHandler);
48553  
48554	  ScrollTrigger$1.isTouch && _addListener$1(scroller, "touchmove", getScroll.wheelHandler);
48555	  return getTween;
48556	};
48557  
48558	var ScrollTrigger$1 = function () {
48559	  function ScrollTrigger(vars, animation) {
48560		_coreInitted$1 || ScrollTrigger.register(gsap$1) || console.warn("Please gsap.registerPlugin(ScrollTrigger)");
48561  
48562		_context$1(this);
48563  
48564		this.init(vars, animation);
48565	  }
48566  
48567	  var _proto = ScrollTrigger.prototype;
48568  
48569	  _proto.init = function init(vars, animation) {
48570		this.progress = this.start = 0;
48571		this.vars && this.kill(true, true);
48572  
48573		if (!_enabled) {
48574		  this.update = this.refresh = this.kill = _passThrough;
48575		  return;
48576		}
48577  
48578		vars = _setDefaults(_isString(vars) || _isNumber(vars) || vars.nodeType ? {
48579		  trigger: vars
48580		} : vars, _defaults);
48581  
48582		var _vars = vars,
vendor: 4,184 bytes, lines 48583-48723
48583			onUpdate = _vars.onUpdate,
48584			toggleClass = _vars.toggleClass,
48585			id = _vars.id,
48586			onToggle = _vars.onToggle,
48587			onRefresh = _vars.onRefresh,
48588			scrub = _vars.scrub,
48589			trigger = _vars.trigger,
48590			pin = _vars.pin,
48591			pinSpacing = _vars.pinSpacing,
48592			invalidateOnRefresh = _vars.invalidateOnRefresh,
48593			anticipatePin = _vars.anticipatePin,
48594			onScrubComplete = _vars.onScrubComplete,
48595			onSnapComplete = _vars.onSnapComplete,
48596			once = _vars.once,
48597			snap = _vars.snap,
48598			pinReparent = _vars.pinReparent,
48599			pinSpacer = _vars.pinSpacer,
48600			containerAnimation = _vars.containerAnimation,
48601			fastScrollEnd = _vars.fastScrollEnd,
48602			preventOverlaps = _vars.preventOverlaps,
48603			direction = vars.horizontal || vars.containerAnimation && vars.horizontal !== false ? _horizontal : _vertical,
48604			isToggle = !scrub && scrub !== 0,
48605			scroller = _getTarget(vars.scroller || _win$1),
48606			scrollerCache = gsap$1.core.getCache(scroller),
48607			isViewport = _isViewport$1(scroller),
48608			useFixedPosition = ("pinType" in vars ? vars.pinType : _getProxyProp(scroller, "pinType") || isViewport && "fixed") === "fixed",
48609			callbacks = [vars.onEnter, vars.onLeave, vars.onEnterBack, vars.onLeaveBack],
48610			toggleActions = isToggle && vars.toggleActions.split(" "),
48611			markers = "markers" in vars ? vars.markers : _defaults.markers,
48612			borderWidth = isViewport ? 0 : parseFloat(_getComputedStyle(scroller)["border" + direction.p2 + _Width]) || 0,
48613			self = this,
48614			onRefreshInit = vars.onRefreshInit && function () {
48615		  return vars.onRefreshInit(self);
48616		},
48617			getScrollerSize = _getSizeFunc(scroller, isViewport, direction),
48618			getScrollerOffsets = _getOffsetsFunc(scroller, isViewport),
48619			lastSnap = 0,
48620			lastRefresh = 0,
48621			prevProgress = 0,
48622			scrollFunc = _getScrollFunc(scroller, direction),
48623			tweenTo,
48624			pinCache,
48625			snapFunc,
48626			scroll1,
48627			scroll2,
48628			start,
48629			end,
48630			markerStart,
48631			markerEnd,
48632			markerStartTrigger,
48633			markerEndTrigger,
48634			markerVars,
48635			executingOnRefresh,
48636			change,
48637			pinOriginalState,
48638			pinActiveState,
48639			pinState,
48640			spacer,
48641			offset,
48642			pinGetter,
48643			pinSetter,
48644			pinStart,
48645			pinChange,
48646			spacingStart,
48647			spacerState,
48648			markerStartSetter,
48649			pinMoves,
48650			markerEndSetter,
48651			cs,
48652			snap1,
48653			snap2,
48654			scrubTween,
48655			scrubSmooth,
48656			snapDurClamp,
48657			snapDelayedCall,
48658			prevScroll,
48659			prevAnimProgress,
48660			caMarkerSetter,
48661			customRevertReturn;
48662  
48663		self._startClamp = self._endClamp = false;
48664		self._dir = direction;
48665		anticipatePin *= 45;
48666		self.scroller = scroller;
48667		self.scroll = containerAnimation ? containerAnimation.time.bind(containerAnimation) : scrollFunc;
48668		scroll1 = scrollFunc();
48669		self.vars = vars;
48670		animation = animation || vars.animation;
48671  
48672		if ("refreshPriority" in vars) {
48673		  _sort = 1;
48674		  vars.refreshPriority === -9999 && (_primary = self);
48675		}
48676  
48677		scrollerCache.tweenScroll = scrollerCache.tweenScroll || {
48678		  top: _getTweenCreator(scroller, _vertical),
48679		  left: _getTweenCreator(scroller, _horizontal)
48680		};
48681		self.tweenTo = tweenTo = scrollerCache.tweenScroll[direction.p];
48682  
48683		self.scrubDuration = function (value) {
48684		  scrubSmooth = _isNumber(value) && value;
48685  
48686		  if (!scrubSmooth) {
48687			scrubTween && scrubTween.progress(1).kill();
48688			scrubTween = 0;
48689		  } else {
48690			scrubTween ? scrubTween.duration(value) : scrubTween = gsap$1.to(animation, {
48691			  ease: "expo",
48692			  totalProgress: "+=0",
48693			  inherit: false,
48694			  duration: scrubSmooth,
48695			  paused: true,
48696			  onComplete: function onComplete() {
48697				return onScrubComplete && onScrubComplete(self);
48698			  }
48699			});
48700		  }
48701		};
48702  
48703		if (animation) {
48704		  animation.vars.lazy = false;
48705		  animation._initted && !self.isReverted || animation.vars.immediateRender !== false && vars.immediateRender !== false && animation.duration() && animation.render(0, true, true);
48706		  self.animation = animation.pause();
48707		  animation.scrollTrigger = self;
48708		  self.scrubDuration(scrub);
48709		  snap1 = 0;
48710		  id || (id = animation.vars.id);
48711		}
48712  
48713		if (snap) {
48714		  if (!_isObject(snap) || snap.push) {
48715			snap = {
48716			  snapTo: snap
48717			};
48718		  }
48719  
48720		  "scrollBehavior" in _body$1.style && gsap$1.set(isViewport ? [_body$1, _docEl$1] : scroller, {
48721			scrollBehavior: "auto"
48722		  });
48723  
vendor: 4,259 bytes, lines 48724-48819
48724		  _scrollers.forEach(function (o) {
48725			return _isFunction(o) && o.target === (isViewport ? _doc$1.scrollingElement || _docEl$1 : scroller) && (o.smooth = false);
48726		  });
48727  
48728		  snapFunc = _isFunction(snap.snapTo) ? snap.snapTo : snap.snapTo === "labels" ? _getClosestLabel(animation) : snap.snapTo === "labelsDirectional" ? _getLabelAtDirection(animation) : snap.directional !== false ? function (value, st) {
48729			return _snapDirectional(snap.snapTo)(value, _getTime$1() - lastRefresh < 500 ? 0 : st.direction);
48730		  } : gsap$1.utils.snap(snap.snapTo);
48731		  snapDurClamp = snap.duration || {
48732			min: 0.1,
48733			max: 2
48734		  };
48735		  snapDurClamp = _isObject(snapDurClamp) ? _clamp$1(snapDurClamp.min, snapDurClamp.max) : _clamp$1(snapDurClamp, snapDurClamp);
48736		  snapDelayedCall = gsap$1.delayedCall(snap.delay || scrubSmooth / 2 || 0.1, function () {
48737			var scroll = scrollFunc(),
48738				refreshedRecently = _getTime$1() - lastRefresh < 500,
48739				tween = tweenTo.tween;
48740  
48741			if ((refreshedRecently || Math.abs(self.getVelocity()) < 10) && !tween && !_pointerIsDown && lastSnap !== scroll) {
48742			  var progress = (scroll - start) / change,
48743				  totalProgress = animation && !isToggle ? animation.totalProgress() : progress,
48744				  velocity = refreshedRecently ? 0 : (totalProgress - snap2) / (_getTime$1() - _time2) * 1000 || 0,
48745				  change1 = gsap$1.utils.clamp(-progress, 1 - progress, _abs(velocity / 2) * velocity / 0.185),
48746				  naturalEnd = progress + (snap.inertia === false ? 0 : change1),
48747				  endValue,
48748				  endScroll,
48749				  _snap = snap,
48750				  onStart = _snap.onStart,
48751				  _onInterrupt = _snap.onInterrupt,
48752				  _onComplete = _snap.onComplete;
48753			  endValue = snapFunc(naturalEnd, self);
48754			  _isNumber(endValue) || (endValue = naturalEnd);
48755			  endScroll = Math.round(start + endValue * change);
48756  
48757			  if (scroll <= end && scroll >= start && endScroll !== scroll) {
48758				if (tween && !tween._initted && tween.data <= _abs(endScroll - scroll)) {
48759				  return;
48760				}
48761  
48762				if (snap.inertia === false) {
48763				  change1 = endValue - progress;
48764				}
48765  
48766				tweenTo(endScroll, {
48767				  duration: snapDurClamp(_abs(Math.max(_abs(naturalEnd - totalProgress), _abs(endValue - totalProgress)) * 0.185 / velocity / 0.05 || 0)),
48768				  ease: snap.ease || "power3",
48769				  data: _abs(endScroll - scroll),
48770				  onInterrupt: function onInterrupt() {
48771					return snapDelayedCall.restart(true) && _onInterrupt && _onInterrupt(self);
48772				  },
48773				  onComplete: function onComplete() {
48774					self.update();
48775					lastSnap = scrollFunc();
48776  
48777					if (animation) {
48778					  scrubTween ? scrubTween.resetTo("totalProgress", endValue, animation._tTime / animation._tDur) : animation.progress(endValue);
48779					}
48780  
48781					snap1 = snap2 = animation && !isToggle ? animation.totalProgress() : self.progress;
48782					onSnapComplete && onSnapComplete(self);
48783					_onComplete && _onComplete(self);
48784				  }
48785				}, scroll, change1 * change, endScroll - scroll - change1 * change);
48786				onStart && onStart(self, tweenTo.tween);
48787			  }
48788			} else if (self.isActive && lastSnap !== scroll) {
48789			  snapDelayedCall.restart(true);
48790			}
48791		  }).pause();
48792		}
48793  
48794		id && (_ids[id] = self);
48795		trigger = self.trigger = _getTarget(trigger || pin !== true && pin);
48796		customRevertReturn = trigger && trigger._gsap && trigger._gsap.stRevert;
48797		customRevertReturn && (customRevertReturn = customRevertReturn(self));
48798		pin = pin === true ? trigger : _getTarget(pin);
48799		_isString(toggleClass) && (toggleClass = {
48800		  targets: trigger,
48801		  className: toggleClass
48802		});
48803  
48804		if (pin) {
48805		  pinSpacing === false || pinSpacing === _margin || (pinSpacing = !pinSpacing && pin.parentNode && pin.parentNode.style && _getComputedStyle(pin.parentNode).display === "flex" ? false : _padding);
48806		  self.pin = pin;
48807		  pinCache = gsap$1.core.getCache(pin);
48808  
48809		  if (!pinCache.spacer) {
48810			if (pinSpacer) {
48811			  pinSpacer = _getTarget(pinSpacer);
48812			  pinSpacer && !pinSpacer.nodeType && (pinSpacer = pinSpacer.current || pinSpacer.nativeElement);
48813			  pinCache.spacerIsNative = !!pinSpacer;
48814			  pinSpacer && (pinCache.spacerState = _getState(pinSpacer));
48815			}
48816  
48817			pinCache.spacer = spacer = pinSpacer || _doc$1.createElement("div");
48818			spacer.classList.add("pin-spacer");
48819			id && spacer.classList.add("pin-spacer-" + id);
vendor: 4,987 bytes, lines 48820-48974
48820			pinCache.pinState = pinOriginalState = _getState(pin);
48821		  } else {
48822			pinOriginalState = pinCache.pinState;
48823		  }
48824  
48825		  vars.force3D !== false && gsap$1.set(pin, {
48826			force3D: true
48827		  });
48828		  self.spacer = spacer = pinCache.spacer;
48829		  cs = _getComputedStyle(pin);
48830		  spacingStart = cs[pinSpacing + direction.os2];
48831		  pinGetter = gsap$1.getProperty(pin);
48832		  pinSetter = gsap$1.quickSetter(pin, direction.a, _px);
48833  
48834		  _swapPinIn(pin, spacer, cs);
48835  
48836		  pinState = _getState(pin);
48837		}
48838  
48839		if (markers) {
48840		  markerVars = _isObject(markers) ? _setDefaults(markers, _markerDefaults) : _markerDefaults;
48841		  markerStartTrigger = _createMarker("scroller-start", id, scroller, direction, markerVars, 0);
48842		  markerEndTrigger = _createMarker("scroller-end", id, scroller, direction, markerVars, 0, markerStartTrigger);
48843		  offset = markerStartTrigger["offset" + direction.op.d2];
48844  
48845		  var content = _getTarget(_getProxyProp(scroller, "content") || scroller);
48846  
48847		  markerStart = this.markerStart = _createMarker("start", id, content, direction, markerVars, offset, 0, containerAnimation);
48848		  markerEnd = this.markerEnd = _createMarker("end", id, content, direction, markerVars, offset, 0, containerAnimation);
48849		  containerAnimation && (caMarkerSetter = gsap$1.quickSetter([markerStart, markerEnd], direction.a, _px));
48850  
48851		  if (!useFixedPosition && !(_proxies.length && _getProxyProp(scroller, "fixedMarkers") === true)) {
48852			_makePositionable(isViewport ? _body$1 : scroller);
48853  
48854			gsap$1.set([markerStartTrigger, markerEndTrigger], {
48855			  force3D: true
48856			});
48857			markerStartSetter = gsap$1.quickSetter(markerStartTrigger, direction.a, _px);
48858			markerEndSetter = gsap$1.quickSetter(markerEndTrigger, direction.a, _px);
48859		  }
48860		}
48861  
48862		if (containerAnimation) {
48863		  var oldOnUpdate = containerAnimation.vars.onUpdate,
48864			  oldParams = containerAnimation.vars.onUpdateParams;
48865		  containerAnimation.eventCallback("onUpdate", function () {
48866			self.update(0, 0, 1);
48867			oldOnUpdate && oldOnUpdate.apply(containerAnimation, oldParams || []);
48868		  });
48869		}
48870  
48871		self.previous = function () {
48872		  return _triggers[_triggers.indexOf(self) - 1];
48873		};
48874  
48875		self.next = function () {
48876		  return _triggers[_triggers.indexOf(self) + 1];
48877		};
48878  
48879		self.revert = function (revert, temp) {
48880		  if (!temp) {
48881			return self.kill(true);
48882		  }
48883  
48884		  var r = revert !== false || !self.enabled,
48885			  prevRefreshing = _refreshing;
48886  
48887		  if (r !== self.isReverted) {
48888			if (r) {
48889			  prevScroll = Math.max(scrollFunc(), self.scroll.rec || 0);
48890			  prevProgress = self.progress;
48891			  prevAnimProgress = animation && animation.progress();
48892			}
48893  
48894			markerStart && [markerStart, markerEnd, markerStartTrigger, markerEndTrigger].forEach(function (m) {
48895			  return m.style.display = r ? "none" : "block";
48896			});
48897  
48898			if (r) {
48899			  _refreshing = self;
48900			  self.update(r);
48901			}
48902  
48903			if (pin && (!pinReparent || !self.isActive)) {
48904			  if (r) {
48905				_swapPinOut(pin, spacer, pinOriginalState);
48906			  } else {
48907				_swapPinIn(pin, spacer, _getComputedStyle(pin), spacerState);
48908			  }
48909			}
48910  
48911			r || self.update(r);
48912			_refreshing = prevRefreshing;
48913			self.isReverted = r;
48914		  }
48915		};
48916  
48917		self.refresh = function (soft, force, position, pinOffset) {
48918		  if ((_refreshing || !self.enabled) && !force) {
48919			return;
48920		  }
48921  
48922		  if (pin && soft && _lastScrollTime) {
48923			_addListener$1(ScrollTrigger, "scrollEnd", _softRefresh);
48924  
48925			return;
48926		  }
48927  
48928		  !_refreshingAll && onRefreshInit && onRefreshInit(self);
48929		  _refreshing = self;
48930  
48931		  if (tweenTo.tween && !position) {
48932			tweenTo.tween.kill();
48933			tweenTo.tween = 0;
48934		  }
48935  
48936		  scrubTween && scrubTween.pause();
48937		  invalidateOnRefresh && animation && animation.revert({
48938			kill: false
48939		  }).invalidate();
48940		  self.isReverted || self.revert(true, true);
48941		  self._subPinOffset = false;
48942  
48943		  var size = getScrollerSize(),
48944			  scrollerBounds = getScrollerOffsets(),
48945			  max = containerAnimation ? containerAnimation.duration() : _maxScroll(scroller, direction),
48946			  isFirstRefresh = change <= 0.01,
48947			  offset = 0,
48948			  otherPinOffset = pinOffset || 0,
48949			  parsedEnd = _isObject(position) ? position.end : vars.end,
48950			  parsedEndTrigger = vars.endTrigger || trigger,
48951			  parsedStart = _isObject(position) ? position.start : vars.start || (vars.start === 0 || !trigger ? 0 : pin ? "0 0" : "0 100%"),
48952			  pinnedContainer = self.pinnedContainer = vars.pinnedContainer && _getTarget(vars.pinnedContainer, self),
48953			  triggerIndex = trigger && Math.max(0, _triggers.indexOf(self)) || 0,
48954			  i = triggerIndex,
48955			  cs,
48956			  bounds,
48957			  scroll,
48958			  isVertical,
48959			  override,
48960			  curTrigger,
48961			  curPin,
48962			  oppositeScroll,
48963			  initted,
48964			  revertedPins,
48965			  forcedOverflow,
48966			  markerStartOffset,
48967			  markerEndOffset;
48968  
48969		  if (markers && _isObject(position)) {
48970			markerStartOffset = gsap$1.getProperty(markerStartTrigger, direction.p);
48971			markerEndOffset = gsap$1.getProperty(markerEndTrigger, direction.p);
48972		  }
48973  
48974		  while (i--) {
vendor: 4,360 bytes, lines 48975-49086
48975			curTrigger = _triggers[i];
48976			curTrigger.end || curTrigger.refresh(0, 1) || (_refreshing = self);
48977			curPin = curTrigger.pin;
48978  
48979			if (curPin && (curPin === trigger || curPin === pin || curPin === pinnedContainer) && !curTrigger.isReverted) {
48980			  revertedPins || (revertedPins = []);
48981			  revertedPins.unshift(curTrigger);
48982			  curTrigger.revert(true, true);
48983			}
48984  
48985			if (curTrigger !== _triggers[i]) {
48986			  triggerIndex--;
48987			  i--;
48988			}
48989		  }
48990  
48991		  _isFunction(parsedStart) && (parsedStart = parsedStart(self));
48992		  parsedStart = _parseClamp(parsedStart, "start", self);
48993		  start = _parsePosition(parsedStart, trigger, size, direction, scrollFunc(), markerStart, markerStartTrigger, self, scrollerBounds, borderWidth, useFixedPosition, max, containerAnimation, self._startClamp && "_startClamp") || (pin ? -0.001 : 0);
48994		  _isFunction(parsedEnd) && (parsedEnd = parsedEnd(self));
48995  
48996		  if (_isString(parsedEnd) && !parsedEnd.indexOf("+=")) {
48997			if (~parsedEnd.indexOf(" ")) {
48998			  parsedEnd = (_isString(parsedStart) ? parsedStart.split(" ")[0] : "") + parsedEnd;
48999			} else {
49000			  offset = _offsetToPx(parsedEnd.substr(2), size);
49001			  parsedEnd = _isString(parsedStart) ? parsedStart : (containerAnimation ? gsap$1.utils.mapRange(0, containerAnimation.duration(), containerAnimation.scrollTrigger.start, containerAnimation.scrollTrigger.end, start) : start) + offset;
49002			  parsedEndTrigger = trigger;
49003			}
49004		  }
49005  
49006		  parsedEnd = _parseClamp(parsedEnd, "end", self);
49007		  end = Math.max(start, _parsePosition(parsedEnd || (parsedEndTrigger ? "100% 0" : max), parsedEndTrigger, size, direction, scrollFunc() + offset, markerEnd, markerEndTrigger, self, scrollerBounds, borderWidth, useFixedPosition, max, containerAnimation, self._endClamp && "_endClamp")) || -0.001;
49008		  offset = 0;
49009		  i = triggerIndex;
49010  
49011		  while (i--) {
49012			curTrigger = _triggers[i];
49013			curPin = curTrigger.pin;
49014  
49015			if (curPin && curTrigger.start - curTrigger._pinPush <= start && !containerAnimation && curTrigger.end > 0) {
49016			  cs = curTrigger.end - (self._startClamp ? Math.max(0, curTrigger.start) : curTrigger.start);
49017  
49018			  if ((curPin === trigger && curTrigger.start - curTrigger._pinPush < start || curPin === pinnedContainer) && isNaN(parsedStart)) {
49019				offset += cs * (1 - curTrigger.progress);
49020			  }
49021  
49022			  curPin === pin && (otherPinOffset += cs);
49023			}
49024		  }
49025  
49026		  start += offset;
49027		  end += offset;
49028		  self._startClamp && (self._startClamp += offset);
49029  
49030		  if (self._endClamp && !_refreshingAll) {
49031			self._endClamp = end || -0.001;
49032			end = Math.min(end, _maxScroll(scroller, direction));
49033		  }
49034  
49035		  change = end - start || (start -= 0.01) && 0.001;
49036  
49037		  if (isFirstRefresh) {
49038			prevProgress = gsap$1.utils.clamp(0, 1, gsap$1.utils.normalize(start, end, prevScroll));
49039		  }
49040  
49041		  self._pinPush = otherPinOffset;
49042  
49043		  if (markerStart && offset) {
49044			cs = {};
49045			cs[direction.a] = "+=" + offset;
49046			pinnedContainer && (cs[direction.p] = "-=" + scrollFunc());
49047			gsap$1.set([markerStart, markerEnd], cs);
49048		  }
49049  
49050		  if (pin && !(_clampingMax && self.end >= _maxScroll(scroller, direction))) {
49051			cs = _getComputedStyle(pin);
49052			isVertical = direction === _vertical;
49053			scroll = scrollFunc();
49054			pinStart = parseFloat(pinGetter(direction.a)) + otherPinOffset;
49055  
49056			if (!max && end > 1) {
49057			  forcedOverflow = (isViewport ? _doc$1.scrollingElement || _docEl$1 : scroller).style;
49058			  forcedOverflow = {
49059				style: forcedOverflow,
49060				value: forcedOverflow["overflow" + direction.a.toUpperCase()]
49061			  };
49062  
49063			  if (isViewport && _getComputedStyle(_body$1)["overflow" + direction.a.toUpperCase()] !== "scroll") {
49064				forcedOverflow.style["overflow" + direction.a.toUpperCase()] = "scroll";
49065			  }
49066			}
49067  
49068			_swapPinIn(pin, spacer, cs);
49069  
49070			pinState = _getState(pin);
49071			bounds = _getBounds(pin, true);
49072			oppositeScroll = useFixedPosition && _getScrollFunc(scroller, isVertical ? _horizontal : _vertical)();
49073  
49074			if (pinSpacing) {
49075			  spacerState = [pinSpacing + direction.os2, change + otherPinOffset + _px];
49076			  spacerState.t = spacer;
49077			  i = pinSpacing === _padding ? _getSize(pin, direction) + change + otherPinOffset : 0;
49078  
49079			  if (i) {
49080				spacerState.push(direction.d, i + _px);
49081				spacer.style.flexBasis !== "auto" && (spacer.style.flexBasis = i + _px);
49082			  }
49083  
49084			  _setState(spacerState);
49085  
49086			  if (pinnedContainer) {
vendor: 9,034 bytes, lines 49087-49329
49087				_triggers.forEach(function (t) {
49088				  if (t.pin === pinnedContainer && t.vars.pinSpacing !== false) {
49089					t._subPinOffset = true;
49090				  }
49091				});
49092			  }
49093  
49094			  useFixedPosition && scrollFunc(prevScroll);
49095			} else {
49096			  i = _getSize(pin, direction);
49097			  i && spacer.style.flexBasis !== "auto" && (spacer.style.flexBasis = i + _px);
49098			}
49099  
49100			if (useFixedPosition) {
49101			  override = {
49102				top: bounds.top + (isVertical ? scroll - start : oppositeScroll) + _px,
49103				left: bounds.left + (isVertical ? oppositeScroll : scroll - start) + _px,
49104				boxSizing: "border-box",
49105				position: "fixed"
49106			  };
49107			  override[_width] = override["max" + _Width] = Math.ceil(bounds.width) + _px;
49108			  override[_height] = override["max" + _Height] = Math.ceil(bounds.height) + _px;
49109			  override[_margin] = override[_margin + _Top] = override[_margin + _Right] = override[_margin + _Bottom] = override[_margin + _Left] = "0";
49110			  override[_padding] = cs[_padding];
49111			  override[_padding + _Top] = cs[_padding + _Top];
49112			  override[_padding + _Right] = cs[_padding + _Right];
49113			  override[_padding + _Bottom] = cs[_padding + _Bottom];
49114			  override[_padding + _Left] = cs[_padding + _Left];
49115			  pinActiveState = _copyState(pinOriginalState, override, pinReparent);
49116			  _refreshingAll && scrollFunc(0);
49117			}
49118  
49119			if (animation) {
49120			  initted = animation._initted;
49121  
49122			  _suppressOverwrites(1);
49123  
49124			  animation.render(animation.duration(), true, true);
49125			  pinChange = pinGetter(direction.a) - pinStart + change + otherPinOffset;
49126			  pinMoves = Math.abs(change - pinChange) > 1;
49127			  useFixedPosition && pinMoves && pinActiveState.splice(pinActiveState.length - 2, 2);
49128			  animation.render(0, true, true);
49129			  initted || animation.invalidate(true);
49130			  animation.parent || animation.totalTime(animation.totalTime());
49131  
49132			  _suppressOverwrites(0);
49133			} else {
49134			  pinChange = change;
49135			}
49136  
49137			forcedOverflow && (forcedOverflow.value ? forcedOverflow.style["overflow" + direction.a.toUpperCase()] = forcedOverflow.value : forcedOverflow.style.removeProperty("overflow-" + direction.a));
49138		  } else if (trigger && scrollFunc() && !containerAnimation) {
49139			bounds = trigger.parentNode;
49140  
49141			while (bounds && bounds !== _body$1) {
49142			  if (bounds._pinOffset) {
49143				start -= bounds._pinOffset;
49144				end -= bounds._pinOffset;
49145			  }
49146  
49147			  bounds = bounds.parentNode;
49148			}
49149		  }
49150  
49151		  revertedPins && revertedPins.forEach(function (t) {
49152			return t.revert(false, true);
49153		  });
49154		  self.start = start;
49155		  self.end = end;
49156		  scroll1 = scroll2 = _refreshingAll ? prevScroll : scrollFunc();
49157  
49158		  if (!containerAnimation && !_refreshingAll) {
49159			scroll1 < prevScroll && scrollFunc(prevScroll);
49160			self.scroll.rec = 0;
49161		  }
49162  
49163		  self.revert(false, true);
49164		  lastRefresh = _getTime$1();
49165  
49166		  if (snapDelayedCall) {
49167			lastSnap = -1;
49168			snapDelayedCall.restart(true);
49169		  }
49170  
49171		  _refreshing = 0;
49172		  animation && isToggle && (animation._initted || prevAnimProgress) && animation.progress() !== prevAnimProgress && animation.progress(prevAnimProgress || 0, true).render(animation.time(), true, true);
49173  
49174		  if (isFirstRefresh || prevProgress !== self.progress || containerAnimation || invalidateOnRefresh) {
49175			animation && !isToggle && animation.totalProgress(containerAnimation && start < -0.001 && !prevProgress ? gsap$1.utils.normalize(start, end, 0) : prevProgress, true);
49176			self.progress = isFirstRefresh || (scroll1 - start) / change === prevProgress ? 0 : prevProgress;
49177		  }
49178  
49179		  pin && pinSpacing && (spacer._pinOffset = Math.round(self.progress * pinChange));
49180		  scrubTween && scrubTween.invalidate();
49181  
49182		  if (!isNaN(markerStartOffset)) {
49183			markerStartOffset -= gsap$1.getProperty(markerStartTrigger, direction.p);
49184			markerEndOffset -= gsap$1.getProperty(markerEndTrigger, direction.p);
49185  
49186			_shiftMarker(markerStartTrigger, direction, markerStartOffset);
49187  
49188			_shiftMarker(markerStart, direction, markerStartOffset - (pinOffset || 0));
49189  
49190			_shiftMarker(markerEndTrigger, direction, markerEndOffset);
49191  
49192			_shiftMarker(markerEnd, direction, markerEndOffset - (pinOffset || 0));
49193		  }
49194  
49195		  isFirstRefresh && !_refreshingAll && self.update();
49196  
49197		  if (onRefresh && !_refreshingAll && !executingOnRefresh) {
49198			executingOnRefresh = true;
49199			onRefresh(self);
49200			executingOnRefresh = false;
49201		  }
49202		};
49203  
49204		self.getVelocity = function () {
49205		  return (scrollFunc() - scroll2) / (_getTime$1() - _time2) * 1000 || 0;
49206		};
49207  
49208		self.endAnimation = function () {
49209		  _endAnimation(self.callbackAnimation);
49210  
49211		  if (animation) {
49212			scrubTween ? scrubTween.progress(1) : !animation.paused() ? _endAnimation(animation, animation.reversed()) : isToggle || _endAnimation(animation, self.direction < 0, 1);
49213		  }
49214		};
49215  
49216		self.labelToScroll = function (label) {
49217		  return animation && animation.labels && (start || self.refresh() || start) + animation.labels[label] / animation.duration() * change || 0;
49218		};
49219  
49220		self.getTrailing = function (name) {
49221		  var i = _triggers.indexOf(self),
49222			  a = self.direction > 0 ? _triggers.slice(0, i).reverse() : _triggers.slice(i + 1);
49223  
49224		  return (_isString(name) ? a.filter(function (t) {
49225			return t.vars.preventOverlaps === name;
49226		  }) : a).filter(function (t) {
49227			return self.direction > 0 ? t.end <= start : t.start >= end;
49228		  });
49229		};
49230  
49231		self.update = function (reset, recordVelocity, forceFake) {
49232		  if (containerAnimation && !forceFake && !reset) {
49233			return;
49234		  }
49235  
49236		  var scroll = _refreshingAll === true ? prevScroll : self.scroll(),
49237			  p = reset ? 0 : (scroll - start) / change,
49238			  clipped = p < 0 ? 0 : p > 1 ? 1 : p || 0,
49239			  prevProgress = self.progress,
49240			  isActive,
49241			  wasActive,
49242			  toggleState,
49243			  action,
49244			  stateChanged,
49245			  toggled,
49246			  isAtMax,
49247			  isTakingAction;
49248  
49249		  if (recordVelocity) {
49250			scroll2 = scroll1;
49251			scroll1 = containerAnimation ? scrollFunc() : scroll;
49252  
49253			if (snap) {
49254			  snap2 = snap1;
49255			  snap1 = animation && !isToggle ? animation.totalProgress() : clipped;
49256			}
49257		  }
49258  
49259		  if (anticipatePin && pin && !_refreshing && !_startup$1 && _lastScrollTime) {
49260			if (!clipped && start < scroll + (scroll - scroll2) / (_getTime$1() - _time2) * anticipatePin) {
49261			  clipped = 0.0001;
49262			} else if (clipped === 1 && end > scroll + (scroll - scroll2) / (_getTime$1() - _time2) * anticipatePin) {
49263			  clipped = 0.9999;
49264			}
49265		  }
49266  
49267		  if (clipped !== prevProgress && self.enabled) {
49268			isActive = self.isActive = !!clipped && clipped < 1;
49269			wasActive = !!prevProgress && prevProgress < 1;
49270			toggled = isActive !== wasActive;
49271			stateChanged = toggled || !!clipped !== !!prevProgress;
49272			self.direction = clipped > prevProgress ? 1 : -1;
49273			self.progress = clipped;
49274  
49275			if (stateChanged && !_refreshing) {
49276			  toggleState = clipped && !prevProgress ? 0 : clipped === 1 ? 1 : prevProgress === 1 ? 2 : 3;
49277  
49278			  if (isToggle) {
49279				action = !toggled && toggleActions[toggleState + 1] !== "none" && toggleActions[toggleState + 1] || toggleActions[toggleState];
49280				isTakingAction = animation && (action === "complete" || action === "reset" || action in animation);
49281			  }
49282			}
49283  
49284			preventOverlaps && (toggled || isTakingAction) && (isTakingAction || scrub || !animation) && (_isFunction(preventOverlaps) ? preventOverlaps(self) : self.getTrailing(preventOverlaps).forEach(function (t) {
49285			  return t.endAnimation();
49286			}));
49287  
49288			if (!isToggle) {
49289			  if (scrubTween && !_refreshing && !_startup$1) {
49290				scrubTween._dp._time - scrubTween._start !== scrubTween._time && scrubTween.render(scrubTween._dp._time - scrubTween._start);
49291  
49292				if (scrubTween.resetTo) {
49293				  scrubTween.resetTo("totalProgress", clipped, animation._tTime / animation._tDur);
49294				} else {
49295				  scrubTween.vars.totalProgress = clipped;
49296				  scrubTween.invalidate().restart();
49297				}
49298			  } else if (animation) {
49299				animation.totalProgress(clipped, !!(_refreshing && (lastRefresh || reset)));
49300			  }
49301			}
49302  
49303			if (pin) {
49304			  reset && pinSpacing && (spacer.style[pinSpacing + direction.os2] = spacingStart);
49305  
49306			  if (!useFixedPosition) {
49307				pinSetter(_round(pinStart + pinChange * clipped));
49308			  } else if (stateChanged) {
49309				isAtMax = !reset && clipped > prevProgress && end + 1 > scroll && scroll + 1 >= _maxScroll(scroller, direction);
49310  
49311				if (pinReparent) {
49312				  if (!reset && (isActive || isAtMax)) {
49313					var bounds = _getBounds(pin, true),
49314						_offset = scroll - start;
49315  
49316					_reparent(pin, _body$1, bounds.top + (direction === _vertical ? _offset : 0) + _px, bounds.left + (direction === _vertical ? 0 : _offset) + _px);
49317				  } else {
49318					_reparent(pin, spacer);
49319				  }
49320				}
49321  
49322				_setState(isActive || isAtMax ? pinActiveState : pinState);
49323  
49324				pinMoves && clipped < 1 && isActive || pinSetter(pinStart + (clipped === 1 && !isAtMax ? pinChange : 0));
49325			  }
49326			}
49327  
49328			snap && !tweenTo.tween && !_refreshing && !_startup$1 && snapDelayedCall.restart(true);
49329			toggleClass && (toggled || once && clipped && (clipped < 1 || !_limitCallbacks)) && _toArray(toggleClass.targets).forEac
vendor: 10,394 bytes, lines 49329-49696
49329h(function (el) {
49330			  return el.classList[isActive || once ? "add" : "remove"](toggleClass.className);
49331			});
49332			onUpdate && !isToggle && !reset && onUpdate(self);
49333  
49334			if (stateChanged && !_refreshing) {
49335			  if (isToggle) {
49336				if (isTakingAction) {
49337				  if (action === "complete") {
49338					animation.pause().totalProgress(1);
49339				  } else if (action === "reset") {
49340					animation.restart(true).pause();
49341				  } else if (action === "restart") {
49342					animation.restart(true);
49343				  } else {
49344					animation[action]();
49345				  }
49346				}
49347  
49348				onUpdate && onUpdate(self);
49349			  }
49350  
49351			  if (toggled || !_limitCallbacks) {
49352				onToggle && toggled && _callback(self, onToggle);
49353				callbacks[toggleState] && _callback(self, callbacks[toggleState]);
49354				once && (clipped === 1 ? self.kill(false, 1) : callbacks[toggleState] = 0);
49355  
49356				if (!toggled) {
49357				  toggleState = clipped === 1 ? 1 : 3;
49358				  callbacks[toggleState] && _callback(self, callbacks[toggleState]);
49359				}
49360			  }
49361  
49362			  if (fastScrollEnd && !isActive && Math.abs(self.getVelocity()) > (_isNumber(fastScrollEnd) ? fastScrollEnd : 2500)) {
49363				_endAnimation(self.callbackAnimation);
49364  
49365				scrubTween ? scrubTween.progress(1) : _endAnimation(animation, action === "reverse" ? 1 : !clipped, 1);
49366			  }
49367			} else if (isToggle && onUpdate && !_refreshing) {
49368			  onUpdate(self);
49369			}
49370		  }
49371  
49372		  if (markerEndSetter) {
49373			var n = containerAnimation ? scroll / containerAnimation.duration() * (containerAnimation._caScrollDist || 0) : scroll;
49374			markerStartSetter(n + (markerStartTrigger._isFlipped ? 1 : 0));
49375			markerEndSetter(n);
49376		  }
49377  
49378		  caMarkerSetter && caMarkerSetter(-scroll / containerAnimation.duration() * (containerAnimation._caScrollDist || 0));
49379		};
49380  
49381		self.enable = function (reset, refresh) {
49382		  if (!self.enabled) {
49383			self.enabled = true;
49384  
49385			_addListener$1(scroller, "resize", _onResize);
49386  
49387			isViewport || _addListener$1(scroller, "scroll", _onScroll$1);
49388			onRefreshInit && _addListener$1(ScrollTrigger, "refreshInit", onRefreshInit);
49389  
49390			if (reset !== false) {
49391			  self.progress = prevProgress = 0;
49392			  scroll1 = scroll2 = lastSnap = scrollFunc();
49393			}
49394  
49395			refresh !== false && self.refresh();
49396		  }
49397		};
49398  
49399		self.getTween = function (snap) {
49400		  return snap && tweenTo ? tweenTo.tween : scrubTween;
49401		};
49402  
49403		self.setPositions = function (newStart, newEnd, keepClamp, pinOffset) {
49404		  if (containerAnimation) {
49405			var st = containerAnimation.scrollTrigger,
49406				duration = containerAnimation.duration(),
49407				_change = st.end - st.start;
49408  
49409			newStart = st.start + _change * newStart / duration;
49410			newEnd = st.start + _change * newEnd / duration;
49411		  }
49412  
49413		  self.refresh(false, false, {
49414			start: _keepClamp(newStart, keepClamp && !!self._startClamp),
49415			end: _keepClamp(newEnd, keepClamp && !!self._endClamp)
49416		  }, pinOffset);
49417		  self.update();
49418		};
49419  
49420		self.adjustPinSpacing = function (amount) {
49421		  if (spacerState && amount) {
49422			var i = spacerState.indexOf(direction.d) + 1;
49423			spacerState[i] = parseFloat(spacerState[i]) + amount + _px;
49424			spacerState[1] = parseFloat(spacerState[1]) + amount + _px;
49425  
49426			_setState(spacerState);
49427		  }
49428		};
49429  
49430		self.disable = function (reset, allowAnimation) {
49431		  if (self.enabled) {
49432			reset !== false && self.revert(true, true);
49433			self.enabled = self.isActive = false;
49434			allowAnimation || scrubTween && scrubTween.pause();
49435			prevScroll = 0;
49436			pinCache && (pinCache.uncache = 1);
49437			onRefreshInit && _removeListener$1(ScrollTrigger, "refreshInit", onRefreshInit);
49438  
49439			if (snapDelayedCall) {
49440			  snapDelayedCall.pause();
49441			  tweenTo.tween && tweenTo.tween.kill() && (tweenTo.tween = 0);
49442			}
49443  
49444			if (!isViewport) {
49445			  var i = _triggers.length;
49446  
49447			  while (i--) {
49448				if (_triggers[i].scroller === scroller && _triggers[i] !== self) {
49449				  return;
49450				}
49451			  }
49452  
49453			  _removeListener$1(scroller, "resize", _onResize);
49454  
49455			  isViewport || _removeListener$1(scroller, "scroll", _onScroll$1);
49456			}
49457		  }
49458		};
49459  
49460		self.kill = function (revert, allowAnimation) {
49461		  self.disable(revert, allowAnimation);
49462		  scrubTween && !allowAnimation && scrubTween.kill();
49463		  id && delete _ids[id];
49464  
49465		  var i = _triggers.indexOf(self);
49466  
49467		  i >= 0 && _triggers.splice(i, 1);
49468		  i === _i && _direction > 0 && _i--;
49469		  i = 0;
49470  
49471		  _triggers.forEach(function (t) {
49472			return t.scroller === self.scroller && (i = 1);
49473		  });
49474  
49475		  i || _refreshingAll || (self.scroll.rec = 0);
49476  
49477		  if (animation) {
49478			animation.scrollTrigger = null;
49479			revert && animation.revert({
49480			  kill: false
49481			});
49482			allowAnimation || animation.kill();
49483		  }
49484  
49485		  markerStart && [markerStart, markerEnd, markerStartTrigger, markerEndTrigger].forEach(function (m) {
49486			return m.parentNode && m.parentNode.removeChild(m);
49487		  });
49488		  _primary === self && (_primary = 0);
49489  
49490		  if (pin) {
49491			pinCache && (pinCache.uncache = 1);
49492			i = 0;
49493  
49494			_triggers.forEach(function (t) {
49495			  return t.pin === pin && i++;
49496			});
49497  
49498			i || (pinCache.spacer = 0);
49499		  }
49500  
49501		  vars.onKill && vars.onKill(self);
49502		};
49503  
49504		_triggers.push(self);
49505  
49506		self.enable(false, false);
49507		customRevertReturn && customRevertReturn(self);
49508  
49509		if (animation && animation.add && !change) {
49510		  var updateFunc = self.update;
49511  
49512		  self.update = function () {
49513			self.update = updateFunc;
49514			start || end || self.refresh();
49515		  };
49516  
49517		  gsap$1.delayedCall(0.01, self.update);
49518		  change = 0.01;
49519		  start = end = 0;
49520		} else {
49521		  self.refresh();
49522		}
49523  
49524		pin && _queueRefreshAll();
49525	  };
49526  
49527	  ScrollTrigger.register = function register(core) {
49528		if (!_coreInitted$1) {
49529		  gsap$1 = core || _getGSAP$1();
49530		  _windowExists() && window.document && ScrollTrigger.enable();
49531		  _coreInitted$1 = _enabled;
49532		}
49533  
49534		return _coreInitted$1;
49535	  };
49536  
49537	  ScrollTrigger.defaults = function defaults(config) {
49538		if (config) {
49539		  for (var p in config) {
49540			_defaults[p] = config[p];
49541		  }
49542		}
49543  
49544		return _defaults;
49545	  };
49546  
49547	  ScrollTrigger.disable = function disable(reset, kill) {
49548		_enabled = 0;
49549  
49550		_triggers.forEach(function (trigger) {
49551		  return trigger[kill ? "kill" : "disable"](reset);
49552		});
49553  
49554		_removeListener$1(_win$1, "wheel", _onScroll$1);
49555  
49556		_removeListener$1(_doc$1, "scroll", _onScroll$1);
49557  
49558		clearInterval(_syncInterval);
49559  
49560		_removeListener$1(_doc$1, "touchcancel", _passThrough);
49561  
49562		_removeListener$1(_body$1, "touchstart", _passThrough);
49563  
49564		_multiListener(_removeListener$1, _doc$1, "pointerdown,touchstart,mousedown", _pointerDownHandler);
49565  
49566		_multiListener(_removeListener$1, _doc$1, "pointerup,touchend,mouseup", _pointerUpHandler);
49567  
49568		_resizeDelay.kill();
49569  
49570		_iterateAutoRefresh(_removeListener$1);
49571  
49572		for (var i = 0; i < _scrollers.length; i += 3) {
49573		  _wheelListener(_removeListener$1, _scrollers[i], _scrollers[i + 1]);
49574  
49575		  _wheelListener(_removeListener$1, _scrollers[i], _scrollers[i + 2]);
49576		}
49577	  };
49578  
49579	  ScrollTrigger.enable = function enable() {
49580		_win$1 = window;
49581		_doc$1 = document;
49582		_docEl$1 = _doc$1.documentElement;
49583		_body$1 = _doc$1.body;
49584  
49585		if (gsap$1) {
49586		  _toArray = gsap$1.utils.toArray;
49587		  _clamp$1 = gsap$1.utils.clamp;
49588		  _context$1 = gsap$1.core.context || _passThrough;
49589		  _suppressOverwrites = gsap$1.core.suppressOverwrites || _passThrough;
49590		  _scrollRestoration = _win$1.history.scrollRestoration || "auto";
49591		  _lastScroll = _win$1.pageYOffset;
49592		  gsap$1.core.globals("ScrollTrigger", ScrollTrigger);
49593  
49594		  if (_body$1) {
49595			_enabled = 1;
49596			_div100vh = document.createElement("div");
49597			_div100vh.style.height = "100vh";
49598			_div100vh.style.position = "absolute";
49599  
49600			_refresh100vh();
49601  
49602			_rafBugFix();
49603  
49604			Observer.register(gsap$1);
49605			ScrollTrigger.isTouch = Observer.isTouch;
49606			_fixIOSBug = Observer.isTouch && /(iPad|iPhone|iPod|Mac)/g.test(navigator.userAgent);
49607			_ignoreMobileResize = Observer.isTouch === 1;
49608  
49609			_addListener$1(_win$1, "wheel", _onScroll$1);
49610  
49611			_root$1 = [_win$1, _doc$1, _docEl$1, _body$1];
49612  
49613			if (gsap$1.matchMedia) {
49614			  ScrollTrigger.matchMedia = function (vars) {
49615				var mm = gsap$1.matchMedia(),
49616					p;
49617  
49618				for (p in vars) {
49619				  mm.add(p, vars[p]);
49620				}
49621  
49622				return mm;
49623			  };
49624  
49625			  gsap$1.addEventListener("matchMediaInit", function () {
49626				return _revertAll();
49627			  });
49628			  gsap$1.addEventListener("matchMediaRevert", function () {
49629				return _revertRecorded();
49630			  });
49631			  gsap$1.addEventListener("matchMedia", function () {
49632				_refreshAll(0, 1);
49633  
49634				_dispatch("matchMedia");
49635			  });
49636			  gsap$1.matchMedia("(orientation: portrait)", function () {
49637				_setBaseDimensions();
49638  
49639				return _setBaseDimensions;
49640			  });
49641			} else {
49642			  console.warn("Requires GSAP 3.11.0 or later");
49643			}
49644  
49645			_setBaseDimensions();
49646  
49647			_addListener$1(_doc$1, "scroll", _onScroll$1);
49648  
49649			var bodyStyle = _body$1.style,
49650				border = bodyStyle.borderTopStyle,
49651				AnimationProto = gsap$1.core.Animation.prototype,
49652				bounds,
49653				i;
49654			AnimationProto.revert || Object.defineProperty(AnimationProto, "revert", {
49655			  value: function value() {
49656				return this.time(-0.01, true);
49657			  }
49658			});
49659			bodyStyle.borderTopStyle = "solid";
49660			bounds = _getBounds(_body$1);
49661			_vertical.m = Math.round(bounds.top + _vertical.sc()) || 0;
49662			_horizontal.m = Math.round(bounds.left + _horizontal.sc()) || 0;
49663			border ? bodyStyle.borderTopStyle = border : bodyStyle.removeProperty("border-top-style");
49664			_syncInterval = setInterval(_sync, 250);
49665			gsap$1.delayedCall(0.5, function () {
49666			  return _startup$1 = 0;
49667			});
49668  
49669			_addListener$1(_doc$1, "touchcancel", _passThrough);
49670  
49671			_addListener$1(_body$1, "touchstart", _passThrough);
49672  
49673			_multiListener(_addListener$1, _doc$1, "pointerdown,touchstart,mousedown", _pointerDownHandler);
49674  
49675			_multiListener(_addListener$1, _doc$1, "pointerup,touchend,mouseup", _pointerUpHandler);
49676  
49677			_transformProp = gsap$1.utils.checkPrefix("transform");
49678  
49679			_stateProps.push(_transformProp);
49680  
49681			_coreInitted$1 = _getTime$1();
49682			_resizeDelay = gsap$1.delayedCall(0.2, _refreshAll).pause();
49683			_autoRefresh = [_doc$1, "visibilitychange", function () {
49684			  var w = _win$1.innerWidth,
49685				  h = _win$1.innerHeight;
49686  
49687			  if (_doc$1.hidden) {
49688				_prevWidth = w;
49689				_prevHeight = h;
49690			  } else if (_prevWidth !== w || _prevHeight !== h) {
49691				_onResize();
49692			  }
49693			}, _doc$1, "DOMContentLoaded", _refreshAll, _win$1, "load", _refreshAll, _win$1, "resize", _onResize];
49694  
49695			_iterateAutoRefresh(_addListener$1);
49696  
vendor: 4,962 bytes, lines 49697-49842
49697			_triggers.forEach(function (trigger) {
49698			  return trigger.enable(0, 1);
49699			});
49700  
49701			for (i = 0; i < _scrollers.length; i += 3) {
49702			  _wheelListener(_removeListener$1, _scrollers[i], _scrollers[i + 1]);
49703  
49704			  _wheelListener(_removeListener$1, _scrollers[i], _scrollers[i + 2]);
49705			}
49706		  }
49707		}
49708	  };
49709  
49710	  ScrollTrigger.config = function config(vars) {
49711		"limitCallbacks" in vars && (_limitCallbacks = !!vars.limitCallbacks);
49712		var ms = vars.syncInterval;
49713		ms && clearInterval(_syncInterval) || (_syncInterval = ms) && setInterval(_sync, ms);
49714		"ignoreMobileResize" in vars && (_ignoreMobileResize = ScrollTrigger.isTouch === 1 && vars.ignoreMobileResize);
49715  
49716		if ("autoRefreshEvents" in vars) {
49717		  _iterateAutoRefresh(_removeListener$1) || _iterateAutoRefresh(_addListener$1, vars.autoRefreshEvents || "none");
49718		  _ignoreResize = (vars.autoRefreshEvents + "").indexOf("resize") === -1;
49719		}
49720	  };
49721  
49722	  ScrollTrigger.scrollerProxy = function scrollerProxy(target, vars) {
49723		var t = _getTarget(target),
49724			i = _scrollers.indexOf(t),
49725			isViewport = _isViewport$1(t);
49726  
49727		if (~i) {
49728		  _scrollers.splice(i, isViewport ? 6 : 2);
49729		}
49730  
49731		if (vars) {
49732		  isViewport ? _proxies.unshift(_win$1, vars, _body$1, vars, _docEl$1, vars) : _proxies.unshift(t, vars);
49733		}
49734	  };
49735  
49736	  ScrollTrigger.clearMatchMedia = function clearMatchMedia(query) {
49737		_triggers.forEach(function (t) {
49738		  return t._ctx && t._ctx.query === query && t._ctx.kill(true, true);
49739		});
49740	  };
49741  
49742	  ScrollTrigger.isInViewport = function isInViewport(element, ratio, horizontal) {
49743		var bounds = (_isString(element) ? _getTarget(element) : element).getBoundingClientRect(),
49744			offset = bounds[horizontal ? _width : _height] * ratio || 0;
49745		return horizontal ? bounds.right - offset > 0 && bounds.left + offset < _win$1.innerWidth : bounds.bottom - offset > 0 && bounds.top + offset < _win$1.innerHeight;
49746	  };
49747  
49748	  ScrollTrigger.positionInViewport = function positionInViewport(element, referencePoint, horizontal) {
49749		_isString(element) && (element = _getTarget(element));
49750		var bounds = element.getBoundingClientRect(),
49751			size = bounds[horizontal ? _width : _height],
49752			offset = referencePoint == null ? size / 2 : referencePoint in _keywords ? _keywords[referencePoint] * size : ~referencePoint.indexOf("%") ? parseFloat(referencePoint) * size / 100 : parseFloat(referencePoint) || 0;
49753		return horizontal ? (bounds.left + offset) / _win$1.innerWidth : (bounds.top + offset) / _win$1.innerHeight;
49754	  };
49755  
49756	  ScrollTrigger.killAll = function killAll(allowListeners) {
49757		_triggers.slice(0).forEach(function (t) {
49758		  return t.vars.id !== "ScrollSmoother" && t.kill();
49759		});
49760  
49761		if (allowListeners !== true) {
49762		  var listeners = _listeners.killAll || [];
49763		  _listeners = {};
49764		  listeners.forEach(function (f) {
49765			return f();
49766		  });
49767		}
49768	  };
49769  
49770	  return ScrollTrigger;
49771	}();
49772	ScrollTrigger$1.version = "3.12.5";
49773  
49774	ScrollTrigger$1.saveStyles = function (targets) {
49775	  return targets ? _toArray(targets).forEach(function (target) {
49776		if (target && target.style) {
49777		  var i = _savedStyles.indexOf(target);
49778  
49779		  i >= 0 && _savedStyles.splice(i, 5);
49780  
49781		  _savedStyles.push(target, target.style.cssText, target.getBBox && target.getAttribute("transform"), gsap$1.core.getCache(target), _context$1());
49782		}
49783	  }) : _savedStyles;
49784	};
49785  
49786	ScrollTrigger$1.revert = function (soft, media) {
49787	  return _revertAll(!soft, media);
49788	};
49789  
49790	ScrollTrigger$1.create = function (vars, animation) {
49791	  return new ScrollTrigger$1(vars, animation);
49792	};
49793  
49794	ScrollTrigger$1.refresh = function (safe) {
49795	  return safe ? _onResize() : (_coreInitted$1 || ScrollTrigger$1.register()) && _refreshAll(true);
49796	};
49797  
49798	ScrollTrigger$1.update = function (force) {
49799	  return ++_scrollers.cache && _updateAll(force === true ? 2 : 0);
49800	};
49801  
49802	ScrollTrigger$1.clearScrollMemory = _clearScrollMemory;
49803  
49804	ScrollTrigger$1.maxScroll = function (element, horizontal) {
49805	  return _maxScroll(element, horizontal ? _horizontal : _vertical);
49806	};
49807  
49808	ScrollTrigger$1.getScrollFunc = function (element, horizontal) {
49809	  return _getScrollFunc(_getTarget(element), horizontal ? _horizontal : _vertical);
49810	};
49811  
49812	ScrollTrigger$1.getById = function (id) {
49813	  return _ids[id];
49814	};
49815  
49816	ScrollTrigger$1.getAll = function () {
49817	  return _triggers.filter(function (t) {
49818		return t.vars.id !== "ScrollSmoother";
49819	  });
49820	};
49821  
49822	ScrollTrigger$1.isScrolling = function () {
49823	  return !!_lastScrollTime;
49824	};
49825  
49826	ScrollTrigger$1.snapDirectional = _snapDirectional;
49827  
49828	ScrollTrigger$1.addEventListener = function (type, callback) {
49829	  var a = _listeners[type] || (_listeners[type] = []);
49830	  ~a.indexOf(callback) || a.push(callback);
49831	};
49832  
49833	ScrollTrigger$1.removeEventListener = function (type, callback) {
49834	  var a = _listeners[type],
49835		  i = a && a.indexOf(callback);
49836	  i >= 0 && a.splice(i, 1);
49837	};
49838  
49839	ScrollTrigger$1.batch = function (targets, vars) {
49840	  var result = [],
49841		  varsCopy = {},
49842		  interval = vars.interval || 0.016,
vendor: 4,448 bytes, lines 49843-49977
49843		  batchMax = vars.batchMax || 1e9,
49844		  proxyCallback = function proxyCallback(type, callback) {
49845		var elements = [],
49846			triggers = [],
49847			delay = gsap$1.delayedCall(interval, function () {
49848		  callback(elements, triggers);
49849		  elements = [];
49850		  triggers = [];
49851		}).pause();
49852		return function (self) {
49853		  elements.length || delay.restart(true);
49854		  elements.push(self.trigger);
49855		  triggers.push(self);
49856		  batchMax <= elements.length && delay.progress(1);
49857		};
49858	  },
49859		  p;
49860  
49861	  for (p in vars) {
49862		varsCopy[p] = p.substr(0, 2) === "on" && _isFunction(vars[p]) && p !== "onRefreshInit" ? proxyCallback(p, vars[p]) : vars[p];
49863	  }
49864  
49865	  if (_isFunction(batchMax)) {
49866		batchMax = batchMax();
49867  
49868		_addListener$1(ScrollTrigger$1, "refresh", function () {
49869		  return batchMax = vars.batchMax();
49870		});
49871	  }
49872  
49873	  _toArray(targets).forEach(function (target) {
49874		var config = {};
49875  
49876		for (p in varsCopy) {
49877		  config[p] = varsCopy[p];
49878		}
49879  
49880		config.trigger = target;
49881		result.push(ScrollTrigger$1.create(config));
49882	  });
49883  
49884	  return result;
49885	};
49886  
49887	var _clampScrollAndGetDurationMultiplier = function _clampScrollAndGetDurationMultiplier(scrollFunc, current, end, max) {
49888	  current > max ? scrollFunc(max) : current < 0 && scrollFunc(0);
49889	  return end > max ? (max - current) / (end - current) : end < 0 ? current / (current - end) : 1;
49890	},
49891		_allowNativePanning = function _allowNativePanning(target, direction) {
49892	  if (direction === true) {
49893		target.style.removeProperty("touch-action");
49894	  } else {
49895		target.style.touchAction = direction === true ? "auto" : direction ? "pan-" + direction + (Observer.isTouch ? " pinch-zoom" : "") : "none";
49896	  }
49897  
49898	  target === _docEl$1 && _allowNativePanning(_body$1, direction);
49899	},
49900		_overflow = {
49901	  auto: 1,
49902	  scroll: 1
49903	},
49904		_nestedScroll = function _nestedScroll(_ref5) {
49905	  var event = _ref5.event,
49906		  target = _ref5.target,
49907		  axis = _ref5.axis;
49908  
49909	  var node = (event.changedTouches ? event.changedTouches[0] : event).target,
49910		  cache = node._gsap || gsap$1.core.getCache(node),
49911		  time = _getTime$1(),
49912		  cs;
49913  
49914	  if (!cache._isScrollT || time - cache._isScrollT > 2000) {
49915		while (node && node !== _body$1 && (node.scrollHeight <= node.clientHeight && node.scrollWidth <= node.clientWidth || !(_overflow[(cs = _getComputedStyle(node)).overflowY] || _overflow[cs.overflowX]))) {
49916		  node = node.parentNode;
49917		}
49918  
49919		cache._isScroll = node && node !== target && !_isViewport$1(node) && (_overflow[(cs = _getComputedStyle(node)).overflowY] || _overflow[cs.overflowX]);
49920		cache._isScrollT = time;
49921	  }
49922  
49923	  if (cache._isScroll || axis === "x") {
49924		event.stopPropagation();
49925		event._gsapAllow = true;
49926	  }
49927	},
49928		_inputObserver = function _inputObserver(target, type, inputs, nested) {
49929	  return Observer.create({
49930		target: target,
49931		capture: true,
49932		debounce: false,
49933		lockAxis: true,
49934		type: type,
49935		onWheel: nested = nested && _nestedScroll,
49936		onPress: nested,
49937		onDrag: nested,
49938		onScroll: nested,
49939		onEnable: function onEnable() {
49940		  return inputs && _addListener$1(_doc$1, Observer.eventTypes[0], _captureInputs, false, true);
49941		},
49942		onDisable: function onDisable() {
49943		  return _removeListener$1(_doc$1, Observer.eventTypes[0], _captureInputs, true);
49944		}
49945	  });
49946	},
49947		_inputExp = /(input|label|select|textarea)/i,
49948		_inputIsFocused,
49949		_captureInputs = function _captureInputs(e) {
49950	  var isInput = _inputExp.test(e.target.tagName);
49951  
49952	  if (isInput || _inputIsFocused) {
49953		e._gsapAllow = true;
49954		_inputIsFocused = isInput;
49955	  }
49956	},
49957		_getScrollNormalizer = function _getScrollNormalizer(vars) {
49958	  _isObject(vars) || (vars = {});
49959	  vars.preventDefault = vars.isNormalizer = vars.allowClicks = true;
49960	  vars.type || (vars.type = "wheel,touch");
49961	  vars.debounce = !!vars.debounce;
49962	  vars.id = vars.id || "normalizer";
49963  
49964	  var _vars2 = vars,
49965		  normalizeScrollX = _vars2.normalizeScrollX,
49966		  momentum = _vars2.momentum,
49967		  allowNestedScroll = _vars2.allowNestedScroll,
49968		  onRelease = _vars2.onRelease,
49969		  self,
49970		  maxY,
49971		  target = _getTarget(vars.target) || _docEl$1,
49972		  smoother = gsap$1.core.globals().ScrollSmoother,
49973		  smootherInstance = smoother && smoother.get(),
49974		  content = _fixIOSBug && (vars.content && _getTarget(vars.content) || smootherInstance && vars.content !== false && !smootherInstance.smooth() && smootherInstance.content()),
49975		  scrollFuncY = _getScrollFunc(target, _vertical),
49976		  scrollFuncX = _getScrollFunc(target, _horizontal),
49977		  scale = 1,
vendor: 4,132 bytes, lines 49978-50099
49978		  initialScale = (Observer.isTouch && _win$1.visualViewport ? _win$1.visualViewport.scale * _win$1.visualViewport.width : _win$1.outerWidth) / _win$1.innerWidth,
49979		  wheelRefresh = 0,
49980		  resolveMomentumDuration = _isFunction(momentum) ? function () {
49981		return momentum(self);
49982	  } : function () {
49983		return momentum || 2.8;
49984	  },
49985		  lastRefreshID,
49986		  skipTouchMove,
49987		  inputObserver = _inputObserver(target, vars.type, true, allowNestedScroll),
49988		  resumeTouchMove = function resumeTouchMove() {
49989		return skipTouchMove = false;
49990	  },
49991		  scrollClampX = _passThrough,
49992		  scrollClampY = _passThrough,
49993		  updateClamps = function updateClamps() {
49994		maxY = _maxScroll(target, _vertical);
49995		scrollClampY = _clamp$1(_fixIOSBug ? 1 : 0, maxY);
49996		normalizeScrollX && (scrollClampX = _clamp$1(0, _maxScroll(target, _horizontal)));
49997		lastRefreshID = _refreshID;
49998	  },
49999		  removeContentOffset = function removeContentOffset() {
50000		content._gsap.y = _round(parseFloat(content._gsap.y) + scrollFuncY.offset) + "px";
50001		content.style.transform = "matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, " + parseFloat(content._gsap.y) + ", 0, 1)";
50002		scrollFuncY.offset = scrollFuncY.cacheID = 0;
50003	  },
50004		  ignoreDrag = function ignoreDrag() {
50005		if (skipTouchMove) {
50006		  requestAnimationFrame(resumeTouchMove);
50007  
50008		  var offset = _round(self.deltaY / 2),
50009			  scroll = scrollClampY(scrollFuncY.v - offset);
50010  
50011		  if (content && scroll !== scrollFuncY.v + scrollFuncY.offset) {
50012			scrollFuncY.offset = scroll - scrollFuncY.v;
50013  
50014			var y = _round((parseFloat(content && content._gsap.y) || 0) - scrollFuncY.offset);
50015  
50016			content.style.transform = "matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, " + y + ", 0, 1)";
50017			content._gsap.y = y + "px";
50018			scrollFuncY.cacheID = _scrollers.cache;
50019  
50020			_updateAll();
50021		  }
50022  
50023		  return true;
50024		}
50025  
50026		scrollFuncY.offset && removeContentOffset();
50027		skipTouchMove = true;
50028	  },
50029		  tween,
50030		  startScrollX,
50031		  startScrollY,
50032		  onStopDelayedCall,
50033		  onResize = function onResize() {
50034		updateClamps();
50035  
50036		if (tween.isActive() && tween.vars.scrollY > maxY) {
50037		  scrollFuncY() > maxY ? tween.progress(1) && scrollFuncY(maxY) : tween.resetTo("scrollY", maxY);
50038		}
50039	  };
50040  
50041	  content && gsap$1.set(content, {
50042		y: "+=0"
50043	  });
50044  
50045	  vars.ignoreCheck = function (e) {
50046		return _fixIOSBug && e.type === "touchmove" && ignoreDrag() || scale > 1.05 && e.type !== "touchstart" || self.isGesturing || e.touches && e.touches.length > 1;
50047	  };
50048  
50049	  vars.onPress = function () {
50050		skipTouchMove = false;
50051		var prevScale = scale;
50052		scale = _round((_win$1.visualViewport && _win$1.visualViewport.scale || 1) / initialScale);
50053		tween.pause();
50054		prevScale !== scale && _allowNativePanning(target, scale > 1.01 ? true : normalizeScrollX ? false : "x");
50055		startScrollX = scrollFuncX();
50056		startScrollY = scrollFuncY();
50057		updateClamps();
50058		lastRefreshID = _refreshID;
50059	  };
50060  
50061	  vars.onRelease = vars.onGestureStart = function (self, wasDragging) {
50062		scrollFuncY.offset && removeContentOffset();
50063  
50064		if (!wasDragging) {
50065		  onStopDelayedCall.restart(true);
50066		} else {
50067		  _scrollers.cache++;
50068		  var dur = resolveMomentumDuration(),
50069			  currentScroll,
50070			  endScroll;
50071  
50072		  if (normalizeScrollX) {
50073			currentScroll = scrollFuncX();
50074			endScroll = currentScroll + dur * 0.05 * -self.velocityX / 0.227;
50075			dur *= _clampScrollAndGetDurationMultiplier(scrollFuncX, currentScroll, endScroll, _maxScroll(target, _horizontal));
50076			tween.vars.scrollX = scrollClampX(endScroll);
50077		  }
50078  
50079		  currentScroll = scrollFuncY();
50080		  endScroll = currentScroll + dur * 0.05 * -self.velocityY / 0.227;
50081		  dur *= _clampScrollAndGetDurationMultiplier(scrollFuncY, currentScroll, endScroll, _maxScroll(target, _vertical));
50082		  tween.vars.scrollY = scrollClampY(endScroll);
50083		  tween.invalidate().duration(dur).play(0.01);
50084  
50085		  if (_fixIOSBug && tween.vars.scrollY >= maxY || currentScroll >= maxY - 1) {
50086			gsap$1.to({}, {
50087			  onUpdate: onResize,
50088			  duration: dur
50089			});
50090		  }
50091		}
50092  
50093		onRelease && onRelease(self);
50094	  };
50095  
50096	  vars.onWheel = function () {
50097		tween._ts && tween.pause();
50098  
50099		if (_getTime$1() - wheelRefresh > 1000) {
vendor: 28,617 bytes, lines 50100-51154
50100		  lastRefreshID = 0;
50101		  wheelRefresh = _getTime$1();
50102		}
50103	  };
50104  
50105	  vars.onChange = function (self, dx, dy, xArray, yArray) {
50106		_refreshID !== lastRefreshID && updateClamps();
50107		dx && normalizeScrollX && scrollFuncX(scrollClampX(xArray[2] === dx ? startScrollX + (self.startX - self.x) : scrollFuncX() + dx - xArray[1]));
50108  
50109		if (dy) {
50110		  scrollFuncY.offset && removeContentOffset();
50111		  var isTouch = yArray[2] === dy,
50112			  y = isTouch ? startScrollY + self.startY - self.y : scrollFuncY() + dy - yArray[1],
50113			  yClamped = scrollClampY(y);
50114		  isTouch && y !== yClamped && (startScrollY += yClamped - y);
50115		  scrollFuncY(yClamped);
50116		}
50117  
50118		(dy || dx) && _updateAll();
50119	  };
50120  
50121	  vars.onEnable = function () {
50122		_allowNativePanning(target, normalizeScrollX ? false : "x");
50123  
50124		ScrollTrigger$1.addEventListener("refresh", onResize);
50125  
50126		_addListener$1(_win$1, "resize", onResize);
50127  
50128		if (scrollFuncY.smooth) {
50129		  scrollFuncY.target.style.scrollBehavior = "auto";
50130		  scrollFuncY.smooth = scrollFuncX.smooth = false;
50131		}
50132  
50133		inputObserver.enable();
50134	  };
50135  
50136	  vars.onDisable = function () {
50137		_allowNativePanning(target, true);
50138  
50139		_removeListener$1(_win$1, "resize", onResize);
50140  
50141		ScrollTrigger$1.removeEventListener("refresh", onResize);
50142		inputObserver.kill();
50143	  };
50144  
50145	  vars.lockAxis = vars.lockAxis !== false;
50146	  self = new Observer(vars);
50147	  self.iOS = _fixIOSBug;
50148	  _fixIOSBug && !scrollFuncY() && scrollFuncY(1);
50149	  _fixIOSBug && gsap$1.ticker.add(_passThrough);
50150	  onStopDelayedCall = self._dc;
50151	  tween = gsap$1.to(self, {
50152		ease: "power4",
50153		paused: true,
50154		inherit: false,
50155		scrollX: normalizeScrollX ? "+=0.1" : "+=0",
50156		scrollY: "+=0.1",
50157		modifiers: {
50158		  scrollY: _interruptionTracker(scrollFuncY, scrollFuncY(), function () {
50159			return tween.pause();
50160		  })
50161		},
50162		onUpdate: _updateAll,
50163		onComplete: onStopDelayedCall.vars.onComplete
50164	  });
50165	  return self;
50166	};
50167  
50168	ScrollTrigger$1.sort = function (func) {
50169	  return _triggers.sort(func || function (a, b) {
50170		return (a.vars.refreshPriority || 0) * -1e6 + a.start - (b.start + (b.vars.refreshPriority || 0) * -1e6);
50171	  });
50172	};
50173  
50174	ScrollTrigger$1.observe = function (vars) {
50175	  return new Observer(vars);
50176	};
50177  
50178	ScrollTrigger$1.normalizeScroll = function (vars) {
50179	  if (typeof vars === "undefined") {
50180		return _normalizer$1;
50181	  }
50182  
50183	  if (vars === true && _normalizer$1) {
50184		return _normalizer$1.enable();
50185	  }
50186  
50187	  if (vars === false) {
50188		_normalizer$1 && _normalizer$1.kill();
50189		_normalizer$1 = vars;
50190		return;
50191	  }
50192  
50193	  var normalizer = vars instanceof Observer ? vars : _getScrollNormalizer(vars);
50194	  _normalizer$1 && _normalizer$1.target === normalizer.target && _normalizer$1.kill();
50195	  _isViewport$1(normalizer.target) && (_normalizer$1 = normalizer);
50196	  return normalizer;
50197	};
50198  
50199	ScrollTrigger$1.core = {
50200	  _getVelocityProp: _getVelocityProp,
50201	  _inputObserver: _inputObserver,
50202	  _scrollers: _scrollers,
50203	  _proxies: _proxies,
50204	  bridge: {
50205		ss: function ss() {
50206		  _lastScrollTime || _dispatch("scrollStart");
50207		  _lastScrollTime = _getTime$1();
50208		},
50209		ref: function ref() {
50210		  return _refreshing;
50211		}
50212	  }
50213	};
50214	_getGSAP$1() && gsap$1.registerPlugin(ScrollTrigger$1);
50215  
50216	exports.ScrollTrigger = ScrollTrigger$1;
50217	exports.default = ScrollTrigger$1;
50218  
50219	if (typeof(window) === 'undefined' || window !== exports) {Object.defineProperty(exports, '__esModule', { value: true });} else {delete window.default;}
50220  
50221  })));
50222
50223/*!
50224 * CustomEase 3.12.7
50225 * https://gsap.com
50226 * 
50227 * @license Copyright 2025, GreenSock. All rights reserved.
50228 * Subject to the terms at https://gsap.com/standard-license or for Club GSAP members, the agreement issued with that membership.
50229 * @author: Jack Doyle, [email protected]
50230 */
50231
50232  (function (global, factory) {
50233	typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
50234	typeof define === 'function' && define.amd ? define(['exports'], factory) :
50235	(global = global || self, factory(global.window = global.window || {}));
50236}(this, (function (exports) { 'use strict';
50237
50238	var _svgPathExp = /[achlmqstvz]|(-?\d*\.?\d*(?:e[\-+]?\d+)?)[0-9]/ig,
50239	    _scientific = /[\+\-]?\d*\.?\d+e[\+\-]?\d+/ig,
50240	    _DEG2RAD = Math.PI / 180,
50241	    _sin = Math.sin,
50242	    _cos = Math.cos,
50243	    _abs = Math.abs,
50244	    _sqrt = Math.sqrt,
50245	    _isNumber = function _isNumber(value) {
50246	  return typeof value === "number";
50247	},
50248	    _roundingNum = 1e5,
50249	    _round = function _round(value) {
50250	  return Math.round(value * _roundingNum) / _roundingNum || 0;
50251	};
50252	function transformRawPath(rawPath, a, b, c, d, tx, ty) {
50253	  var j = rawPath.length,
50254	      segment,
50255	      l,
50256	      i,
50257	      x,
50258	      y;
50259
50260	  while (--j > -1) {
50261	    segment = rawPath[j];
50262	    l = segment.length;
50263
50264	    for (i = 0; i < l; i += 2) {
50265	      x = segment[i];
50266	      y = segment[i + 1];
50267	      segment[i] = x * a + y * c + tx;
50268	      segment[i + 1] = x * b + y * d + ty;
50269	    }
50270	  }
50271
50272	  rawPath._dirty = 1;
50273	  return rawPath;
50274	}
50275
50276	function arcToSegment(lastX, lastY, rx, ry, angle, largeArcFlag, sweepFlag, x, y) {
50277	  if (lastX === x && lastY === y) {
50278	    return;
50279	  }
50280
50281	  rx = _abs(rx);
50282	  ry = _abs(ry);
50283
50284	  var angleRad = angle % 360 * _DEG2RAD,
50285	      cosAngle = _cos(angleRad),
50286	      sinAngle = _sin(angleRad),
50287	      PI = Math.PI,
50288	      TWOPI = PI * 2,
50289	      dx2 = (lastX - x) / 2,
50290	      dy2 = (lastY - y) / 2,
50291	      x1 = cosAngle * dx2 + sinAngle * dy2,
50292	      y1 = -sinAngle * dx2 + cosAngle * dy2,
50293	      x1_sq = x1 * x1,
50294	      y1_sq = y1 * y1,
50295	      radiiCheck = x1_sq / (rx * rx) + y1_sq / (ry * ry);
50296
50297	  if (radiiCheck > 1) {
50298	    rx = _sqrt(radiiCheck) * rx;
50299	    ry = _sqrt(radiiCheck) * ry;
50300	  }
50301
50302	  var rx_sq = rx * rx,
50303	      ry_sq = ry * ry,
50304	      sq = (rx_sq * ry_sq - rx_sq * y1_sq - ry_sq * x1_sq) / (rx_sq * y1_sq + ry_sq * x1_sq);
50305
50306	  if (sq < 0) {
50307	    sq = 0;
50308	  }
50309
50310	  var coef = (largeArcFlag === sweepFlag ? -1 : 1) * _sqrt(sq),
50311	      cx1 = coef * (rx * y1 / ry),
50312	      cy1 = coef * -(ry * x1 / rx),
50313	      sx2 = (lastX + x) / 2,
50314	      sy2 = (lastY + y) / 2,
50315	      cx = sx2 + (cosAngle * cx1 - sinAngle * cy1),
50316	      cy = sy2 + (sinAngle * cx1 + cosAngle * cy1),
50317	      ux = (x1 - cx1) / rx,
50318	      uy = (y1 - cy1) / ry,
50319	      vx = (-x1 - cx1) / rx,
50320	      vy = (-y1 - cy1) / ry,
50321	      temp = ux * ux + uy * uy,
50322	      angleStart = (uy < 0 ? -1 : 1) * Math.acos(ux / _sqrt(temp)),
50323	      angleExtent = (ux * vy - uy * vx < 0 ? -1 : 1) * Math.acos((ux * vx + uy * vy) / _sqrt(temp * (vx * vx + vy * vy)));
50324
50325	  isNaN(angleExtent) && (angleExtent = PI);
50326
50327	  if (!sweepFlag && angleExtent > 0) {
50328	    angleExtent -= TWOPI;
50329	  } else if (sweepFlag && angleExtent < 0) {
50330	    angleExtent += TWOPI;
50331	  }
50332
50333	  angleStart %= TWOPI;
50334	  angleExtent %= TWOPI;
50335
50336	  var segments = Math.ceil(_abs(angleExtent) / (TWOPI / 4)),
50337	      rawPath = [],
50338	      angleIncrement = angleExtent / segments,
50339	      controlLength = 4 / 3 * _sin(angleIncrement / 2) / (1 + _cos(angleIncrement / 2)),
50340	      ma = cosAngle * rx,
50341	      mb = sinAngle * rx,
50342	      mc = sinAngle * -ry,
50343	      md = cosAngle * ry,
50344	      i;
50345
50346	  for (i = 0; i < segments; i++) {
50347	    angle = angleStart + i * angleIncrement;
50348	    x1 = _cos(angle);
50349	    y1 = _sin(angle);
50350	    ux = _cos(angle += angleIncrement);
50351	    uy = _sin(angle);
50352	    rawPath.push(x1 - controlLength * y1, y1 + controlLength * x1, ux + controlLength * uy, uy - controlLength * ux, ux, uy);
50353	  }
50354
50355	  for (i = 0; i < rawPath.length; i += 2) {
50356	    x1 = rawPath[i];
50357	    y1 = rawPath[i + 1];
50358	    rawPath[i] = x1 * ma + y1 * mc + cx;
50359	    rawPath[i + 1] = x1 * mb + y1 * md + cy;
50360	  }
50361
50362	  rawPath[i - 2] = x;
50363	  rawPath[i - 1] = y;
50364	  return rawPath;
50365	}
50366
50367	function stringToRawPath(d) {
50368	  var a = (d + "").replace(_scientific, function (m) {
50369	    var n = +m;
50370	    return n < 0.0001 && n > -0.0001 ? 0 : n;
50371	  }).match(_svgPathExp) || [],
50372	      path = [],
50373	      relativeX = 0,
50374	      relativeY = 0,
50375	      twoThirds = 2 / 3,
50376	      elements = a.length,
50377	      points = 0,
50378	      errorMessage = "ERROR: malformed path: " + d,
50379	      i,
50380	      j,
50381	      x,
50382	      y,
50383	      command,
50384	      isRelative,
50385	      segment,
50386	      startX,
50387	      startY,
50388	      difX,
50389	      difY,
50390	      beziers,
50391	      prevCommand,
50392	      flag1,
50393	      flag2,
50394	      line = function line(sx, sy, ex, ey) {
50395	    difX = (ex - sx) / 3;
50396	    difY = (ey - sy) / 3;
50397	    segment.push(sx + difX, sy + difY, ex - difX, ey - difY, ex, ey);
50398	  };
50399
50400	  if (!d || !isNaN(a[0]) || isNaN(a[1])) {
50401	    console.log(errorMessage);
50402	    return path;
50403	  }
50404
50405	  for (i = 0; i < elements; i++) {
50406	    prevCommand = command;
50407
50408	    if (isNaN(a[i])) {
50409	      command = a[i].toUpperCase();
50410	      isRelative = command !== a[i];
50411	    } else {
50412	      i--;
50413	    }
50414
50415	    x = +a[i + 1];
50416	    y = +a[i + 2];
50417
50418	    if (isRelative) {
50419	      x += relativeX;
50420	      y += relativeY;
50421	    }
50422
50423	    if (!i) {
50424	      startX = x;
50425	      startY = y;
50426	    }
50427
50428	    if (command === "M") {
50429	      if (segment) {
50430	        if (segment.length < 8) {
50431	          path.length -= 1;
50432	        } else {
50433	          points += segment.length;
50434	        }
50435	      }
50436
50437	      relativeX = startX = x;
50438	      relativeY = startY = y;
50439	      segment = [x, y];
50440	      path.push(segment);
50441	      i += 2;
50442	      command = "L";
50443	    } else if (command === "C") {
50444	      if (!segment) {
50445	        segment = [0, 0];
50446	      }
50447
50448	      if (!isRelative) {
50449	        relativeX = relativeY = 0;
50450	      }
50451
50452	      segment.push(x, y, relativeX + a[i + 3] * 1, relativeY + a[i + 4] * 1, relativeX += a[i + 5] * 1, relativeY += a[i + 6] * 1);
50453	      i += 6;
50454	    } else if (command === "S") {
50455	      difX = relativeX;
50456	      difY = relativeY;
50457
50458	      if (prevCommand === "C" || prevCommand === "S") {
50459	        difX += relativeX - segment[segment.length - 4];
50460	        difY += relativeY - segment[segment.length - 3];
50461	      }
50462
50463	      if (!isRelative) {
50464	        relativeX = relativeY = 0;
50465	      }
50466
50467	      segment.push(difX, difY, x, y, relativeX += a[i + 3] * 1, relativeY += a[i + 4] * 1);
50468	      i += 4;
50469	    } else if (command === "Q") {
50470	      difX = relativeX + (x - relativeX) * twoThirds;
50471	      difY = relativeY + (y - relativeY) * twoThirds;
50472
50473	      if (!isRelative) {
50474	        relativeX = relativeY = 0;
50475	      }
50476
50477	      relativeX += a[i + 3] * 1;
50478	      relativeY += a[i + 4] * 1;
50479	      segment.push(difX, difY, relativeX + (x - relativeX) * twoThirds, relativeY + (y - relativeY) * twoThirds, relativeX, relativeY);
50480	      i += 4;
50481	    } else if (command === "T") {
50482	      difX = relativeX - segment[segment.length - 4];
50483	      difY = relativeY - segment[segment.length - 3];
50484	      segment.push(relativeX + difX, relativeY + difY, x + (relativeX + difX * 1.5 - x) * twoThirds, y + (relativeY + difY * 1.5 - y) * twoThirds, relativeX = x, relativeY = y);
50485	      i += 2;
50486	    } else if (command === "H") {
50487	      line(relativeX, relativeY, relativeX = x, relativeY);
50488	      i += 1;
50489	    } else if (command === "V") {
50490	      line(relativeX, relativeY, relativeX, relativeY = x + (isRelative ? relativeY - relativeX : 0));
50491	      i += 1;
50492	    } else if (command === "L" || command === "Z") {
50493	      if (command === "Z") {
50494	        x = startX;
50495	        y = startY;
50496	        segment.closed = true;
50497	      }
50498
50499	      if (command === "L" || _abs(relativeX - x) > 0.5 || _abs(relativeY - y) > 0.5) {
50500	        line(relativeX, relativeY, x, y);
50501
50502	        if (command === "L") {
50503	          i += 2;
50504	        }
50505	      }
50506
50507	      relativeX = x;
50508	      relativeY = y;
50509	    } else if (command === "A") {
50510	      flag1 = a[i + 4];
50511	      flag2 = a[i + 5];
50512	      difX = a[i + 6];
50513	      difY = a[i + 7];
50514	      j = 7;
50515
50516	      if (flag1.length > 1) {
50517	        if (flag1.length < 3) {
50518	          difY = difX;
50519	          difX = flag2;
50520	          j--;
50521	        } else {
50522	          difY = flag2;
50523	          difX = flag1.substr(2);
50524	          j -= 2;
50525	        }
50526
50527	        flag2 = flag1.charAt(1);
50528	        flag1 = flag1.charAt(0);
50529	      }
50530
50531	      beziers = arcToSegment(relativeX, relativeY, +a[i + 1], +a[i + 2], +a[i + 3], +flag1, +flag2, (isRelative ? relativeX : 0) + difX * 1, (isRelative ? relativeY : 0) + difY * 1);
50532	      i += j;
50533
50534	      if (beziers) {
50535	        for (j = 0; j < beziers.length; j++) {
50536	          segment.push(beziers[j]);
50537	        }
50538	      }
50539
50540	      relativeX = segment[segment.length - 2];
50541	      relativeY = segment[segment.length - 1];
50542	    } else {
50543	      console.log(errorMessage);
50544	    }
50545	  }
50546
50547	  i = segment.length;
50548
50549	  if (i < 6) {
50550	    path.pop();
50551	    i = 0;
50552	  } else if (segment[0] === segment[i - 2] && segment[1] === segment[i - 1]) {
50553	    segment.closed = true;
50554	  }
50555
50556	  path.totalPoints = points + i;
50557	  return path;
50558	}
50559	function rawPathToString(rawPath) {
50560	  if (_isNumber(rawPath[0])) {
50561	    rawPath = [rawPath];
50562	  }
50563
50564	  var result = "",
50565	      l = rawPath.length,
50566	      sl,
50567	      s,
50568	      i,
50569	      segment;
50570
50571	  for (s = 0; s < l; s++) {
50572	    segment = rawPath[s];
50573	    result += "M" + _round(segment[0]) + "," + _round(segment[1]) + " C";
50574	    sl = segment.length;
50575
50576	    for (i = 2; i < sl; i++) {
50577	      result += _round(segment[i++]) + "," + _round(segment[i++]) + " " + _round(segment[i++]) + "," + _round(segment[i++]) + " " + _round(segment[i++]) + "," + _round(segment[i]) + " ";
50578	    }
50579
50580	    if (segment.closed) {
50581	      result += "z";
50582	    }
50583	  }
50584
50585	  return result;
50586	}
50587
50588	/*!
50589	 * CustomEase 3.12.7
50590	 * https://gsap.com
50591	 *
50592	 * @license Copyright 2008-2025, GreenSock. All rights reserved.
50593	 * Subject to the terms at https://gsap.com/standard-license or for
50594	 * Club GSAP members, the agreement issued with that membership.
50595	 * @author: Jack Doyle, [email protected]
50596	*/
50597
50598	var gsap,
50599	    _coreInitted,
50600	    _getGSAP = function _getGSAP() {
50601	  return gsap || typeof window !== "undefined" && (gsap = window.gsap) && gsap.registerPlugin && gsap;
50602	},
50603	    _initCore = function _initCore() {
50604	  gsap = _getGSAP();
50605
50606	  if (gsap) {
50607	    gsap.registerEase("_CE", CustomEase.create);
50608	    _coreInitted = 1;
50609	  } else {
50610	    console.warn("Please gsap.registerPlugin(CustomEase)");
50611	  }
50612	},
50613	    _bigNum = 1e20,
50614	    _round$1 = function _round(value) {
50615	  return ~~(value * 1000 + (value < 0 ? -.5 : .5)) / 1000;
50616	},
50617	    _numExp = /[-+=.]*\d+[.e\-+]*\d*[e\-+]*\d*/gi,
50618	    _needsParsingExp = /[cLlsSaAhHvVtTqQ]/g,
50619	    _findMinimum = function _findMinimum(values) {
50620	  var l = values.length,
50621	      min = _bigNum,
50622	      i;
50623
50624	  for (i = 1; i < l; i += 6) {
50625	    +values[i] < min && (min = +values[i]);
50626	  }
50627
50628	  return min;
50629	},
50630	    _normalize = function _normalize(values, height, originY) {
50631	  if (!originY && originY !== 0) {
50632	    originY = Math.max(+values[values.length - 1], +values[1]);
50633	  }
50634
50635	  var tx = +values[0] * -1,
50636	      ty = -originY,
50637	      l = values.length,
50638	      sx = 1 / (+values[l - 2] + tx),
50639	      sy = -height || (Math.abs(+values[l - 1] - +values[1]) < 0.01 * (+values[l - 2] - +values[0]) ? _findMinimum(values) + ty : +values[l - 1] + ty),
50640	      i;
50641
50642	  if (sy) {
50643	    sy = 1 / sy;
50644	  } else {
50645	    sy = -sx;
50646	  }
50647
50648	  for (i = 0; i < l; i += 2) {
50649	    values[i] = (+values[i] + tx) * sx;
50650	    values[i + 1] = (+values[i + 1] + ty) * sy;
50651	  }
50652	},
50653	    _bezierToPoints = function _bezierToPoints(x1, y1, x2, y2, x3, y3, x4, y4, threshold, points, index) {
50654	  var x12 = (x1 + x2) / 2,
50655	      y12 = (y1 + y2) / 2,
50656	      x23 = (x2 + x3) / 2,
50657	      y23 = (y2 + y3) / 2,
50658	      x34 = (x3 + x4) / 2,
50659	      y34 = (y3 + y4) / 2,
50660	      x123 = (x12 + x23) / 2,
50661	      y123 = (y12 + y23) / 2,
50662	      x234 = (x23 + x34) / 2,
50663	      y234 = (y23 + y34) / 2,
50664	      x1234 = (x123 + x234) / 2,
50665	      y1234 = (y123 + y234) / 2,
50666	      dx = x4 - x1,
50667	      dy = y4 - y1,
50668	      d2 = Math.abs((x2 - x4) * dy - (y2 - y4) * dx),
50669	      d3 = Math.abs((x3 - x4) * dy - (y3 - y4) * dx),
50670	      length;
50671
50672	  if (!points) {
50673	    points = [{
50674	      x: x1,
50675	      y: y1
50676	    }, {
50677	      x: x4,
50678	      y: y4
50679	    }];
50680	    index = 1;
50681	  }
50682
50683	  points.splice(index || points.length - 1, 0, {
50684	    x: x1234,
50685	    y: y1234
50686	  });
50687
50688	  if ((d2 + d3) * (d2 + d3) > threshold * (dx * dx + dy * dy)) {
50689	    length = points.length;
50690
50691	    _bezierToPoints(x1, y1, x12, y12, x123, y123, x1234, y1234, threshold, points, index);
50692
50693	    _bezierToPoints(x1234, y1234, x234, y234, x34, y34, x4, y4, threshold, points, index + 1 + (points.length - length));
50694	  }
50695
50696	  return points;
50697	};
50698
50699	var CustomEase = function () {
50700	  function CustomEase(id, data, config) {
50701	    _coreInitted || _initCore();
50702	    this.id = id;
50703	     this.setData(data, config);
50704	  }
50705
50706	  var _proto = CustomEase.prototype;
50707
50708	  _proto.setData = function setData(data, config) {
50709	    config = config || {};
50710	    data = data || "0,0,1,1";
50711	    var values = data.match(_numExp),
50712	        closest = 1,
50713	        points = [],
50714	        lookup = [],
50715	        precision = config.precision || 1,
50716	        fast = precision <= 1,
50717	        l,
50718	        a1,
50719	        a2,
50720	        i,
50721	        inc,
50722	        j,
50723	        point,
50724	        prevPoint,
50725	        p;
50726	    this.data = data;
50727
50728	    if (_needsParsingExp.test(data) || ~data.indexOf("M") && data.indexOf("C") < 0) {
50729	      values = stringToRawPath(data)[0];
50730	    }
50731
50732	    l = values.length;
50733
50734	    if (l === 4) {
50735	      values.unshift(0, 0);
50736	      values.push(1, 1);
50737	      l = 8;
50738	    } else if ((l - 2) % 6) {
50739	      throw "Invalid CustomEase";
50740	    }
50741
50742	    if (+values[0] !== 0 || +values[l - 2] !== 1) {
50743	      _normalize(values, config.height, config.originY);
50744	    }
50745
50746	    this.segment = values;
50747
50748	    for (i = 2; i < l; i += 6) {
50749	      a1 = {
50750	        x: +values[i - 2],
50751	        y: +values[i - 1]
50752	      };
50753	      a2 = {
50754	        x: +values[i + 4],
50755	        y: +values[i + 5]
50756	      };
50757	      points.push(a1, a2);
50758
50759	      _bezierToPoints(a1.x, a1.y, +values[i], +values[i + 1], +values[i + 2], +values[i + 3], a2.x, a2.y, 1 / (precision * 200000), points, points.length - 1);
50760	    }
50761
50762	    l = points.length;
50763
50764	    for (i = 0; i < l; i++) {
50765	      point = points[i];
50766	      prevPoint = points[i - 1] || point;
50767
50768	      if ((point.x > prevPoint.x || prevPoint.y !== point.y && prevPoint.x === point.x || point === prevPoint) && point.x <= 1) {
50769	        prevPoint.cx = point.x - prevPoint.x;
50770	        prevPoint.cy = point.y - prevPoint.y;
50771	        prevPoint.n = point;
50772	        prevPoint.nx = point.x;
50773
50774	        if (fast && i > 1 && Math.abs(prevPoint.cy / prevPoint.cx - points[i - 2].cy / points[i - 2].cx) > 2) {
50775	          fast = 0;
50776	        }
50777
50778	        if (prevPoint.cx < closest) {
50779	          if (!prevPoint.cx) {
50780	            prevPoint.cx = 0.001;
50781
50782	            if (i === l - 1) {
50783	              prevPoint.x -= 0.001;
50784	              closest = Math.min(closest, 0.001);
50785	              fast = 0;
50786	            }
50787	          } else {
50788	            closest = prevPoint.cx;
50789	          }
50790	        }
50791	      } else {
50792	        points.splice(i--, 1);
50793	        l--;
50794	      }
50795	    }
50796
50797	    l = 1 / closest + 1 | 0;
50798	    inc = 1 / l;
50799	    j = 0;
50800	    point = points[0];
50801
50802	    if (fast) {
50803	      for (i = 0; i < l; i++) {
50804	        p = i * inc;
50805
50806	        if (point.nx < p) {
50807	          point = points[++j];
50808	        }
50809
50810	        a1 = point.y + (p - point.x) / point.cx * point.cy;
50811	        lookup[i] = {
50812	          x: p,
50813	          cx: inc,
50814	          y: a1,
50815	          cy: 0,
50816	          nx: 9
50817	        };
50818
50819	        if (i) {
50820	          lookup[i - 1].cy = a1 - lookup[i - 1].y;
50821	        }
50822	      }
50823
50824	      j = points[points.length - 1];
50825	      lookup[l - 1].cy = j.y - a1;
50826	      lookup[l - 1].cx = j.x - lookup[lookup.length - 1].x;
50827	    } else {
50828	      for (i = 0; i < l; i++) {
50829	        if (point.nx < i * inc) {
50830	          point = points[++j];
50831	        }
50832
50833	        lookup[i] = point;
50834	      }
50835
50836	      if (j < points.length - 1) {
50837	        lookup[i - 1] = points[points.length - 2];
50838	      }
50839	    }
50840
50841	    this.ease = function (p) {
50842	      var point = lookup[p * l | 0] || lookup[l - 1];
50843
50844	      if (point.nx < p) {
50845	        point = point.n;
50846	      }
50847
50848	      return point.y + (p - point.x) / point.cx * point.cy;
50849	    };
50850
50851	    this.ease.custom = this;
50852	    this.id && gsap && gsap.registerEase(this.id, this.ease);
50853	    return this;
50854	  };
50855
50856	  _proto.getSVGData = function getSVGData(config) {
50857	    return CustomEase.getSVGData(this, config);
50858	  };
50859
50860	  CustomEase.create = function create(id, data, config) {
50861	    return new CustomEase(id, data, config).ease;
50862	  };
50863
50864	  CustomEase.register = function register(core) {
50865	    gsap = core;
50866
50867	    _initCore();
50868	  };
50869
50870	  CustomEase.get = function get(id) {
50871	    return gsap.parseEase(id);
50872	  };
50873
50874	  CustomEase.getSVGData = function getSVGData(ease, config) {
50875	    config = config || {};
50876	    var width = config.width || 100,
50877	        height = config.height || 100,
50878	        x = config.x || 0,
50879	        y = (config.y || 0) + height,
50880	        e = gsap.utils.toArray(config.path)[0],
50881	        a,
50882	        slope,
50883	        i,
50884	        inc,
50885	        tx,
50886	        ty,
50887	        precision,
50888	        threshold,
50889	        prevX,
50890	        prevY;
50891
50892	    if (config.invert) {
50893	      height = -height;
50894	      y = 0;
50895	    }
50896
50897	    if (typeof ease === "string") {
50898	      ease = gsap.parseEase(ease);
50899	    }
50900
50901	    if (ease.custom) {
50902	      ease = ease.custom;
50903	    }
50904
50905	    if (ease instanceof CustomEase) {
50906	      a = rawPathToString(transformRawPath([ease.segment], width, 0, 0, -height, x, y));
50907	    } else {
50908	      a = [x, y];
50909	      precision = Math.max(5, (config.precision || 1) * 200);
50910	      inc = 1 / precision;
50911	      precision += 2;
50912	      threshold = 5 / precision;
50913	      prevX = _round$1(x + inc * width);
50914	      prevY = _round$1(y + ease(inc) * -height);
50915	      slope = (prevY - y) / (prevX - x);
50916
50917	      for (i = 2; i < precision; i++) {
50918	        tx = _round$1(x + i * inc * width);
50919	        ty = _round$1(y + ease(i * inc) * -height);
50920
50921	        if (Math.abs((ty - prevY) / (tx - prevX) - slope) > threshold || i === precision - 1) {
50922	          a.push(prevX, prevY);
50923	          slope = (ty - prevY) / (tx - prevX);
50924	        }
50925
50926	        prevX = tx;
50927	        prevY = ty;
50928	      }
50929
50930	      a = "M" + a.join(",");
50931	    }
50932
50933	    e && e.setAttribute("d", a);
50934	    return a;
50935	  };
50936
50937	  return CustomEase;
50938	}();
50939	CustomEase.version = "3.12.7";
50940	CustomEase.headless = true;
50941	_getGSAP() && gsap.registerPlugin(CustomEase);
50942
50943	exports.CustomEase = CustomEase;
50944	exports.default = CustomEase;
50945
50946	Object.defineProperty(exports, '__esModule', { value: true });
50947
50948})));
50949(function (global, factory) {
50950  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
50951  typeof define === 'function' && define.amd ? define(['exports'], factory) :
50952  (global = global || self, factory(global.window = global.window || {}));
50953}(this, (function (exports) { 'use strict';
50954
50955  function _inheritsLoose(subClass, superClass) {
50956    subClass.prototype = Object.create(superClass.prototype);
50957    subClass.prototype.constructor = subClass;
50958    subClass.__proto__ = superClass;
50959  }
50960
50961  function _assertThisInitialized(self) {
50962    if (self === void 0) {
50963      throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
50964    }
50965
50966    return self;
50967  }
50968
50969  var _doc,
50970      _win,
50971      _docElement,
50972      _body,
50973      _divContainer,
50974      _svgContainer,
50975      _identityMatrix,
50976      _gEl,
50977      _transformProp = "transform",
50978      _transformOriginProp = _transformProp + "Origin",
50979      _hasOffsetBug,
50980      _setDoc = function _setDoc(element) {
50981    var doc = element.ownerDocument || element;
50982
50983    if (!(_transformProp in element.style) && "msTransform" in element.style) {
50984      _transformProp = "msTransform";
50985      _transformOriginProp = _transformProp + "Origin";
50986    }
50987
50988    while (doc.parentNode && (doc = doc.parentNode)) {}
50989
50990    _win = window;
50991    _identityMatrix = new Matrix2D();
50992
50993    if (doc) {
50994      _doc = doc;
50995      _docElement = doc.documentElement;
50996      _body = doc.body;
50997      _gEl = _doc.createElementNS("http://www.w3.org/2000/svg", "g");
50998      _gEl.style.transform = "none";
50999      var d1 = doc.createElement("div"),
51000          d2 = doc.createElement("div"),
51001          root = doc && (doc.body || doc.firstElementChild);
51002
51003      if (root && root.appendChild) {
51004        root.appendChild(d1);
51005        d1.appendChild(d2);
51006        d1.setAttribute("style", "position:static;transform:translate3d(0,0,1px)");
51007        _hasOffsetBug = d2.offsetParent !== d1;
51008        root.removeChild(d1);
51009      }
51010    }
51011
51012    return doc;
51013  },
51014      _forceNonZeroScale = function _forceNonZeroScale(e) {
51015    var a, cache;
51016
51017    while (e && e !== _body) {
51018      cache = e._gsap;
51019      cache && cache.uncache && cache.get(e, "x");
51020
51021      if (cache && !cache.scaleX && !cache.scaleY && cache.renderTransform) {
51022        cache.scaleX = cache.scaleY = 1e-4;
51023        cache.renderTransform(1, cache);
51024        a ? a.push(cache) : a = [cache];
51025      }
51026
51027      e = e.parentNode;
51028    }
51029
51030    return a;
51031  },
51032      _svgTemps = [],
51033      _divTemps = [],
51034      _getDocScrollTop = function _getDocScrollTop() {
51035    return _win.pageYOffset || _doc.scrollTop || _docElement.scrollTop || _body.scrollTop || 0;
51036  },
51037      _getDocScrollLeft = function _getDocScrollLeft() {
51038    return _win.pageXOffset || _doc.scrollLeft || _docElement.scrollLeft || _body.scrollLeft || 0;
51039  },
51040      _svgOwner = function _svgOwner(element) {
51041    return element.ownerSVGElement || ((element.tagName + "").toLowerCase() === "svg" ? element : null);
51042  },
51043      _isFixed = function _isFixed(element) {
51044    if (_win.getComputedStyle(element).position === "fixed") {
51045      return true;
51046    }
51047
51048    element = element.parentNode;
51049
51050    if (element && element.nodeType === 1) {
51051      return _isFixed(element);
51052    }
51053  },
51054      _createSibling = function _createSibling(element, i) {
51055    if (element.parentNode && (_doc || _setDoc(element))) {
51056      var svg = _svgOwner(element),
51057          ns = svg ? svg.getAttribute("xmlns") || "http://www.w3.org/2000/svg" : "http://www.w3.org/1999/xhtml",
51058          type = svg ? i ? "rect" : "g" : "div",
51059          x = i !== 2 ? 0 : 100,
51060          y = i === 3 ? 100 : 0,
51061          css = "position:absolute;display:block;pointer-events:none;margin:0;padding:0;",
51062          e = _doc.createElementNS ? _doc.createElementNS(ns.replace(/^https/, "http"), type) : _doc.createElement(type);
51063
51064      if (i) {
51065        if (!svg) {
51066          if (!_divContainer) {
51067            _divContainer = _createSibling(element);
51068            _divContainer.style.cssText = css;
51069          }
51070
51071          e.style.cssText = css + "width:0.1px;height:0.1px;top:" + y + "px;left:" + x + "px";
51072
51073          _divContainer.appendChild(e);
51074        } else {
51075          _svgContainer || (_svgContainer = _createSibling(element));
51076          e.setAttribute("width", 0.01);
51077          e.setAttribute("height", 0.01);
51078          e.setAttribute("transform", "translate(" + x + "," + y + ")");
51079
51080          _svgContainer.appendChild(e);
51081        }
51082      }
51083
51084      return e;
51085    }
51086
51087    throw "Need document and parent.";
51088  },
51089      _consolidate = function _consolidate(m) {
51090    var c = new Matrix2D(),
51091        i = 0;
51092
51093    for (; i < m.numberOfItems; i++) {
51094      c.multiply(m.getItem(i).matrix);
51095    }
51096
51097    return c;
51098  },
51099      _getCTM = function _getCTM(svg) {
51100    var m = svg.getCTM(),
51101        transform;
51102
51103    if (!m) {
51104      transform = svg.style[_transformProp];
51105      svg.style[_transformProp] = "none";
51106      svg.appendChild(_gEl);
51107      m = _gEl.getCTM();
51108      svg.removeChild(_gEl);
51109      transform ? svg.style[_transformProp] = transform : svg.style.removeProperty(_transformProp.replace(/([A-Z])/g, "-$1").toLowerCase());
51110    }
51111
51112    return m || _identityMatrix.clone();
51113  },
51114      _placeSiblings = function _placeSiblings(element, adjustGOffset) {
51115    var svg = _svgOwner(element),
51116        isRootSVG = element === svg,
51117        siblings = svg ? _svgTemps : _divTemps,
51118        parent = element.parentNode,
51119        container,
51120        m,
51121        b,
51122        x,
51123        y,
51124        cs;
51125
51126    if (element === _win) {
51127      return element;
51128    }
51129
51130    siblings.length || siblings.push(_createSibling(element, 1), _createSibling(element, 2), _createSibling(element, 3));
51131    container = svg ? _svgContainer : _divContainer;
51132
51133    if (svg) {
51134      if (isRootSVG) {
51135        b = _getCTM(element);
51136        x = -b.e / b.a;
51137        y = -b.f / b.d;
51138        m = _identityMatrix;
51139      } else if (element.getBBox) {
51140        b = element.getBBox();
51141        m = element.transform ? element.transform.baseVal : {};
51142        m = !m.numberOfItems ? _identityMatrix : m.numberOfItems > 1 ? _consolidate(m) : m.getItem(0).matrix;
51143        x = m.a * b.x + m.c * b.y;
51144        y = m.b * b.x + m.d * b.y;
51145      } else {
51146        m = new Matrix2D();
51147        x = y = 0;
51148      }
51149
51150      if (adjustGOffset && element.tagName.toLowerCase() === "g") {
51151        x = y = 0;
51152      }
51153
51154      (isRootSVG ? svg : parent).appendChild(container);
vendor: 1,139 bytes, lines 51155-51190
51155      container.setAttribute("transform", "matrix(" + m.a + "," + m.b + "," + m.c + "," + m.d + "," + (m.e + x) + "," + (m.f + y) + ")");
51156    } else {
51157      x = y = 0;
51158
51159      if (_hasOffsetBug) {
51160        m = element.offsetParent;
51161        b = element;
51162
51163        while (b && (b = b.parentNode) && b !== m && b.parentNode) {
51164          if ((_win.getComputedStyle(b)[_transformProp] + "").length > 4) {
51165            x = b.offsetLeft;
51166            y = b.offsetTop;
51167            b = 0;
51168          }
51169        }
51170      }
51171
51172      cs = _win.getComputedStyle(element);
51173
51174      if (cs.position !== "absolute" && cs.position !== "fixed") {
51175        m = element.offsetParent;
51176
51177        while (parent && parent !== m) {
51178          x += parent.scrollLeft || 0;
51179          y += parent.scrollTop || 0;
51180          parent = parent.parentNode;
51181        }
51182      }
51183
51184      b = container.style;
51185      b.top = element.offsetTop - y + "px";
51186      b.left = element.offsetLeft - x + "px";
51187      b[_transformProp] = cs[_transformProp];
51188      b[_transformOriginProp] = cs[_transformOriginProp];
51189      b.position = cs.position === "fixed" ? "fixed" : "absolute";
51190      element.parentNode
vendor: 37,456 bytes, lines 51190-52445
51190.appendChild(container);
51191    }
51192
51193    return container;
51194  },
51195      _setMatrix = function _setMatrix(m, a, b, c, d, e, f) {
51196    m.a = a;
51197    m.b = b;
51198    m.c = c;
51199    m.d = d;
51200    m.e = e;
51201    m.f = f;
51202    return m;
51203  };
51204
51205  var Matrix2D = function () {
51206    function Matrix2D(a, b, c, d, e, f) {
51207      if (a === void 0) {
51208        a = 1;
51209      }
51210
51211      if (b === void 0) {
51212        b = 0;
51213      }
51214
51215      if (c === void 0) {
51216        c = 0;
51217      }
51218
51219      if (d === void 0) {
51220        d = 1;
51221      }
51222
51223      if (e === void 0) {
51224        e = 0;
51225      }
51226
51227      if (f === void 0) {
51228        f = 0;
51229      }
51230
51231      _setMatrix(this, a, b, c, d, e, f);
51232    }
51233
51234    var _proto = Matrix2D.prototype;
51235
51236    _proto.inverse = function inverse() {
51237      var a = this.a,
51238          b = this.b,
51239          c = this.c,
51240          d = this.d,
51241          e = this.e,
51242          f = this.f,
51243          determinant = a * d - b * c || 1e-10;
51244      return _setMatrix(this, d / determinant, -b / determinant, -c / determinant, a / determinant, (c * f - d * e) / determinant, -(a * f - b * e) / determinant);
51245    };
51246
51247    _proto.multiply = function multiply(matrix) {
51248      var a = this.a,
51249          b = this.b,
51250          c = this.c,
51251          d = this.d,
51252          e = this.e,
51253          f = this.f,
51254          a2 = matrix.a,
51255          b2 = matrix.c,
51256          c2 = matrix.b,
51257          d2 = matrix.d,
51258          e2 = matrix.e,
51259          f2 = matrix.f;
51260      return _setMatrix(this, a2 * a + c2 * c, a2 * b + c2 * d, b2 * a + d2 * c, b2 * b + d2 * d, e + e2 * a + f2 * c, f + e2 * b + f2 * d);
51261    };
51262
51263    _proto.clone = function clone() {
51264      return new Matrix2D(this.a, this.b, this.c, this.d, this.e, this.f);
51265    };
51266
51267    _proto.equals = function equals(matrix) {
51268      var a = this.a,
51269          b = this.b,
51270          c = this.c,
51271          d = this.d,
51272          e = this.e,
51273          f = this.f;
51274      return a === matrix.a && b === matrix.b && c === matrix.c && d === matrix.d && e === matrix.e && f === matrix.f;
51275    };
51276
51277    _proto.apply = function apply(point, decoratee) {
51278      if (decoratee === void 0) {
51279        decoratee = {};
51280      }
51281
51282      var x = point.x,
51283          y = point.y,
51284          a = this.a,
51285          b = this.b,
51286          c = this.c,
51287          d = this.d,
51288          e = this.e,
51289          f = this.f;
51290      decoratee.x = x * a + y * c + e || 0;
51291      decoratee.y = x * b + y * d + f || 0;
51292      return decoratee;
51293    };
51294
51295    return Matrix2D;
51296  }();
51297  function getGlobalMatrix(element, inverse, adjustGOffset, includeScrollInFixed) {
51298    if (!element || !element.parentNode || (_doc || _setDoc(element)).documentElement === element) {
51299      return new Matrix2D();
51300    }
51301
51302    var zeroScales = _forceNonZeroScale(element),
51303        svg = _svgOwner(element),
51304        temps = svg ? _svgTemps : _divTemps,
51305        container = _placeSiblings(element, adjustGOffset),
51306        b1 = temps[0].getBoundingClientRect(),
51307        b2 = temps[1].getBoundingClientRect(),
51308        b3 = temps[2].getBoundingClientRect(),
51309        parent = container.parentNode,
51310        isFixed = !includeScrollInFixed && _isFixed(element),
51311        m = new Matrix2D((b2.left - b1.left) / 100, (b2.top - b1.top) / 100, (b3.left - b1.left) / 100, (b3.top - b1.top) / 100, b1.left + (isFixed ? 0 : _getDocScrollLeft()), b1.top + (isFixed ? 0 : _getDocScrollTop()));
51312
51313    parent.removeChild(container);
51314
51315    if (zeroScales) {
51316      b1 = zeroScales.length;
51317
51318      while (b1--) {
51319        b2 = zeroScales[b1];
51320        b2.scaleX = b2.scaleY = 0;
51321        b2.renderTransform(1, b2);
51322      }
51323    }
51324
51325    return inverse ? m.inverse() : m;
51326  }
51327
51328  var gsap,
51329      _win$1,
51330      _doc$1,
51331      _docElement$1,
51332      _body$1,
51333      _tempDiv,
51334      _placeholderDiv,
51335      _coreInitted,
51336      _checkPrefix,
51337      _toArray,
51338      _supportsPassive,
51339      _isTouchDevice,
51340      _touchEventLookup,
51341      _isMultiTouching,
51342      _isAndroid,
51343      InertiaPlugin,
51344      _defaultCursor,
51345      _supportsPointer,
51346      _context,
51347      _getStyleSaver,
51348      _dragCount = 0,
51349      _windowExists = function _windowExists() {
51350    return typeof window !== "undefined";
51351  },
51352      _getGSAP = function _getGSAP() {
51353    return gsap || _windowExists() && (gsap = window.gsap) && gsap.registerPlugin && gsap;
51354  },
51355      _isFunction = function _isFunction(value) {
51356    return typeof value === "function";
51357  },
51358      _isObject = function _isObject(value) {
51359    return typeof value === "object";
51360  },
51361      _isUndefined = function _isUndefined(value) {
51362    return typeof value === "undefined";
51363  },
51364      _emptyFunc = function _emptyFunc() {
51365    return false;
51366  },
51367      _transformProp$1 = "transform",
51368      _transformOriginProp$1 = "transformOrigin",
51369      _round = function _round(value) {
51370    return Math.round(value * 10000) / 10000;
51371  },
51372      _isArray = Array.isArray,
51373      _createElement = function _createElement(type, ns) {
51374    var e = _doc$1.createElementNS ? _doc$1.createElementNS((ns || "http://www.w3.org/1999/xhtml").replace(/^https/, "http"), type) : _doc$1.createElement(type);
51375    return e.style ? e : _doc$1.createElement(type);
51376  },
51377      _RAD2DEG = 180 / Math.PI,
51378      _bigNum = 1e20,
51379      _identityMatrix$1 = new Matrix2D(),
51380      _getTime = Date.now || function () {
51381    return new Date().getTime();
51382  },
51383      _renderQueue = [],
51384      _lookup = {},
51385      _lookupCount = 0,
51386      _clickableTagExp = /^(?:a|input|textarea|button|select)$/i,
51387      _lastDragTime = 0,
51388      _temp1 = {},
51389      _windowProxy = {},
51390      _copy = function _copy(obj, factor) {
51391    var copy = {},
51392        p;
51393
51394    for (p in obj) {
51395      copy[p] = factor ? obj[p] * factor : obj[p];
51396    }
51397
51398    return copy;
51399  },
51400      _extend = function _extend(obj, defaults) {
51401    for (var p in defaults) {
51402      if (!(p in obj)) {
51403        obj[p] = defaults[p];
51404      }
51405    }
51406
51407    return obj;
51408  },
51409      _setTouchActionForAllDescendants = function _setTouchActionForAllDescendants(elements, value) {
51410    var i = elements.length,
51411        children;
51412
51413    while (i--) {
51414      value ? elements[i].style.touchAction = value : elements[i].style.removeProperty("touch-action");
51415      children = elements[i].children;
51416      children && children.length && _setTouchActionForAllDescendants(children, value);
51417    }
51418  },
51419      _renderQueueTick = function _renderQueueTick() {
51420    return _renderQueue.forEach(function (func) {
51421      return func();
51422    });
51423  },
51424      _addToRenderQueue = function _addToRenderQueue(func) {
51425    _renderQueue.push(func);
51426
51427    if (_renderQueue.length === 1) {
51428      gsap.ticker.add(_renderQueueTick);
51429    }
51430  },
51431      _renderQueueTimeout = function _renderQueueTimeout() {
51432    return !_renderQueue.length && gsap.ticker.remove(_renderQueueTick);
51433  },
51434      _removeFromRenderQueue = function _removeFromRenderQueue(func) {
51435    var i = _renderQueue.length;
51436
51437    while (i--) {
51438      if (_renderQueue[i] === func) {
51439        _renderQueue.splice(i, 1);
51440      }
51441    }
51442
51443    gsap.to(_renderQueueTimeout, {
51444      overwrite: true,
51445      delay: 15,
51446      duration: 0,
51447      onComplete: _renderQueueTimeout,
51448      data: "_draggable"
51449    });
51450  },
51451      _setDefaults = function _setDefaults(obj, defaults) {
51452    for (var p in defaults) {
51453      if (!(p in obj)) {
51454        obj[p] = defaults[p];
51455      }
51456    }
51457
51458    return obj;
51459  },
51460      _addListener = function _addListener(element, type, func, capture) {
51461    if (element.addEventListener) {
51462      var touchType = _touchEventLookup[type];
51463      capture = capture || (_supportsPassive ? {
51464        passive: false
51465      } : null);
51466      element.addEventListener(touchType || type, func, capture);
51467      touchType && type !== touchType && element.addEventListener(type, func, capture);
51468    }
51469  },
51470      _removeListener = function _removeListener(element, type, func, capture) {
51471    if (element.removeEventListener) {
51472      var touchType = _touchEventLookup[type];
51473      element.removeEventListener(touchType || type, func, capture);
51474      touchType && type !== touchType && element.removeEventListener(type, func, capture);
51475    }
51476  },
51477      _preventDefault = function _preventDefault(event) {
51478    event.preventDefault && event.preventDefault();
51479    event.preventManipulation && event.preventManipulation();
51480  },
51481      _hasTouchID = function _hasTouchID(list, ID) {
51482    var i = list.length;
51483
51484    while (i--) {
51485      if (list[i].identifier === ID) {
51486        return true;
51487      }
51488    }
51489  },
51490      _onMultiTouchDocumentEnd = function _onMultiTouchDocumentEnd(event) {
51491    _isMultiTouching = event.touches && _dragCount < event.touches.length;
51492
51493    _removeListener(event.target, "touchend", _onMultiTouchDocumentEnd);
51494  },
51495      _onMultiTouchDocument = function _onMultiTouchDocument(event) {
51496    _isMultiTouching = event.touches && _dragCount < event.touches.length;
51497
51498    _addListener(event.target, "touchend", _onMultiTouchDocumentEnd);
51499  },
51500      _getDocScrollTop$1 = function _getDocScrollTop(doc) {
51501    return _win$1.pageYOffset || doc.scrollTop || doc.documentElement.scrollTop || doc.body.scrollTop || 0;
51502  },
51503      _getDocScrollLeft$1 = function _getDocScrollLeft(doc) {
51504    return _win$1.pageXOffset || doc.scrollLeft || doc.documentElement.scrollLeft || doc.body.scrollLeft || 0;
51505  },
51506      _addScrollListener = function _addScrollListener(e, callback) {
51507    _addListener(e, "scroll", callback);
51508
51509    if (!_isRoot(e.parentNode)) {
51510      _addScrollListener(e.parentNode, callback);
51511    }
51512  },
51513      _removeScrollListener = function _removeScrollListener(e, callback) {
51514    _removeListener(e, "scroll", callback);
51515
51516    if (!_isRoot(e.parentNode)) {
51517      _removeScrollListener(e.parentNode, callback);
51518    }
51519  },
51520      _isRoot = function _isRoot(e) {
51521    return !!(!e || e === _docElement$1 || e.nodeType === 9 || e === _doc$1.body || e === _win$1 || !e.nodeType || !e.parentNode);
51522  },
51523      _getMaxScroll = function _getMaxScroll(element, axis) {
51524    var dim = axis === "x" ? "Width" : "Height",
51525        scroll = "scroll" + dim,
51526        client = "client" + dim;
51527    return Math.max(0, _isRoot(element) ? Math.max(_docElement$1[scroll], _body$1[scroll]) - (_win$1["inner" + dim] || _docElement$1[client] || _body$1[client]) : element[scroll] - element[client]);
51528  },
51529      _recordMaxScrolls = function _recordMaxScrolls(e, skipCurrent) {
51530    var x = _getMaxScroll(e, "x"),
51531        y = _getMaxScroll(e, "y");
51532
51533    if (_isRoot(e)) {
51534      e = _windowProxy;
51535    } else {
51536      _recordMaxScrolls(e.parentNode, skipCurrent);
51537    }
51538
51539    e._gsMaxScrollX = x;
51540    e._gsMaxScrollY = y;
51541
51542    if (!skipCurrent) {
51543      e._gsScrollX = e.scrollLeft || 0;
51544      e._gsScrollY = e.scrollTop || 0;
51545    }
51546  },
51547      _setStyle = function _setStyle(element, property, value) {
51548    var style = element.style;
51549
51550    if (!style) {
51551      return;
51552    }
51553
51554    if (_isUndefined(style[property])) {
51555      property = _checkPrefix(property, element) || property;
51556    }
51557
51558    if (value == null) {
51559      style.removeProperty && style.removeProperty(property.replace(/([A-Z])/g, "-$1").toLowerCase());
51560    } else {
51561      style[property] = value;
51562    }
51563  },
51564      _getComputedStyle = function _getComputedStyle(element) {
51565    return _win$1.getComputedStyle(element instanceof Element ? element : element.host || (element.parentNode || {}).host || element);
51566  },
51567      _tempRect = {},
51568      _parseRect = function _parseRect(e) {
51569    if (e === _win$1) {
51570      _tempRect.left = _tempRect.top = 0;
51571      _tempRect.width = _tempRect.right = _docElement$1.clientWidth || e.innerWidth || _body$1.clientWidth || 0;
51572      _tempRect.height = _tempRect.bottom = (e.innerHeight || 0) - 20 < _docElement$1.clientHeight ? _docElement$1.clientHeight : e.innerHeight || _body$1.clientHeight || 0;
51573      return _tempRect;
51574    }
51575
51576    var doc = e.ownerDocument || _doc$1,
51577        r = !_isUndefined(e.pageX) ? {
51578      left: e.pageX - _getDocScrollLeft$1(doc),
51579      top: e.pageY - _getDocScrollTop$1(doc),
51580      right: e.pageX - _getDocScrollLeft$1(doc) + 1,
51581      bottom: e.pageY - _getDocScrollTop$1(doc) + 1
51582    } : !e.nodeType && !_isUndefined(e.left) && !_isUndefined(e.top) ? e : _toArray(e)[0].getBoundingClientRect();
51583
51584    if (_isUndefined(r.right) && !_isUndefined(r.width)) {
51585      r.right = r.left + r.width;
51586      r.bottom = r.top + r.height;
51587    } else if (_isUndefined(r.width)) {
51588      r = {
51589        width: r.right - r.left,
51590        height: r.bottom - r.top,
51591        right: r.right,
51592        left: r.left,
51593        bottom: r.bottom,
51594        top: r.top
51595      };
51596    }
51597
51598    return r;
51599  },
51600      _dispatchEvent = function _dispatchEvent(target, type, callbackName) {
51601    var vars = target.vars,
51602        callback = vars[callbackName],
51603        listeners = target._listeners[type],
51604        result;
51605
51606    if (_isFunction(callback)) {
51607      result = callback.apply(vars.callbackScope || target, vars[callbackName + "Params"] || [target.pointerEvent]);
51608    }
51609
51610    if (listeners && target.dispatchEvent(type) === false) {
51611      result = false;
51612    }
51613
51614    return result;
51615  },
51616      _getBounds = function _getBounds(target, context) {
51617    var e = _toArray(target)[0],
51618        top,
51619        left,
51620        offset;
51621
51622    if (!e.nodeType && e !== _win$1) {
51623      if (!_isUndefined(target.left)) {
51624        offset = {
51625          x: 0,
51626          y: 0
51627        };
51628        return {
51629          left: target.left - offset.x,
51630          top: target.top - offset.y,
51631          width: target.width,
51632          height: target.height
51633        };
51634      }
51635
51636      left = target.min || target.minX || target.minRotation || 0;
51637      top = target.min || target.minY || 0;
51638      return {
51639        left: left,
51640        top: top,
51641        width: (target.max || target.maxX || target.maxRotation || 0) - left,
51642        height: (target.max || target.maxY || 0) - top
51643      };
51644    }
51645
51646    return _getElementBounds(e, context);
51647  },
51648      _point1 = {},
51649      _getElementBounds = function _getElementBounds(element, context) {
51650    context = _toArray(context)[0];
51651    var isSVG = element.getBBox && element.ownerSVGElement,
51652        doc = element.ownerDocument || _doc$1,
51653        left,
51654        right,
51655        top,
51656        bottom,
51657        matrix,
51658        p1,
51659        p2,
51660        p3,
51661        p4,
51662        bbox,
51663        width,
51664        height,
51665        cs;
51666
51667    if (element === _win$1) {
51668      top = _getDocScrollTop$1(doc);
51669      left = _getDocScrollLeft$1(doc);
51670      right = left + (doc.documentElement.clientWidth || element.innerWidth || doc.body.clientWidth || 0);
51671      bottom = top + ((element.innerHeight || 0) - 20 < doc.documentElement.clientHeight ? doc.documentElement.clientHeight : element.innerHeight || doc.body.clientHeight || 0);
51672    } else if (context === _win$1 || _isUndefined(context)) {
51673      return element.getBoundingClientRect();
51674    } else {
51675      left = top = 0;
51676
51677      if (isSVG) {
51678        bbox = element.getBBox();
51679        width = bbox.width;
51680        height = bbox.height;
51681      } else {
51682        if (element.viewBox && (bbox = element.viewBox.baseVal)) {
51683          left = bbox.x || 0;
51684          top = bbox.y || 0;
51685          width = bbox.width;
51686          height = bbox.height;
51687        }
51688
51689        if (!width) {
51690          cs = _getComputedStyle(element);
51691          bbox = cs.boxSizing === "border-box";
51692          width = (parseFloat(cs.width) || element.clientWidth || 0) + (bbox ? 0 : parseFloat(cs.borderLeftWidth) + parseFloat(cs.borderRightWidth));
51693          height = (parseFloat(cs.height) || element.clientHeight || 0) + (bbox ? 0 : parseFloat(cs.borderTopWidth) + parseFloat(cs.borderBottomWidth));
51694        }
51695      }
51696
51697      right = width;
51698      bottom = height;
51699    }
51700
51701    if (element === context) {
51702      return {
51703        left: left,
51704        top: top,
51705        width: right - left,
51706        height: bottom - top
51707      };
51708    }
51709
51710    matrix = getGlobalMatrix(context, true).multiply(getGlobalMatrix(element));
51711    p1 = matrix.apply({
51712      x: left,
51713      y: top
51714    });
51715    p2 = matrix.apply({
51716      x: right,
51717      y: top
51718    });
51719    p3 = matrix.apply({
51720      x: right,
51721      y: bottom
51722    });
51723    p4 = matrix.apply({
51724      x: left,
51725      y: bottom
51726    });
51727    left = Math.min(p1.x, p2.x, p3.x, p4.x);
51728    top = Math.min(p1.y, p2.y, p3.y, p4.y);
51729    return {
51730      left: left,
51731      top: top,
51732      width: Math.max(p1.x, p2.x, p3.x, p4.x) - left,
51733      height: Math.max(p1.y, p2.y, p3.y, p4.y) - top
51734    };
51735  },
51736      _parseInertia = function _parseInertia(draggable, snap, max, min, factor, forceZeroVelocity) {
51737    var vars = {},
51738        a,
51739        i,
51740        l;
51741
51742    if (snap) {
51743      if (factor !== 1 && snap instanceof Array) {
51744        vars.end = a = [];
51745        l = snap.length;
51746
51747        if (_isObject(snap[0])) {
51748          for (i = 0; i < l; i++) {
51749            a[i] = _copy(snap[i], factor);
51750          }
51751        } else {
51752          for (i = 0; i < l; i++) {
51753            a[i] = snap[i] * factor;
51754          }
51755        }
51756
51757        max += 1.1;
51758        min -= 1.1;
51759      } else if (_isFunction(snap)) {
51760        vars.end = function (value) {
51761          var result = snap.call(draggable, value),
51762              copy,
51763              p;
51764
51765          if (factor !== 1) {
51766            if (_isObject(result)) {
51767              copy = {};
51768
51769              for (p in result) {
51770                copy[p] = result[p] * factor;
51771              }
51772
51773              result = copy;
51774            } else {
51775              result *= factor;
51776            }
51777          }
51778
51779          return result;
51780        };
51781      } else {
51782        vars.end = snap;
51783      }
51784    }
51785
51786    if (max || max === 0) {
51787      vars.max = max;
51788    }
51789
51790    if (min || min === 0) {
51791      vars.min = min;
51792    }
51793
51794    if (forceZeroVelocity) {
51795      vars.velocity = 0;
51796    }
51797
51798    return vars;
51799  },
51800      _isClickable = function _isClickable(element) {
51801    var data;
51802    return !element || !element.getAttribute || element === _body$1 ? false : (data = element.getAttribute("data-clickable")) === "true" || data !== "false" && (_clickableTagExp.test(element.nodeName + "") || element.getAttribute("contentEditable") === "true") ? true : _isClickable(element.parentNode);
51803  },
51804      _setSelectable = function _setSelectable(elements, selectable) {
51805    var i = elements.length,
51806        e;
51807
51808    while (i--) {
51809      e = elements[i];
51810      e.ondragstart = e.onselectstart = selectable ? null : _emptyFunc;
51811      gsap.set(e, {
51812        lazy: true,
51813        userSelect: selectable ? "text" : "none"
51814      });
51815    }
51816  },
51817      _isFixed$1 = function _isFixed(element) {
51818    if (_getComputedStyle(element).position === "fixed") {
51819      return true;
51820    }
51821
51822    element = element.parentNode;
51823
51824    if (element && element.nodeType === 1) {
51825      return _isFixed(element);
51826    }
51827  },
51828      _supports3D,
51829      _addPaddingBR,
51830      ScrollProxy = function ScrollProxy(element, vars) {
51831    element = gsap.utils.toArray(element)[0];
51832    vars = vars || {};
51833    var content = document.createElement("div"),
51834        style = content.style,
51835        node = element.firstChild,
51836        offsetTop = 0,
51837        offsetLeft = 0,
51838        prevTop = element.scrollTop,
51839        prevLeft = element.scrollLeft,
51840        scrollWidth = element.scrollWidth,
51841        scrollHeight = element.scrollHeight,
51842        extraPadRight = 0,
51843        maxLeft = 0,
51844        maxTop = 0,
51845        elementWidth,
51846        elementHeight,
51847        contentHeight,
51848        nextNode,
51849        transformStart,
51850        transformEnd;
51851
51852    if (_supports3D && vars.force3D !== false) {
51853      transformStart = "translate3d(";
51854      transformEnd = "px,0px)";
51855    } else if (_transformProp$1) {
51856      transformStart = "translate(";
51857      transformEnd = "px)";
51858    }
51859
51860    this.scrollTop = function (value, force) {
51861      if (!arguments.length) {
51862        return -this.top();
51863      }
51864
51865      this.top(-value, force);
51866    };
51867
51868    this.scrollLeft = function (value, force) {
51869      if (!arguments.length) {
51870        return -this.left();
51871      }
51872
51873      this.left(-value, force);
51874    };
51875
51876    this.left = function (value, force) {
51877      if (!arguments.length) {
51878        return -(element.scrollLeft + offsetLeft);
51879      }
51880
51881      var dif = element.scrollLeft - prevLeft,
51882          oldOffset = offsetLeft;
51883
51884      if ((dif > 2 || dif < -2) && !force) {
51885        prevLeft = element.scrollLeft;
51886        gsap.killTweensOf(this, {
51887          left: 1,
51888          scrollLeft: 1
51889        });
51890        this.left(-prevLeft);
51891
51892        if (vars.onKill) {
51893          vars.onKill();
51894        }
51895
51896        return;
51897      }
51898
51899      value = -value;
51900
51901      if (value < 0) {
51902        offsetLeft = value - 0.5 | 0;
51903        value = 0;
51904      } else if (value > maxLeft) {
51905        offsetLeft = value - maxLeft | 0;
51906        value = maxLeft;
51907      } else {
51908        offsetLeft = 0;
51909      }
51910
51911      if (offsetLeft || oldOffset) {
51912        if (!this._skip) {
51913          style[_transformProp$1] = transformStart + -offsetLeft + "px," + -offsetTop + transformEnd;
51914        }
51915
51916        if (offsetLeft + extraPadRight >= 0) {
51917          style.paddingRight = offsetLeft + extraPadRight + "px";
51918        }
51919      }
51920
51921      element.scrollLeft = value | 0;
51922      prevLeft = element.scrollLeft;
51923    };
51924
51925    this.top = function (value, force) {
51926      if (!arguments.length) {
51927        return -(element.scrollTop + offsetTop);
51928      }
51929
51930      var dif = element.scrollTop - prevTop,
51931          oldOffset = offsetTop;
51932
51933      if ((dif > 2 || dif < -2) && !force) {
51934        prevTop = element.scrollTop;
51935        gsap.killTweensOf(this, {
51936          top: 1,
51937          scrollTop: 1
51938        });
51939        this.top(-prevTop);
51940
51941        if (vars.onKill) {
51942          vars.onKill();
51943        }
51944
51945        return;
51946      }
51947
51948      value = -value;
51949
51950      if (value < 0) {
51951        offsetTop = value - 0.5 | 0;
51952        value = 0;
51953      } else if (value > maxTop) {
51954        offsetTop = value - maxTop | 0;
51955        value = maxTop;
51956      } else {
51957        offsetTop = 0;
51958      }
51959
51960      if (offsetTop || oldOffset) {
51961        if (!this._skip) {
51962          style[_transformProp$1] = transformStart + -offsetLeft + "px," + -offsetTop + transformEnd;
51963        }
51964      }
51965
51966      element.scrollTop = value | 0;
51967      prevTop = element.scrollTop;
51968    };
51969
51970    this.maxScrollTop = function () {
51971      return maxTop;
51972    };
51973
51974    this.maxScrollLeft = function () {
51975      return maxLeft;
51976    };
51977
51978    this.disable = function () {
51979      node = content.firstChild;
51980
51981      while (node) {
51982        nextNode = node.nextSibling;
51983        element.appendChild(node);
51984        node = nextNode;
51985      }
51986
51987      if (element === content.parentNode) {
51988        element.removeChild(content);
51989      }
51990    };
51991
51992    this.enable = function () {
51993      node = element.firstChild;
51994
51995      if (node === content) {
51996        return;
51997      }
51998
51999      while (node) {
52000        nextNode = node.nextSibling;
52001        content.appendChild(node);
52002        node = nextNode;
52003      }
52004
52005      element.appendChild(content);
52006      this.calibrate();
52007    };
52008
52009    this.calibrate = function (force) {
52010      var widthMatches = element.clientWidth === elementWidth,
52011          cs,
52012          x,
52013          y;
52014      prevTop = element.scrollTop;
52015      prevLeft = element.scrollLeft;
52016
52017      if (widthMatches && element.clientHeight === elementHeight && content.offsetHeight === contentHeight && scrollWidth === element.scrollWidth && scrollHeight === element.scrollHeight && !force) {
52018        return;
52019      }
52020
52021      if (offsetTop || offsetLeft) {
52022        x = this.left();
52023        y = this.top();
52024        this.left(-element.scrollLeft);
52025        this.top(-element.scrollTop);
52026      }
52027
52028      cs = _getComputedStyle(element);
52029
52030      if (!widthMatches || force) {
52031        style.display = "block";
52032        style.width = "auto";
52033        style.paddingRight = "0px";
52034        extraPadRight = Math.max(0, element.scrollWidth - element.clientWidth);
52035
52036        if (extraPadRight) {
52037          extraPadRight += parseFloat(cs.paddingLeft) + (_addPaddingBR ? parseFloat(cs.paddingRight) : 0);
52038        }
52039      }
52040
52041      style.display = "inline-block";
52042      style.position = "relative";
52043      style.overflow = "visible";
52044      style.verticalAlign = "top";
52045      style.boxSizing = "content-box";
52046      style.width = "100%";
52047      style.paddingRight = extraPadRight + "px";
52048
52049      if (_addPaddingBR) {
52050        style.paddingBottom = cs.paddingBottom;
52051      }
52052
52053      elementWidth = element.clientWidth;
52054      elementHeight = element.clientHeight;
52055      scrollWidth = element.scrollWidth;
52056      scrollHeight = element.scrollHeight;
52057      maxLeft = element.scrollWidth - elementWidth;
52058      maxTop = element.scrollHeight - elementHeight;
52059      contentHeight = content.offsetHeight;
52060      style.display = "block";
52061
52062      if (x || y) {
52063        this.left(x);
52064        this.top(y);
52065      }
52066    };
52067
52068    this.content = content;
52069    this.element = element;
52070    this._skip = false;
52071    this.enable();
52072  },
52073      _initCore = function _initCore(required) {
52074    if (_windowExists() && document.body) {
52075      var nav = window && window.navigator;
52076      _win$1 = window;
52077      _doc$1 = document;
52078      _docElement$1 = _doc$1.documentElement;
52079      _body$1 = _doc$1.body;
52080      _tempDiv = _createElement("div");
52081      _supportsPointer = !!window.PointerEvent;
52082      _placeholderDiv = _createElement("div");
52083      _placeholderDiv.style.cssText = "visibility:hidden;height:1px;top:-1px;pointer-events:none;position:relative;clear:both;cursor:grab";
52084      _defaultCursor = _placeholderDiv.style.cursor === "grab" ? "grab" : "move";
52085      _isAndroid = nav && nav.userAgent.toLowerCase().indexOf("android") !== -1;
52086      _isTouchDevice = "ontouchstart" in _docElement$1 && "orientation" in _win$1 || nav && (nav.MaxTouchPoints > 0 || nav.msMaxTouchPoints > 0);
52087
52088      _addPaddingBR = function () {
52089        var div = _createElement("div"),
52090            child = _createElement("div"),
52091            childStyle = child.style,
52092            parent = _body$1,
52093            val;
52094
52095        childStyle.display = "inline-block";
52096        childStyle.position = "relative";
52097        div.style.cssText = "width:90px;height:40px;padding:10px;overflow:auto;visibility:hidden";
52098        div.appendChild(child);
52099        parent.appendChild(div);
52100        val = child.offsetHeight + 18 > div.scrollHeight;
52101        parent.removeChild(div);
52102        return val;
52103      }();
52104
52105      _touchEventLookup = function (types) {
52106        var standard = types.split(","),
52107            converted = ("onpointerdown" in _tempDiv ? "pointerdown,pointermove,pointerup,pointercancel" : "onmspointerdown" in _tempDiv ? "MSPointerDown,MSPointerMove,MSPointerUp,MSPointerCancel" : types).split(","),
52108            obj = {},
52109            i = 4;
52110
52111        while (--i > -1) {
52112          obj[standard[i]] = converted[i];
52113          obj[converted[i]] = standard[i];
52114        }
52115
52116        try {
52117          _docElement$1.addEventListener("test", null, Object.defineProperty({}, "passive", {
52118            get: function get() {
52119              _supportsPassive = 1;
52120            }
52121          }));
52122        } catch (e) {}
52123
52124        return obj;
52125      }("touchstart,touchmove,touchend,touchcancel");
52126
52127      _addListener(_doc$1, "touchcancel", _emptyFunc);
52128
52129      _addListener(_win$1, "touchmove", _emptyFunc);
52130
52131      _body$1 && _body$1.addEventListener("touchstart", _emptyFunc);
52132
52133      _addListener(_doc$1, "contextmenu", function () {
52134        for (var p in _lookup) {
52135          if (_lookup[p].isPressed) {
52136            _lookup[p].endDrag();
52137          }
52138        }
52139      });
52140
52141      gsap = _coreInitted = _getGSAP();
52142    }
52143
52144    if (gsap) {
52145      InertiaPlugin = gsap.plugins.inertia;
52146
52147      _context = gsap.core.context || function () {};
52148
52149      _checkPrefix = gsap.utils.checkPrefix;
52150      _transformProp$1 = _checkPrefix(_transformProp$1);
52151      _transformOriginProp$1 = _checkPrefix(_transformOriginProp$1);
52152      _toArray = gsap.utils.toArray;
52153      _getStyleSaver = gsap.core.getStyleSaver;
52154      _supports3D = !!_checkPrefix("perspective");
52155    } else if (required) {
52156      console.warn("Please gsap.registerPlugin(Draggable)");
52157    }
52158  };
52159
52160  var EventDispatcher = function () {
52161    function EventDispatcher(target) {
52162      this._listeners = {};
52163      this.target = target || this;
52164    }
52165
52166    var _proto = EventDispatcher.prototype;
52167
52168    _proto.addEventListener = function addEventListener(type, callback) {
52169      var list = this._listeners[type] || (this._listeners[type] = []);
52170
52171      if (!~list.indexOf(callback)) {
52172        list.push(callback);
52173      }
52174    };
52175
52176    _proto.removeEventListener = function removeEventListener(type, callback) {
52177      var list = this._listeners[type],
52178          i = list && list.indexOf(callback);
52179      i >= 0 && list.splice(i, 1);
52180    };
52181
52182    _proto.dispatchEvent = function dispatchEvent(type) {
52183      var _this = this;
52184
52185      var result;
52186      (this._listeners[type] || []).forEach(function (callback) {
52187        return callback.call(_this, {
52188          type: type,
52189          target: _this.target
52190        }) === false && (result = false);
52191      });
52192      return result;
52193    };
52194
52195    return EventDispatcher;
52196  }();
52197
52198  var Draggable = function (_EventDispatcher) {
52199    _inheritsLoose(Draggable, _EventDispatcher);
52200
52201    function Draggable(target, vars) {
52202      var _this2;
52203
52204      _this2 = _EventDispatcher.call(this) || this;
52205      _coreInitted || _initCore(1);
52206      target = _toArray(target)[0];
52207      _this2.styles = _getStyleSaver && _getStyleSaver(target, "transform,left,top");
52208
52209      if (!InertiaPlugin) {
52210        InertiaPlugin = gsap.plugins.inertia;
52211      }
52212
52213      _this2.vars = vars = _copy(vars || {});
52214      _this2.target = target;
52215      _this2.x = _this2.y = _this2.rotation = 0;
52216      _this2.dragResistance = parseFloat(vars.dragResistance) || 0;
52217      _this2.edgeResistance = isNaN(vars.edgeResistance) ? 1 : parseFloat(vars.edgeResistance) || 0;
52218      _this2.lockAxis = vars.lockAxis;
52219      _this2.autoScroll = vars.autoScroll || 0;
52220      _this2.lockedAxis = null;
52221      _this2.allowEventDefault = !!vars.allowEventDefault;
52222      gsap.getProperty(target, "x");
52223
52224      var type = (vars.type || "x,y").toLowerCase(),
52225          xyMode = ~type.indexOf("x") || ~type.indexOf("y"),
52226          rotationMode = type.indexOf("rotation") !== -1,
52227          xProp = rotationMode ? "rotation" : xyMode ? "x" : "left",
52228          yProp = xyMode ? "y" : "top",
52229          allowX = !!(~type.indexOf("x") || ~type.indexOf("left") || type === "scroll"),
52230          allowY = !!(~type.indexOf("y") || ~type.indexOf("top") || type === "scroll"),
52231          minimumMovement = vars.minimumMovement || 2,
52232          self = _assertThisInitialized(_this2),
52233          triggers = _toArray(vars.trigger || vars.handle || target),
52234          killProps = {},
52235          dragEndTime = 0,
52236          checkAutoScrollBounds = false,
52237          autoScrollMarginTop = vars.autoScrollMarginTop || 40,
52238          autoScrollMarginRight = vars.autoScrollMarginRight || 40,
52239          autoScrollMarginBottom = vars.autoScrollMarginBottom || 40,
52240          autoScrollMarginLeft = vars.autoScrollMarginLeft || 40,
52241          isClickable = vars.clickableTest || _isClickable,
52242          clickTime = 0,
52243          gsCache = target._gsap || gsap.core.getCache(target),
52244          isFixed = _isFixed$1(target),
52245          getPropAsNum = function getPropAsNum(property, unit) {
52246        return parseFloat(gsCache.get(target, property, unit));
52247      },
52248          ownerDoc = target.ownerDocument || _doc$1,
52249          enabled,
52250          scrollProxy,
52251          startPointerX,
52252          startPointerY,
52253          startElementX,
52254          startElementY,
52255          hasBounds,
52256          hasDragCallback,
52257          hasMoveCallback,
52258          maxX,
52259          minX,
52260          maxY,
52261          minY,
52262          touch,
52263          touchID,
52264          rotationOrigin,
52265          dirty,
52266          old,
52267          snapX,
52268          snapY,
52269          snapXY,
52270          isClicking,
52271          touchEventTarget,
52272          matrix,
52273          interrupted,
52274          allowNativeTouchScrolling,
52275          touchDragAxis,
52276          isDispatching,
52277          clickDispatch,
52278          trustedClickDispatch,
52279          isPreventingDefault,
52280          innerMatrix,
52281          dragged,
52282          onContextMenu = function onContextMenu(e) {
52283        _preventDefault(e);
52284
52285        e.stopImmediatePropagation && e.stopImmediatePropagation();
52286        return false;
52287      },
52288          render = function render(suppressEvents) {
52289        if (self.autoScroll && self.isDragging && (checkAutoScrollBounds || dirty)) {
52290          var e = target,
52291              autoScrollFactor = self.autoScroll * 15,
52292              parent,
52293              isRoot,
52294              rect,
52295              pointerX,
52296              pointerY,
52297              changeX,
52298              changeY,
52299              gap;
52300          checkAutoScrollBounds = false;
52301          _windowProxy.scrollTop = _win$1.pageYOffset != null ? _win$1.pageYOffset : ownerDoc.documentElement.scrollTop != null ? ownerDoc.documentElement.scrollTop : ownerDoc.body.scrollTop;
52302          _windowProxy.scrollLeft = _win$1.pageXOffset != null ? _win$1.pageXOffset : ownerDoc.documentElement.scrollLeft != null ? ownerDoc.documentElement.scrollLeft : ownerDoc.body.scrollLeft;
52303          pointerX = self.pointerX - _windowProxy.scrollLeft;
52304          pointerY = self.pointerY - _windowProxy.scrollTop;
52305
52306          while (e && !isRoot) {
52307            isRoot = _isRoot(e.parentNode);
52308            parent = isRoot ? _windowProxy : e.parentNode;
52309            rect = isRoot ? {
52310              bottom: Math.max(_docElement$1.clientHeight, _win$1.innerHeight || 0),
52311              right: Math.max(_docElement$1.clientWidth, _win$1.innerWidth || 0),
52312              left: 0,
52313              top: 0
52314            } : parent.getBoundingClientRect();
52315            changeX = changeY = 0;
52316
52317            if (allowY) {
52318              gap = parent._gsMaxScrollY - parent.scrollTop;
52319
52320              if (gap < 0) {
52321                changeY = gap;
52322              } else if (pointerY > rect.bottom - autoScrollMarginBottom && gap) {
52323                checkAutoScrollBounds = true;
52324                changeY = Math.min(gap, autoScrollFactor * (1 - Math.max(0, rect.bottom - pointerY) / autoScrollMarginBottom) | 0);
52325              } else if (pointerY < rect.top + autoScrollMarginTop && parent.scrollTop) {
52326                checkAutoScrollBounds = true;
52327                changeY = -Math.min(parent.scrollTop, autoScrollFactor * (1 - Math.max(0, pointerY - rect.top) / autoScrollMarginTop) | 0);
52328              }
52329
52330              if (changeY) {
52331                parent.scrollTop += changeY;
52332              }
52333            }
52334
52335            if (allowX) {
52336              gap = parent._gsMaxScrollX - parent.scrollLeft;
52337
52338              if (gap < 0) {
52339                changeX = gap;
52340              } else if (pointerX > rect.right - autoScrollMarginRight && gap) {
52341                checkAutoScrollBounds = true;
52342                changeX = Math.min(gap, autoScrollFactor * (1 - Math.max(0, rect.right - pointerX) / autoScrollMarginRight) | 0);
52343              } else if (pointerX < rect.left + autoScrollMarginLeft && parent.scrollLeft) {
52344                checkAutoScrollBounds = true;
52345                changeX = -Math.min(parent.scrollLeft, autoScrollFactor * (1 - Math.max(0, pointerX - rect.left) / autoScrollMarginLeft) | 0);
52346              }
52347
52348              if (changeX) {
52349                parent.scrollLeft += changeX;
52350              }
52351            }
52352
52353            if (isRoot && (changeX || changeY)) {
52354              _win$1.scrollTo(parent.scrollLeft, parent.scrollTop);
52355
52356              setPointerPosition(self.pointerX + changeX, self.pointerY + changeY);
52357            }
52358
52359            e = parent;
52360          }
52361        }
52362
52363        if (dirty) {
52364          var x = self.x,
52365              y = self.y;
52366
52367          if (rotationMode) {
52368            self.deltaX = x - parseFloat(gsCache.rotation);
52369            self.rotation = x;
52370            gsCache.rotation = x + "deg";
52371            gsCache.renderTransform(1, gsCache);
52372          } else {
52373            if (scrollProxy) {
52374              if (allowY) {
52375                self.deltaY = y - scrollProxy.top();
52376                scrollProxy.top(y);
52377              }
52378
52379              if (allowX) {
52380                self.deltaX = x - scrollProxy.left();
52381                scrollProxy.left(x);
52382              }
52383            } else if (xyMode) {
52384              if (allowY) {
52385                self.deltaY = y - parseFloat(gsCache.y);
52386                gsCache.y = y + "px";
52387              }
52388
52389              if (allowX) {
52390                self.deltaX = x - parseFloat(gsCache.x);
52391                gsCache.x = x + "px";
52392              }
52393
52394              gsCache.renderTransform(1, gsCache);
52395            } else {
52396              if (allowY) {
52397                self.deltaY = y - parseFloat(target.style.top || 0);
52398                target.style.top = y + "px";
52399              }
52400
52401              if (allowX) {
52402                self.deltaX = x - parseFloat(target.style.left || 0);
52403                target.style.left = x + "px";
52404              }
52405            }
52406          }
52407
52408          if (hasDragCallback && !suppressEvents && !isDispatching) {
52409            isDispatching = true;
52410
52411            if (_dispatchEvent(self, "drag", "onDrag") === false) {
52412              if (allowX) {
52413                self.x -= self.deltaX;
52414              }
52415
52416              if (allowY) {
52417                self.y -= self.deltaY;
52418              }
52419
52420              render(true);
52421            }
52422
52423            isDispatching = false;
52424          }
52425        }
52426
52427        dirty = false;
52428      },
52429          syncXY = function syncXY(skipOnUpdate, skipSnap) {
52430        var x = self.x,
52431            y = self.y,
52432            snappedValue,
52433            cs;
52434
52435        if (!target._gsap) {
52436          gsCache = gsap.core.getCache(target);
52437        }
52438
52439        gsCache.uncache && gsap.getProperty(target, "x");
52440
52441        if (xyMode) {
52442          self.x = parseFloat(gsCache.x);
52443          self.y = parseFloat(gsCache.y);
52444        } else if (rotationMode) {
52445          self.x = self.rotation = 
52445parseFloat(gsCache.rotation
vendor: 18,327 bytes, lines 52445-52995
52445);
52446        } else if (scrollProxy) {
52447          self.y = scrollProxy.top();
52448          self.x = scrollProxy.left();
52449        } else {
52450          self.y = parseFloat(target.style.top || (cs = _getComputedStyle(target)) && cs.top) || 0;
52451          self.x = parseFloat(target.style.left || (cs || {}).left) || 0;
52452        }
52453
52454        if ((snapX || snapY || snapXY) && !skipSnap && (self.isDragging || self.isThrowing)) {
52455          if (snapXY) {
52456            _temp1.x = self.x;
52457            _temp1.y = self.y;
52458            snappedValue = snapXY(_temp1);
52459
52460            if (snappedValue.x !== self.x) {
52461              self.x = snappedValue.x;
52462              dirty = true;
52463            }
52464
52465            if (snappedValue.y !== self.y) {
52466              self.y = snappedValue.y;
52467              dirty = true;
52468            }
52469          }
52470
52471          if (snapX) {
52472            snappedValue = snapX(self.x);
52473
52474            if (snappedValue !== self.x) {
52475              self.x = snappedValue;
52476
52477              if (rotationMode) {
52478                self.rotation = snappedValue;
52479              }
52480
52481              dirty = true;
52482            }
52483          }
52484
52485          if (snapY) {
52486            snappedValue = snapY(self.y);
52487
52488            if (snappedValue !== self.y) {
52489              self.y = snappedValue;
52490            }
52491
52492            dirty = true;
52493          }
52494        }
52495
52496        dirty && render(true);
52497
52498        if (!skipOnUpdate) {
52499          self.deltaX = self.x - x;
52500          self.deltaY = self.y - y;
52501
52502          _dispatchEvent(self, "throwupdate", "onThrowUpdate");
52503        }
52504      },
52505          buildSnapFunc = function buildSnapFunc(snap, min, max, factor) {
52506        if (min == null) {
52507          min = -_bigNum;
52508        }
52509
52510        if (max == null) {
52511          max = _bigNum;
52512        }
52513
52514        if (_isFunction(snap)) {
52515          return function (n) {
52516            var edgeTolerance = !self.isPressed ? 1 : 1 - self.edgeResistance;
52517            return snap.call(self, (n > max ? max + (n - max) * edgeTolerance : n < min ? min + (n - min) * edgeTolerance : n) * factor) * factor;
52518          };
52519        }
52520
52521        if (_isArray(snap)) {
52522          return function (n) {
52523            var i = snap.length,
52524                closest = 0,
52525                absDif = _bigNum,
52526                val,
52527                dif;
52528
52529            while (--i > -1) {
52530              val = snap[i];
52531              dif = val - n;
52532
52533              if (dif < 0) {
52534                dif = -dif;
52535              }
52536
52537              if (dif < absDif && val >= min && val <= max) {
52538                closest = i;
52539                absDif = dif;
52540              }
52541            }
52542
52543            return snap[closest];
52544          };
52545        }
52546
52547        return isNaN(snap) ? function (n) {
52548          return n;
52549        } : function () {
52550          return snap * factor;
52551        };
52552      },
52553          buildPointSnapFunc = function buildPointSnapFunc(snap, minX, maxX, minY, maxY, radius, factor) {
52554        radius = radius && radius < _bigNum ? radius * radius : _bigNum;
52555
52556        if (_isFunction(snap)) {
52557          return function (point) {
52558            var edgeTolerance = !self.isPressed ? 1 : 1 - self.edgeResistance,
52559                x = point.x,
52560                y = point.y,
52561                result,
52562                dx,
52563                dy;
52564            point.x = x = x > maxX ? maxX + (x - maxX) * edgeTolerance : x < minX ? minX + (x - minX) * edgeTolerance : x;
52565            point.y = y = y > maxY ? maxY + (y - maxY) * edgeTolerance : y < minY ? minY + (y - minY) * edgeTolerance : y;
52566            result = snap.call(self, point);
52567
52568            if (result !== point) {
52569              point.x = result.x;
52570              point.y = result.y;
52571            }
52572
52573            if (factor !== 1) {
52574              point.x *= factor;
52575              point.y *= factor;
52576            }
52577
52578            if (radius < _bigNum) {
52579              dx = point.x - x;
52580              dy = point.y - y;
52581
52582              if (dx * dx + dy * dy > radius) {
52583                point.x = x;
52584                point.y = y;
52585              }
52586            }
52587
52588            return point;
52589          };
52590        }
52591
52592        if (_isArray(snap)) {
52593          return function (p) {
52594            var i = snap.length,
52595                closest = 0,
52596                minDist = _bigNum,
52597                x,
52598                y,
52599                point,
52600                dist;
52601
52602            while (--i > -1) {
52603              point = snap[i];
52604              x = point.x - p.x;
52605              y = point.y - p.y;
52606              dist = x * x + y * y;
52607
52608              if (dist < minDist) {
52609                closest = i;
52610                minDist = dist;
52611              }
52612            }
52613
52614            return minDist <= radius ? snap[closest] : p;
52615          };
52616        }
52617
52618        return function (n) {
52619          return n;
52620        };
52621      },
52622          calculateBounds = function calculateBounds() {
52623        var bounds, targetBounds, snap, snapIsRaw;
52624        hasBounds = false;
52625
52626        if (scrollProxy) {
52627          scrollProxy.calibrate();
52628          self.minX = minX = -scrollProxy.maxScrollLeft();
52629          self.minY = minY = -scrollProxy.maxScrollTop();
52630          self.maxX = maxX = self.maxY = maxY = 0;
52631          hasBounds = true;
52632        } else if (!!vars.bounds) {
52633          bounds = _getBounds(vars.bounds, target.parentNode);
52634
52635          if (rotationMode) {
52636            self.minX = minX = bounds.left;
52637            self.maxX = maxX = bounds.left + bounds.width;
52638            self.minY = minY = self.maxY = maxY = 0;
52639          } else if (!_isUndefined(vars.bounds.maxX) || !_isUndefined(vars.bounds.maxY)) {
52640            bounds = vars.bounds;
52641            self.minX = minX = bounds.minX;
52642            self.minY = minY = bounds.minY;
52643            self.maxX = maxX = bounds.maxX;
52644            self.maxY = maxY = bounds.maxY;
52645          } else {
52646            targetBounds = _getBounds(target, target.parentNode);
52647            self.minX = minX = Math.round(getPropAsNum(xProp, "px") + bounds.left - targetBounds.left);
52648            self.minY = minY = Math.round(getPropAsNum(yProp, "px") + bounds.top - targetBounds.top);
52649            self.maxX = maxX = Math.round(minX + (bounds.width - targetBounds.width));
52650            self.maxY = maxY = Math.round(minY + (bounds.height - targetBounds.height));
52651          }
52652
52653          if (minX > maxX) {
52654            self.minX = maxX;
52655            self.maxX = maxX = minX;
52656            minX = self.minX;
52657          }
52658
52659          if (minY > maxY) {
52660            self.minY = maxY;
52661            self.maxY = maxY = minY;
52662            minY = self.minY;
52663          }
52664
52665          if (rotationMode) {
52666            self.minRotation = minX;
52667            self.maxRotation = maxX;
52668          }
52669
52670          hasBounds = true;
52671        }
52672
52673        if (vars.liveSnap) {
52674          snap = vars.liveSnap === true ? vars.snap || {} : vars.liveSnap;
52675          snapIsRaw = _isArray(snap) || _isFunction(snap);
52676
52677          if (rotationMode) {
52678            snapX = buildSnapFunc(snapIsRaw ? snap : snap.rotation, minX, maxX, 1);
52679            snapY = null;
52680          } else {
52681            if (snap.points) {
52682              snapXY = buildPointSnapFunc(snapIsRaw ? snap : snap.points, minX, maxX, minY, maxY, snap.radius, scrollProxy ? -1 : 1);
52683            } else {
52684              if (allowX) {
52685                snapX = buildSnapFunc(snapIsRaw ? snap : snap.x || snap.left || snap.scrollLeft, minX, maxX, scrollProxy ? -1 : 1);
52686              }
52687
52688              if (allowY) {
52689                snapY = buildSnapFunc(snapIsRaw ? snap : snap.y || snap.top || snap.scrollTop, minY, maxY, scrollProxy ? -1 : 1);
52690              }
52691            }
52692          }
52693        }
52694      },
52695          onThrowComplete = function onThrowComplete() {
52696        self.isThrowing = false;
52697
52698        _dispatchEvent(self, "throwcomplete", "onThrowComplete");
52699      },
52700          onThrowInterrupt = function onThrowInterrupt() {
52701        self.isThrowing = false;
52702      },
52703          animate = function animate(inertia, forceZeroVelocity) {
52704        var snap, snapIsRaw, tween, overshootTolerance;
52705
52706        if (inertia && InertiaPlugin) {
52707          if (inertia === true) {
52708            snap = vars.snap || vars.liveSnap || {};
52709            snapIsRaw = _isArray(snap) || _isFunction(snap);
52710            inertia = {
52711              resistance: (vars.throwResistance || vars.resistance || 1000) / (rotationMode ? 10 : 1)
52712            };
52713
52714            if (rotationMode) {
52715              inertia.rotation = _parseInertia(self, snapIsRaw ? snap : snap.rotation, maxX, minX, 1, forceZeroVelocity);
52716            } else {
52717              if (allowX) {
52718                inertia[xProp] = _parseInertia(self, snapIsRaw ? snap : snap.points || snap.x || snap.left, maxX, minX, scrollProxy ? -1 : 1, forceZeroVelocity || self.lockedAxis === "x");
52719              }
52720
52721              if (allowY) {
52722                inertia[yProp] = _parseInertia(self, snapIsRaw ? snap : snap.points || snap.y || snap.top, maxY, minY, scrollProxy ? -1 : 1, forceZeroVelocity || self.lockedAxis === "y");
52723              }
52724
52725              if (snap.points || _isArray(snap) && _isObject(snap[0])) {
52726                inertia.linkedProps = xProp + "," + yProp;
52727                inertia.radius = snap.radius;
52728              }
52729            }
52730          }
52731
52732          self.isThrowing = true;
52733          overshootTolerance = !isNaN(vars.overshootTolerance) ? vars.overshootTolerance : vars.edgeResistance === 1 ? 0 : 1 - self.edgeResistance + 0.2;
52734
52735          if (!inertia.duration) {
52736            inertia.duration = {
52737              max: Math.max(vars.minDuration || 0, "maxDuration" in vars ? vars.maxDuration : 2),
52738              min: !isNaN(vars.minDuration) ? vars.minDuration : overshootTolerance === 0 || _isObject(inertia) && inertia.resistance > 1000 ? 0 : 0.5,
52739              overshoot: overshootTolerance
52740            };
52741          }
52742
52743          self.tween = tween = gsap.to(scrollProxy || target, {
52744            inertia: inertia,
52745            data: "_draggable",
52746            inherit: false,
52747            onComplete: onThrowComplete,
52748            onInterrupt: onThrowInterrupt,
52749            onUpdate: vars.fastMode ? _dispatchEvent : syncXY,
52750            onUpdateParams: vars.fastMode ? [self, "onthrowupdate", "onThrowUpdate"] : snap && snap.radius ? [false, true] : []
52751          });
52752
52753          if (!vars.fastMode) {
52754            if (scrollProxy) {
52755              scrollProxy._skip = true;
52756            }
52757
52758            tween.render(1e9, true, true);
52759            syncXY(true, true);
52760            self.endX = self.x;
52761            self.endY = self.y;
52762
52763            if (rotationMode) {
52764              self.endRotation = self.x;
52765            }
52766
52767            tween.play(0);
52768            syncXY(true, true);
52769
52770            if (scrollProxy) {
52771              scrollProxy._skip = false;
52772            }
52773          }
52774        } else if (hasBounds) {
52775          self.applyBounds();
52776        }
52777      },
52778          updateMatrix = function updateMatrix(shiftStart) {
52779        var start = matrix,
52780            p;
52781        matrix = getGlobalMatrix(target.parentNode, true);
52782
52783        if (shiftStart && self.isPressed && !matrix.equals(start || new Matrix2D())) {
52784          p = start.inverse().apply({
52785            x: startPointerX,
52786            y: startPointerY
52787          });
52788          matrix.apply(p, p);
52789          startPointerX = p.x;
52790          startPointerY = p.y;
52791        }
52792
52793        if (matrix.equals(_identityMatrix$1)) {
52794          matrix = null;
52795        }
52796      },
52797          recordStartPositions = function recordStartPositions() {
52798        var edgeTolerance = 1 - self.edgeResistance,
52799            offsetX = isFixed ? _getDocScrollLeft$1(ownerDoc) : 0,
52800            offsetY = isFixed ? _getDocScrollTop$1(ownerDoc) : 0,
52801            parsedOrigin,
52802            x,
52803            y;
52804
52805        if (xyMode) {
52806          gsCache.x = getPropAsNum(xProp, "px") + "px";
52807          gsCache.y = getPropAsNum(yProp, "px") + "px";
52808          gsCache.renderTransform();
52809        }
52810
52811        updateMatrix(false);
52812        _point1.x = self.pointerX - offsetX;
52813        _point1.y = self.pointerY - offsetY;
52814        matrix && matrix.apply(_point1, _point1);
52815        startPointerX = _point1.x;
52816        startPointerY = _point1.y;
52817
52818        if (dirty) {
52819          setPointerPosition(self.pointerX, self.pointerY);
52820          render(true);
52821        }
52822
52823        innerMatrix = getGlobalMatrix(target);
52824
52825        if (scrollProxy) {
52826          calculateBounds();
52827          startElementY = scrollProxy.top();
52828          startElementX = scrollProxy.left();
52829        } else {
52830          if (isTweening()) {
52831            syncXY(true, true);
52832            calculateBounds();
52833          } else {
52834            self.applyBounds();
52835          }
52836
52837          if (rotationMode) {
52838            parsedOrigin = target.ownerSVGElement ? [gsCache.xOrigin - target.getBBox().x, gsCache.yOrigin - target.getBBox().y] : (_getComputedStyle(target)[_transformOriginProp$1] || "0 0").split(" ");
52839            rotationOrigin = self.rotationOrigin = getGlobalMatrix(target).apply({
52840              x: parseFloat(parsedOrigin[0]) || 0,
52841              y: parseFloat(parsedOrigin[1]) || 0
52842            });
52843            syncXY(true, true);
52844            x = self.pointerX - rotationOrigin.x - offsetX;
52845            y = rotationOrigin.y - self.pointerY + offsetY;
52846            startElementX = self.x;
52847            startElementY = self.y = Math.atan2(y, x) * _RAD2DEG;
52848          } else {
52849            startElementY = getPropAsNum(yProp, "px");
52850            startElementX = getPropAsNum(xProp, "px");
52851          }
52852        }
52853
52854        if (hasBounds && edgeTolerance) {
52855          if (startElementX > maxX) {
52856            startElementX = maxX + (startElementX - maxX) / edgeTolerance;
52857          } else if (startElementX < minX) {
52858            startElementX = minX - (minX - startElementX) / edgeTolerance;
52859          }
52860
52861          if (!rotationMode) {
52862            if (startElementY > maxY) {
52863              startElementY = maxY + (startElementY - maxY) / edgeTolerance;
52864            } else if (startElementY < minY) {
52865              startElementY = minY - (minY - startElementY) / edgeTolerance;
52866            }
52867          }
52868        }
52869
52870        self.startX = startElementX = _round(startElementX);
52871        self.startY = startElementY = _round(startElementY);
52872      },
52873          isTweening = function isTweening() {
52874        return self.tween && self.tween.isActive();
52875      },
52876          removePlaceholder = function removePlaceholder() {
52877        if (_placeholderDiv.parentNode && !isTweening() && !self.isDragging) {
52878          _placeholderDiv.parentNode.removeChild(_placeholderDiv);
52879        }
52880      },
52881          onPress = function onPress(e, force) {
52882        var i;
52883
52884        if (!enabled || self.isPressed || !e || (e.type === "mousedown" || e.type === "pointerdown") && !force && _getTime() - clickTime < 30 && _touchEventLookup[self.pointerEvent.type]) {
52885          isPreventingDefault && e && enabled && _preventDefault(e);
52886          return;
52887        }
52888
52889        interrupted = isTweening();
52890        dragged = false;
52891        self.pointerEvent = e;
52892
52893        if (_touchEventLookup[e.type]) {
52894          touchEventTarget = ~e.type.indexOf("touch") ? e.currentTarget || e.target : ownerDoc;
52895
52896          _addListener(touchEventTarget, "touchend", onRelease);
52897
52898          _addListener(touchEventTarget, "touchmove", onMove);
52899
52900          _addListener(touchEventTarget, "touchcancel", onRelease);
52901
52902          _addListener(ownerDoc, "touchstart", _onMultiTouchDocument);
52903        } else {
52904          touchEventTarget = null;
52905
52906          _addListener(ownerDoc, "mousemove", onMove);
52907        }
52908
52909        touchDragAxis = null;
52910
52911        if (!_supportsPointer || !touchEventTarget) {
52912          _addListener(ownerDoc, "mouseup", onRelease);
52913
52914          e && e.target && _addListener(e.target, "mouseup", onRelease);
52915        }
52916
52917        isClicking = isClickable.call(self, e.target) && vars.dragClickables === false && !force;
52918
52919        if (isClicking) {
52920          _addListener(e.target, "change", onRelease);
52921
52922          _dispatchEvent(self, "pressInit", "onPressInit");
52923
52924          _dispatchEvent(self, "press", "onPress");
52925
52926          _setSelectable(triggers, true);
52927
52928          isPreventingDefault = false;
52929          return;
52930        }
52931
52932        allowNativeTouchScrolling = !touchEventTarget || allowX === allowY || self.vars.allowNativeTouchScrolling === false || self.vars.allowContextMenu && e && (e.ctrlKey || e.which > 2) ? false : allowX ? "y" : "x";
52933        isPreventingDefault = !allowNativeTouchScrolling && !self.allowEventDefault;
52934
52935        if (isPreventingDefault) {
52936          _preventDefault(e);
52937
52938          _addListener(_win$1, "touchforcechange", _preventDefault);
52939        }
52940
52941        if (e.changedTouches) {
52942          e = touch = e.changedTouches[0];
52943          touchID = e.identifier;
52944        } else if (e.pointerId) {
52945          touchID = e.pointerId;
52946        } else {
52947          touch = touchID = null;
52948        }
52949
52950        _dragCount++;
52951
52952        _addToRenderQueue(render);
52953
52954        startPointerY = self.pointerY = e.pageY;
52955        startPointerX = self.pointerX = e.pageX;
52956
52957        _dispatchEvent(self, "pressInit", "onPressInit");
52958
52959        if (allowNativeTouchScrolling || self.autoScroll) {
52960          _recordMaxScrolls(target.parentNode);
52961        }
52962
52963        if (target.parentNode && self.autoScroll && !scrollProxy && !rotationMode && target.parentNode._gsMaxScrollX && !_placeholderDiv.parentNode && !target.getBBox) {
52964          _placeholderDiv.style.width = target.parentNode.scrollWidth + "px";
52965          target.parentNode.appendChild(_placeholderDiv);
52966        }
52967
52968        recordStartPositions();
52969        self.tween && self.tween.kill();
52970        self.isThrowing = false;
52971        gsap.killTweensOf(scrollProxy || target, killProps, true);
52972        scrollProxy && gsap.killTweensOf(target, {
52973          scrollTo: 1
52974        }, true);
52975        self.tween = self.lockedAxis = null;
52976
52977        if (vars.zIndexBoost || !rotationMode && !scrollProxy && vars.zIndexBoost !== false) {
52978          target.style.zIndex = Draggable.zIndex++;
52979        }
52980
52981        self.isPressed = true;
52982        hasDragCallback = !!(vars.onDrag || self._listeners.drag);
52983        hasMoveCallback = !!(vars.onMove || self._listeners.move);
52984
52985        if (vars.cursor !== false || vars.activeCursor) {
52986          i = triggers.length;
52987
52988          while (--i > -1) {
52989            gsap.set(triggers[i], {
52990              cursor: vars.activeCursor || vars.cursor || (_defaultCursor === "grab" ? "grabbing" : _defaultCursor)
52991            });
52992          }
52993        }
52994
52995        _dispatchEvent(self, "press", "onPress");
vendor: 2,447 bytes, lines 52996-53063
52996      },
52997          onMove = function onMove(e) {
52998        var originalEvent = e,
52999            touches,
53000            pointerX,
53001            pointerY,
53002            i,
53003            dx,
53004            dy;
53005
53006        if (!enabled || _isMultiTouching || !self.isPressed || !e) {
53007          isPreventingDefault && e && enabled && _preventDefault(e);
53008          return;
53009        }
53010
53011        self.pointerEvent = e;
53012        touches = e.changedTouches;
53013
53014        if (touches) {
53015          e = touches[0];
53016
53017          if (e !== touch && e.identifier !== touchID) {
53018            i = touches.length;
53019
53020            while (--i > -1 && (e = touches[i]).identifier !== touchID && e.target !== target) {}
53021
53022            if (i < 0) {
53023              return;
53024            }
53025          }
53026        } else if (e.pointerId && touchID && e.pointerId !== touchID) {
53027          return;
53028        }
53029
53030        if (touchEventTarget && allowNativeTouchScrolling && !touchDragAxis) {
53031          _point1.x = e.pageX - (isFixed ? _getDocScrollLeft$1(ownerDoc) : 0);
53032          _point1.y = e.pageY - (isFixed ? _getDocScrollTop$1(ownerDoc) : 0);
53033          matrix && matrix.apply(_point1, _point1);
53034          pointerX = _point1.x;
53035          pointerY = _point1.y;
53036          dx = Math.abs(pointerX - startPointerX);
53037          dy = Math.abs(pointerY - startPointerY);
53038
53039          if (dx !== dy && (dx > minimumMovement || dy > minimumMovement) || _isAndroid && allowNativeTouchScrolling === touchDragAxis) {
53040            touchDragAxis = dx > dy && allowX ? "x" : "y";
53041
53042            if (allowNativeTouchScrolling && touchDragAxis !== allowNativeTouchScrolling) {
53043              _addListener(_win$1, "touchforcechange", _preventDefault);
53044            }
53045
53046            if (self.vars.lockAxisOnTouchScroll !== false && allowX && allowY) {
53047              self.lockedAxis = touchDragAxis === "x" ? "y" : "x";
53048              _isFunction(self.vars.onLockAxis) && self.vars.onLockAxis.call(self, originalEvent);
53049            }
53050
53051            if (_isAndroid && allowNativeTouchScrolling === touchDragAxis) {
53052              onRelease(originalEvent);
53053              return;
53054            }
53055          }
53056        }
53057
53058        if (!self.allowEventDefault && (!allowNativeTouchScrolling || touchDragAxis && allowNativeTouchScrolling !== touchDragAxis) && originalEvent.cancelable !== false) {
53059          _preventDefault(originalEvent);
53060
53061          isPreventingDefault = true;
53062        } else if (isPreventingDefault) {
53063          isPreventingDefault = false;
vendor: 3,917 bytes, lines 53064-53192
53064        }
53065
53066        if (self.autoScroll) {
53067          checkAutoScrollBounds = true;
53068        }
53069
53070        setPointerPosition(e.pageX, e.pageY, hasMoveCallback);
53071      },
53072          setPointerPosition = function setPointerPosition(pointerX, pointerY, invokeOnMove) {
53073        var dragTolerance = 1 - self.dragResistance,
53074            edgeTolerance = 1 - self.edgeResistance,
53075            prevPointerX = self.pointerX,
53076            prevPointerY = self.pointerY,
53077            prevStartElementY = startElementY,
53078            prevX = self.x,
53079            prevY = self.y,
53080            prevEndX = self.endX,
53081            prevEndY = self.endY,
53082            prevEndRotation = self.endRotation,
53083            prevDirty = dirty,
53084            xChange,
53085            yChange,
53086            x,
53087            y,
53088            dif,
53089            temp;
53090        self.pointerX = pointerX;
53091        self.pointerY = pointerY;
53092
53093        if (isFixed) {
53094          pointerX -= _getDocScrollLeft$1(ownerDoc);
53095          pointerY -= _getDocScrollTop$1(ownerDoc);
53096        }
53097
53098        if (rotationMode) {
53099          y = Math.atan2(rotationOrigin.y - pointerY, pointerX - rotationOrigin.x) * _RAD2DEG;
53100          dif = self.y - y;
53101
53102          if (dif > 180) {
53103            startElementY -= 360;
53104            self.y = y;
53105          } else if (dif < -180) {
53106            startElementY += 360;
53107            self.y = y;
53108          }
53109
53110          if (self.x !== startElementX || Math.abs(startElementY - y) > minimumMovement) {
53111            self.y = y;
53112            x = startElementX + (startElementY - y) * dragTolerance;
53113          } else {
53114            x = startElementX;
53115          }
53116        } else {
53117          if (matrix) {
53118            temp = pointerX * matrix.a + pointerY * matrix.c + matrix.e;
53119            pointerY = pointerX * matrix.b + pointerY * matrix.d + matrix.f;
53120            pointerX = temp;
53121          }
53122
53123          yChange = pointerY - startPointerY;
53124          xChange = pointerX - startPointerX;
53125
53126          if (yChange < minimumMovement && yChange > -minimumMovement) {
53127            yChange = 0;
53128          }
53129
53130          if (xChange < minimumMovement && xChange > -minimumMovement) {
53131            xChange = 0;
53132          }
53133
53134          if ((self.lockAxis || self.lockedAxis) && (xChange || yChange)) {
53135            temp = self.lockedAxis;
53136
53137            if (!temp) {
53138              self.lockedAxis = temp = allowX && Math.abs(xChange) > Math.abs(yChange) ? "y" : allowY ? "x" : null;
53139
53140              if (temp && _isFunction(self.vars.onLockAxis)) {
53141                self.vars.onLockAxis.call(self, self.pointerEvent);
53142              }
53143            }
53144
53145            if (temp === "y") {
53146              yChange = 0;
53147            } else if (temp === "x") {
53148              xChange = 0;
53149            }
53150          }
53151
53152          x = _round(startElementX + xChange * dragTolerance);
53153          y = _round(startElementY + yChange * dragTolerance);
53154        }
53155
53156        if ((snapX || snapY || snapXY) && (self.x !== x || self.y !== y && !rotationMode)) {
53157          if (snapXY) {
53158            _temp1.x = x;
53159            _temp1.y = y;
53160            temp = snapXY(_temp1);
53161            x = _round(temp.x);
53162            y = _round(temp.y);
53163          }
53164
53165          if (snapX) {
53166            x = _round(snapX(x));
53167          }
53168
53169          if (snapY) {
53170            y = _round(snapY(y));
53171          }
53172        }
53173
53174        if (hasBounds) {
53175          if (x > maxX) {
53176            x = maxX + Math.round((x - maxX) * edgeTolerance);
53177          } else if (x < minX) {
53178            x = minX + Math.round((x - minX) * edgeTolerance);
53179          }
53180
53181          if (!rotationMode) {
53182            if (y > maxY) {
53183              y = Math.round(maxY + (y - maxY) * edgeTolerance);
53184            } else if (y < minY) {
53185              y = Math.round(minY + (y - minY) * edgeTolerance);
53186            }
53187          }
53188        }
53189
53190        if (self.x !== x || self.y !== y && !rotationMode) {
53191          if (rotationMode) {
53192            self.endRotation = self.x = self.endX = x
vendor: 13,666 bytes, lines 53192-53599
53192;
53193            dirty = true;
53194          } else {
53195            if (allowY) {
53196              self.y = self.endY = y;
53197              dirty = true;
53198            }
53199
53200            if (allowX) {
53201              self.x = self.endX = x;
53202              dirty = true;
53203            }
53204          }
53205
53206          if (!invokeOnMove || _dispatchEvent(self, "move", "onMove") !== false) {
53207            if (!self.isDragging && self.isPressed) {
53208              self.isDragging = dragged = true;
53209
53210              _dispatchEvent(self, "dragstart", "onDragStart");
53211            }
53212          } else {
53213            self.pointerX = prevPointerX;
53214            self.pointerY = prevPointerY;
53215            startElementY = prevStartElementY;
53216            self.x = prevX;
53217            self.y = prevY;
53218            self.endX = prevEndX;
53219            self.endY = prevEndY;
53220            self.endRotation = prevEndRotation;
53221            dirty = prevDirty;
53222          }
53223        }
53224      },
53225          onRelease = function onRelease(e, force) {
53226        if (!enabled || !self.isPressed || e && touchID != null && !force && (e.pointerId && e.pointerId !== touchID && e.target !== target || e.changedTouches && !_hasTouchID(e.changedTouches, touchID))) {
53227          isPreventingDefault && e && enabled && _preventDefault(e);
53228          return;
53229        }
53230
53231        self.isPressed = false;
53232        var originalEvent = e,
53233            wasDragging = self.isDragging,
53234            isContextMenuRelease = self.vars.allowContextMenu && e && (e.ctrlKey || e.which > 2),
53235            placeholderDelayedCall = gsap.delayedCall(0.001, removePlaceholder),
53236            touches,
53237            i,
53238            syntheticEvent,
53239            eventTarget,
53240            syntheticClick;
53241
53242        if (touchEventTarget) {
53243          _removeListener(touchEventTarget, "touchend", onRelease);
53244
53245          _removeListener(touchEventTarget, "touchmove", onMove);
53246
53247          _removeListener(touchEventTarget, "touchcancel", onRelease);
53248
53249          _removeListener(ownerDoc, "touchstart", _onMultiTouchDocument);
53250        } else {
53251          _removeListener(ownerDoc, "mousemove", onMove);
53252        }
53253
53254        _removeListener(_win$1, "touchforcechange", _preventDefault);
53255
53256        if (!_supportsPointer || !touchEventTarget) {
53257          _removeListener(ownerDoc, "mouseup", onRelease);
53258
53259          e && e.target && _removeListener(e.target, "mouseup", onRelease);
53260        }
53261
53262        dirty = false;
53263
53264        if (wasDragging) {
53265          dragEndTime = _lastDragTime = _getTime();
53266          self.isDragging = false;
53267        }
53268
53269        _removeFromRenderQueue(render);
53270
53271        if (isClicking && !isContextMenuRelease) {
53272          if (e) {
53273            _removeListener(e.target, "change", onRelease);
53274
53275            self.pointerEvent = originalEvent;
53276          }
53277
53278          _setSelectable(triggers, false);
53279
53280          _dispatchEvent(self, "release", "onRelease");
53281
53282          _dispatchEvent(self, "click", "onClick");
53283
53284          isClicking = false;
53285          return;
53286        }
53287
53288        i = triggers.length;
53289
53290        while (--i > -1) {
53291          _setStyle(triggers[i], "cursor", vars.cursor || (vars.cursor !== false ? _defaultCursor : null));
53292        }
53293
53294        _dragCount--;
53295
53296        if (e) {
53297          touches = e.changedTouches;
53298
53299          if (touches) {
53300            e = touches[0];
53301
53302            if (e !== touch && e.identifier !== touchID) {
53303              i = touches.length;
53304
53305              while (--i > -1 && (e = touches[i]).identifier !== touchID && e.target !== target) {}
53306
53307              if (i < 0 && !force) {
53308                return;
53309              }
53310            }
53311          }
53312
53313          self.pointerEvent = originalEvent;
53314          self.pointerX = e.pageX;
53315          self.pointerY = e.pageY;
53316        }
53317
53318        if (isContextMenuRelease && originalEvent) {
53319          _preventDefault(originalEvent);
53320
53321          isPreventingDefault = true;
53322
53323          _dispatchEvent(self, "release", "onRelease");
53324        } else if (originalEvent && !wasDragging) {
53325          isPreventingDefault = false;
53326
53327          if (interrupted && (vars.snap || vars.bounds)) {
53328            animate(vars.inertia || vars.throwProps);
53329          }
53330
53331          _dispatchEvent(self, "release", "onRelease");
53332
53333          if ((!_isAndroid || originalEvent.type !== "touchmove") && originalEvent.type.indexOf("cancel") === -1) {
53334            _dispatchEvent(self, "click", "onClick");
53335
53336            if (_getTime() - clickTime < 300) {
53337              _dispatchEvent(self, "doubleclick", "onDoubleClick");
53338            }
53339
53340            eventTarget = originalEvent.target || target;
53341            clickTime = _getTime();
53342
53343            syntheticClick = function syntheticClick() {
53344              if (clickTime !== clickDispatch && self.enabled() && !self.isPressed && !originalEvent.defaultPrevented) {
53345                if (eventTarget.click) {
53346                  eventTarget.click();
53347                } else if (ownerDoc.createEvent) {
53348                  syntheticEvent = ownerDoc.createEvent("MouseEvents");
53349                  syntheticEvent.initMouseEvent("click", true, true, _win$1, 1, self.pointerEvent.screenX, self.pointerEvent.screenY, self.pointerX, self.pointerY, false, false, false, false, 0, null);
53350                  eventTarget.dispatchEvent(syntheticEvent);
53351                }
53352              }
53353            };
53354
53355            if (!_isAndroid && !originalEvent.defaultPrevented) {
53356              gsap.delayedCall(0.05, syntheticClick);
53357            }
53358          }
53359        } else {
53360          animate(vars.inertia || vars.throwProps);
53361
53362          if (!self.allowEventDefault && originalEvent && (vars.dragClickables !== false || !isClickable.call(self, originalEvent.target)) && wasDragging && (!allowNativeTouchScrolling || touchDragAxis && allowNativeTouchScrolling === touchDragAxis) && originalEvent.cancelable !== false) {
53363            isPreventingDefault = true;
53364
53365            _preventDefault(originalEvent);
53366          } else {
53367            isPreventingDefault = false;
53368          }
53369
53370          _dispatchEvent(self, "release", "onRelease");
53371        }
53372
53373        isTweening() && placeholderDelayedCall.duration(self.tween.duration());
53374        wasDragging && _dispatchEvent(self, "dragend", "onDragEnd");
53375        return true;
53376      },
53377          updateScroll = function updateScroll(e) {
53378        if (e && self.isDragging && !scrollProxy) {
53379          var parent = e.target || target.parentNode,
53380              deltaX = parent.scrollLeft - parent._gsScrollX,
53381              deltaY = parent.scrollTop - parent._gsScrollY;
53382
53383          if (deltaX || deltaY) {
53384            if (matrix) {
53385              startPointerX -= deltaX * matrix.a + deltaY * matrix.c;
53386              startPointerY -= deltaY * matrix.d + deltaX * matrix.b;
53387            } else {
53388              startPointerX -= deltaX;
53389              startPointerY -= deltaY;
53390            }
53391
53392            parent._gsScrollX += deltaX;
53393            parent._gsScrollY += deltaY;
53394            setPointerPosition(self.pointerX, self.pointerY);
53395          }
53396        }
53397      },
53398          onClick = function onClick(e) {
53399        var time = _getTime(),
53400            recentlyClicked = time - clickTime < 100,
53401            recentlyDragged = time - dragEndTime < 50,
53402            alreadyDispatched = recentlyClicked && clickDispatch === clickTime,
53403            defaultPrevented = self.pointerEvent && self.pointerEvent.defaultPrevented,
53404            alreadyDispatchedTrusted = recentlyClicked && trustedClickDispatch === clickTime,
53405            trusted = e.isTrusted || e.isTrusted == null && recentlyClicked && alreadyDispatched;
53406
53407        if ((alreadyDispatched || recentlyDragged && self.vars.suppressClickOnDrag !== false) && e.stopImmediatePropagation) {
53408          e.stopImmediatePropagation();
53409        }
53410
53411        if (recentlyClicked && !(self.pointerEvent && self.pointerEvent.defaultPrevented) && (!alreadyDispatched || trusted && !alreadyDispatchedTrusted)) {
53412          if (trusted && alreadyDispatched) {
53413            trustedClickDispatch = clickTime;
53414          }
53415
53416          clickDispatch = clickTime;
53417          return;
53418        }
53419
53420        if (self.isPressed || recentlyDragged || recentlyClicked) {
53421          if (!trusted || !e.detail || !recentlyClicked || defaultPrevented) {
53422            _preventDefault(e);
53423          }
53424        }
53425
53426        if (!recentlyClicked && !recentlyDragged && !dragged) {
53427          e && e.target && (self.pointerEvent = e);
53428
53429          _dispatchEvent(self, "click", "onClick");
53430        }
53431      },
53432          localizePoint = function localizePoint(p) {
53433        return matrix ? {
53434          x: p.x * matrix.a + p.y * matrix.c + matrix.e,
53435          y: p.x * matrix.b + p.y * matrix.d + matrix.f
53436        } : {
53437          x: p.x,
53438          y: p.y
53439        };
53440      };
53441
53442      old = Draggable.get(target);
53443      old && old.kill();
53444
53445      _this2.startDrag = function (event, align) {
53446        var r1, r2, p1, p2;
53447        onPress(event || self.pointerEvent, true);
53448
53449        if (align && !self.hitTest(event || self.pointerEvent)) {
53450          r1 = _parseRect(event || self.pointerEvent);
53451          r2 = _parseRect(target);
53452          p1 = localizePoint({
53453            x: r1.left + r1.width / 2,
53454            y: r1.top + r1.height / 2
53455          });
53456          p2 = localizePoint({
53457            x: r2.left + r2.width / 2,
53458            y: r2.top + r2.height / 2
53459          });
53460          startPointerX -= p1.x - p2.x;
53461          startPointerY -= p1.y - p2.y;
53462        }
53463
53464        if (!self.isDragging) {
53465          self.isDragging = dragged = true;
53466
53467          _dispatchEvent(self, "dragstart", "onDragStart");
53468        }
53469      };
53470
53471      _this2.drag = onMove;
53472
53473      _this2.endDrag = function (e) {
53474        return onRelease(e || self.pointerEvent, true);
53475      };
53476
53477      _this2.timeSinceDrag = function () {
53478        return self.isDragging ? 0 : (_getTime() - dragEndTime) / 1000;
53479      };
53480
53481      _this2.timeSinceClick = function () {
53482        return (_getTime() - clickTime) / 1000;
53483      };
53484
53485      _this2.hitTest = function (target, threshold) {
53486        return Draggable.hitTest(self.target, target, threshold);
53487      };
53488
53489      _this2.getDirection = function (from, diagonalThreshold) {
53490        var mode = from === "velocity" && InertiaPlugin ? from : _isObject(from) && !rotationMode ? "element" : "start",
53491            xChange,
53492            yChange,
53493            ratio,
53494            direction,
53495            r1,
53496            r2;
53497
53498        if (mode === "element") {
53499          r1 = _parseRect(self.target);
53500          r2 = _parseRect(from);
53501        }
53502
53503        xChange = mode === "start" ? self.x - startElementX : mode === "velocity" ? InertiaPlugin.getVelocity(target, xProp) : r1.left + r1.width / 2 - (r2.left + r2.width / 2);
53504
53505        if (rotationMode) {
53506          return xChange < 0 ? "counter-clockwise" : "clockwise";
53507        } else {
53508          diagonalThreshold = diagonalThreshold || 2;
53509          yChange = mode === "start" ? self.y - startElementY : mode === "velocity" ? InertiaPlugin.getVelocity(target, yProp) : r1.top + r1.height / 2 - (r2.top + r2.height / 2);
53510          ratio = Math.abs(xChange / yChange);
53511          direction = ratio < 1 / diagonalThreshold ? "" : xChange < 0 ? "left" : "right";
53512
53513          if (ratio < diagonalThreshold) {
53514            if (direction !== "") {
53515              direction += "-";
53516            }
53517
53518            direction += yChange < 0 ? "up" : "down";
53519          }
53520        }
53521
53522        return direction;
53523      };
53524
53525      _this2.applyBounds = function (newBounds, sticky) {
53526        var x, y, forceZeroVelocity, e, parent, isRoot;
53527
53528        if (newBounds && vars.bounds !== newBounds) {
53529          vars.bounds = newBounds;
53530          return self.update(true, sticky);
53531        }
53532
53533        syncXY(true);
53534        calculateBounds();
53535
53536        if (hasBounds && !isTweening()) {
53537          x = self.x;
53538          y = self.y;
53539
53540          if (x > maxX) {
53541            x = maxX;
53542          } else if (x < minX) {
53543            x = minX;
53544          }
53545
53546          if (y > maxY) {
53547            y = maxY;
53548          } else if (y < minY) {
53549            y = minY;
53550          }
53551
53552          if (self.x !== x || self.y !== y) {
53553            forceZeroVelocity = true;
53554            self.x = self.endX = x;
53555
53556            if (rotationMode) {
53557              self.endRotation = x;
53558            } else {
53559              self.y = self.endY = y;
53560            }
53561
53562            dirty = true;
53563            render(true);
53564
53565            if (self.autoScroll && !self.isDragging) {
53566              _recordMaxScrolls(target.parentNode);
53567
53568              e = target;
53569              _windowProxy.scrollTop = _win$1.pageYOffset != null ? _win$1.pageYOffset : ownerDoc.documentElement.scrollTop != null ? ownerDoc.documentElement.scrollTop : ownerDoc.body.scrollTop;
53570              _windowProxy.scrollLeft = _win$1.pageXOffset != null ? _win$1.pageXOffset : ownerDoc.documentElement.scrollLeft != null ? ownerDoc.documentElement.scrollLeft : ownerDoc.body.scrollLeft;
53571
53572              while (e && !isRoot) {
53573                isRoot = _isRoot(e.parentNode);
53574                parent = isRoot ? _windowProxy : e.parentNode;
53575
53576                if (allowY && parent.scrollTop > parent._gsMaxScrollY) {
53577                  parent.scrollTop = parent._gsMaxScrollY;
53578                }
53579
53580                if (allowX && parent.scrollLeft > parent._gsMaxScrollX) {
53581                  parent.scrollLeft = parent._gsMaxScrollX;
53582                }
53583
53584                e = parent;
53585              }
53586            }
53587          }
53588
53589          if (self.isThrowing && (forceZeroVelocity || self.endX > maxX || self.endX < minX || self.endY > maxY || self.endY < minY)) {
53590            animate(vars.inertia || vars.throwProps, forceZeroVelocity);
53591          }
53592        }
53593
53594        return self;
53595      };
53596
53597      _this2.update = function (applyBounds, sticky, ignoreExternalChanges) {
53598        if (sticky && self.isPressed) {
53599          
vendor: 3,070 bytes, lines 53599-53700
53599var m = getGlobalMatrix(target),
53600              p = innerMatrix.apply({
53601            x: self.x - startElementX,
53602            y: self.y - startElementY
53603          }),
53604              m2 = getGlobalMatrix(target.parentNode, true);
53605          m2.apply({
53606            x: m.e - p.x,
53607            y: m.f - p.y
53608          }, p);
53609          self.x -= p.x - m2.e;
53610          self.y -= p.y - m2.f;
53611          render(true);
53612          recordStartPositions();
53613        }
53614
53615        var x = self.x,
53616            y = self.y;
53617        updateMatrix(!sticky);
53618
53619        if (applyBounds) {
53620          self.applyBounds();
53621        } else {
53622          dirty && ignoreExternalChanges && render(true);
53623          syncXY(true);
53624        }
53625
53626        if (sticky) {
53627          setPointerPosition(self.pointerX, self.pointerY);
53628          dirty && render(true);
53629        }
53630
53631        if (self.isPressed && !sticky && (allowX && Math.abs(x - self.x) > 0.01 || allowY && Math.abs(y - self.y) > 0.01 && !rotationMode)) {
53632          recordStartPositions();
53633        }
53634
53635        if (self.autoScroll) {
53636          _recordMaxScrolls(target.parentNode, self.isDragging);
53637
53638          checkAutoScrollBounds = self.isDragging;
53639          render(true);
53640
53641          _removeScrollListener(target, updateScroll);
53642
53643          _addScrollListener(target, updateScroll);
53644        }
53645
53646        return self;
53647      };
53648
53649      _this2.enable = function (type) {
53650        var setVars = {
53651          lazy: true
53652        },
53653            id,
53654            i,
53655            trigger;
53656
53657        if (vars.cursor !== false) {
53658          setVars.cursor = vars.cursor || _defaultCursor;
53659        }
53660
53661        if (gsap.utils.checkPrefix("touchCallout")) {
53662          setVars.touchCallout = "none";
53663        }
53664
53665        if (type !== "soft") {
53666          _setTouchActionForAllDescendants(triggers, allowX === allowY ? "none" : vars.allowNativeTouchScrolling && target.scrollHeight === target.clientHeight === (target.scrollWidth === target.clientHeight) || vars.allowEventDefault ? "manipulation" : allowX ? "pan-y" : "pan-x");
53667
53668          i = triggers.length;
53669
53670          while (--i > -1) {
53671            trigger = triggers[i];
53672            _supportsPointer || _addListener(trigger, "mousedown", onPress);
53673
53674            _addListener(trigger, "touchstart", onPress);
53675
53676            _addListener(trigger, "click", onClick, true);
53677
53678            gsap.set(trigger, setVars);
53679
53680            if (trigger.getBBox && trigger.ownerSVGElement && allowX !== allowY) {
53681              gsap.set(trigger.ownerSVGElement, {
53682                touchAction: vars.allowNativeTouchScrolling || vars.allowEventDefault ? "manipulation" : allowX ? "pan-y" : "pan-x"
53683              });
53684            }
53685
53686            vars.allowContextMenu || _addListener(trigger, "contextmenu", onContextMenu);
53687          }
53688
53689          _setSelectable(triggers, false);
53690        }
53691
53692        _addScrollListener(target, updateScroll);
53693
53694        enabled = true;
53695
53696        if (InertiaPlugin && type !== "soft") {
53697          InertiaPlugin.track(scrollProxy || target, xyMode ? "x,y" : rotationMode ? "rotation" : "top,left");
53698        }
53699
53700        target._gsDragID = id =
vendor: 5,466 bytes, lines 53700-53906
53700 "d" + _lookupCount++;
53701        _lookup[id] = self;
53702
53703        if (scrollProxy) {
53704          scrollProxy.enable();
53705          scrollProxy.element._gsDragID = id;
53706        }
53707
53708        (vars.bounds || rotationMode) && recordStartPositions();
53709        vars.bounds && self.applyBounds();
53710        return self;
53711      };
53712
53713      _this2.disable = function (type) {
53714        var dragging = self.isDragging,
53715            i = triggers.length,
53716            trigger;
53717
53718        while (--i > -1) {
53719          _setStyle(triggers[i], "cursor", null);
53720        }
53721
53722        if (type !== "soft") {
53723          _setTouchActionForAllDescendants(triggers, null);
53724
53725          i = triggers.length;
53726
53727          while (--i > -1) {
53728            trigger = triggers[i];
53729
53730            _setStyle(trigger, "touchCallout", null);
53731
53732            _removeListener(trigger, "mousedown", onPress);
53733
53734            _removeListener(trigger, "touchstart", onPress);
53735
53736            _removeListener(trigger, "click", onClick, true);
53737
53738            _removeListener(trigger, "contextmenu", onContextMenu);
53739          }
53740
53741          _setSelectable(triggers, true);
53742
53743          if (touchEventTarget) {
53744            _removeListener(touchEventTarget, "touchcancel", onRelease);
53745
53746            _removeListener(touchEventTarget, "touchend", onRelease);
53747
53748            _removeListener(touchEventTarget, "touchmove", onMove);
53749          }
53750
53751          _removeListener(ownerDoc, "mouseup", onRelease);
53752
53753          _removeListener(ownerDoc, "mousemove", onMove);
53754        }
53755
53756        _removeScrollListener(target, updateScroll);
53757
53758        enabled = false;
53759
53760        if (InertiaPlugin && type !== "soft") {
53761          InertiaPlugin.untrack(scrollProxy || target, xyMode ? "x,y" : rotationMode ? "rotation" : "top,left");
53762          self.tween && self.tween.kill();
53763        }
53764
53765        scrollProxy && scrollProxy.disable();
53766
53767        _removeFromRenderQueue(render);
53768
53769        self.isDragging = self.isPressed = isClicking = false;
53770        dragging && _dispatchEvent(self, "dragend", "onDragEnd");
53771        return self;
53772      };
53773
53774      _this2.enabled = function (value, type) {
53775        return arguments.length ? value ? self.enable(type) : self.disable(type) : enabled;
53776      };
53777
53778      _this2.kill = function () {
53779        self.isThrowing = false;
53780        self.tween && self.tween.kill();
53781        self.disable();
53782        gsap.set(triggers, {
53783          clearProps: "userSelect"
53784        });
53785        delete _lookup[target._gsDragID];
53786        return self;
53787      };
53788
53789      _this2.revert = function () {
53790        this.kill();
53791        this.styles && this.styles.revert();
53792      };
53793
53794      if (~type.indexOf("scroll")) {
53795        scrollProxy = _this2.scrollProxy = new ScrollProxy(target, _extend({
53796          onKill: function onKill() {
53797            self.isPressed && onRelease(null);
53798          }
53799        }, vars));
53800        target.style.overflowY = allowY && !_isTouchDevice ? "auto" : "hidden";
53801        target.style.overflowX = allowX && !_isTouchDevice ? "auto" : "hidden";
53802        target = scrollProxy.content;
53803      }
53804
53805      if (rotationMode) {
53806        killProps.rotation = 1;
53807      } else {
53808        if (allowX) {
53809          killProps[xProp] = 1;
53810        }
53811
53812        if (allowY) {
53813          killProps[yProp] = 1;
53814        }
53815      }
53816
53817      gsCache.force3D = "force3D" in vars ? vars.force3D : true;
53818
53819      _context(_assertThisInitialized(_this2));
53820
53821      _this2.enable();
53822
53823      return _this2;
53824    }
53825
53826    Draggable.register = function register(core) {
53827      gsap = core;
53828
53829      _initCore();
53830    };
53831
53832    Draggable.create = function create(targets, vars) {
53833      _coreInitted || _initCore(true);
53834      return _toArray(targets).map(function (target) {
53835        return new Draggable(target, vars);
53836      });
53837    };
53838
53839    Draggable.get = function get(target) {
53840      return _lookup[(_toArray(target)[0] || {})._gsDragID];
53841    };
53842
53843    Draggable.timeSinceDrag = function timeSinceDrag() {
53844      return (_getTime() - _lastDragTime) / 1000;
53845    };
53846
53847    Draggable.hitTest = function hitTest(obj1, obj2, threshold) {
53848      if (obj1 === obj2) {
53849        return false;
53850      }
53851
53852      var r1 = _parseRect(obj1),
53853          r2 = _parseRect(obj2),
53854          top = r1.top,
53855          left = r1.left,
53856          right = r1.right,
53857          bottom = r1.bottom,
53858          width = r1.width,
53859          height = r1.height,
53860          isOutside = r2.left > right || r2.right < left || r2.top > bottom || r2.bottom < top,
53861          overlap,
53862          area,
53863          isRatio;
53864
53865      if (isOutside || !threshold) {
53866        return !isOutside;
53867      }
53868
53869      isRatio = (threshold + "").indexOf("%") !== -1;
53870      threshold = parseFloat(threshold) || 0;
53871      overlap = {
53872        left: Math.max(left, r2.left),
53873        top: Math.max(top, r2.top)
53874      };
53875      overlap.width = Math.min(right, r2.right) - overlap.left;
53876      overlap.height = Math.min(bottom, r2.bottom) - overlap.top;
53877
53878      if (overlap.width < 0 || overlap.height < 0) {
53879        return false;
53880      }
53881
53882      if (isRatio) {
53883        threshold *= 0.01;
53884        area = overlap.width * overlap.height;
53885        return area >= width * height * threshold || area >= r2.width * r2.height * threshold;
53886      }
53887
53888      return overlap.width > threshold && overlap.height > threshold;
53889    };
53890
53891    return Draggable;
53892  }(EventDispatcher);
53893
53894  _setDefaults(Draggable.prototype, {
53895    pointerX: 0,
53896    pointerY: 0,
53897    startX: 0,
53898    startY: 0,
53899    deltaX: 0,
53900    deltaY: 0,
53901    isDragging: false,
53902    isPressed: false
53903  });
53904
53905  Draggable.zIndex = 1000;
53906  Draggable.version = "3.1
vendor: 15,817 bytes, lines 53906-54449
539062.5";
53907  _getGSAP() && gsap.registerPlugin(Draggable);
53908
53909  exports.Draggable = Draggable;
53910  exports.default = Draggable;
53911
53912  if (typeof(window) === 'undefined' || window !== exports) {Object.defineProperty(exports, '__esModule', { value: true });} else {delete window.default;}
53913
53914})));
53915/* ========================================================================
53916 * Bootstrap: collapse.js v3.1.1
53917 * http://getbootstrap.com/javascript/#collapse
53918 * ========================================================================
53919 * Copyright 2011-2014 Twitter, Inc.
53920 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
53921 * ======================================================================== */
53922
53923
53924+function ($) {
53925	'use strict';
53926
53927	// COLLAPSE PUBLIC CLASS DEFINITION
53928	// ================================
53929
53930	var Collapse = function (element, options) {
53931		this.$element      = $(element)
53932		this.options       = $.extend({}, Collapse.DEFAULTS, options)
53933		this.transitioning = null
53934
53935		if (this.options.parent) this.$parent = $(this.options.parent)
53936		if (this.options.toggle) this.toggle()
53937	}
53938
53939	Collapse.DEFAULTS = {
53940		toggle: true
53941	}
53942
53943	Collapse.prototype.dimension = function () {
53944		var hasWidth = this.$element.hasClass('width')
53945		return hasWidth ? 'width' : 'height'
53946	}
53947
53948	Collapse.prototype.show = function () {
53949		if (this.transitioning || this.$element.hasClass('in')) return
53950
53951		var startEvent = $.Event('show.bs.collapse')
53952		this.$element.trigger(startEvent)
53953		if (startEvent.isDefaultPrevented()) return
53954
53955		var actives = this.$parent && this.$parent.find('> .panel > .in')
53956
53957		if (actives && actives.length) {
53958			var hasData = actives.data('bs.collapse')
53959			if (hasData && hasData.transitioning) return
53960			//START UNCODE EDIT
53961			var parentNoToggle = this.$parent.data('no-toggle')
53962			if (!parentNoToggle) {
53963				actives.collapse('hide')
53964			}
53965			//END UNCODE EDIT
53966			hasData || actives.data('bs.collapse', null)
53967		}
53968
53969		var dimension = this.dimension()
53970
53971		this.$element
53972			.removeClass('collapse')
53973			.addClass('collapsing')[dimension](0)
53974
53975		this.transitioning = 1
53976
53977		var complete = function (e) {
53978			if (e && e.target != this.$element[0]) return
53979			this.$element
53980				.removeClass('collapsing')
53981				.addClass('collapse in')[dimension]('auto')
53982			this.transitioning = 0
53983			this.$element.trigger('shown.bs.collapse')
53984		}
53985
53986		if (!$.support.transition) return complete.call(this)
53987
53988		var scrollSize = $.camelCase(['scroll', dimension].join('-'))
53989
53990		this.$element
53991			.one($.support.transition.end, $.proxy(complete, this))
53992			.emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize])
53993	}
53994
53995	Collapse.prototype.hide = function () {
53996		if (this.transitioning || !this.$element.hasClass('in')) return
53997
53998		var startEvent = $.Event('hide.bs.collapse')
53999		this.$element.trigger(startEvent)
54000		if (startEvent.isDefaultPrevented()) return
54001
54002		var dimension = this.dimension()
54003
54004		this.$element[dimension](this.$element[dimension]())[0].offsetHeight
54005
54006		this.$element
54007			.addClass('collapsing')
54008			.removeClass('collapse')
54009			.removeClass('in')
54010
54011		this.transitioning = 1
54012
54013		var complete = function (e) {
54014			if (e && e.target != this.$element[0]) return
54015			this.transitioning = 0
54016			this.$element
54017				.trigger('hidden.bs.collapse')
54018				.removeClass('collapsing')
54019				.addClass('collapse')
54020		}
54021
54022		if (!$.support.transition) return complete.call(this)
54023
54024		this.$element
54025			[dimension](0)
54026			.one($.support.transition.end, $.proxy(complete, this))
54027			.emulateTransitionEnd(350)
54028	}
54029
54030	Collapse.prototype.toggle = function () {
54031		this[this.$element.hasClass('in') ? 'hide' : 'show']()
54032	}
54033
54034
54035	// COLLAPSE PLUGIN DEFINITION
54036	// ==========================
54037
54038	var old = $.fn.collapse
54039
54040	$.fn.collapse = function (option) {
54041		return this.each(function () {
54042			var $this   = $(this)
54043			var data    = $this.data('bs.collapse')
54044			var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
54045
54046			if (!data && options.toggle && option == 'show') option = !option
54047			if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
54048			if (typeof option == 'string') data[option]()
54049		})
54050	}
54051
54052	$.fn.collapse.Constructor = Collapse
54053
54054
54055	// COLLAPSE NO CONFLICT
54056	// ====================
54057
54058	$.fn.collapse.noConflict = function () {
54059		$.fn.collapse = old
54060		return this
54061	}
54062
54063
54064	// COLLAPSE DATA-API
54065	// =================
54066
54067	$(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
54068		var $this   = $(this), href
54069		var target  = $this.attr('data-target')
54070				|| e.preventDefault()
54071				|| (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
54072		//Edited by Uncode to replace ID in panel [START]
54073		var _target = href.replace(/^#/, "");
54074		if ( $('[data-id="' + _target + '"]').length ) {
54075			var $target = $('[data-id="' + _target + '"]')
54076		} else {
54077			var $target = $(target)
54078		}
54079		//Edited by Uncode to replace ID in panel [END]
54080		var data    = $target.data('bs.collapse')
54081		var option  = data ? 'toggle' : $this.data()
54082		var parent  = $this.attr('data-parent')
54083		var $parent = parent && $(parent)
54084
54085		if (!data || !data.transitioning) {
54086			if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed')
54087			$this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
54088		}
54089
54090		$target.collapse(option)
54091	})
54092
54093}(jQuery);
54094
54095/* ========================================================================
54096 * Bootstrap: tab.js v3.1.1
54097 * http://getbootstrap.com/javascript/#tabs
54098 * ========================================================================
54099 * Copyright 2011-2014 Twitter, Inc.
54100 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
54101 * ======================================================================== */
54102
54103
54104+function ($) {
54105  'use strict';
54106
54107  // TAB CLASS DEFINITION
54108  // ====================
54109
54110  var Tab = function (element) {
54111    this.element = $(element)
54112  }
54113
54114  Tab.prototype.show = function () {
54115    var $this    = this.element
54116    var $ul      = $this.closest('ul:not(.dropdown-menu)')
54117    var selector = $this.data('target')
54118
54119    if (!selector) {
54120      selector = $this.attr('href')
54121      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
54122    }
54123
54124    if ($this.parent('li').hasClass('active')) return
54125
54126    var previous = $ul.find('.active:last a')[0]
54127    var e        = $.Event('show.bs.tab', {
54128      relatedTarget: previous
54129    })
54130
54131    $this.trigger(e)
54132
54133    if (e.isDefaultPrevented()) return
54134
54135    //Edited by Uncode to replace ID in panel [START]
54136    var _target = selector.replace(/^#/, "");
54137    if ( $('[data-id="' + _target + '"]').length )
54138      var $target = $('[data-id="' + _target + '"]')
54139    else
54140      var $target = $(selector)
54141    //Edited by Uncode to replace ID in panel [END]
54142
54143    this.activate($this.parent('li'), $ul)
54144    this.activate($target, $target.parent(), function () {
54145      $this.trigger({
54146        type: 'shown.bs.tab',
54147        relatedTarget: previous
54148      })
54149    })
54150  }
54151
54152  Tab.prototype.activate = function (element, container, callback) {
54153    var $active    = container.find('> .active').add(container.find('> .active > .active'))
54154    var transition = callback
54155      && $.support.transition
54156      && $active.hasClass('fade')
54157
54158    function next() {
54159      $active
54160        .removeClass('active')
54161        .find('> .dropdown-menu > .active')
54162        .removeClass('active')
54163
54164      $active
54165        .find('.tab-excerpt').slideUp();
54166
54167      element.addClass('active')
54168      $('.tab-excerpt', element).slideDown();
54169
54170      //if (transition) {
54171        element[0].offsetWidth // reflow for transition
54172        element.add($active).addClass('in')
54173      /*} else {
54174        element.removeClass('fade')
54175      }*/
54176
54177      if (element.parents('.dropdown-menu').length) {
54178        element.closest('li.dropdown').addClass('active')
54179      }
54180
54181      if ( ! element.is('li') ) {
54182        element.closest('.tab-content').find('> .active').not(element).removeClass('active');
54183      }
54184
54185      callback && callback()
54186    }
54187
54188    transition ? 
54189      $active
54190        .one($.support.transition.end, next)
54191        .emulateTransitionEnd(150) :
54192      next()
54193
54194    $active.removeClass('in')
54195  }
54196
54197
54198  // TAB PLUGIN DEFINITION
54199  // =====================
54200
54201  var old = $.fn.tab
54202
54203  $.fn.tab = function ( option ) {
54204    return this.each(function () {
54205      var $this = $(this)
54206      var data  = $this.data('bs.tab')
54207
54208      if (!data) $this.data('bs.tab', (data = new Tab(this)))
54209      if (typeof option == 'string') data[option]()
54210    })
54211  }
54212
54213  $.fn.tab.Constructor = Tab
54214
54215
54216  // TAB NO CONFLICT
54217  // ===============
54218
54219  $.fn.tab.noConflict = function () {
54220    $.fn.tab = old
54221    return this
54222  }
54223
54224
54225  // TAB DATA-API
54226  // ============
54227
54228  $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
54229    e.preventDefault()
54230    $(this).tab('show')
54231  })
54232
54233}(jQuery);
54234
54235/* ========================================================================
54236 * Bootstrap: tooltip.js v3.1.1
54237 * http://getbootstrap.com/javascript/#tooltip
54238 * Inspired by the original jQuery.tipsy by Jason Frame
54239 * ========================================================================
54240 * Copyright 2011-2014 Twitter, Inc.
54241 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
54242 * ======================================================================== */
54243
54244
54245+function ($) {
54246  'use strict';
54247
54248  // TOOLTIP PUBLIC CLASS DEFINITION
54249  // ===============================
54250
54251  var Tooltip = function (element, options) {
54252    this.type       =
54253    this.options    =
54254    this.enabled    =
54255    this.timeout    =
54256    this.hoverState =
54257    this.$element   = null
54258
54259    this.init('tooltip', element, options)
54260  }
54261
54262  Tooltip.DEFAULTS = {
54263    animation: true,
54264    placement: 'top',
54265    selector: false,
54266    template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
54267    trigger: 'hover focus',
54268    title: '',
54269    delay: 0,
54270    html: false,
54271    container: false,
54272    viewport: {
54273      selector: 'body',
54274      padding: 0
54275    }
54276  }
54277
54278  Tooltip.prototype.init = function (type, element, options) {
54279    this.enabled   = true
54280    this.type      = type
54281    this.$element  = $(element)
54282    this.options   = this.getOptions(options)
54283    this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
54284
54285    var triggers = this.options.trigger.split(' ')
54286
54287    for (var i = triggers.length; i--;) {
54288      var trigger = triggers[i]
54289
54290      if (trigger == 'click') {
54291        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
54292      } else if (trigger != 'manual') {
54293        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin'
54294        var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
54295
54296        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
54297        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
54298      }
54299    }
54300
54301    this.options.selector ?
54302      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
54303      this.fixTitle()
54304  }
54305
54306  Tooltip.prototype.getDefaults = function () {
54307    return Tooltip.DEFAULTS
54308  }
54309
54310  Tooltip.prototype.getOptions = function (options) {
54311    options = $.extend({}, this.getDefaults(), this.$element.data(), options)
54312
54313    if (options.delay && typeof options.delay == 'number') {
54314      options.delay = {
54315        show: options.delay,
54316        hide: options.delay
54317      }
54318    }
54319
54320    return options
54321  }
54322
54323  Tooltip.prototype.getDelegateOptions = function () {
54324    var options  = {}
54325    var defaults = this.getDefaults()
54326
54327    this._options && $.each(this._options, function (key, value) {
54328      if (defaults[key] != value) options[key] = value
54329    })
54330
54331    return options
54332  }
54333
54334  Tooltip.prototype.enter = function (obj) {
54335    var self = obj instanceof this.constructor ?
54336      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
54337
54338    clearTimeout(self.timeout)
54339
54340    self.hoverState = 'in'
54341
54342    if (!self.options.delay || !self.options.delay.show) return self.show()
54343
54344    self.timeout = setTimeout(function () {
54345      if (self.hoverState == 'in') self.show()
54346    }, self.options.delay.show)
54347  }
54348
54349  Tooltip.prototype.leave = function (obj) {
54350    var self = obj instanceof this.constructor ?
54351      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
54352
54353    clearTimeout(self.timeout)
54354
54355    self.hoverState = 'out'
54356
54357    if (!self.options.delay || !self.options.delay.hide) return self.hide()
54358
54359    self.timeout = setTimeout(function () {
54360      if (self.hoverState == 'out') self.hide()
54361    }, self.options.delay.hide)
54362  }
54363
54364  Tooltip.prototype.show = function () {
54365    var e = $.Event('show.bs.' + this.type)
54366
54367    if (this.hasContent() && this.enabled) {
54368      this.$element.trigger(e)
54369
54370      if (e.isDefaultPrevented()) return
54371      var that = this;
54372
54373      var $tip = this.tip()
54374
54375      this.setContent()
54376
54377      if (this.options.animation) $tip.addClass('fade')
54378
54379      var placement = typeof this.options.placement == 'function' ?
54380        this.options.placement.call(this, $tip[0], this.$element[0]) :
54381        this.options.placement
54382
54383      var autoToken = /\s?auto?\s?/i
54384      var autoPlace = autoToken.test(placement)
54385      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
54386
54387      $tip
54388        .detach()
54389        .css({ top: 0, left: 0, display: 'block' })
54390        .addClass(placement)
54391
54392      this.options.container ? $tip.appendTo($(document).find(this.options.container)) : $tip.insertAfter(this.$element)
54393
54394      var pos          = this.getPosition()
54395      var actualWidth  = $tip[0].offsetWidth
54396      var actualHeight = $tip[0].offsetHeight
54397
54398      if (autoPlace) {
54399        var orgPlacement = placement
54400        var $parent      = this.$element.parent()
54401        var parentDim    = this.getPosition($parent)
54402
54403        placement = placement == 'bottom' && pos.top   + pos.height       + actualHeight - parentDim.scroll > parentDim.height ? 'top'    :
54404                    placement == 'top'    && pos.top   - parentDim.scroll - actualHeight < 0                                   ? 'bottom' :
54405                    placement == 'right'  && pos.right + actualWidth      > parentDim.width                                    ? 'left'   :
54406                    placement == 'left'   && pos.left  - actualWidth      < parentDim.left                                     ? 'right'  :
54407                    placement
54408
54409        $tip
54410          .removeClass(orgPlacement)
54411          .addClass(placement)
54412      }
54413
54414      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
54415
54416      this.applyPlacement(calculatedOffset, placement)
54417      this.hoverState = null
54418
54419      var complete = function() {
54420        that.$element.trigger('shown.bs.' + that.type)
54421      }
54422
54423      $.support.transition && this.$tip.hasClass('fade') ?
54424        $tip
54425          .one($.support.transition.end, complete)
54426          .emulateTransitionEnd(150) :
54427        complete()
54428    }
54429  }
54430
54431  Tooltip.prototype.applyPlacement = function (offset, placement) {
54432    var $tip   = this.tip()
54433    var width  = $tip[0].offsetWidth
54434    var height = $tip[0].offsetHeight
54435
54436    // manually read margins because getBoundingClientRect includes difference
54437    var marginTop = parseInt($tip.css('margin-top'), 10)
54438    var marginLeft = parseInt($tip.css('margin-left'), 10)
54439
54440    // we must check for NaN for ie 8/9
54441    if (isNaN(marginTop))  marginTop  = 0
54442    if (isNaN(marginLeft)) marginLeft = 0
54443
54444    offset.top  = offset.top  + marginTop
54445    offset.left = offset.left + marginLeft
54446
54447    // $.fn.offset doesn't round pixel values
54448    // so we use setOffset directly with our own function B-0
54449    $.offset.setOffset($tip[
544490], $.extend({
54450      using: function (props) {
54451        $tip.css({
54452          top: Math.round(props.top),
54453          left: Math.round(props.left)
54454        })
54455      }
54456    }, offset), 0)
54457
54458    $tip.addClass('in')
54459
54460    // check to see if placing tip in new offset caused the tip to resize itself
54461    var actualWidth  = $tip[0].offsetWidth
54462    var actualHeight = $tip[0].offsetHeight
54463
54464    if (placement == 'top' && actualHeight != height) {
54465      offset.top = offset.top + height - actualHeight
54466    }
54467
54468    var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
54469
54470    if (delta.left) offset.left += delta.left
54471    else offset.top += delta.top
54472
54473    var arrowDelta          = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
54474    var arrowPosition       = delta.left ? 'left'        : 'top'
54475    var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight'
54476
54477    $tip.offset(offset)
54478    this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition)
54479  }
54480
54481  Tooltip.prototype.replaceArrow = function (delta, dimension, position) {
54482    this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '')
54483  }
54484
54485  Tooltip.prototype.setContent = function () {
54486    var $tip  = this.tip()
54487    var title = this.getTitle()
54488
54489    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
54490    $tip.removeClass('fade in top bottom left right')
54491  }
54492
54493  Tooltip.prototype.hide = function () {
54494    var that = this
54495    var $tip = this.tip()
54496    var e    = $.Event('hide.bs.' + this.type)
54497
54498    function complete() {
54499      if (that.hoverState != 'in') $tip.detach()
54500      that.$element.trigger('hidden.bs.' + that.type)
54501    }
54502
54503    this.$element.trigger(e)
54504
54505    if (e.isDefaultPrevented()) return
54506
54507    $tip.removeClass('in')
54508
54509    $.support.transition && this.$tip.hasClass('fade') ?
54510      $tip
54511        .one($.support.transition.end, complete)
54512        .emulateTransitionEnd(150) :
54513      complete()
54514
54515    this.hoverState = null
54516
54517    return this
54518  }
54519
54520  Tooltip.prototype.fixTitle = function () {
54521    var $e = this.$element
54522    if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
54523      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
54524    }
54525  }
54526
54527  Tooltip.prototype.hasContent = function () {
54528    return this.getTitle()
54529  }
54530
54531  Tooltip.prototype.getPosition = function ($element) {
54532    $element   = $element || this.$element
54533    var el     = $element[0]
54534    var isBody = el.tagName == 'BODY'
54535    return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, {
54536      scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(),
54537      width:  isBody ? $(window).width()  : $element.outerWidth(),
54538      height: isBody ? $(window).height() : $element.outerHeight()
54539    }, isBody ? {top: 0, left: 0} : $element.offset())
54540  }
54541
54542  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
54543    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2  } :
54544           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2  } :
54545           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
54546        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width   }
54547
54548  }
54549
54550  Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
54551    var delta = { top: 0, left: 0 }
54552    if (!this.$viewport) return delta
54553
54554    var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
54555    var viewportDimensions = this.getPosition(this.$viewport)
54556
54557    if (/right|left/.test(placement)) {
54558      var topEdgeOffset    = pos.top - viewportPadding - viewportDimensions.scroll
54559      var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
54560      if (topEdgeOffset < viewportDimensions.top) { // top overflow
54561        delta.top = viewportDimensions.top - topEdgeOffset
54562      } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
54563        delta.top = viewportDimensions.top + viewportDimensions.height - bottom
54563EdgeOffset
54564      }
54565    } else {
54566      var leftEdgeOffset  = pos.left - viewportPadding
54567      var rightEdgeOffset = pos.left + viewportPadding + actualWidth
54568      if (leftEdgeOffset < viewportDimensions.left) { // left overflow
54569        delta.left = viewportDimensions.left - leftEdgeOffset
54570      } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
54571        delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
54572      }
54573    }
54574
54575    return delta
54576  }
54577
54578  Tooltip.prototype.getTitle = function () {
54579    var title
54580    var $e = this.$element
54581    var o  = this.options
54582
54583    title = $e.attr('data-original-title')
54584      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
54585
54586    return title
54587  }
54588
54589  Tooltip.prototype.tip = function () {
54590    return this.$tip = this.$tip || $(this.options.template)
54591  }
54592
54593  Tooltip.prototype.arrow = function () {
54594    return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')
54595  }
54596
54597  Tooltip.prototype.validate = function () {
54598    if (!this.$element[0].parentNode) {
54599      this.hide()
54600      this.$element = null
54601      this.options  = null
54602    }
54603  }
54604
54605  Tooltip.prototype.enable = function () {
54606    this.enabled = true
54607  }
54608
54609  Tooltip.prototype.disable = function () {
54610    this.enabled = false
54611  }
54612
54613  Tooltip.prototype.toggleEnabled = function () {
54614    this.enabled = !this.enabled
54615  }
54616
54617  Tooltip.prototype.toggle = function (e) {
54618    var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this
54619    self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
54620  }
54621
54622  Tooltip.prototype.destroy = function () {
54623    clearTimeout(this.timeout)
54624    this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
54625  }
54626
54627
54628  // TOOLTIP PLUGIN DEFINITION
54629  // =========================
54630
54631  var old = $.fn.tooltip
54632
54633  $.fn.tooltip = function (option) {
54634    return this.each(function () {
54635      var $this   = $(this)
54636      var data    = $this.data('bs.tooltip')
54637      var options = typeof option == 'object' && option
54638
54639      if (!data && option == 'destroy') return
54640      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
54641      if (typeof option == 'string') data[option]()
54642    })
54643  }
54644
54645  $.fn.tooltip.Constructor = Tooltip
54646
54647
54648  // TOOLTIP NO CONFLICT
54649  // ===================
54650
54651  $.fn.tooltip.noConflict = function () {
54652    $.fn.tooltip = old
54653    return this
54654  }
54655
54656}(jQuery);
54657
54658/* ========================================================================
54659 * Bootstrap: transition.js v3.1.1
54660 * http://getbootstrap.com/javascript/#transitions
54661 * ========================================================================
54662 * Copyright 2011-2014 Twitter, Inc.
54663 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
54664 * ======================================================================== */
54665
54666
54667+function ($) {
54668  'use strict';
54669
54670  // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
54671  // ============================================================
54672
54673  function transitionEnd() {
54674    var el = document.createElement('bootstrap')
54675
54676    var transEndEventNames = {
54677      WebkitTransition : 'webkitTransitionEnd',
54678      MozTransition    : 'transitionend',
54679      OTransition      : 'oTransitionEnd otransitionend',
54680      transition       : 'transitionend'
54681    }
54682
54683    for (var name in transEndEventNames) {
54684      if (el.style[name] !== undefined) {
54685        return { end: transEndEventNames[name] }
54686      }
54687    }
54688
54689    return false // explicit for ie8 (  ._.)
54690  }
54691
54692  // http://blog.alexmaccaw.com/css-transitions
54693  $.fn.emulateTransitionEnd = function (duration) {
54694    var called = false, $el = this
54695    $(this).one($.support.transition.end, function () { called = true })
54696    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
54697    setTimeout(callback, duration)
54698    return this
54699  }
54700
54701  $(function () {
54702    $.support.transition = transitionEnd()
54703  })
54704
54705}(jQuery);
54706
54707
54708// ------------------------------------------
54709// Rellax.js
54710// Buttery smooth parallax library
54711// Copyright (c) 2016 Moe Amaya (@moeamaya)
54712// MIT license
54713//
54714// Thanks to Paraxify.js and Jaime Cabllero
54715// for parallax concepts
54716// ------------------------------------------
54717
54718(function (root, factory) {
54719	if (typeof define === 'function' && define.amd) {
54720		// AMD. Register as an anonymous module.
54721		define([], factory);
54722	} else if (typeof module === 'object' && module.exports) {
54723		// Node. Does not work with strict CommonJS, but
54724		// only CommonJS-like environments that support module.exports,
54725		// like Node.
54726		module.exports = factory();
54727	} else {
54728		// Browser globals (root is window)
54729		root.Rellax = factory();
54730	}
54731}(typeof window !== "undefined" ? window : global, function () {
54732	var Rellax = function(el, options){
54733		"use strict";
54734
54735		var self = Object.create(Rellax.prototype);
54736
54737		var posY = 0;
54738		var screenY = 0;
54739		var posX = 0;
54740		var screenX = 0;
54741		var blocks = [];
54742		var pause = true;
54743
54744		// check what requestAnimationFrame to use, and if
54745		// it's not supported, use the onscroll event
54746		var loop = window.requestAnimationFrame ||
54747			window.webkitRequestAnimationFrame ||
54748			window.mozRequestAnimationFrame ||
54749			window.msRequestAnimationFrame ||
54750			window.oRequestAnimationFrame ||
54751			function(callback){ return setTimeout(callback, 1000 / 60); };
54752
54753		// store the id for later use
54754		var loopId = null;
54755
54756		// Test via a getter in the options object to see if the passive property is accessed
54757		var supportsPassive = false;
vendor: 10,724 bytes, lines 54758-55059
54758		try {
54759			var opts = Object.defineProperty({}, 'passive', {
54760				get: function() {
54761					supportsPassive = true;
54762				}
54763			});
54764			window.addEventListener("testPassive", null, opts);
54765			window.removeEventListener("testPassive", null, opts);
54766		} catch (e) {}
54767
54768		// check what cancelAnimation method to use
54769		var clearLoop = window.cancelAnimationFrame || window.mozCancelAnimationFrame || clearTimeout;
54770
54771		// check which transform property to use
54772		var transformProp = window.transformProp || (function(){
54773				var testEl = document.createElement('div');
54774				if (testEl.style.transform === null) {
54775					var vendors = ['Webkit', 'Moz', 'ms'];
54776					for (var vendor in vendors) {
54777						if (testEl.style[ vendors[vendor] + 'Transform' ] !== undefined) {
54778							return vendors[vendor] + 'Transform';
54779						}
54780					}
54781				}
54782				return 'transform';
54783			})();
54784
54785		// Default Settings
54786		self.options = {
54787			speed: -2,
54788			verticalSpeed: null,
54789			horizontalSpeed: null,
54790			breakpoints: [576, 768, 1201],
54791			center: false,
54792			wrapper: null,
54793			relativeToWrapper: false,
54794			round: true,
54795			vertical: true,
54796			horizontal: false,
54797			verticalScrollAxis: "y",
54798			horizontalScrollAxis: "x",
54799			callback: function() {},
54800		};
54801
54802		// User defined options (might have more in the future)
54803		if (options){
54804			Object.keys(options).forEach(function(key){
54805				self.options[key] = options[key];
54806			});
54807		}
54808
54809		function validateCustomBreakpoints () {
54810			if (self.options.breakpoints.length === 3 && Array.isArray(self.options.breakpoints)) {
54811				var isAscending = true;
54812				var isNumerical = true;
54813				var lastVal;
54814				self.options.breakpoints.forEach(function (i) {
54815					if (typeof i !== 'number') isNumerical = false;
54816					if (lastVal !== null) {
54817						if (i < lastVal) isAscending = false;
54818					}
54819					lastVal = i;
54820				});
54821				if (isAscending && isNumerical) return;
54822			}
54823			// revert defaults if set incorrectly
54824			self.options.breakpoints = [576, 768, 1201];
54825			console.warn("Rellax: You must pass an array of 3 numbers in ascending order to the breakpoints option. Defaults reverted");
54826		}
54827
54828		if (options && options.breakpoints) {
54829			validateCustomBreakpoints();
54830		}
54831
54832		// By default, rellax class
54833		if (!el) {
54834			el = '.rellax';
54835		}
54836
54837		// check if el is a className or a node
54838		var elements = typeof el === 'string' ? document.querySelectorAll(el) : [el];
54839
54840		// Now query selector
54841		if (elements.length > 0) {
54842			self.elems = elements;
54843		}
54844
54845		// The elements don't exist
54846		else {
54847			console.warn("Rellax: The elements you're trying to select don't exist.");
54848			return;
54849		}
54850
54851		// Has a wrapper and it exists
54852		if (self.options.wrapper) {
54853			if (!self.options.wrapper.nodeType) {
54854				var wrapper = document.querySelector(self.options.wrapper);
54855
54856				if (wrapper) {
54857					self.options.wrapper = wrapper;
54858				} else {
54859					console.warn("Rellax: The wrapper you're trying to use doesn't exist.");
54860					return;
54861				}
54862			}
54863		}
54864
54865		// set a placeholder for the current breakpoint
54866		var currentBreakpoint;
54867
54868		// helper to determine current breakpoint
54869		var getCurrentBreakpoint = function (w) {
54870			var bp = self.options.breakpoints;
54871			if (w < bp[0]) return 'xs';
54872			if (w >= bp[0] && w < bp[1]) return 'sm';
54873			if (w >= bp[1] && w < bp[2]) return 'md';
54874			return 'lg';
54875		};
54876
54877		// Get and cache initial position of all elements
54878		var cacheBlocks = function() {
54879			for (var i = 0; i < self.elems.length; i++){
54880				var block = createBlock(self.elems[i]);
54881				blocks.push(block);
54882			}
54883		};
54884
54885
54886		// Let's kick this script off
54887		// Build array for cached element values
54888		var init = function() {
54889			for (var i = 0; i < blocks.length; i++){
54890				self.elems[i].style.cssText = blocks[i].style;
54891			}
54892
54893			blocks = [];
54894
54895			screenY = window.innerHeight;
54896			screenX = window.innerWidth;
54897			currentBreakpoint = getCurrentBreakpoint(screenX);
54898
54899			setPosition();
54900
54901			cacheBlocks();
54902
54903			animate();
54904
54905			// If paused, unpause and set listener for window resizing events
54906			if (pause) {
54907				window.addEventListener('resize', init);
54908				pause = false;
54909				// Start the loop
54910				update();
54911			}
54912		};
54913
54914		// We want to cache the parallax blocks'
54915		// values: base, top, height, speed
54916		// el: is dom object, return: el cache values
54917		var createBlock = function(el) {
54918			var dataPercentage = el.getAttribute( 'data-rellax-percentage' );
54919			var dataSpeed = el.getAttribute( 'data-rellax-speed' );
54920			var dataXsSpeed = el.getAttribute( 'data-rellax-xs-speed' );
54921			var dataMobileSpeed = el.getAttribute( 'data-rellax-mobile-speed' );
54922			var dataTabletSpeed = el.getAttribute( 'data-rellax-tablet-speed' );
54923			var dataDesktopSpeed = el.getAttribute( 'data-rellax-desktop-speed' );
54924			var dataVerticalSpeed = el.getAttribute('data-rellax-vertical-speed');
54925			var dataHorizontalSpeed = el.getAttribute('data-rellax-horizontal-speed');
54926			var dataVericalScrollAxis = el.getAttribute('data-rellax-vertical-scroll-axis');
54927			var dataHorizontalScrollAxis = el.getAttribute('data-rellax-horizontal-scroll-axis');
54928			var dataZindex = el.getAttribute( 'data-rellax-zindex' ) || 0;
54929			var dataMin = el.getAttribute( 'data-rellax-min' );
54930			var dataMax = el.getAttribute( 'data-rellax-max' );
54931			var dataMinX = el.getAttribute('data-rellax-min-x');
54932			var dataMaxX = el.getAttribute('data-rellax-max-x');
54933			var dataMinY = el.getAttribute('data-rellax-min-y');
54934			var dataMaxY = el.getAttribute('data-rellax-max-y');
54935			var mapBreakpoints;
54936			var breakpoints = true;
54937
54938			if (!dataXsSpeed && !dataMobileSpeed && !dataTabletSpeed && !dataDesktopSpeed) {
54939				breakpoints = false;
54940			} else {
54941				mapBreakpoints = {
54942					'xs': dataXsSpeed,
54943					'sm': dataMobileSpeed,
54944					'md': dataTabletSpeed,
54945					'lg': dataDesktopSpeed
54946				};
54947			}
54948
54949			// initializing at scrollY = 0 (top of browser), scrollX = 0 (left of browser)
54950			// ensures elements are positioned based on HTML layout.
54951			//
54952			// If the element has the percentage attribute, the posY and posX needs to be
54953			// the current scroll position's value, so that the elements are still positioned based on HTML layout
54954			var wrapperPosY = self.options.wrapper ? self.options.wrapper.scrollTop : (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
54955			// If the option relativeToWrapper is true, use the wrappers offset to top, subtracted from the current page scroll.
54956			if (self.options.relativeToWrapper) {
54957				var scrollPosY = (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
54958				wrapperPosY = scrollPosY - self.options.wrapper.offsetTop;
54959			}
54960			var posY = self.options.vertical ? ( dataPercentage || self.options.center ? wrapperPosY : 0 ) : 0;
54961			var posX = self.options.horizontal ? ( dataPercentage || self.options.center ? self.options.wrapper ? self.options.wrapper.scrollLeft : (window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft) : 0 ) : 0;
54962
54963			var blockTop = posY + el.getBoundingClientRect().top;
54964			var blockHeight = el.clientHeight || el.offsetHeight || el.scrollHeight;
54965
54966			var blockLeft = posX + el.getBoundingClientRect().left;
54967			var blockWidth = el.clientWidth || el.offsetWidth || el.scrollWidth;
54968
54969			// apparently parallax equation everyone uses
54970			var percentageY = dataPercentage ? dataPercentage : (posY - blockTop + screenY) / (blockHeight + screenY);
54971			var percentageX = dataPercentage ? dataPercentage : (posX - blockLeft + screenX) / (blockWidth + screenX);
54972			if(self.options.center){ percentageX = 0.5; percentageY = 0.5; }
54973
54974			// Optional individual block speed as data attr, otherwise global speed
54975			var speed = (breakpoints && mapBreakpoints[currentBreakpoint] !== null) ? Number(mapBreakpoints[currentBreakpoint]) : (dataSpeed ? dataSpeed : self.options.speed);
54976			var verticalSpeed = dataVerticalSpeed ? dataVerticalSpeed : self.options.verticalSpeed;
54977			var horizontalSpeed = dataHorizontalSpeed ? dataHorizontalSpeed : self.options.horizontalSpeed;
54978
54979			// Optional individual block movement axis direction as data attr, otherwise global movement direction
54980			var verticalScrollAxis = dataVericalScrollAxis ? dataVericalScrollAxis : self.options.verticalScrollAxis;
54981			var horizontalScrollAxis = dataHorizontalScrollAxis ? dataHorizontalScrollAxis : self.options.horizontalScrollAxis;
54982
54983			var bases = updatePosition(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed);
54984
54985			// ~~Store non-translate3d transforms~~
54986			// Store inline styles and extract transforms
54987			var style = el.style.cssText;
54988			var transform = '';
54989
54990			// Check if there's an inline styled transform
54991			var searchResult = /transform\s*:/i.exec(style);
54992			if (searchResult) {
54993				// Get the index of the transform
54994				var index = searchResult.index;
54995
54996				// Trim the style to the transform point and get the following semi-colon index
54997				var trimmedStyle = style.slice(index);
54998				var delimiter = trimmedStyle.indexOf(';');
54999
55000				// Remove "transform" string and save the attribute
55001				if (delimiter) {
55002					transform = " " + trimmedStyle.slice(11, delimiter).replace(/\s/g,'');
55003				} else {
55004					transform = " " + trimmedStyle.slice(11).replace(/\s/g,'');
55005				}
55006			}
55007
55008			return {
55009				baseX: bases.x,
55010				baseY: bases.y,
55011				top: blockTop,
55012				left: blockLeft,
55013				height: blockHeight,
55014				width: blockWidth,
55015				speed: speed,
55016				verticalSpeed: verticalSpeed,
55017				horizontalSpeed: horizontalSpeed,
55018				verticalScrollAxis: verticalScrollAxis,
55019				horizontalScrollAxis: horizontalScrollAxis,
55020				style: style,
55021				transform: transform,
55022				zindex: dataZindex,
55023				min: dataMin,
55024				max: dataMax,
55025				minX: dataMinX,
55026				maxX: dataMaxX,
55027				minY: dataMinY,
55028				maxY: dataMaxY
55029			};
55030		};
55031
55032		// set scroll position (posY, posX)
55033		// side effect method is not ideal, but okay for now
55034		// returns true if the scroll changed, false if nothing happened
55035		var setPosition = function() {
55036			var oldY = posY;
55037			var oldX = posX;
55038
55039			posY = self.options.wrapper ? self.options.wrapper.scrollTop : (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset;
55040			posX = self.options.wrapper ? self.options.wrapper.scrollLeft : (document.documentElement || document.body.parentNode || document.body).scrollLeft || window.pageXOffset;
55041			// If option relativeToWrapper is true, use relative wrapper value instead.
55042			if (self.options.relativeToWrapper) {
55043				var scrollPosY = (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset;
55044				posY = scrollPosY - self.options.wrapper.offsetTop;
55045			}
55046
55047
55048			if (oldY != posY && self.options.vertical) {
55049				// scroll changed, return true
55050				return true;
55051			}
55052
55053			if (oldX != posX && self.options.horizontal) {
55054				// scroll changed, return true
55055				return true;
55056			}
55057
55058			// scroll did not change
55059			return false;
55060		};
55061
55062		// Ahh a pure function, gets new transform value
55063		// based on scrollPosition and speed
55064		// Allow for decimal pixel values
55065		var updatePosition = function(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed) {
55066			var result = {};
55067			var valueX = ((horizontalSpeed ? horizontalSpeed : speed) * (100 * (1 - percentageX)));
55068			var valueY = ((verticalSpeed ? verticalSpeed : speed) * (100 * (1 - percentageY)));
55069
55070			result.x = self.options.round ? Math.round(valueX) : Math.round(valueX * 100) / 100;
55071			result.y = self.options.round ? Math.round(valueY) : Math.round(valueY * 100) / 100;
55072
55073			return result;
55074		};
55075
55076		// Remove event listeners and loop again
55077		var deferredUpdate = function() {
55078			window.removeEventListener('resize', deferredUpdate);
55079			window.removeEventListener('orientationchange', deferredUpdate);
55080			(self.options.wrapper ? self.options.wrapper : window).removeEventListener('scroll', deferredUpdate);
55081			(self.options.wrapper ? self.options.wrapper : document).removeEventListener('touchmove', deferredUpdate);
55082
55083			// loop again
55084			loopId = loop(update);
55085		};
55086
55087		// Loop
55088		var update = function() {
55089			if (setPosition() && pause === false) {
55090				animate();
55091
55092				// loop again
55093				loopId = loop(update);
55094			} else {
55095				loopId = null;
55096
55097				// Don't animate until we get a position updating event
55098				window.addEventListener('resize', deferredUpdate);
55099				window.addEventListener('orientationchange', deferredUpdate);
55100				(self.options.wrapper ? self.options.wrapper : window).addEventListener('scroll', deferredUpdate, supportsPassive ? { passive: true } : false);
55101				(self.options.wrapper ? self.options.wrapper : document).addEventListener('touchmove', deferredUpdate, supportsPassive ? { passive: true } : false);
55102			}
55103		};
55104
55105		// Transform3d on parallax element
55106		var animate = function() {
55107			var positions;
55108			for (var i = 0; i < self.elems.length; i++){
55109				// Determine relevant movement directions
55110				var verticalScrollAxis = blocks[i].verticalScrollAxis.toLowerCase();
55111				var horizontalScrollAxis = blocks[i].horizontalScrollAxis.toLowerCase();
55112				var verticalScrollX = verticalScrollAxis.indexOf("x") != -1 ? posY : 0;
55113				var verticalScrollY = verticalScrollAxis.indexOf("y") != -1 ? posY : 0;
55114				var horizontalScrollX = horizontalScrollAxis.indexOf("x") != -1 ? posX : 0;
55115				var horizontalScrollY = horizontalScrollAxis.indexOf("y") != -1 ? posX : 0;
55116
55117				var percentageY = ((verticalScrollY + horizontalScrollY - blocks[i].top + screenY) / (blocks[i].height + screenY));
55118				var percentageX = ((verticalScrollX + horizontalScrollX - blocks[i].left + screenX) / (blocks[i].width + screenX));
55119
55120				// Subtracting initialize value, so element stays in same spot as HTML
55121				positions = updatePosition(percentageX, percentageY, blocks[i].speed, blocks[i].verticalSpeed, blocks[i].horizontalSpeed);
55122				var positionY = positions.y - blocks[i].baseY;
55123				var positionX = positions.x - blocks[i].baseX;
55124
55125				// The next two "if" blocks go like this:
55126				// Check if a limit is defined (first "min", then "max");
55127				// Check if we need to change the Y or the X
55128				// (Currently working only if just one of the axes is enabled)
55129				// Then, check if the new position is inside the allowed limit
55130				// If so, use new position. If not, set position to limit.
55131
55132				// Check if a min limit is defined
55133				if (blocks[i].min !== null) {
55134					if (self.options.vertical && !self.options.horizontal) {
55135						positionY = positionY <= blocks[i].min ? blocks[i].min : positionY;
55136					}
55137					if (self.options.horizontal && !self.options.vertical) {
55138						positionX = positionX <= blocks[i].min ? blocks[i].min : positionX;
55139					}
55140				}
55141
55142				// Check if directional min limits are defined
55143				if (blocks[i].minY != null) {
55144						positionY = positionY <= blocks[i].minY ? blocks[i].minY : positionY;
55145				}
55146				if (blocks[i].minX != null) {
55147						positionX = positionX <= blocks[i].minX ? blocks[i].minX : positionX;
55148				}
55149
55150				// Check if a max limit is defined
55151				if (blocks[i].max !== null) {
55152					if (self.options.vertical && !self.options.horizontal) {
55153						positionY = positionY >= blocks[i].max ? blocks[i].max : positionY;
55154					}
55155					if (self.options.horizontal && !self.options.vertical) {
55156						positionX = positionX >= blocks[i].max ? blocks[i].max : positionX;
55157					}
55158				}
55159
55160				// Check if directional max limits are defined
55161				if (blocks[i].maxY != null) {
55162						positionY = positionY >= blocks[i].maxY ? blocks[i].maxY : positionY;
55163				}
55164				if (blocks[i].maxX != null) {
55165						positionX = positionX >= blocks[i].maxX ? blocks[i].maxX : positionX;
55166				}
55167
55168				var zindex = blocks[i].zindex;
55169
55170				// Move that element
55171				// (Set the new translation and append initial inline transforms.)
55172				var translate = 'translate3d(' + (self.options.horizontal ? positionX : '0') + 'px,' + (self.options.vertical ? positionY : '0') + 'px,' + zindex + 'px) ' + blocks[i].transform;
55173				self.elems[i].style[transformProp] = translate;
55174			}
55175			self.options.callback(positions);
55176		};
55177
55178		self.destroy = function() {
55179			for (var i = 0; i < self.elems.length; i++){
55180				self.elems[i].style.cssText = blocks[i].style;
55181			}
55182
55183			// Remove resize event listener if not pause, and pause
55184			if (!pause) {
55185				window.removeEventListener('resize', init);
55186				pause = true;
55187			}
55188
55189			// Clear the animation loop to prevent possible memory leak
55190			clearLoop(loopId);
55191			loopId = null;
55192		};
55193
55194		// Init
55195		init();
55196
55197		// Allow to recalculate the initial values whenever we want
55198		self.refresh = init;
55199
55200		return self;
55201	};
55202	return Rellax;
55203}));
55204
55205/*
55206 * OKVideo by OKFocus v2.3.2
55207 * http://okfoc.us
55208 *
55209 * Copyright 2014, OKFocus
55210 * Licensed under the MIT license.
55211 *
55212 */
55213var player, OKEvents, options, videoWidth, videoHeight, YTplayers, youtubePlayers = new Array();
55214// youtube player ready
55215function onYouTubeIframeAPIReady() {
55216	YTplayers = new Array();
55217	jQuery('.uncode-video-container.video').each(function() {
55218		var playerY;
55219		if (jQuery(this).attr('data-provider') == 'youtube') {
55220			var id = jQuery(this).attr('data-id'),
55221				start = jQuery(this).attr('data-start'),
55222				end = jQuery(this).attr('data-end');
55223			start = typeof start && start !== null ? start : 0;
55224			end = typeof end && end !== null ? end : 0;
55225			options = jQuery(window).data('okoptions-' + id);
55226			if ( typeof options === 'undefined' ) {
55227				return true;
55228			}
55229			options.time = jQuery(this).attr('data-t');
55230			playerY = new YT.Player('okplayer-' + id, {
55231				videoId: options.video ? options.video.id : null,
55232				playerVars: {
55233					'autohide': 1,
55234					'autoplay': jQuery(this).hasClass('is-no-control') ? options.autoplay : 0, //options.autoplay,
55235					'disablekb': 1,
55236					'cc_load_policy': options.captions,
55237					'controls': 0,
55238					'enablejsapi': 1,
55239					'fs': 0,
55240					'modestbranding': 1,
55241					'origin': window.location.origin || (window.location.protocol + '//' + window.location.hostname),
55242					'iv_load_policy': options.annotations,
55243					'loop': options.loop,
55244					'showinfo': 0,
55245					'rel': 0,
55246					'wmode': 'opaque',
55247					'hd': options.hd,
55248					'mute': 1,
55249					'start': start,
55250					'end': end
55251				},
55252				events: {
55253					'onReady': OKEvents.yt.ready,
55254					'onStateChange': OKEvents.yt.onStateChange,
55255					'onError': OKEvents.yt.error
55256				}
55257			});
55258			YTplayers[id] = playerY;
55259			playerY.videoId = id;
55260		}
55261
55262	});
55263}
55264// vimeo player ready
55265function vimeoPlayerReady(id) {
55266	options = jQuery(window).data('okoptions-' + id);
55267	if ( typeof options === 'undefined' ) {
55268		return true;
55269	}
55270	var jIframe = options.jobject,
55271		iframe = jIframe[0];
55272
55273	jIframe.attr('src', jIframe.data('src'));
55274	var playerV = new Vimeo.Player(iframe);
55275	// hide player until Vimeo hides controls...
55276	playerV.on('loaded', function(e) {
55277		OKEvents.v.onReady(iframe);
55278		var carouselContainer = jQuery(iframe).closest('.owl-carousel');
55279		if (carouselContainer.length) {
55280			UNCODE.owlPlayVideo(carouselContainer);
55281		}
55282		// "Do not try to add listeners or call functions before receiving this event."
55283		if (OKEvents.utils.isMobile()) {
55284			// mobile devices cannot listen for play event
55285			OKEvents.v.onPlay(playerV);
55286		} else {
55287			playerV.on('play', function(){
55288				OKEvents.v.onPlay(playerV);
55289				jQuery(window).trigger('okevents.v.play', [playerV]);
55290			});
55291			playerV.on('pause', function(){
55292				OKEvents.v.onPause;
55293				jQuery(window).trigger('okevents.v.pause', [playerV]);
55294			});
55295			playerV.on('ended', function(){
55296				OKEvents.v.onFinish
55297				jQuery(window).trigger('okevents.v.ended', [playerV]);
55298			});
55299		}
55300		if (options.time != null) {
55301			var optsTimeStr = (options.time).replace('t=', ''),
55302				timeV = '';
55303
55304			if ( /[a-zA-Z]/g.test(optsTimeStr) ) {
55305				var timeArr = optsTimeStr.split(/([^\d.-])/);
55306				for ( var i = 0; i < timeArr.length; i++ ) {
55307					if ( timeArr[i] === 'h' ) {
55308						timeV += parseFloat(timeArr[i-1]) * 3600;
55309					} else if ( timeArr[i] === 'm' ) {
55310						timeV += parseFloat(timeArr[i-1]) * 60;
55311					} else if ( timeArr[i] === 's' ) {
55312						timeV += parseFloat(timeArr[i-1]);
55313					}
55314				}
55315			} else {
55316				timeV = optsTimeStr;
55317			}
55318
55319			playerV.setCurrentTime(timeV);
55320		}
55321
55322		playerV.setVolume(0);
55323		playerV.play();
55324		jQuery(iframe).css({
55325			visibility: 'visible',
55326			opacity: 1
55327		});
55328		jQuery(iframe).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1');
55329		jQuery(iframe).closest('#page-header').addClass('video-started');
55330		jQuery(iframe).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1');
55331
55332		jQuery(window).trigger('okevents.v.loaded', [playerV]);
55333	});
55334}
55335OKEvents = {
55336	yt: {
55337		ready: function(event) {
55338			var id = event.target.videoId,
55339				$video = jQuery('#okplayer-' + id),
55340				options = jQuery(window).data('okoptions-' + id);
55341			if ( typeof options === 'undefined' ) {
55342				return true;
55343			}
55344			youtubePlayers[id] = event.target;
55345			event.target.setVolume(options.volume);
55346			if (options.autoplay === 1) {
55347				if (options.playlist.list) {
55348					player.loadPlaylist(options.playlist.list, options.playlist.index, options.playlist.startSeconds, options.playlist.suggestedQuality);
55349				} else {
55350					var inCarousel = $video.closest('.owl-item');
55351					if (!inCarousel.length || (inCarousel.length && inCarousel.hasClass('active'))) {
55352						if (options.time != null) {
55353							event.target.seekTo(parseInt(options.time));
55354						}
55355						event.target.playVideo();
55356					} else {
55357						event.target.pauseVideo();
55358					}
55359				}
55360			}
55361			OKEvents.utils.isFunction(options.onReady) && options.onReady(event.target);
55362
55363			$video.closest('[data-provider]').on('uncode-resume', function(){
55364				if (options.time != null) {
55365					event.target.seekTo(parseInt(options.time)).playVideo();
55366				} else {
55367					event.target.seekTo(0).playVideo();
55368				}
55369			});
55370
55371			$video.closest('[data-provider]').on('uncode-pause', function(){
55372				if (options.time != null) {
55373					event.target.seekTo(parseInt(options.time)).pauseVideo();
55374				} else {
55375					event.target.seekTo(0).pauseVideo();
55376				}
55377			});
55378			jQuery(window).trigger('okevents.y.loaded', [event]);
55379		},
55380		onStateChange: function(event) {
55381			var id = event.target.videoId,
55382				$video = jQuery('#okplayer-' + id),
55383				options = jQuery(window).data('okoptions-' + id);
55384			if ( typeof options === 'undefined' || typeof event.target.setVolume === 'undefined' ) {
55385				return true;
55386			}
55387			youtubePlayers[id] = event.target;
55388			event.target.setVolume(options.volume);
55389			var $fluid = $video.closest('.fluid-object'),
55390				$tmb = $video.closest('.tmb'),
55391				setTime;
55392			switch (event.data) {
55393				case -1:
55394					OKEvents.utils.isFunction(options.unstarted) && options.unstarted();
55395					break;
55396				case 0:
55397					OKEvents.utils.isFunction(options.onFinished) && options.onFinished();
55398					options.loop && event.target.playVideo();
55399					break;
55400				case 1:
55401					OKEvents.utils.isFunction(options.onPlay) && options.onPlay();
55402					setTimeout(function() {
55403						UNCODE.initVideoComponent(document.body, '.uncode-video-container.video:not(.drop-move), .uncode-video-container.self-video:not(.drop-move)');
55404						jQuery('#okplayer-' + id).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1');
55405						jQuery('#okplayer-' + id).closest('#page-header').addClass('video-started');
55406						jQuery('#okplayer-' + id).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1');
55407					}, 300);
55408				break;
55409				case 2:
55410					OKEvents.utils.isFunction(options.onPause) && options.onPause();
55411					break;
55412				case 3:
55413					OKEvents.utils.isFunction(options.buffering) && options.buffering();
55414					break;
55415				case 5:
55416					OKEvents.utils.isFunction(options.cued) && options.cued();
55417					break;
55418				default:
55419					throw "OKVideo: received invalid data from YT player.";
55420			}
55421
55422			jQuery(window).trigger('okevents.y.change', [event]);
55423		},
55424		error: function(event) {
55425			throw event;
55426		}
55427	},
55428	v: {
55429		onReady: function(target) {
55430			if ( typeof options === 'undefined' ) {
55431				return true;
55432			}
55433			OKEvents.utils.isFunction(options.onReady) && options.onReady(target);
55434		},
55435		onPlay: function(player) {
55436			if ( typeof options === 'undefined' ) {
55437				return true;
55438			}
55439			if (!OKEvents.utils.isMobile()) player.setVolume(options.volume);
55440			OKEvents.utils.isFunction(options.onPlay) && options.onPlay();
55441			jQuery(player.element).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1');
55442			jQuery(player.element).closest('#page-header').addClass('video-started');
55443			jQuery(player.element).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1');
55444		},
55445		onPause: function() {
55446			if ( typeof options === 'undefined' ) {
55447				return true;
55448			}
55449			OKEvents.utils.isFunction(options.onPause) && options.onPause();
55450		},
55451		onFinish: function() {
55452			if ( typeof options === 'undefined' ) {
55453				return true;
55454			}
55455			OKEvents.utils.isFunction(options.onFinish) && options.onFinish();
55456		}
55457	},
55458	utils: {
55459		isFunction: function(func) {
55460			if (typeof func === 'function') {
55461				return true;
55462			} else {
55463				return false;
55464			}
55465		},
55466		isMobile: function() {
55467			if (navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry)/)) {
55468				return true;
55469			} else {
55470				return false;
55471			}
55472		}
55473	}
55474};
55475/**
55476 * vivus - JavaScript library to make drawing animation on SVG
55477 * @version v0.4.4
55478 * @link https://github.com/maxwellito/vivus
55479 * @license MIT
55480 */
55481
55482'use strict';
55483
55484(function () {
55485
55486  'use strict';
55487
55488/**
55489 * Pathformer
55490 * Beta version
55491 *
55492 * Take any SVG version 1.1 and transform
55493 * child elements to 'path' elements
55494 *
55495 * This code is purely forked from
55496 * https://github.com/Waest/SVGPathConverter
55497 */
55498
55499/**
55500 * Class constructor
55501 *
55502 * @param {DOM|String} element Dom element of the SVG or id of it
55503 */
55504function Pathformer(element) {
55505  // Test params
55506  if (typeof element === 'undefined') {
55507	throw new Error('Pathformer [constructor]: "element" parameter is required');
55508  }
55509
55510  // Set the element
55511  if (element.constructor === String) {
55512	element = document.getElementById(element);
55513	if (!element) {
55514	  throw new Error('Pathformer [constructor]: "element" parameter is not related to an existing ID');
55515	}
55516  }
55517  if (element instanceof window.SVGElement ||
55518	  element instanceof window.SVGGElement ||
55519	  /^svg$/i.test(element.nodeName)) {
55520	this.el = element;
55521  } else {
55522	throw new Error('Pathformer [constructor]: "element" parameter must be a string or a SVGelement');
55523  }
55524
55525  // Start
55526  this.scan(element);
55527}
55528
55529/**
55530 * List of tags which can be transformed
55531 * to path elements
55532 *
55533 * @type {Array}
55534 */
55535Pathformer.prototype.TYPES = ['line', 'ellipse', 'circle', 'polygon', 'polyline', 'rect'];
55536
55537/**
55538 * List of attribute names which contain
55539 * data. This array list them to check if
55540 * they contain bad values, like percentage.
55541 *
55542 * @type {Array}
55543 */
55544Pathformer.prototype.ATTR_WATCH = ['cx', 'cy', 'points', 'r', 'rx', 'ry', 'x', 'x1', 'x2', 'y', '
vendor: 24,640 bytes, lines 55544-56342
55544y1', 'y2'];
55545
55546/**
55547 * Finds the elements compatible for transform
55548 * and apply the liked method
55549 *
55550 * @param  {object} options Object from the constructor
55551 */
55552Pathformer.prototype.scan = function (svg) {
55553  var fn, element, pathData, pathDom,
55554	  elements = svg.querySelectorAll(this.TYPES.join(','));
55555
55556  for (var i = 0; i < elements.length; i++) {
55557	element = elements[i];
55558	fn = this[element.tagName.toLowerCase() + 'ToPath'];
55559	pathData = fn(this.parseAttr(element.attributes));
55560	pathDom = this.pathMaker(element, pathData);
55561	element.parentNode.replaceChild(pathDom, element);
55562  }
55563};
55564
55565
55566/**
55567 * Read `line` element to extract and transform
55568 * data, to make it ready for a `path` object.
55569 *
55570 * @param  {DOMelement} element Line element to transform
55571 * @return {object}			 Data for a `path` element
55572 */
55573Pathformer.prototype.lineToPath = function (element) {
55574  var newElement = {},
55575	  x1 = element.x1 || 0,
55576	  y1 = element.y1 || 0,
55577	  x2 = element.x2 || 0,
55578	  y2 = element.y2 || 0;
55579
55580  newElement.d = 'M' + x1 + ',' + y1 + 'L' + x2 + ',' + y2;
55581  return newElement;
55582};
55583
55584/**
55585 * Read `rect` element to extract and transform
55586 * data, to make it ready for a `path` object.
55587 * The radius-border is not taken in charge yet.
55588 * (your help is more than welcomed)
55589 *
55590 * @param  {DOMelement} element Rect element to transform
55591 * @return {object}             Data for a `path` element
55592 */
55593Pathformer.prototype.rectToPath = function (element) {
55594  var newElement = {},
55595      x      = parseFloat(element.x)      || 0,
55596      y      = parseFloat(element.y)      || 0,
55597      width  = parseFloat(element.width)  || 0,
55598      height = parseFloat(element.height) || 0;
55599
55600  if (element.rx || element.ry) {
55601    var rx = parseInt(element.rx, 10) || -1,
55602        ry = parseInt(element.ry, 10) || -1;
55603    rx = Math.min(Math.max(rx < 0 ? ry : rx, 0), width/2);
55604    ry = Math.min(Math.max(ry < 0 ? rx : ry, 0), height/2);
55605
55606    newElement.d = 'M ' + (x + rx) + ',' + y + ' ' +
55607                   'L ' + (x + width - rx) + ',' + y + ' ' +
55608                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + width) + ',' + (y + ry) + ' ' +
55609                   'L ' + (x + width) + ',' + (y + height - ry) + ' ' +
55610                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + width - rx) + ',' + (y + height) + ' ' +
55611                   'L ' + (x + rx) + ',' + (y + height) + ' ' +
55612                   'A ' + rx + ',' + ry + ',0,0,1,' + x + ',' + (y + height - ry) + ' ' +
55613                   'L ' + x + ',' + (y + ry) + ' ' +
55614                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + rx) + ',' + y;
55615  }
55616  else {
55617    newElement.d = 'M' + x + ' ' + y + ' ' +
55618                   'L' + (x + width) + ' ' + y + ' ' +
55619                   'L' + (x + width) + ' ' + (y + height) + ' ' +
55620                   'L' + x + ' ' + (y + height) + ' Z';
55621  }
55622  return newElement;
55623};
55624
55625/**
55626 * Read `polyline` element to extract and transform
55627 * data, to make it ready for a `path` object.
55628 *
55629 * @param  {DOMelement} element Polyline element to transform
55630 * @return {object}             Data for a `path` element
55631 */
55632Pathformer.prototype.polylineToPath = function (element) {
55633  var newElement = {},
55634      points = element.points.trim().split(' '),
55635      i, path;
55636
55637  // Reformatting if points are defined without commas
55638  if (element.points.indexOf(',') === -1) {
55639    var formattedPoints = [];
55640    for (i = 0; i < points.length; i+=2) {
55641      formattedPoints.push(points[i] + ',' + points[i+1]);
55642    }
55643    points = formattedPoints;
55644  }
55645
55646  // Generate the path.d value
55647  path = 'M' + points[0];
55648  for(i = 1; i < points.length; i++) {
55649    if (points[i].indexOf(',') !== -1) {
55650      path += 'L' + points[i];
55651    }
55652  }
55653  newElement.d = path;
55654  return newElement;
55655};
55656
55657/**
55658 * Read `polygon` element to extract and transform
55659 * data, to make it ready for a `path` object.
55660 * This method rely on polylineToPath, because the
55661 * logic is similar. The path created is just closed,
55662 * so it needs an 'Z' at the end.
55663 *
55664 * @param  {DOMelement} element Polygon element to transform
55665 * @return {object}             Data for a `path` element
55666 */
55667Pathformer.prototype.polygonToPath = function (element) {
55668  var newElement = Pathformer.prototype.polylineToPath(element);
55669
55670  newElement.d += 'Z';
55671  return newElement;
55672};
55673
55674/**
55675 * Read `ellipse` element to extract and transform
55676 * data, to make it ready for a `path` object.
55677 *
55678 * @param  {DOMelement} element ellipse element to transform
55679 * @return {object}             Data for a `path` element
55680 */
55681Pathformer.prototype.ellipseToPath = function (element) {
55682  var newElement = {},
55683      rx = parseFloat(element.rx) || 0,
55684      ry = parseFloat(element.ry) || 0,
55685      cx = parseFloat(element.cx) || 0,
55686      cy = parseFloat(element.cy) || 0,
55687      startX = cx - rx,
55688      startY = cy,
55689      endX = parseFloat(cx) + parseFloat(rx),
55690      endY = cy;
55691
55692  newElement.d = 'M' + startX + ',' + startY +
55693                 'A' + rx + ',' + ry + ' 0,1,1 ' + endX + ',' + endY +
55694                 'A' + rx + ',' + ry + ' 0,1,1 ' + startX + ',' + endY;
55695  return newElement;
55696};
55697
55698/**
55699 * Read `circle` element to extract and transform
55700 * data, to make it ready for a `path` object.
55701 *
55702 * @param  {DOMelement} element Circle element to transform
55703 * @return {object}             Data for a `path` element
55704 */
55705Pathformer.prototype.circleToPath = function (element) {
55706  var newElement = {},
55707      r  = parseFloat(element.r)  || 0,
55708      cx = parseFloat(element.cx) || 0,
55709      cy = parseFloat(element.cy) || 0,
55710      startX = cx - r,
55711      startY = cy,
55712      endX = parseFloat(cx) + parseFloat(r),
55713      endY = cy;
55714
55715  newElement.d =  'M' + startX + ',' + startY +
55716                  'A' + r + ',' + r + ' 0,1,1 ' + endX + ',' + endY +
55717                  'A' + r + ',' + r + ' 0,1,1 ' + startX + ',' + endY;
55718  return newElement;
55719};
55720
55721/**
55722 * Create `path` elements form original element
55723 * and prepared objects
55724 *
55725 * @param  {DOMelement} element  Original element to transform
55726 * @param  {object} pathData     Path data (from `toPath` methods)
55727 * @return {DOMelement}          Path element
55728 */
55729Pathformer.prototype.pathMaker = function (element, pathData) {
55730  var i, attr, pathTag = document.createElementNS('http://www.w3.org/2000/svg','path');
55731  for(i = 0; i < element.attributes.length; i++) {
55732    attr = element.attributes[i];
55733    if (this.ATTR_WATCH.indexOf(attr.name) === -1) {
55734      pathTag.setAttribute(attr.name, attr.value);
55735    }
55736  }
55737  for(i in pathData) {
55738    pathTag.setAttribute(i, pathData[i]);
55739  }
55740  return pathTag;
55741};
55742
55743/**
55744 * Parse attributes of a DOM element to
55745 * get an object of attribute => value
55746 *
55747 * @param  {NamedNodeMap} attributes Attributes object from DOM element to parse
55748 * @return {object}                  Object of attributes
55749 */
55750Pathformer.prototype.parseAttr = function (element) {
55751  var attr, output = {};
55752  for (var i = 0; i < element.length; i++) {
55753    attr = element[i];
55754    // Check if no data attribute contains '%', or the transformation is impossible
55755    if (this.ATTR_WATCH.indexOf(attr.name) !== -1 && attr.value.indexOf('%') !== -1) {
55756      throw new Error('Pathformer [parseAttr]: a SVG shape got values in percentage. This cannot be transformed into \'path\' tags. Please use \'viewBox\'.');
55757    }
55758    output[attr.name] = attr.value;
55759  }
55760  return output;
55761};
55762
55763  'use strict';
55764
55765var setupEnv, requestAnimFrame, cancelAnimFrame, parsePositiveInt;
55766
55767/**
55768 * Vivus
55769 * Beta version
55770 *
55771 * Take any SVG and make the animation
55772 * to give give the impression of live drawing
55773 *
55774 * This in more than just inspired from codrops
55775 * At that point, it's a pure fork.
55776 */
55777
55778/**
55779 * Class constructor
55780 * option structure
55781 *   type: 'delayed'|'sync'|'oneByOne'|'script' (to know if the items must be drawn synchronously or not, default: delayed)
55782 *   duration: <int> (in frames)
55783 *   start: 'inViewport'|'manual'|'autostart' (start automatically the animation, default: inViewport)
55784 *   delay: <int> (delay between the drawing of first and last path)
55785 *   dashGap <integer> whitespace extra margin between dashes
55786 *   pathTimingFunction <function> timing animation function for each path element of the SVG
55787 *   animTimingFunction <function> timing animation function for the complete SVG
55788 *   forceRender <boolean> force the browser to re-render all updated path items
55789 *   selfDestroy <boolean> removes all extra styling on the SVG, and leaves it as original
55790 *
55791 * The attribute 'type' is by default on 'delayed'.
55792 *  - 'delayed'
55793 *    all paths are draw at the same time but with a
55794 *    little delay between them before start
55795 *  - 'sync'
55796 *    all path are start and finish at the same time
55797 *  - 'oneByOne'
55798 *    only one path is draw at the time
55799 *    the end of the first one will trigger the draw
55800 *    of the next one
55801 *
55802 * All these values can be overwritten individually
55803 * for each path item in the SVG
55804 * The value of frames will always take the advantage of
55805 * the duration value.
55806 * If you fail somewhere, an error will be thrown.
55807 * Good luck.
55808 *
55809 * @constructor
55810 * @this {Vivus}
55811 * @param {DOM|String}   element  Dom element of the SVG or id of it
55812 * @param {Object}       options  Options about the animation
55813 * @param {Function}     callback Callback for the end of the animation
55814 */
55815function Vivus (element, options, callback) {
55816
55817  setupEnv();
55818
55819  // Setup
55820  this.isReady = false;
55821  this.setElement(element, options);
55822  this.setOptions(options);
55823  this.setCallback(callback);
55824
55825  if (this.isReady) {
55826    this.init();
55827  }
55828}
55829
55830/**
55831 * Timing functions
55832 **************************************
55833 *
55834 * Default functions to help developers.
55835 * It always take a number as parameter (between 0 to 1) then
55836 * return a number (between 0 and 1)
55837 */
55838Vivus.LINEAR          = function (x) {return x;};
55839Vivus.EASE            = function (x) {return -Math.cos(x * Math.PI) / 2 + 0.5;};
55840Vivus.EASE_OUT        = function (x) {return 1 - Math.pow(1-x, 3);};
55841Vivus.EASE_IN         = function (x) {return Math.pow(x, 3);};
55842Vivus.EASE_OUT_BOUNCE = function (x) {
55843  var base = -Math.cos(x * (0.5 * Math.PI)) + 1,
55844    rate = Math.pow(base,1.5),
55845    rateR = Math.pow(1 - x, 2),
55846    progress = -Math.abs(Math.cos(rate * (2.5 * Math.PI) )) + 1;
55847  return (1- rateR) + (progress * rateR);
55848};
55849
55850
55851/**
55852 * Setters
55853 **************************************
55854 */
55855
55856/**
55857 * Check and set the element in the instance
55858 * The method will not return anything, but will throw an
55859 * error if the parameter is invalid
55860 *
55861 * @param {DOM|String}   element  SVG Dom element or id of it
55862 */
55863Vivus.prototype.setElement = function (element, options) {
55864  var onLoad, self;
55865
55866  // Basic check
55867  if (typeof element === 'undefined') {
55868    throw new Error('Vivus [constructor]: "element" parameter is required');
55869  }
55870
55871  // Set the element
55872  if (element.constructor === String) {
55873    element = document.getElementById(element);
55874    if (!element) {
55875      throw new Error('Vivus [constructor]: "element" parameter is not related to an existing ID');
55876    }
55877  }
55878  this.parentEl = element;
55879
55880  // Load the SVG with XMLHttpRequest and extract the SVG
55881  if (options && options.file) {
55882    var self = this;
55883    onLoad = function (e) {
55884      var domSandbox = document.createElement('div');
55885      domSandbox.innerHTML = this.responseText;
55886
55887      var svgTag = domSandbox.querySelector('svg');
55888      if (!svgTag) {
55889        throw new Error('Vivus [load]: Cannot find the SVG in the loaded file : ' + options.file);
55890      }
55891
55892      self.el = svgTag
55893      self.el.setAttribute('width', '100%');
55894      self.el.setAttribute('height', '100%');
55895      self.parentEl.appendChild(self.el)
55896      self.isReady = true;
55897      self.init();
55898      self = null;
55899    }
55900
55901    var oReq = new window.XMLHttpRequest();
55902    oReq.addEventListener('load', onLoad);
55903    oReq.open('GET', options.file);
55904    oReq.send();
55905    return;
55906  }
55907
55908  switch (element.constructor) {
55909  case window.SVGSVGElement:
55910  case window.SVGElement:
55911  case window.SVGGElement:
55912    this.el = element;
55913    this.isReady = true;
55914    break;
55915
55916  case window.HTMLObjectElement:
55917    self = this;
55918    onLoad = function (e) {
55919      if (self.isReady) {
55920        return;
55921      }
55922      self.el = element.contentDocument && element.contentDocument.querySelector('svg');
55923      if (!self.el && e) {
55924        throw new Error('Vivus [constructor]: object loaded does not contain any SVG');
55925      }
55926      else if (self.el) {
55927        if (element.getAttribute('built-by-vivus')) {
55928          self.parentEl.insertBefore(self.el, element);
55929          self.parentEl.removeChild(element);
55930          self.el.setAttribute('width', '100%');
55931          self.el.setAttribute('height', '100%');
55932        }
55933        self.isReady = true;
55934        self.init();
55935        self = null;
55936      }
55937    };
55938
55939    if (!onLoad()) {
55940      element.addEventListener('load', onLoad);
55941    }
55942    break;
55943
55944  default:
55945    throw new Error('Vivus [constructor]: "element" parameter is not valid (or miss the "file" attribute)');
55946  }
55947};
55948
55949/**
55950 * Set up user option to the instance
55951 * The method will not return anything, but will throw an
55952 * error if the parameter is invalid
55953 *
55954 * @param  {object} options Object from the constructor
55955 */
55956Vivus.prototype.setOptions = function (options) {
55957  var allowedTypes = ['delayed', 'sync', 'async', 'nsync', 'oneByOne', 'scenario', 'scenario-sync'];
55958  var allowedStarts =  ['inViewport', 'manual', 'autostart'];
55959
55960  // Basic check
55961  if (options !== undefined && options.constructor !== Object) {
55962    throw new Error('Vivus [constructor]: "options" parameter must be an object');
55963  }
55964  else {
55965    options = options || {};
55966  }
55967
55968  // Set the animation type
55969  if (options.type && allowedTypes.indexOf(options.type) === -1) {
55970    throw new Error('Vivus [constructor]: ' + options.type + ' is not an existing animation `type`');
55971  }
55972  else {
55973    this.type = options.type || allowedTypes[0];
55974  }
55975
55976  // Set the start type
55977  if (options.start && allowedStarts.indexOf(options.start) === -1) {
55978    throw new Error('Vivus [constructor]: ' + options.start + ' is not an existing `start` option');
55979  }
55980  else {
55981    this.start = options.start || allowedStarts[0];
55982  }
55983
55984  this.isIE         = (window.navigator.userAgent.indexOf('MSIE') !== -1 || window.navigator.userAgent.indexOf('Trident/') !== -1 || window.navigator.userAgent.indexOf('Edge/') !== -1 );
55985  this.duration     = parsePositiveInt(options.duration, 120);
55986  this.delay        = parsePositiveInt(options.delay, null);
55987  //Uncode addition
55988  this.delayStart   = parsePositiveInt(options.delayStart, null);
55989  //#END
55990  this.dashGap      = parsePositiveInt(options.dashGap, 1);
55991  this.forceRender  = options.hasOwnProperty('forceRender') ? !!options.forceRender : this.isIE;
55992  this.reverseStack = !!options.reverseStack;
55993  this.selfDestroy  = !!options.selfDestroy;
55994  this.onReady      = options.onReady;
55995  this.map          = [];
55996  this.frameLength  = this.currentFrame = this.delayUnit = this.speed = this.handle = null;
55997
55998  this.ignoreInvisible = options.hasOwnProperty('ignoreInvisible') ? !!options.ignoreInvisible : false;
55999
56000  this.animTimingFunction = options.animTimingFunction || Vivus.LINEAR;
56001  this.pathTimingFunction = options.pathTimingFunction || Vivus.LINEAR;
56002
56003  if (this.delay >= this.duration) {
56004    throw new Error('Vivus [constructor]: delay must be shorter than duration');
56005  }
56006};
56007
56008/**
56009 * Set up callback to the instance
56010 * The method will not return enything, but will throw an
56011 * error if the parameter is invalid
56012 *
56013 * @param  {Function} callback Callback for the animation end
56014 */
56015Vivus.prototype.setCallback = function (callback) {
56016  // Basic check
56017  if (!!callback && callback.constructor !== Function) {
56018    throw new Error('Vivus [constructor]: "callback" parameter must be a function');
56019  }
56020  this.callback = callback || function () {};
56021};
56022
56023
56024/**
56025 * Core
56026 **************************************
56027 */
56028
56029/**
56030 * Map the svg, path by path.
56031 * The method return nothing, it just fill the
56032 * `map` array. Each item in this array represent
56033 * a path element from the SVG, with informations for
56034 * the animation.
56035 *
56036 * ```
56037 * [
56038 *   {
56039 *     el: <DOMobj> the path element
56040 *     length: <number> length of the path line
56041 *     startAt: <number> time start of the path animation (in frames)
56042 *     duration: <number> path animation duration (in frames)
56043 *   },
56044 *   ...
56045 * ]
56046 * ```
56047 *
56048 */
56049Vivus.prototype.mapping = function () {
56050  var i, paths, path, pAttrs, pathObj, totalLength, lengthMeter, timePoint;
56051  timePoint = totalLength = lengthMeter = 0;
56052  paths = this.el.querySelectorAll('path');
56053
56054  for (i = 0; i < paths.length; i++) {
56055    path = paths[i];
56056    if (this.isInvisible(path)) {
56057      continue;
56058    }
56059    pathObj = {
56060      el: path,
56061      length: Math.ceil(path.getTotalLength())
56062    };
56063    // Test if the path length is correct
56064    if (isNaN(pathObj.length)) {
56065      if (window.console && console.warn) {
56066        console.warn('Vivus [mapping]: cannot retrieve a path element length', path);
56067      }
56068      continue;
56069    }
56070    this.map.push(pathObj);
56071    path.style.strokeDasharray  = pathObj.length + ' ' + (pathObj.length + this.dashGap * 2);
56072    path.style.strokeDashoffset = pathObj.length + this.dashGap;
56073    pathObj.length += this.dashGap;
56074    totalLength += pathObj.length;
56075
56076    this.renderPath(i);
56077  }
56078
56079  totalLength = totalLength === 0 ? 1 : totalLength;
56080  this.delay = this.delay === null ? this.duration / 3 : this.delay;
56081  this.delayUnit = this.delay / (paths.length > 1 ? paths.length - 1 : 1);
56082
56083  // Reverse stack if asked
56084  if (this.reverseStack) {
56085    this.map.reverse();
56086  }
56087
56088  for (i = 0; i < this.map.length; i++) {
56089    pathObj = this.map[i];
56090
56091    switch (this.type) {
56092    case 'delayed':
56093      pathObj.startAt = this.delayUnit * i;
56094      pathObj.duration = this.duration - this.delay;
56095      break;
56096
56097    case 'oneByOne':
56098      pathObj.startAt = lengthMeter / totalLength * this.duration;
56099      pathObj.duration = pathObj.length / totalLength * this.duration;
56100      break;
56101
56102    case 'sync':
56103    case 'async':
56104    case 'nsync':
56105      pathObj.startAt = 0;
56106      pathObj.duration = this.duration;
56107      break;
56108
56109    case 'scenario-sync':
56110      path = pathObj.el;
56111      pAttrs = this.parseAttr(path);
56112      pathObj.startAt = timePoint + (parsePositiveInt(pAttrs['data-delay'], this.delayUnit) || 0);
56113      pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration);
56114      timePoint = pAttrs['data-async'] !== undefined ? pathObj.startAt : pathObj.startAt + pathObj.duration;
56115      this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration));
56116      break;
56117
56118    case 'scenario':
56119      path = pathObj.el;
56120      pAttrs = this.parseAttr(path);
56121      pathObj.startAt = parsePositiveInt(pAttrs['data-start'], this.delayUnit) || 0;
56122      pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration);
56123      this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration));
56124      break;
56125    }
56126    lengthMeter += pathObj.length;
56127    this.frameLength = this.frameLength || this.duration;
56128  }
56129};
56130
56131/**
56132 * Interval method to draw the SVG from current
56133 * position of the animation. It update the value of
56134 * `currentFrame` and re-trace the SVG.
56135 *
56136 * It use this.handle to store the requestAnimationFrame
56137 * and clear it one the animation is stopped. So this
56138 * attribute can be used to know if the animation is
56139 * playing.
56140 *
56141 * Once the animation at the end, this method will
56142 * trigger the Vivus callback.
56143 *
56144 */
56145Vivus.prototype.drawer = function () {
56146  var self = this;
56147  this.currentFrame += this.speed;
56148
56149  if (this.currentFrame <= 0) {
56150    this.stop();
56151    this.reset();
56152  } else if (this.currentFrame >= this.frameLength) {
56153    this.stop();
56154    this.currentFrame = this.frameLength;
56155    this.trace();
56156    if (this.selfDestroy) {
56157      this.destroy();
56158    }
56159  } else {
56160    this.trace();
56161    this.handle = requestAnimFrame(function () {
56162      self.drawer();
56163    });
56164    return;
56165  }
56166
56167  this.callback(this);
56168  if (this.instanceCallback) {
56169    this.instanceCallback(this);
56170    this.instanceCallback = null;
56171  }
56172};
56173
56174/**
56175 * Draw the SVG at the current instant from the
56176 * `currentFrame` value. Here is where most of the magic is.
56177 * The trick is to use the `strokeDashoffset` style property.
56178 *
56179 * For optimisation reasons, a new property called `progress`
56180 * is added in each item of `map`. This one contain the current
56181 * progress of the path element. Only if the new value is different
56182 * the new value will be applied to the DOM element. This
56183 * method save a lot of resources to re-render the SVG. And could
56184 * be improved if the animation couldn't be played forward.
56185 *
56186 */
56187Vivus.prototype.trace = function () {
56188  var i, progress, path, currentFrame;
56189  currentFrame = this.animTimingFunction(this.currentFrame / this.frameLength) * this.frameLength;
56190  for (i = 0; i < this.map.length; i++) {
56191    path = this.map[i];
56192    progress = (currentFrame - path.startAt) / path.duration;
56193    progress = this.pathTimingFunction(Math.max(0, Math.min(1, progress)));
56194    if (path.progress !== progress) {
56195      path.progress = progress;
56196      path.el.style.strokeDashoffset = Math.floor(path.length * (1 - progress));
56197      this.renderPath(i);
56198    }
56199  }
56200};
56201
56202/**
56203 * Method forcing the browser to re-render a path element
56204 * from it's index in the map. Depending on the `forceRender`
56205 * value.
56206 * The trick is to replace the path element by it's clone.
56207 * This practice is not recommended because it's asking more
56208 * ressources, too much DOM manupulation..
56209 * but it's the only way to let the magic happen on IE.
56210 * By default, this fallback is only applied on IE.
56211 *
56212 * @param  {Number} index Path index
56213 */
56214Vivus.prototype.renderPath = function (index) {
56215  if (this.forceRender && this.map && this.map[index]) {
56216    var pathObj = this.map[index],
56217        newPath = pathObj.el.cloneNode(true);
56218    pathObj.el.parentNode.replaceChild(newPath, pathObj.el);
56219    pathObj.el = newPath;
56220  }
56221};
56222
56223/**
56224 * When the SVG object is loaded and ready,
56225 * this method will continue the initialisation.
56226 *
56227 * This this mainly due to the case of passing an
56228 * object tag in the constructor. It will wait
56229 * the end of the loading to initialise.
56230 *
56231 */
56232Vivus.prototype.init = function () {
56233  // Set object variables
56234  this.frameLength = 0;
56235  this.currentFrame = 0;
56236  this.map = [];
56237
56238  // Start
56239  new Pathformer(this.el);
56240  this.mapping();
56241  this.starter();
56242
56243  if (this.onReady) {
56244    this.onReady(this);
56245  }
56246};
56247
56248/**
56249 * Trigger to start of the animation.
56250 * Depending on the `start` value, a different script
56251 * will be applied.
56252 *
56253 * If the `start` value is not valid, an error will be thrown.
56254 * Even if technically, this is impossible.
56255 *
56256 */
56257Vivus.prototype.starter = function () {
56258  switch (this.start) {
56259  case 'manual':
56260    return;
56261
56262  case 'autostart':
56263    this.play();
56264    break;
56265
56266  case 'inViewport':
56267    var self = this,
56268    listener = function () {
56269      if (self.isInViewport(self.parentEl, 1)) {
56270        self.play();
56271        window.removeEventListener('scroll', listener);
56272        //Uncode addition
56273        window.removeEventListener('fp-slide-changed', listener);
56274        window.removeEventListener('fp-slide-scroll', listener);
56275        //#END
56276      }
56277    };
56278    window.addEventListener('scroll', listener);
56279    //Uncode addition
56280    window.addEventListener('fp-slide-changed', listener);
56281    window.addEventListener('fp-slide-scroll', listener);
56282    //#END
56283    listener();
56284    break;
56285  }
56286};
56287
56288
56289/**
56290 * Controls
56291 **************************************
56292 */
56293
56294/**
56295 * Get the current status of the animation between
56296 * three different states: 'start', 'progress', 'end'.
56297 * @return {string} Instance status
56298 */
56299Vivus.prototype.getStatus = function () {
56300  return this.currentFrame === 0 ? 'start' : this.currentFrame === this.frameLength ? 'end' : 'progress';
56301};
56302
56303/**
56304 * Reset the instance to the initial state : undraw
56305 * Be careful, it just reset the animation, if you're
56306 * playing the animation, this won't stop it. But just
56307 * make it start from start.
56308 *
56309 */
56310Vivus.prototype.reset = function () {
56311  return this.setFrameProgress(0);
56312};
56313
56314/**
56315 * Set the instance to the final state : drawn
56316 * Be careful, it just set the animation, if you're
56317 * playing the animation on rewind, this won't stop it.
56318 * But just make it start from the end.
56319 *
56320 */
56321Vivus.prototype.finish = function () {
56322  return this.setFrameProgress(1);
56323};
56324
56325/**
56326 * Set the level of progress of the drawing.
56327 *
56328 * @param {number} progress Level of progress to set
56329 */
56330Vivus.prototype.setFrameProgress = function (progress) {
56331  progress = Math.min(1, Math.max(0, progress));
56332  this.currentFrame = Math.round(this.frameLength * progress);
56333  this.trace();
56334  return this;
56335};
56336
56337/**
56338 * Play the animation at the desired speed.
56339 * Speed must be a valid number (no zero).
56340 * By default, the speed value is 1.
56341 * But a negative value is accepted to go forward.
56342 *
56343 * And works with float too.
56344 * But don't forget we are in JavaScript, se be nice
56345 * with him and give him a 1/2^x value.
56346 *
56347 * @param  {number} speed Animation speed [optional]
56348 */
56349Vivus.prototype.play = function (speed, callback) {
56350  this.instanceCallback = null;
56351
56352  if (speed && typeof speed === 'function') {
56353    this.instanceCallback = speed; // first parameter is actually the callback function
56354    speed = null;
56355  }
56356  else if (speed && typeof speed !== 'number') {
56357    throw new Error('Vivus [play]: invalid speed');
56358  }
56359  // if the first parameter wasn't the callback, check if the seconds was
56360  if (callback && typeof(callback) === 'function' && !this.instanceCallback) {
56361    this.instanceCallback = callback;
56362  }
56363
56364
56365  this.speed = speed || 1;
56366  //Uncode addition
56367  if (!this.handle) {
56368    var $this = this,
56369    delay = (this.delayStart != null) ? this.delayStart : 0;
56370    setTimeout(function() {
56371      $this.drawer();
56372    }, delay);
56373  }
56374  //#END
56375  return this;
56376};
56377
56378/**
56379 * Stop the current animation, if on progress.
56380 * Should not trigger any error.
56381 *
56382 */
56383Vivus.prototype.stop = function () {
56384  if (this.handle) {
56385    cancelAnimFrame(this.handle);
56386    this.handle = null;
56387  }
56388  return this;
56389};
56390
56391/**
56392 * Destroy the instance.
56393 * Remove all bad styling attributes on all
56394 * path tags
56395 *
56396 */
56397Vivus.prototype.destroy = function () {
56398  this.stop();
56399  var i, path;
56400  for (i = 0; i < this.map.length; i++) {
56401    path = this.map[i];
56402    path.el.style.strokeDashoffset = null;
56403    path.el.style.strokeDasharray = null;
56404    this.renderPath(i);
56405  }
56406};
56407
56408
56409/**
56410 * Utils methods
56411 * include methods from Codrops
56412 **************************************
56413 */
56414
56415/**
56416 * Method to best guess if a path should added into
56417 * the animation or not.
56418 *
56419 * 1. Use the `data-vivus-ignore` attribute if set
56420 * 2. Check if the instance must ignore invisible paths
56421 * 3. Check if the path is visible
56422 *
56423 * For now the visibility checking is unstable.
56424 * It will be used for a beta phase.
56425 *
56426 * Other improvments are planned. Like detecting
56427 * is the path got a stroke or a valid opacity.
56428 */
56429Vivus.prototype.isInvisible = function (el) {
56430  var rect,
56431    ignoreAttr = el.getAttribute('data-ignore');
56432
56433  if (ignoreAttr !== null) {
56434    return ignoreAttr !== 'false';
56435  }
56436
56437  if (this.ignoreInvisible) {
56438    rect = el.getBoundingClientRect();
56439    return !rect.width && !rect.height;
56440  }
56441  else {
56442    return false;
56443  }
56444};
56445
56446/**
56447 * Parse attributes of a DOM element to
56448 * get an object of {attributeName => attributeValue}
56449 *
56450 * @param  {object} element DOM element to parse
56451 * @return {object}         Object of attributes
56452 */
56453Vivus.prototype.parseAttr = function (element) {
56454  var attr, output = {};
56455  if (element && element.attributes) {
56456    for (var i = 0; i < element.attributes.length; i++) {
56457      attr = element.attributes[i];
56458      output[attr.name] = attr.value;
56459    }
56460  }
56461  return output;
56462};
56463
56464/**
56465 * Reply if an element is in the page viewport
56466 *
56467 * @param  {object} el Element to observe
56468 * @param  {number} h  Percentage of height
56469 * @return {boolean}
56470 */
56471Vivus.prototype.isInViewport = function (el, h) {
56472  var scrolled   = this.scrollY(),
56473    viewed       = scrolled + this.getViewportH(),
56474    elBCR        = el.getBoundingClientRect(),
56475    elHeight     = elBCR.height,
56476    elTop        = scrolled + elBCR.top,
56477    elBottom     = elTop + elHeight;
56478
56479  // if 0, the element is considered in the viewport as soon as it enters.
56480  // if 1, the element is considered in the viewport only when it's fully inside
56481  // value in percentage (1 >= h >= 0)
56482  h = h || 0;
56483
56484  return (elTop + elHeight * h) <= viewed && (elBottom) >= scrolled;
56485};
56486
56487
56488/**
56489 * Get the viewport height in pixels
56490 *
56491 * @return {integer} Viewport height
56492 */
56493Vivus.prototype.getViewportH = function () {
56494  var client = this.docElem.clientHeight,
56495    inner = window.innerHeight;
56496
56497  if (client < inner) {
56498    return inner;
56499  }
56500  else {
56501    return client;
56502  }
56503};
56504
56505/**
56506 * Get the page Y offset
56507 *
56508 * @return {integer} Page Y offset
56509 */
56510Vivus.prototype.scrollY = function () {
56511  return window.pageYOffset || this.docElem.scrollTop;
56512};
56513
56514setupEnv = function () {
56515
56516  if (Vivus.prototype.docElem) {
56517    return;
56518  }
56519
56520  /**
56521   * Alias for document element
56522   *
56523   * @type {DOMelement}
56524   */
56525  Vivus.prototype.docElem = window.document.documentElement;
56526
56527  /**
56528   * Alias for `requestAnimationFrame` or
56529   * `setTimeout` function for deprecated browsers.
56530   *
56531   */
56532  requestAnimFrame = (function () {
56533    return (
56534      window.requestAnimationFrame       ||
56535      window.webkitRequestAnimationFrame ||
56536      window.mozRequestAnimationFrame    ||
56537      window.oRequestAnimationFrame      ||
56538      window.msRequestAnimationFrame     ||
56539      function(/* function */ callback){
56540        return window.setTimeout(callback, 1000 / 60);
56541      }
56542    );
56543  })();
56544
56545  /**
56546   * Alias for `cancelAnimationFrame` or
56547   * `cancelTimeout` function for deprecated browsers.
56548   *
56549   */
56550  cancelAnimFrame = (function () {
56551    return (
56552      window.cancelAnimationFrame       ||
56553      window.webkitCancelAnimationFrame ||
56554      window.mozCancelAnimationFrame    ||
56555      window.oCancelAnimationFrame      ||
56556      window.msCancelAnimationFrame     ||
56557      function(id){
56558        return window.clearTimeout(id);
56559      }
56560    );
56561  })();
56562};
56563
56564/**
56565 * Parse string to integer.
56566 * If the number is not positive or null
56567 * the method will return the default value
56568 * or 0 if undefined
56569 *
56570 * @param {string} value String to parse
56571 * @param {*}
56571 defaultValue Value to return if the result parsed is invalid
56572 * @return {number}
56573 *
56574 */
56575parsePositiveInt = function (value, defaultValue) {
56576  var output = parseInt(value, 10);
56577  return (output >= 0) ? output : defaultValue;
56578};
56579
56580
56581  if (typeof define === 'function' && define.amd) {
56582    // AMD. Register as an anonymous module.
56583    define([], function() {
56584      return Vivus;
56585    });
56586  } else if (typeof exports === 'object') {
56587    // Node. Does not work with strict CommonJS, but
56588    // only CommonJS-like environments that support module.exports,
56589    // like Node.
56590    module.exports = Vivus;
56591  } else {
56592    // Browser globals
56593    window.Vivus = Vivus;
56594  }
56595
56596}());
56597
56598//Noise.js
56599!function(){"use strict";var r=.5*(Math.sqrt(3)-1),e=(3-Math.sqrt(3))/6,t=1/6,a=(Math.sqrt(5)-1)/4,o=(5-Math.sqrt(5))/20;function i(r){var e;e="function"==typeof r?r:r?function(){var r=0,e=0,t=0,a=1,o=(i=4022871197,function(r){r=r.toString();for(var e=0;e<r.length;e++){var t=.02519603282416938*(i+=r.charCodeAt(e));t-=i=t>>>0,i=(t*=i)>>>0,i+=4294967296*(t-=i)}return 2.3283064365386963e-10*(i>>>0)});var i;r=o(" "),e=o(" "),t=o(" ");for(var n=0;n<arguments.length;n++)(r-=o(arguments[n]))<0&&(r+=1),(e-=o(arguments[n]))<0&&(e+=1),(t-=o(arguments[n]))<0&&(t+=1);return o=null,function(){var o=2091639*r+2.3283064365386963e-10*a;return r=e,e=t,t=o-(a=0|o)}}(r):Math.random,this.p=n(e),this.perm=new Uint8Array(512),this.permMod12=new Uint8Array(512);for(var t=0;t<512;t++)this.perm[t]=this.p[255&t],this.permMod12[t]=this.perm[t]%12}function n(r){var e,t=new Uint8Array(256);for(e=0;e<256;e++)t[e]=e;for(e=0;e<255;e++){var a=e+~~(r()*(256-e)),o=t[e];t[e]=t[a],t[a]=o}return t}i.prototype={grad3:new Float32Array([1,1,0,-1,1,0,1,-1,0,-1,-1,0,1,0,1,-1,0,1,1,0,-1,-1,0,-1,0,1,1,0,-1,1,0,1,-1,0,-1,-1]),grad4:new Float32Array([0,1,1,1,0,1,1,-1,0,1,-1,1,0,1,-1,-1,0,-1,1,1,0,-1,1,-1,0,-1,-1,1,0,-1,-1,-1,1,0,1,1,1,0,1,-1,1,0,-1,1,1,0,-1,-1,-1,0,1,1,-1,0,1,-1,-1,0,-1,1,-1,0,-1,-1,1,1,0,1,1,1,0,-1,1,-1,0,1,1,-1,0,-1,-1,1,0,1,-1,1,0,-1,-1,-1,0,1,-1,-1,0,-1,1,1,1,0,1,1,-1,0,1,-1,1,0,1,-1,-1,0,-1,1,1,0,-1,1,-1,0,-1,-1,1,0,-1,-1,-1,0]),noise2D:function(t,a){var o,i,n=this.permMod12,f=this.perm,s=this.grad3,v=0,h=0,l=0,u=(t+a)*r,d=Math.floor(t+u),p=Math.floor(a+u),M=(d+p)*e,m=t-(d-M),c=a-(p-M);m>c?(o=1,i=0):(o=0,i=1);var y=m-o+e,w=c-i+e,g=m-1+2*e,A=c-1+2*e,x=255&d,q=255&p,D=.5-m*m-c*c;if(D>=0){var S=3*n[x+f[q]];v=(D*=D)*D*(s[S]*m+s[S+1]*c)}var U=.5-y*y-w*w;if(U>=0){var b=3*n[x+o+f[q+i]];h=(U*=U)*U*(s[b]*y+s[b+1]*w)}var F=.5-g*g-A*A;if(F>=0){var N=3*n[x+1+f[q+1]];l=(F*=F)*F*(s[N]*g+s[N+1]*A)}return 70*(v+h+l)},noise3D:function(r,e,a){var o,i,n,f,s,v,h,l,u,d,p=this.permMod12,M=this.perm,m=this.grad3,c=(r+e+a)*(1/3),y=Math.floor(r+c),w=Math.floor(e+c),g=Math.floor(a+c),A=(y+w+g)*t,x=r-(y-A),q=e-(w-A),D=a-(g-A);x>=q?q>=D?(s=1,v=0,h=0,l=1,u=1,d=0):x>=D?(s=1,v=0,h=0,l=1,u=0,d=1):(s=0,v=0,h=1,l=1,u=0,d=1):q<D?(s=0,v=0,h=1,l=0,u=1,d=1):x<D?(s=0,v=1,h=0,l=0,u=1,d=1):(s=0,v=1,h=0,l=1,u=1,d=0);var S=x-s+t,U=q-v+t,b=D-h+t,F=x-l+2*t,N=q-u+2*t,C=D-d+2*t,P=x-1+.5,T=q-1+.5,_=D-1+.5,j=255&y,k=255&w,z=255&g,B=.6-x*x-q*q-D*D;if(B<0)o=0;else{var E=3*p[j+M[k+M[z]]];o=(B*=B)*B*(m[E]*x+m[E+1]*q+m[E+2]*D)}var G=.6-S*S-U*U-b*b;if(G<0)i=0;else{var H=3*p[j+s+M[k+v+M[z+h]]];i=(G*=G)*G*(m[H]*S+m[H+1]*U+m[H+2]*b)}var I=.6-F*F-N*N-C*C;if(I<0)n=0;else{var J=3*p[j+l+M[k+u+M[z+d]]];n=(I*=I)*I*(m[J]*F+m[J+1]*N+m[J+2]*C)}var K=.6-P*P-T*T-_*_;if(K<0)f=0;else{var L=3*p[j+1+M[k+1+M[z+1]]];f=(K*=K)*K*(m[L]*P+m[L+1]*T+m[L+2]*_)}return 32*(o+i+n+f)},noise4D:function(r,e,t,i){var n,f,s,v,h,l,u,d,p,M,m,c,y,w,g,A,x,q=this.perm,D=this.grad4,S=(r+e+t+i)*a,U=Math.floor(r+S),b=Math.floor(e+S),F=Math.floor(t+S),N=Math.floor(i+S),C=(U+b+F+N)*o,P=r-(U-C),T=e-(b-C),_=t-(F-C),j=i-(N-C),k=0,z=0,B=0,E=0;P>T?k++:z++,P>_?k++:B++,P>j?k++:E++,T>_?z++:B++,T>j?z++:E++,_>j?B++:E++;var G=P-(l=k>=3?1:0)+o,H=T-(u=z>=3?1:0)+o,I=_-(d=B>=3?1:0)+o,J=j-(p=E>=3?1:0)+o,K=P-(M=k>=2?1:0)+2*o,L=T-(m=z>=2?1:0)+2*o,O=_-(c=B>=2?1:0)+2*o,Q=j-(y=E>=2?1:0)+2*o,R=P-(w=k>=1?1:0)+3*o,V=T-(g=z>=1?1:0)+3*o,W=_-(A=B>=1?1:0)+3*o,X=j-(x=E>=1?1:0)+3*o,Y=P-1+4*o,Z=T-1+4*o,$=_-1+4*o,rr=j-1+4*o,er=255&U,tr=255&b,ar=255&F,or=255&N,ir=.6-P*P-T*T-_*_-j*j;if(ir<0)n=0;else{var nr=q[er+q[tr+q[ar+q[or]]]]%32*4;n=(ir*=ir)*ir*(D[nr]*P+D[nr+1]*T+D[nr+2]*_+D[nr+3]*j)}var fr=.6-G*G-H*H-I*I-J*J;if(fr<0)f=0;else{var sr=q[er+l+q[tr+u+q[ar+d+q[or+p]]]]%32*4;f=(fr*=fr)*fr*(D[sr]*G+D[sr+1]*H+D[sr+2]*I+D[sr+3]*J)}var vr=.6-K*K-L*L-O*O-Q*Q;if(vr<0)s=0;else{var hr=q[er+M+q[tr+m+q[ar+c+q[or+y]]]]%32*4;s=(vr*=vr)*vr*(D[hr]*K+D[hr+1]*L+D[hr+2]*O+D[hr+3]*Q)}
56599var lr=.6-R*R-V*V-W*W-X*X;if(lr<0)v=0;else{var ur=q[er+w+q[tr+g+q[ar+A+q[or+x]]]]%32*4;v=(lr*=lr)*lr*(D[ur]*R+D[ur+1]*V+D[ur+2]*W+D[ur+3]*X)}var dr=.6-Y*Y-Z*Z-$*$-rr*rr;if(dr<0)h=0;else{var pr=q[er+1+q[tr+1+q[ar+1+q[or+1]]]]%32*4;h=(dr*=dr)*dr*(D[pr]*Y+D[pr+1]*Z+D[pr+2]*$+D[pr+3]*rr)}return 27*(n+f+s+v+h)}},i._buildPermutationTable=n,"undefined"!=typeof define&&define.amd&&define(function(){return i}),"undefined"!=typeof exports?exports.SimplexNoise=i:"undefined"!=typeof window&&(window.SimplexNoise=i),"undefined"!=typeof module&&(module.exports=i)}();

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.