PageSourceSearch

https://zeroknowledge.fm/wp-content/themes/uncode/library/js/plugins.js?ver=2026391459

js zeroknowledge.fm collected 2026-09-24 17:18:37 UTC 1,480,819 bytes, 44,820 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: 30,026 bytes, lines 2077-3039
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) {
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
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  };
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})));
5622"use strict";
5623
5624function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
5625function _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); } }
5626function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
5627function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
5628function _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); }
5629function _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); }
5630(function (global, factory) {
5631  (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());
5632})(void 0, function () {
5633  'use strict';
5634
5635  var version = "1.1.9";
5636
5637  // Clamp a value between a minimum and maximum value
5638  function clamp(min, input, max) {
5639    return Math.max(min, Math.min(input, max));
5640  }
5641
5642  // Linearly interpolate between two values using an amount (0 <= t <= 1)
5643  function lerp(x, y, t) {
5644    return (1 - t) * x + t * y;
5645  }
5646
5647  // http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/
5648  function damp(x, y, lambda, dt) {
5649    return lerp(x, y, 1 - Math.exp(-lambda * dt));
5650  }
5651
5652  // Calculate the modulo of the dividend and divisor while keeping the result within the same sign as the divisor
5653  // https://anguscroll.com/just/just-modulo
5654  function modulo(n, d) {
5655    return (n % d + d) % d;
5656  }
5657  var Animate = /*#__PURE__*/function () {
5658    function Animate() {
5659      _classCallCheck(this, Animate);
5660      this.isRunning = false;
5661      this.value = 0;
5662      this.from = 0;
5663      this.to = 0;
5664      this.duration = 0;
5665      this.currentTime = 0;
5666    }
5667    _createClass(Animate, [{
5668      key: "advance",
5669      value: function advance(deltaTime) {
5670        var _a;
5671        if (!this.isRunning) return;
5672        var completed = false;
5673        if (this.duration && this.easing) {
5674          this.currentTime += deltaTime;
5675          var linearProgress = clamp(0, this.currentTime / this.duration, 1);
5676          completed = linearProgress >= 1;
5677          var easedProgress = completed ? 1 : this.easing(linearProgress);
5678          this.value = this.from + (this.to - this.from) * easedProgress;
5679        } else if (this.lerp) {
5680          this.value = damp(this.value, this.to, this.lerp * 60, deltaTime);
5681          if (Math.round(this.value) === this.to) {
5682            this.value = this.to;
5683            completed = true;
5684          }
5685        } else {
5686          this.value = this.to;
5687          completed = true;
5688        }
5689        if (completed) {
5690          this.stop();
5691        }
5692        (_a = this.onUpdate) === null || _a === void 0 ? void 0 : _a.call(this, this.value, completed);
5693      }
5694    }, {
5695      key: "stop",
5696      value: function stop() {
5697        this.isRunning = false;
5698      }
5699    }, {
5700      key: "fromTo",
5701      value: function fromTo(from, to, _ref) {
5702        var lerp = _ref.lerp,
5703          duration = _ref.duration,
5704          easing = _ref.easing,
5705          onStart = _ref.onStart,
5706          onUpdate = _ref.onUpdate;
5707        this.from = this.value = from;
5708        this.to = to;
5709        this.lerp = lerp;
5710        this.duration = duration;
5711        this.easing = easing;
5712        this.currentTime = 0;
5713        this.isRunning = true;
5714        onStart === null || onStart === void 0 ? void 0 : onStart();
5715        this.onUpdate = onUpdate;
5716      }
5717    }]);
5718    return Animate;
5719  }();
5720  function debounce(callback, delay) {
5721    var timer;
5722    return function () {
5723      var args = arguments;
5724      var context = this;
5725      clearTimeout(timer);
5726      timer = setTimeout(function () {
5727        callback.apply(context, args);
5728      }, delay);
5729    };
5730  }
5731  var Dimensions = /*#__PURE__*/function () {
5732    function Dimensions() {
5733      var _this = this;
5734      var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
5735        wrapper = _ref2.wrapper,
5736        content = _ref2.content,
5737        _ref2$autoResize = _ref2.autoResize,
5738        autoResize = _ref2$autoResize === void 0 ? true : _ref2$autoResize,
5739        _ref2$debounce = _ref2.debounce,
5740        debounceValue = _ref2$debounce === void 0 ? 250 : _ref2$debounce;
5741      _classCallCheck(this, Dimensions);
5742      this.width = 0;
5743      this.height = 0;
5744      this.scrollWidth = 0;
5745      this.scrollHeight = 0;
5746      this.resize = function () {
5747        _this.onWrapperResize();
5748        _this.onContentResize();
5749      };
5750      this.onWrapperResize = function () {
5751        if (_this.wrapper === window) {
5752          _this.width = window.innerWidth;
5753          _this.height = window.innerHeight;
5754        } else if (_this.wrapper instanceof HTMLElement) {
5755          _this.width = _this.wrapper.clientWidth;
5756          _this.height = _this.wrapper.clientHeight;
5757        }
5758      };
5759      this.onContentResize = function () {
5760        if (_this.wrapper === window) {
5761          _this.scrollHeight = _this.content.scrollHeight;
5762          _this.scrollWidth = _this.content.scrollWidth;
5763        } else if (_this.wrapper instanceof HTMLElement) {
5764          _this.scrollHeight = _this.wrapper.scrollHeight;
5765          _this.scrollWidth = _this.wrapper.scrollWidth;
5766        }
5767      };
5768      this.wrapper = wrapper;
5769      this.content = content;
5770      if (autoResize) {
5771        this.debouncedResize = debounce(this.resize, debounceValue);
5772        if (this.wrapper === window) {
5773          window.addEventListener('resize', this.debouncedResize, false);
5774        } else {
5775          this.wrapperResizeObserver = new ResizeObserver(this.debouncedResize);
5776          this.wrapperResizeObserver.observe(this.wrapper);
5777        }
5778        this.contentResizeObserver = new ResizeObserver(this.debouncedResize);
5779        this.contentResizeObserver.observe(this.content);
5780      }
5781      this.resize();
5782    }
5783    _createClass(Dimensions, [{
5784      key: "destroy",
5785      value: function destroy() {
5786        var _a, _b;
5787        (_a = this.wrapperResizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
5788        (_b = this.contentResizeObserver) === null || _b === void 0 ? void 0 : _b.disconnect();
5789        window.removeEventListener('resize', this.debouncedResize, false);
5790      }
5791    }, {
5792      key: "limit",
5793      get: function get() {
5794        return {
5795          x: this.scrollWidth - this.width,
5796          y: this.scrollHeight - this.height
5797        };
5798      }
5799    }]);
5800    return Dimensions;
5801  }();
5802  var Emitter = /*#__PURE__*/function () {
5803    function Emitter() {
5804      _classCallCheck(this, Emitter);
5805      this.events = {};
5806    }
5807    _createClass(Emitter, [{
5808      key: "emit",
5809      value: function emit(event) {
5810        var callbacks = this.events[event] || [];
5811        for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
5812          args[_key - 1] = arguments[_key];
5813        }
5814        for (var i = 0, length = callbacks.length; i < length; i++) {
5815          callbacks[i].apply(callbacks, args);
5816        }
5817      }
5818    }, {
5819      key: "on",
5820      value: function on(event, callback) {
5821        var _this2 = this;
5822        var _a;
5823        ((_a = this.events[event]) === null || _a === void 0 ? void 0 : _a.push(callback)) || (this.events[event] = [callback]);
5824        return function () {
5825          var _a;
5826          _this2.events[event] = (_a = _this2.events[event]) === null || _a === void 0 ? void 0 : _a.filter(function (i) {
5827            return callback !== i;
5828          });
5829        };
5830      }
5831    }, {
5832      key: "off",
5833      value: function off(event, callback) {
5834        var _a;
5835        this.events[event] = (_a = this.events[event]) === null || _a === void 0 ? void 0 : _a.filter(function (i) {
5836          return callback !== i;
5837        });
5838      }
5839    }, {
5840      key: "destroy",
5841      value: function destroy() {
5842        this.events = {};
5843      }
5844    }]);
5845    return Emitter;
5846  }();
5847  var LINE_HEIGHT = 100 / 6;
5848  var VirtualScroll = /*#__PURE__*/function () {
5849    function VirtualScroll(element, _ref3) {
5850      var _this3 = this;
5851      var _ref3$wheelMultiplier = _ref3.wheelMultiplier,
5852        wheelMultiplier = _ref3$wheelMultiplier === void 0 ? 1 : _ref3$wheelMultiplier,
5853        _ref3$touchMultiplier = _ref3.touchMultiplier,
5854        touchMultiplier = _ref3$touchMultiplier === void 0 ? 1 : _ref3$touchMultiplier;
5855      _classCallCheck(this, VirtualScroll);
5856      this.lastDelta = {
5857        x: 0,
5858        y: 0
5859      };
5860      this.windowWidth = 0;
5861      this.windowHeight = 0;
5862      this.onTouchStart = function (event) {
5863        var _ref4 = event.targetTouches ? event.targetTouches[0] : event,
5864          clientX = _ref4.clientX,
5865          clientY = _ref4.clientY;
5866        _this3.touchStart.x = clientX;
5867        _this3.touchStart.y = clientY;
5868        _this3.lastDelta = {
5869          x: 0,
5870          y: 0
5871        };
5872        _this3.emitter.emit('scroll', {
5873          deltaX: 0,
5874          deltaY: 0,
5875          event: event
5876        });
5877      };
5878      this.onTouchMove = function (event) {
5879        var _a, _b, _c, _d;
5880        var _ref5 = event.targetTouches ? event.targetTouches[0] : event,
5881          clientX = _ref5.clientX,
5882          clientY = _ref5.clientY;
5883        var deltaX = -(clientX - ((_b = (_a = _this3.touchStart) === null || _a === void 0 ? void 0 : _a.x) !== null && _b !== void 0 ? _b : 0)) * _this3.touchMultiplier;
5884        var deltaY = -(clientY - ((_d = (_c = _this3.touchStart) === null || _c === void 0 ? void 0 : _c.y) !== null && _d !== void 0 ? _d : 0)) * _this3.touchMultiplier;
5885        _this3.touchStart.x = clientX;
5886        _this3.touchStart.y = clientY;
5887        _this3.lastDelta = {
5888          x: deltaX,
5889          y: deltaY
5890        };
5891        _this3.emitter.emit('scroll', {
5892          deltaX: deltaX,
5893          deltaY: deltaY,
5894          event: event
5895        });
5896      };
5897      this.onTouchEnd = function (event) {
5898        _this3.emitter.emit('scroll', {
5899          deltaX: _this3.lastDelta.x,
5900          deltaY: _this3.lastDelta.y,
5901          event: event
5902        });
5903      };
5904      this.onWheel = function (event) {
5905        var deltaX = event.deltaX,
5906          deltaY = event.deltaY,
5907          deltaMode = event.deltaMode;
5908        var multiplierX = deltaMode === 1 ? LINE_HEIGHT : deltaMode === 2 ? _this3.windowWidth : 1;
5909        var multiplierY = deltaMode === 1 ? LINE_HEIGHT : deltaMode === 2 ? _this3.windowHeight : 1;
5910        deltaX *= multiplierX;
5911        deltaY *= multiplierY;
5912        deltaX *= _this3.wheelMultiplier;
5913        deltaY *= _this3.wheelMultiplier;
5914        _this3.emitter.emit('scroll', {
5915          deltaX: deltaX,
5916          deltaY: deltaY,
5917          event: event
5918        });
5919      };
5920      this.onWindowResize = function () {
5921        _this3.windowWidth = window.innerWidth;
5922        _this3.windowHeight = window.innerHeight;
5923      };
5924      this.element = element;
5925      this.wheelMultiplier = wheelMultiplier;
5926      this.touchMultiplier = touchMultiplier;
5927      this.touchStart = {
5928        x: null,
5929        y: null
5930      };
5931      this.emitter = new Emitter();
5932      window.addEventListener('resize', this.onWindowResize, false);
5933      this.onWindowResize();
5934      this.element.addEventListener('wheel', this.onWheel, {
5935        passive: false
5936      });
5937      this.element.addEventListener('touchstart', this.onTouchStart, {
5938        passive: false
5939      });
5940      this.element.addEventListener('touchmove', this.onTouchMove, {
5941        passive: false
5942      });
5943      this.element.addEventListener('touchend', this.onTouchEnd, {
5944        passive: false
5945      });
5946    }
5947    _createClass(VirtualScroll, [{
5948      key: "on",
5949      value: function on(event, callback) {
5950        return this.emitter.on(event, callback);
5951      }
5952    }, {
5953      key: "destroy",
5954      value: function destroy() {
5955        this.emitter.destroy();
5956        window.removeEventListener('resize', this.onWindowResize, false);
5957        this.element.removeEventListener('wheel', this.onWheel);
5958        this.element.removeEventListener('touchstart', this.onTouchStart);
5959        this.element.removeEventListener('touchmove', this.onTouchMove);
5960        this.element.removeEventListener('touchend', this.onTouchEnd);
5961      }
5962    }]);
5963    return VirtualScroll;
5964  }();
5965  var Lenis = /*#__PURE__*/function () {
5966    function Lenis() {
5967      var _this4 = this;
5968      var _ref6 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
5969        _ref6$wrapper = _ref6.wrapper,
5970        wrapper = _ref6$wrapper === void 0 ? window : _ref6$wrapper,
5971        _ref6$content = _ref6.content,
5972        content = _ref6$content === void 0 ? document.documentElement : _ref6$content,
5973        _ref6$wheelEventsTarg = _ref6.wheelEventsTarget,
5974        wheelEventsTarget = _ref6$wheelEventsTarg === void 0 ? wrapper : _ref6$wheelEventsTarg,
5975        _ref6$eventsTarget = _ref6.eventsTarget,
5976        eventsTarget = _ref6$eventsTarget === void 0 ? wheelEventsTarget : _ref6$eventsTarget,
5977        _ref6$smoothWheel = _ref6.smoothWheel,
5978        smoothWheel = _ref6$smoothWheel === void 0 ? true : _ref6$smoothWheel,
5979        _ref6$syncTouch = _ref6.syncTouch,
5980        syncTouch = _ref6$syncTouch === void 0 ? false : _ref6$syncTouch,
5981        _ref6$syncTouchLerp = _ref6.syncTouchLerp,
5982        syncTouchLerp = _ref6$syncTouchLerp === void 0 ? 0.075 : _ref6$syncTouchLerp,
5983        _ref6$touchInertiaMul = _ref6.touchInertiaMultiplier,
5984        touchInertiaMultiplier = _ref6$touchInertiaMul === void 0 ? 35 : _ref6$touchInertiaMul,
5985        duration = _ref6.duration,
5986        _ref6$easing = _ref6.easing,
5987        easing = _ref6$easing === void 0 ? function (t) {
5988          return Math.min(1, 1.001 - Math.pow(2, -10 * t));
5989        } : _ref6$easing,
5990        _ref6$lerp = _ref6.lerp,
5991        lerp = _ref6$lerp === void 0 ? 0.1 : _ref6$lerp,
5992        _ref6$infinite = _ref6.infinite,
5993        infinite = _ref6$infinite === void 0 ? false : _ref6$infinite,
5994        _ref6$orientation = _ref6.orientation,
5995        orientation = _ref6$orientation === void 0 ? 'vertical' : _ref6$orientation,
5996        _ref6$gestureOrientat = _ref6.gestureOrientation,
5997        gestureOrientation = _ref6$gestureOrientat === void 0 ? 'vertical' : _ref6$gestureOrientat,
5998        _ref6$touchMultiplier = _ref6.touchMultiplier,
5999        touchMultiplier = _ref6$touchMultiplier === void 0 ? 1 : _ref6$touchMultiplier,
6000        _ref6$wheelMultiplier = _ref6.wheelMultiplier,
6001        wheelMultiplier = _ref6$wheelMultiplier === void 0 ? 1 : _ref6$wheelMultiplier,
6002        _ref6$autoResize = _ref6.autoResize,
6003        autoResize = _ref6$autoResize === void 0 ? true : _ref6$autoResize,
6004        prevent = _ref6.prevent,
6005        virtualScroll = _ref6.virtualScroll,
6006        _ref6$__experimental_ = _ref6.__experimental__naiveDimensions,
6007        __experimental__naiveDimensions = _ref6$__experimental_ === void 0 ? false : _ref6$__experimental_;
6008      _classCallCheck(this, Lenis);
6009      this.__isScrolling = false;
6010      this.__isStopped = false;
6011      this.__isLocked = false;
6012      this.userData = {};
6013      this.lastVelocity = 0;
6014      this.velocity = 0;
6015      this.direction = 0;
6016      this.onPointerDown = function (event) {
6017        if (event.button === 1) {
6018          _this4.reset();
6019        }
6020      };
6021      this.onVirtualScroll = function (data) {
6022        if (typeof _this4.options.virtualScroll === 'function' && _this4.options.virtualScroll(data) === false) return;
6023        var deltaX = data.deltaX,
6024          deltaY = data.deltaY,
6025          event = data.event;
6026        _this4.emitter.emit('virtual-scroll', {
6027          deltaX: deltaX,
6028          deltaY: deltaY,
6029          event: event
6030        });
6031        if (event.ctrlKey) return;
6032        var isTouch = event.type.includes('touch');
6033        var isWheel = event.type.includes('wheel');
6034        _this4.isTouching = event.type === 'touchstart' || event.type === 'touchmove';
6035        var isTapToStop = _this4.options.syncTouch && isTouch && event.type === 'touchstart' && !_this4.isStopped && !_this4.isLocked;
6036        if (isTapToStop) {
6037          _this4.reset();
6038          return;
6039        }
6040        var isClick = deltaX === 0 && deltaY === 0;
6041        var isUnknownGesture = _this4.options.gestureOrientation === 'vertical' && deltaY === 0 || _this4.options.gestureOrientation === 'horizontal' && deltaX === 0;
6042        if (isClick || isUnknownGesture) {
6043          return;
6044        }
6045        var composedPath = event.composedPath();
6046        composedPath = composedPath.slice(0, composedPath.indexOf(_this4.rootElement));
6047        var prevent = _this4.options.prevent;
6048        if (!!composedPath.find(function (node) {
6049          var _a, _b, _c, _d, _e;
6050          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')));
6051        })) return;
6052        if (_this4.isStopped || _this4.isLocked) {
6053          event.preventDefault();
6054          return;
6055        }
6056        var isSmooth = _this4.options.syncTouch && isTouch || _this4.options.smoothWheel && isWheel;
6057        if (!isSmooth) {
6058          _this4.isScrolling = 'native';
6059          _this4.animate.stop();
6060          return;
6061        }
6062        event.preventDefault();
6063        var delta = deltaY;
6064        if (_this4.options.gestureOrientation === 'both') {
6065          delta = Math.abs(deltaY) > Math.abs(deltaX) ? deltaY : deltaX;
6066        } else if (_this4.options.gestureOrientation === 'horizontal') {
6067          delta = deltaX;
6068        }
6069        var syncTouch = isTouch && _this4.options.syncTouch;
6070        var isTouchEnd = isTouch && event.type === 'touchend';
6071        var hasTouchInertia = isTouchEnd && Math.abs(delta) > 5;
6072        if (hasTouchInertia) {
6073          delta = _this4.velocity * _this4.options.touchInertiaMultiplier;
6074        }
6075        _this4.scrollTo(_this4.targetScroll + delta, Object.assign({
6076          programmatic: false
6077        }, syncTouch ? {
6078          lerp: hasTouchInertia ? _this4.options.syncTouchLerp : 1
6079        } : {
6080          lerp: _this4.options.lerp,
6081          duration: _this4.options.duration,
6082          easing: _this4.options.easing
6083        }));
6084      };
6085      this.onNativeScroll = function () {
6086        clearTimeout(_this4.__resetVelocityTimeout);
6087        delete _this4.__resetVelocityTimeout;
6088        if (_this4.__preventNextNativeScrollEvent) {
6089          delete _this4.__preventNextNativeScrollEvent;
6090          return;
6091        }
6092        if (_this4.isScrolling === false || _this4.isScrolling === 'native') {
6093          var lastScroll = _this4.animatedScroll;
6094          _this4.animatedScroll = _this4.targetScroll = _this4.actualScroll;
6095          _this4.lastVelocity = _this4.velocity;
6096          _this4.velocity = _this4.animatedScroll - lastScroll;
6097          _this4.direction = Math.sign(_this4.animatedScroll - lastScroll);
6098          _this4.isScrolling = 'native';
6099          _this4.emit();
6100          if (_this4.velocity !== 0) {
6101            _this4.__resetVelocityTimeout = setTimeout(function () {
6102              _this4.lastVelocity = _this4.velocity;
6103              _this4.velocity = 0;
6104              _this4.isScrolling = false;
6105              _this4.emit();
6106            }, 400);
6107          }
6108        }
6109      };
6110      window.lenisVersion = version;
6111      if (!wrapper || wrapper === document.documentElement || wrapper === document.body) {
6112        wrapper = window;
6113      }
6114      this.options = {
6115        wrapper: wrapper,
6116        content: content,
6117        wheelEventsTarget: wheelEventsTarget,
6118        eventsTarget: eventsTarget,
6119        smoothWheel: smoothWheel,
6120        syncTouch: syncTouch,
6121        syncTouchLerp: syncTouchLerp,
6122        touchInertiaMultiplier: touchInertiaMultiplier,
6123        duration: duration,
6124        easing: easing,
6125        lerp: lerp,
6126        infinite: infinite,
6127        gestureOrientation: gestureOrientation,
6128        orientation: orientation,
6129        touchMultiplier: touchMultiplier,
6130        wheelMultiplier: wheelMultiplier,
6131        autoResize: autoResize,
6132        prevent: prevent,
6133        virtualScroll: virtualScroll,
6134        __experimental__naiveDimensions: __experimental__naiveDimensions
6135      };
6136      this.animate = new Animate();
6137      this.emitter = new Emitter();
6138      this.dimensions = new Dimensions({
6139        wrapper: wrapper,
6140        content: content,
6141        autoResize: autoResize
6142      });
6143      this.updateClassName();
6144      this.userData = {};
6145      this.time = 0;
6146      this.velocity = this.lastVelocity = 0;
6147      this.isLocked = false;
6148      this.isStopped = false;
6149      this.isScrolling = false;
6150      this.targetScroll = this.animatedScroll = this.actualScroll;
6151      this.options.wrapper.addEventListener('scroll', this.onNativeScroll, false);
6152      this.options.wrapper.addEventListener('pointerdown', this.onPointerDown, false);
6153      this.virtualScroll = new VirtualScroll(eventsTarget, {
6154        touchMultiplier: touchMultiplier,
6155        wheelMultiplier: wheelMultiplier
6156      });
6157      this.virtualScroll.on('scroll', this.onVirtualScroll);
6158    }
6159    _createClass(Lenis, [{
6160      key: "destroy",
6161      value: function destroy() {
6162        this.emitter.destroy();
6163        this.options.wrapper.removeEventListener('scroll', this.onNativeScroll, false);
6164        this.options.wrapper.removeEventListener('pointerdown', this.onPointerDown, false);
6165        this.virtualScroll.destroy();
6166        this.dimensions.destroy();
6167        this.cleanUpClassName();
6168      }
6169    }, {
6170      key: "on",
6171      value: function on(event, callback) {
6172        return this.emitter.on(event, callback);
6173      }
6174    }, {
6175      key: "off",
6176      value: function off(event, callback) {
6177        return this.emitter.off(event, callback);
6178      }
6179    }, {
6180      key: "setScroll",
6181      value: function setScroll(scroll) {
6182        if (this.isHorizontal) {
6183          this.rootElement.scrollLeft = scroll;
6184        } else {
6185          this.rootElement.scrollTop = scroll;
6186        }
6187      }
6188    }, {
6189      key: "resize",
6190      value: function resize() {
6191        this.dimensions.resize();
6192      }
6193    }, {
6194      key: "emit",
6195      value: function emit() {
6196        this.emitter.emit('scroll', this);
6197      }
6198    }, {
6199      key: "reset",
6200      value: function reset() {
6201        this.isLocked = false;
6202        this.isScrolling = false;
6203        this.animatedScroll = this.targetScroll = this.actualScroll;
6204        this.lastVelocity = this.velocity = 0;
6205        this.animate.stop();
6206      }
6207    }, {
6208      key: "start",
6209      value: function start() {
6210        if (!this.isStopped) return;
6211        this.isStopped = false;
6212        this.reset();
6213      }
6214    }, {
6215      key: "stop",
6216      value: function stop() {
6217        if (this.isStopped) return;
6218        this.isStopped = true;
6219        this.animate.stop();
6220        this.reset();
6221      }
6222    }, {
6223      key: "raf",
6224      value: function raf(time) {
6225        var deltaTime = time - (this.time || time);
6226        this.time = time;
6227        this.animate.advance(deltaTime * 0.001);
6228      }
6229    }, {
6230      key: "scrollTo",
6231      value: function scrollTo(target) {
6232        var _this5 = this;
6233        var _ref7 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
6234          _ref7$offset = _ref7.offset,
6235          offset = _ref7$offset === void 0 ? 0 : _ref7$offset,
6236          _ref7$immediate = _ref7.immediate,
6237          immediate = _ref7$immediate === void 0 ? false : _ref7$immediate,
6238          _ref7$lock = _ref7.lock,
6239          lock = _ref7$lock === void 0 ? false : _ref7$lock,
6240          _ref7$duration = _ref7.duration,
6241          duration = _ref7$duration === void 0 ? this.options.duration : _ref7$duration,
6242          _ref7$easing = _ref7.easing,
6243          easing = _ref7$easing === void 0 ? this.options.easing : _ref7$easing,
6244          _ref7$lerp = _ref7.lerp,
6245          lerp = _ref7$lerp === void 0 ? this.options.lerp : _ref7$lerp,
6246          _onStart = _ref7.onStart,
6247          onComplete = _ref7.onComplete,
6248          _ref7$force = _ref7.force,
6249          force = _ref7$force === void 0 ? false : _ref7$force,
6250          _ref7$programmatic = _ref7.programmatic,
6251          programmatic = _ref7$programmatic === void 0 ? true : _ref7$programmatic,
6252          _ref7$userData = _ref7.userData,
6253          userData = _ref7$userData === void 0 ? {} : _ref7$userData;
6254        if ((this.isStopped || this.isLocked) && !force) return;
6255        if (typeof target === 'string' && ['top', 'left', 'start'].includes(target)) {
6256          target = 0;
6257        } else if (typeof target === 'string' && ['bottom', 'right', 'end'].includes(target)) {
6258          target = this.limit;
6259        } else {
6260          var node;
6261          if (typeof target === 'string') {
6262            node = document.querySelector(target);
6263          } else if (target instanceof HTMLElement && (target === null || target === void 0 ? void 0 : target.nodeType)) {
6264            node = target;
6265          }
6266          if (node) {
6267            if (this.options.wrapper !== window) {
6268              var wrapperRect = this.rootElement.getBoundingClientRect();
6269              offset -= this.isHorizontal ? wrapperRect.left : wrapperRect.top;
6270            }
6271            var rect = node.getBoundingClientRect();
6272            target = (this.isHorizontal ? rect.left : rect.top) + this.animatedScroll;
6273          }
6274        }
6275        if (typeof target !== 'number') return;
6276        target += offset;
6277        target = Math.round(target);
6278        if (this.options.infinite) {
6279          if (programmatic) {
6280            this.targetScroll = this.animatedScroll = this.scroll;
6281          }
6282        } else {
6283          target = clamp(0, target, this.limit);
6284        }
6285        if (target === this.targetScroll) return;
6286        this.userData = userData;
6287        if (immediate) {
6288          this.animatedScroll = this.targetScroll = target;
6289          this.setScroll(this.scroll);
6290          this.reset();
6291          this.preventNextNativeScrollEvent();
6292          this.emit();
6293          onComplete === null || onComplete === void 0 ? void 0 : onComplete(this);
6294          this.userData = {};
6295          return;
6296        }
6297        if (!programmatic) {
6298          this.targetScroll = target;
6299        }
6300        this.animate.fromTo(this.animatedScroll, target, {
6301          duration: duration,
6302          easing: easing,
6303          lerp: lerp,
6304          onStart: function onStart() {
6305            if (lock) _this5.isLocked = true;
6306            _this5.isScrolling = 'smooth';
6307            _onStart === null || _onStart === void 0 ? void 0 : _onStart(_this5);
6308          },
6309          onUpdate: function onUpdate(value, completed) {
6310            _this5.isScrolling = 'smooth';
6311            _this5.lastVelocity = _this5.velocity;
6312            _this5.velocity = value - _this5.animatedScroll;
6313            _this5.direction = Math.sign(_this5.velocity);
6314            _this5.animatedScroll = value;
6315            _this5.setScroll(_this5.scroll);
6316            if (programmatic) {
6317              _this5.targetScroll = value;
6318            }
6319            if (!completed) _this5.emit();
6320            if (completed) {
6321              _this5.reset();
6322              _this5.emit();
6323              onComplete === null || onComplete === void 0 ? void 0 : onComplete(_this5);
6324              _this5.userData = {};
6325              _this5.preventNextNativeScrollEvent();
6326            }
6327          }
6328        });
6329      }
6330    }, {
6331      key: "preventNextNativeScrollEvent",
6332      value: function preventNextNativeScrollEvent() {
6333        var _this6 = this;
6334        this.__preventNextNativeScrollEvent = true;
6335        requestAnimationFrame(function () {
6336          delete _this6.__preventNextNativeScrollEvent;
6337        });
6338      }
6339    }, {
6340      key: "rootElement",
6341      get: function get() {
6342        return this.options.wrapper === window ? document.documentElement : this.options.wrapper;
6343      }
6344    }, {
6345      key: "limit",
6346      get: function get() {
6347        if (this.options.__experimental__naiveDimensions) {
6348          if (this.isHorizontal) {
6349            return this.rootElement.scrollWidth - this.rootElement.clientWidth;
6350          } else {
6351            return this.rootElement.scrollHeight - this.rootElement.clientHeight;
6352          }
6353        } else {
6354          return this.dimensions.limit[this.isHorizontal ? 'x' : 'y'];
6355        }
6356      }
6357    }, {
6358      key: "isHorizontal",
6359      get: function get() {
6360        return this.options.orientation === 'horizontal';
6361      }
6362    }, {
6363      key: "actualScroll",
6364      get: function get() {
6365        return this.isHorizontal ? this.rootElement.scrollLeft : this.rootElement.scrollTop;
6366      }
6367    }, {
6368      key: "scroll",
6369      get: function get() {
6370        return this.options.infinite ? modulo(this.animatedScroll, this.limit) : this.animatedScroll;
6371      }
6372    }, {
6373      key: "progress",
6374      get: function get() {
6375        return this.limit === 0 ? 1 : this.scroll / this.limit;
6376      }
6377    }, {
6378      key: "isScrolling",
6379      get: function get() {
6380        return this.__isScrolling;
6381      },
6382      set: function set(value) {
6383        if (this.__isScrolling !== value) {
6384          this.__isScrolling = value;
6385          this.updateClassName();
6386        }
6387      }
6388    }, {
6389      key: "isStopped",
6390      get: function get() {
6391        return this.__isStopped;
6392      },
6393      set: function set(value) {
6394        if (this.__isStopped !== value) {
6395          this.__isStopped = value;
6396          this.updateClassName();
6397        }
6398      }
6399    }, {
6400      key: "isLocked",
6401      get: function get() {
6402        return this.__isLocked;
6403      },
6404      set: function set(value) {
6405        if (this.__isLocked !== value) {
6406          this.__isLocked = value;
6407          this.updateClassName();
6408        }
6409      }
6410    }, {
6411      key: "isSmooth",
6412      get: function get() {
6413        return this.isScrolling === 'smooth';
6414      }
6415    }, {
6416      key: "className",
6417      get: function get() {
6418        var className = 'lenis';
6419        if (this.isStopped) className += ' lenis-stopped';
6420        if (this.isLocked) className += ' lenis-locked';
6421        if (this.isScrolling) className += ' lenis-scrolling';
6422        if (this.isScrolling === 'smooth') className += ' lenis-smooth';
6423        return className;
6424      }
6425    }, {
6426      key: "updateClassName",
6427      value: function updateClassName() {
6428        this.cleanUpClassName();
6429        this.rootElement.className = "".concat(this.rootElement.className, " ").concat(this.className).trim();
6430      }
6431    }, {
6432      key: "cleanUpClassName",
6433      value: function cleanUpClassName() {
6434        this.rootElement.className = this.rootElement.className.replace(/lenis(-\w+)?/g, '').trim();
6435      }
6436    }]);
6437    return Lenis;
6438  }();
6439  return Lenis;
6440});
6441(function(window, $) {
6442  "use strict";
6443
6444  var counter = 0,
6445    $headCache = $('head'),
6446    oldBigText = window.BigText,
6447    oldjQueryMethod = $.fn.bigtext,
6448    BigText = {
6449      DEBUG_MODE: false,
6450      DEFAULT_MIN_FONT_SIZE_PX: null,
6451      DEFAULT_MAX_FONT_SIZE_PX: 528,
6452      GLOBAL_STYLE_ID: 'bigtext-style',
6453      STYLE_ID: 'bigtext-id',
6454      LINE_CLASS_PREFIX: 'bigtext-line',
6455      EXEMPT_CLASS: 'bigtext-exempt',
6456      noConflict: function(restore)
6457      {
6458        if(restore) {
6459          $.fn.bigtext = oldjQueryMethod;
6460          window.BigText = oldBigText;
6461        }
6462        return BigText;
6463      },
6464      supports: {
6465        wholeNumberFontSizeOnly: (function() {
6466          if( !( 'getComputedStyle' in window ) ) {
6467            return true;
6468          }
6469          var test = $('<div/>').css({
6470              position: 'absolute',
6471              'font-size': '14.1px'
6472            }).insertBefore( $('script').eq(0) ),
6473            computedStyle = window.getComputedStyle( test[0], null );
6474
6475          var ret = computedStyle && computedStyle.getPropertyValue( 'font-size' ) === '14px';
6476          test.remove();
6477          return ret;
6478        })()
6479      },
6480      init: function() {
6481        if(!$('#'+BigText.GLOBAL_STYLE_ID).length) {
6482          $headCache.append(BigText.generateStyleTag(BigText.GLOBAL_STYLE_ID, ['.bigtext * { white-space: nowrap; } .bigtext > * { display: block; }',
6483                                          '.bigtext .' + BigText.EXEMPT_CLASS + ', .bigtext .' + BigText.EXEMPT_CLASS + ' * { white-space: normal; }']));
6484        }
6485      },
6486      bindResize: function(eventName, resizeFunction) {
6487        var timeoutId;
6488        $(window).off(eventName).on(eventName, function() {
6489          if( timeoutId ) {
6490            clearTimeout( timeoutId );
6491          }
6492          timeoutId = setTimeout( resizeFunction, 100 );
6493        });
6494      },
6495      getStyleId: function(id)
6496      {
6497        return BigText.STYLE_ID + '-' + id;
6498      },
6499      generateStyleTag: function(id, css)
6500      {
6501        return $('<style>' + css.join('\n') + '</style>').attr('id', id);
6502      },
6503      clearCss: function(id)
6504      {
6505        var styleId = BigText.getStyleId(id);
6506        $('#' + styleId).remove();
6507      },
6508      generateCss: function(id, linesFontSizes, lineWordSpacings, minFontSizes)
6509      {
6510        var css = [];
6511
6512        BigText.clearCss(id);
6513
6514        for(var j=0, k=linesFontSizes.length; j<k; j++) {
6515          css.push('#' + id + ' .' + BigText.LINE_CLASS_PREFIX + j + ' {' +
6516            (minFontSizes[j] ? ' white-space: normal;' : '') +
6517            (linesFontSizes[j] ? ' font-size: ' + linesFontSizes[j] + 'px;' : '') +
6518            (lineWordSpacings[j] ? ' word-spacing: ' + lineWordSpacings[j] + 'px;' : '') +
6519            '}');
6520        }
6521
6522        return BigText.generateStyleTag(BigText.getStyleId(id), css);
6523      },
6524      jQueryMethod: function(options)
6525      {
6526        BigText.init();
6527
6528        options = $.extend({
6529          minfontsize: BigText.DEFAULT_MIN_FONT_SIZE_PX,
6530          maxfontsize: BigText.DEFAULT_MAX_FONT_SIZE_PX,
6531          childSelector: '',
6532          resize: true
6533        }, options || {});
6534
6535        this.each(function()
6536        {
6537          var $t = $(this).addClass('bigtext'),
6538            maxWidth = $t.width(),
6539            id = $t.attr('id'),
6540            $children = options.childSelector ? $t.find( options.childSelector ) : $t.children();
6541
6542          if(!id) {
6543            id = 'bigtext-id' + (counter++);
6544            $t.attr('id', id);
6545          }
6546
6547          if(options.resize) {
6548            BigText.bindResize('resize.bigtext-event-' + id, function()
6549            {
6550              // TODO only call this if the width has changed.
6551              BigText.jQueryMethod.call($('#' + id), options);
6552            });
6553          }
6554
6555          BigText.clearCss(id);
6556
6557          $children.addClass(function(lineNumber, className)
6558          {
6559            // remove existing line classes.
6560            return [className.replace(new RegExp('\\b' + BigText.LINE_CLASS_PREFIX + '\\d+\\b'), ''),
6561                BigText.LINE_CLASS_PREFIX + lineNumber].join(' ');
6562          });
6563
6564          var sizes = BigText.calculateSizes($t, $children, maxWidth, options.maxfontsize, options.minfontsize);
6565          $headCache.append(BigText.generateCss(id, sizes.fontSizes, sizes.wordSpacings, sizes.minFontSizes));
6566        });
6567
6568        return this.trigger('bigtext:complete');
6569      },
6570      testLineDimensions: function($line, maxWidth, property, size, interval, units, previousWidth)
6571      {
6572        var width;
6573        previousWidth = typeof previousWidth === 'number' ? previousWidth : 0;
6574        $line.css(property, size + units);
6575
6576        width = $line.width();
6577
6578        if(width >= maxWidth) {
6579    // console.log(width, ' previous: ' + previousWidth, property + ' at ' + interval, 'prior: ' + (parseFloat(size) - interval), 'new:' + parseFloat(size));
6580          $line.css(property, '');
6581
6582          if(width === maxWidth) {
6583            return {
6584              match: 'exact',
6585              size: parseFloat((parseFloat(size) - 0.1).toFixed(3))
6586            };
6587          }
6588
6589          // Since this is an estimate, we calculate how far over the width we went with the new value.
6590          // If this is word-spacing (our last resort guess) and the over is less than the under, we keep the higher value.
6591          // Otherwise, we revert to the underestimate.
6592          var under = maxWidth - previousWidth,
6593            over = width - maxWidth;
6594
6595          return {
6596            match: 'estimate',
6597            size: parseFloat((parseFloat(size) - (property === 'word-spacing' && previousWidth && ( over < under ) ? 0 : interval)).toFixed(3))
6598          };
6599        }
6600
6601        return width;
6602      },
6603      calculateSizes: function($t, $children, maxWidth, maxFontSize, minFontSize)
6604      {
6605        var $c = $t.clone(true)
6606          .addClass('bigtext-cloned')
6607          .css({
6608            fontFamily: $t.css('font-family'),
6609            textTransform: $t.css('text-transform'),
6610            wordSpacing: $t.css('word-spacing'),
6611            letterSpacing: $t.css('letter-spacing'),
6612            position: 'absolute',
6613            left: BigText.DEBUG_MODE ? 0 : -9999,
6614            top: BigText.DEBUG_MODE ? 0 : -9999
6615          })
6616          .appendTo(document.body);
6617
6618        // font-size isn't the only thing we can modify, we can also mess with:
6619        // word-spacing and letter-spacing. WebKit does not respect subpixel
6620        // letter-spacing, word-spacing, or font-size.
6621        // TODO try -webkit-transform: scale() as a workaround.
6622        var fontSizes = [],
6623          wordSpacings = [],
6624          minFontSizes = [],
6625          ratios = [];
6626
6627        $children.css('float', 'left').each(function() {
6628          var $line = $(this),
6629            // TODO replace 8, 4 with a proportional size to the calculated font-size.
6630            intervals = BigText.supports.wholeNumberFontSizeOnly ? [8, 4, 1] : [8, 4, 1, 0.1],
6631            lineMax,
6632            newFontSize;
6633
6634          if($line.hasClass(BigText.EXEMPT_CLASS)) {
6635            fontSizes.push(null);
6636            ratios.push(null);
6637            minFontSizes.push(false);
6638            return;
6639          }
6640
6641          // TODO we can cache this ratio?
6642          var autoGuessSubtraction = 32, // font size in px
6643            currentFontSize = parseFloat($line.css('font-size')),
6644            ratio = ( $line.width() / currentFontSize ).toFixed(6);
6645
6646          newFontSize = parseInt( maxWidth / ratio, 10 ) - autoGuessSubtraction;
6647
6648          outer: for(var m=0, n=intervals.length; m<n; m++) {
6649            inner: for(var j=1, k=10; j<=k; j++) {
6650              if(newFontSize + j*intervals[m] > maxFontSize) {
6651                newFontSize = maxFontSize;
6652                break outer;
6653              }
6654
6655              lineMax = BigText.testLineDimensions($line, maxWidth, 'font-size', newFontSize + j*intervals[m], intervals[m], 'px', lineMax);
6656              if(typeof lineMax !== 'number') {
6657                newFontSize = lineMax.size;
6658
6659                if(lineMax.match === 'exact') {
6660                  break outer;
6661                }
6662                break inner;
6663              }
6664            }
6665          }
6666
6667          ratios.push(maxWidth / newFontSize);
6668
6669          if(newFontSize > maxFontSize) {
6670            fontSizes.push(maxFontSize);
6671            minFontSizes.push(false);
6672          } else if(!!minFontSize && newFontSize < minFontSize) {
6673            fontSizes.push(minFontSize);
6674            minFontSizes.push(true);
6675          } else {
6676            fontSizes.push(newFontSize);
6677            minFontSizes.push(false);
6678          }
6679        }).each(function(lineNumber) {
6680          var $line = $(this),
6681            wordSpacing = 0,
6682            interval = 1,
6683            maxWordSpacing;
6684
6685          if($line.hasClass(BigText.EXEMPT_CLASS)) {
6686            wordSpacings.push(null);
6687            return;
6688          }
6689
6690          // must re-use font-size, even though it was removed above.
6691          $line.css('font-size', fontSizes[lineNumber] + 'px');
6692
6693          for(var m=1, n=3; m<n; m+=interval) {
6694            maxWordSpacing = BigText.testLineDimensions($line, maxWidth, 'word-spacing', m, interval, 'px', maxWordSpacing);
6695            if(typeof maxWordSpacing !== 'number') {
6696              wordSpacing = maxWordSpacing.size;
6697              break;
6698            }
6699          }
6700
6701          $line.css('font-size', '');
6702          wordSpacings.push(wordSpacing);
6703        }).removeAttr('style');
6704
6705        if( !BigText.DEBUG_MODE ) {
6706          $c.remove();
6707        } else {
6708          $c.css({
6709            'background-color': 'rgba(255,255,255,.4)'
6710          });
6711        }
6712
6713        return {
6714          fontSizes: fontSizes,
6715          wordSpacings: wordSpacings,
6716          ratios: ratios,
6717          minFontSizes: minFontSizes
6718        };
6719      }
6720    };
6721
6722  $.fn.bigtext = BigText.jQueryMethod;
6723  window.BigText = BigText;
6724
6725})(this, jQuery);
6726/*!
6727 * Isotope PACKAGED v3.0.6
6728 *
6729 * Licensed GPLv3 for open source use
6730 * or Isotope Commercial License for commercial use
6731 *
6732 * https://isotope.metafizzy.co
6733 * Copyright 2010-2018 Metafizzy
vendor: 15,902 bytes, lines 6733-7383
6733
6734 */
6735
6736/**
6737 * Bridget makes jQuery widgets
6738 * v2.0.1
6739 * MIT license
6740 */
6741
6742/* jshint browser: true, strict: true, undef: true, unused: true */
6743
6744( function( window, factory ) {
6745  // universal module definition
6746  /*jshint strict: false */ /* globals define, module, require */
6747  if ( typeof define == 'function' && define.amd ) {
6748    // AMD
6749    define( 'jquery-bridget/jquery-bridget',[ 'jquery' ], function( jQuery ) {
6750      return factory( window, jQuery );
6751    });
6752  } else if ( typeof module == 'object' && module.exports ) {
6753    // CommonJS
6754    module.exports = factory(
6755      window,
6756      require('jquery')
6757    );
6758  } else {
6759    // browser global
6760    window.jQueryBridget = factory(
6761      window,
6762      window.jQuery
6763    );
6764  }
6765
6766}( window, function factory( window, jQuery ) {
6767'use strict';
6768
6769// ----- utils ----- //
6770
6771var arraySlice = Array.prototype.slice;
6772
6773// helper function for logging errors
6774// $.error breaks jQuery chaining
6775var console = window.console;
6776var logError = typeof console == 'undefined' ? function() {} :
6777  function( message ) {
6778    console.error( message );
6779  };
6780
6781// ----- jQueryBridget ----- //
6782
6783function jQueryBridget( namespace, PluginClass, $ ) {
6784  $ = $ || jQuery || window.jQuery;
6785  if ( !$ ) {
6786    return;
6787  }
6788
6789  // add option method -> $().plugin('option', {...})
6790  if ( !PluginClass.prototype.option ) {
6791    // option setter
6792    PluginClass.prototype.option = function( opts ) {
6793      // bail out if not an object
6794      if ( !$.isPlainObject( opts ) ){
6795        return;
6796      }
6797      this.options = $.extend( true, this.options, opts );
6798    };
6799  }
6800
6801  // make jQuery plugin
6802  $.fn[ namespace ] = function( arg0 /*, arg1 */ ) {
6803    if ( typeof arg0 == 'string' ) {
6804      // method call $().plugin( 'methodName', { options } )
6805      // shift arguments by 1
6806      var args = arraySlice.call( arguments, 1 );
6807      return methodCall( this, arg0, args );
6808    }
6809    // just $().plugin({ options })
6810    plainCall( this, arg0 );
6811    return this;
6812  };
6813
6814  // $().plugin('methodName')
6815  function methodCall( $elems, methodName, args ) {
6816    var returnValue;
6817    var pluginMethodStr = '$().' + namespace + '("' + methodName + '")';
6818
6819    $elems.each( function( i, elem ) {
6820      // get instance
6821      var instance = $.data( elem, namespace );
6822      if ( !instance ) {
6823        logError( namespace + ' not initialized. Cannot call methods, i.e. ' +
6824          pluginMethodStr );
6825        return;
6826      }
6827
6828      var method = instance[ methodName ];
6829      if ( !method || methodName.charAt(0) == '_' ) {
6830        logError( pluginMethodStr + ' is not a valid method' );
6831        return;
6832      }
6833
6834      // apply method, get return value
6835      var value = method.apply( instance, args );
6836      // set return value if value is returned, use only first value
6837      returnValue = returnValue === undefined ? value : returnValue;
6838    });
6839
6840    return returnValue !== undefined ? returnValue : $elems;
6841  }
6842
6843  function plainCall( $elems, options ) {
6844    $elems.each( function( i, elem ) {
6845      var instance = $.data( elem, namespace );
6846      if ( instance ) {
6847        // set options & init
6848        instance.option( options );
6849        instance._init();
6850      } else {
6851        // initialize new instance
6852        instance = new PluginClass( elem, options );
6853        $.data( elem, namespace, instance );
6854      }
6855    });
6856  }
6857
6858  updateJQuery( $ );
6859
6860}
6861
6862// ----- updateJQuery ----- //
6863
6864// set $.bridget for v1 backwards compatibility
6865function updateJQuery( $ ) {
6866  if ( !$ || ( $ && $.bridget ) ) {
6867    return;
6868  }
6869  $.bridget = jQueryBridget;
6870}
6871
6872updateJQuery( jQuery || window.jQuery );
6873
6874// -----  ----- //
6875
6876return jQueryBridget;
6877
6878}));
6879
6880/**
6881 * EvEmitter v1.1.0
6882 * Lil' event emitter
6883 * MIT License
6884 */
6885
6886/* jshint unused: true, undef: true, strict: true */
6887
6888( function( global, factory ) {
6889  // universal module definition
6890  /* jshint strict: false */ /* globals define, module, window */
6891  if ( typeof define == 'function' && define.amd ) {
6892    // AMD - RequireJS
6893    define( 'ev-emitter/ev-emitter',factory );
6894  } else if ( typeof module == 'object' && module.exports ) {
6895    // CommonJS - Browserify, Webpack
6896    module.exports = factory();
6897  } else {
6898    // Browser globals
6899    global.EvEmitter = factory();
6900  }
6901
6902}( typeof window != 'undefined' ? window : this, function() {
6903
6904
6905
6906function EvEmitter() {}
6907
6908var proto = EvEmitter.prototype;
6909
6910proto.on = function( eventName, listener ) {
6911  if ( !eventName || !listener ) {
6912    return;
6913  }
6914  // set events hash
6915  var events = this._events = this._events || {};
6916  // set listeners array
6917  var listeners = events[ eventName ] = events[ eventName ] || [];
6918  // only add once
6919  if ( listeners.indexOf( listener ) == -1 ) {
6920    listeners.push( listener );
6921  }
6922
6923  return this;
6924};
6925
6926proto.once = function( eventName, listener ) {
6927  if ( !eventName || !listener ) {
6928    return;
6929  }
6930  // add event
6931  this.on( eventName, listener );
6932  // set once flag
6933  // set onceEvents hash
6934  var onceEvents = this._onceEvents = this._onceEvents || {};
6935  // set onceListeners object
6936  var onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {};
6937  // set flag
6938  onceListeners[ listener ] = true;
6939
6940  return this;
6941};
6942
6943proto.off = function( eventName, listener ) {
6944  var listeners = this._events && this._events[ eventName ];
6945  if ( !listeners || !listeners.length ) {
6946    return;
6947  }
6948  var index = listeners.indexOf( listener );
6949  if ( index != -1 ) {
6950    listeners.splice( index, 1 );
6951  }
6952
6953  return this;
6954};
6955
6956proto.emitEvent = function( eventName, args ) {
6957  var listeners = this._events && this._events[ eventName ];
6958  if ( !listeners || !listeners.length ) {
6959    return;
6960  }
6961  // copy over to avoid interference if .off() in listener
6962  listeners = listeners.slice(0);
6963  args = args || [];
6964  // once stuff
6965  var onceListeners = this._onceEvents && this._onceEvents[ eventName ];
6966
6967  for ( var i=0; i < listeners.length; i++ ) {
6968    var listener = listeners[i]
6969    var isOnce = onceListeners && onceListeners[ listener ];
6970    if ( isOnce ) {
6971      // remove listener
6972      // remove before trigger to prevent recursion
6973      this.off( eventName, listener );
6974      // unset once flag
6975      delete onceListeners[ listener ];
6976    }
6977    // trigger listener
6978    listener.apply( this, args );
6979  }
6980
6981  return this;
6982};
6983
6984proto.allOff = function() {
6985  delete this._events;
6986  delete this._onceEvents;
6987};
6988
6989return EvEmitter;
6990
6991}));
6992
6993/*!
6994 * getSize v2.0.3
6995 * measure size of elements
6996 * MIT license
6997 */
6998
6999/* jshint browser: true, strict: true, undef: true, unused: true */
7000/* globals console: false */
7001
7002( function( window, factory ) {
7003  /* jshint strict: false */ /* globals define, module */
7004  if ( typeof define == 'function' && define.amd ) {
7005    // AMD
7006    define( 'get-size/get-size',factory );
7007  } else if ( typeof module == 'object' && module.exports ) {
7008    // CommonJS
7009    module.exports = factory();
7010  } else {
7011    // browser global
7012    window.getSize = factory();
7013  }
7014
7015})( window, function factory() {
7016'use strict';
7017
7018// -------------------------- helpers -------------------------- //
7019
7020// get a number from a string, not a percentage
7021function getStyleSize( value ) {
7022  var num = parseFloat( value );
7023  // not a percent like '100%', and a number
7024  var isValid = value.indexOf('%') == -1 && !isNaN( num );
7025  return isValid && num;
7026}
7027
7028function noop() {}
7029
7030var logError = typeof console == 'undefined' ? noop :
7031  function( message ) {
7032    console.error( message );
7033  };
7034
7035// -------------------------- measurements -------------------------- //
7036
7037var measurements = [
7038  'paddingLeft',
7039  'paddingRight',
7040  'paddingTop',
7041  'paddingBottom',
7042  'marginLeft',
7043  'marginRight',
7044  'marginTop',
7045  'marginBottom',
7046  'borderLeftWidth',
7047  'borderRightWidth',
7048  'borderTopWidth',
7049  'borderBottomWidth'
7050];
7051
7052var measurementsLength = measurements.length;
7053
7054function getZeroSize() {
7055  var size = {
7056    width: 0,
7057    height: 0,
7058    innerWidth: 0,
7059    innerHeight: 0,
7060    outerWidth: 0,
7061    outerHeight: 0
7062  };
7063  for ( var i=0; i < measurementsLength; i++ ) {
7064    var measurement = measurements[i];
7065    size[ measurement ] = 0;
7066  }
7067  return size;
7068}
7069
7070// -------------------------- getStyle -------------------------- //
7071
7072/**
7073 * getStyle, get style of element, check for Firefox bug
7074 * https://bugzilla.mozilla.org/show_bug.cgi?id=548397
7075 */
7076function getStyle( elem ) {
7077  var style = getComputedStyle( elem );
7078  if ( !style ) {
7079    logError( 'Style returned ' + style +
7080      '. Are you running this code in a hidden iframe on Firefox? ' +
7081      'See https://bit.ly/getsizebug1' );
7082  }
7083  return style;
7084}
7085
7086// -------------------------- setup -------------------------- //
7087
7088var isSetup = false;
7089
7090var isBoxSizeOuter;
7091
7092/**
7093 * setup
7094 * check isBoxSizerOuter
7095 * do on first getSize() rather than on page load for Firefox bug
7096 */
7097function setup() {
7098  // setup once
7099  if ( isSetup ) {
7100    return;
7101  }
7102  isSetup = true;
7103
7104  // -------------------------- box sizing -------------------------- //
7105
7106  /**
7107   * Chrome & Safari measure the outer-width on style.width on border-box elems
7108   * IE11 & Firefox<29 measures the inner-width
7109   */
7110  var div = document.createElement('div');
7111  div.style.width = '200px';
7112  div.style.padding = '1px 2px 3px 4px';
7113  div.style.borderStyle = 'solid';
7114  div.style.borderWidth = '1px 2px 3px 4px';
7115  div.style.boxSizing = 'border-box';
7116
7117  var body = document.body || document.documentElement;
7118  body.appendChild( div );
7119  var style = getStyle( div );
7120  // round value for browser zoom. desandro/masonry#928
7121  isBoxSizeOuter = Math.round( getStyleSize( style.width ) ) == 200;
7122  getSize.isBoxSizeOuter = isBoxSizeOuter;
7123
7124  body.removeChild( div );
7125}
7126
7127// -------------------------- getSize -------------------------- //
7128
7129function getSize( elem ) {
7130  setup();
7131
7132  // use querySeletor if elem is string
7133  if ( typeof elem == 'string' ) {
7134    elem = document.querySelector( elem );
7135  }
7136
7137  // do not proceed on non-objects
7138  if ( !elem || typeof elem != 'object' || !elem.nodeType ) {
7139    return;
7140  }
7141
7142  var style = getStyle( elem );
7143
7144  // if hidden, everything is 0
7145  if ( style.display == 'none' ) {
7146    return getZeroSize();
7147  }
7148
7149  var size = {};
7150  size.width = elem.offsetWidth;
7151  size.height = elem.offsetHeight;
7152
7153  var isBorderBox = size.isBorderBox = style.boxSizing == 'border-box';
7154
7155  // get all measurements
7156  for ( var i=0; i < measurementsLength; i++ ) {
7157    var measurement = measurements[i];
7158    var value = style[ measurement ];
7159    var num = parseFloat( value );
7160    // any 'auto', 'medium' value will be 0
7161    size[ measurement ] = !isNaN( num ) ? num : 0;
7162  }
7163
7164  var paddingWidth = size.paddingLeft + size.paddingRight;
7165  var paddingHeight = size.paddingTop + size.paddingBottom;
7166  var marginWidth = size.marginLeft + size.marginRight;
7167  var marginHeight = size.marginTop + size.marginBottom;
7168  var borderWidth = size.borderLeftWidth + size.borderRightWidth;
7169  var borderHeight = size.borderTopWidth + size.borderBottomWidth;
7170
7171  var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter;
7172
7173  // overwrite width and height if we can get it from style
7174  var styleWidth = getStyleSize( style.width );
7175  if ( styleWidth !== false ) {
7176    size.width = styleWidth +
7177      // add padding and border unless it's already including it
7178      ( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth );
7179  }
7180
7181  var styleHeight = getStyleSize( style.height );
7182  if ( styleHeight !== false ) {
7183    size.height = styleHeight +
7184      // add padding and border unless it's already including it
7185      ( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight );
7186  }
7187
7188  size.innerWidth = size.width - ( paddingWidth + borderWidth );
7189  size.innerHeight = size.height - ( paddingHeight + borderHeight );
7190
7191  size.outerWidth = size.width + marginWidth;
7192  size.outerHeight = size.height + marginHeight;
7193
7194  return size;
7195}
7196
7197return getSize;
7198
7199});
7200
7201/**
7202 * matchesSelector v2.0.2
7203 * matchesSelector( element, '.selector' )
7204 * MIT license
7205 */
7206
7207/*jshint browser: true, strict: true, undef: true, unused: true */
7208
7209( function( window, factory ) {
7210  /*global define: false, module: false */
7211  'use strict';
7212  // universal module definition
7213  if ( typeof define == 'function' && define.amd ) {
7214    // AMD
7215    define( 'desandro-matches-selector/matches-selector',factory );
7216  } else if ( typeof module == 'object' && module.exports ) {
7217    // CommonJS
7218    module.exports = factory();
7219  } else {
7220    // browser global
7221    window.matchesSelector = factory();
7222  }
7223
7224}( window, function factory() {
7225  'use strict';
7226
7227  var matchesMethod = ( function() {
7228    var ElemProto = window.Element.prototype;
7229    // check for the standard method name first
7230    if ( ElemProto.matches ) {
7231      return 'matches';
7232    }
7233    // check un-prefixed
7234    if ( ElemProto.matchesSelector ) {
7235      return 'matchesSelector';
7236    }
7237    // check vendor prefixes
7238    var prefixes = [ 'webkit', 'moz', 'ms', 'o' ];
7239
7240    for ( var i=0; i < prefixes.length; i++ ) {
7241      var prefix = prefixes[i];
7242      var method = prefix + 'MatchesSelector';
7243      if ( ElemProto[ method ] ) {
7244        return method;
7245      }
7246    }
7247  })();
7248
7249  return function matchesSelector( elem, selector ) {
7250    return elem[ matchesMethod ]( selector );
7251  };
7252
7253}));
7254
7255/**
7256 * Fizzy UI utils v2.0.7
7257 * MIT license
7258 */
7259
7260/*jshint browser: true, undef: true, unused: true, strict: true */
7261
7262( function( window, factory ) {
7263  // universal module definition
7264  /*jshint strict: false */ /*globals define, module, require */
7265
7266  if ( typeof define == 'function' && define.amd ) {
7267    // AMD
7268    define( 'fizzy-ui-utils/utils',[
7269      'desandro-matches-selector/matches-selector'
7270    ], function( matchesSelector ) {
7271      return factory( window, matchesSelector );
7272    });
7273  } else if ( typeof module == 'object' && module.exports ) {
7274    // CommonJS
7275    module.exports = factory(
7276      window,
7277      require('desandro-matches-selector')
7278    );
7279  } else {
7280    // browser global
7281    window.fizzyUIUtils = factory(
7282      window,
7283      window.matchesSelector
7284    );
7285  }
7286
7287}( window, function factory( window, matchesSelector ) {
7288
7289
7290
7291var utils = {};
7292
7293// ----- extend ----- //
7294
7295// extends objects
7296utils.extend = function( a, b ) {
7297  for ( var prop in b ) {
7298    a[ prop ] = b[ prop ];
7299  }
7300  return a;
7301};
7302
7303// ----- modulo ----- //
7304
7305utils.modulo = function( num, div ) {
7306  return ( ( num % div ) + div ) % div;
7307};
7308
7309// ----- makeArray ----- //
7310
7311var arraySlice = Array.prototype.slice;
7312
7313// turn element or nodeList into an array
7314utils.makeArray = function( obj ) {
7315  if ( Array.isArray( obj ) ) {
7316    // use object if already an array
7317    return obj;
7318  }
7319  // return empty array if undefined or null. #6
7320  if ( obj === null || obj === undefined ) {
7321    return [];
7322  }
7323
7324  var isArrayLike = typeof obj == 'object' && typeof obj.length == 'number';
7325  if ( isArrayLike ) {
7326    // convert nodeList to array
7327    return arraySlice.call( obj );
7328  }
7329
7330  // array of single index
7331  return [ obj ];
7332};
7333
7334// ----- removeFrom ----- //
7335
7336utils.removeFrom = function( ary, obj ) {
7337  var index = ary.indexOf( obj );
7338  if ( index != -1 ) {
7339    ary.splice( index, 1 );
7340  }
7341};
7342
7343// ----- getParent ----- //
7344
7345utils.getParent = function( elem, selector ) {
7346  while ( elem.parentNode && elem != document.body ) {
7347    elem = elem.parentNode;
7348    if ( matchesSelector( elem, selector ) ) {
7349      return elem;
7350    }
7351  }
7352};
7353
7354// ----- getQueryElement ----- //
7355
7356// use element as selector string
7357utils.getQueryElement = function( elem ) {
7358  if ( typeof elem == 'string' ) {
7359    return document.querySelector( elem );
7360  }
7361  return elem;
7362};
7363
7364// ----- handleEvent ----- //
7365
7366// enable .ontype to trigger from .addEventListener( elem, 'type' )
7367utils.handleEvent = function( event ) {
7368  var method = 'on' + event.type;
7369  if ( this[ method ] ) {
7370    this[ method ]( event );
7371  }
7372};
7373
7374// ----- filterFindElements ----- //
7375
7376utils.filterFindElements = function( elems, selector ) {
7377  // make array of elems
7378  elems = utils.makeArray( elems );
7379  var ffElems = [];
7380
7381  elems.forEach( function( elem ) {
7382    // check that elem is an actual element
7383    
7383// START UNCODE EDIT
7384    // if ( !( elem instanceof HTMLElement ) ) {
7385    if ( !( elem instanceof HTMLElement ) && !SiteParameters.is_frontend_editor ) {
7386    // END UNCODE EDIT
vendor: 36,979 bytes, lines 7386-8867
7386
7387      return;
7388    }
7389    // add elem if no selector
7390    if ( !selector ) {
7391      ffElems.push( elem );
7392      return;
7393    }
7394    // filter & find items if we have a selector
7395    // filter
7396    if ( matchesSelector( elem, selector ) ) {
7397      ffElems.push( elem );
7398    }
7399    // find children
7400    var childElems = elem.querySelectorAll( selector );
7401    // concat childElems to filterFound array
7402    for ( var i=0; i < childElems.length; i++ ) {
7403      ffElems.push( childElems[i] );
7404    }
7405  });
7406
7407  return ffElems;
7408};
7409
7410// ----- debounceMethod ----- //
7411
7412utils.debounceMethod = function( _class, methodName, threshold ) {
7413  threshold = threshold || 100;
7414  // original method
7415  var method = _class.prototype[ methodName ];
7416  var timeoutName = methodName + 'Timeout';
7417
7418  _class.prototype[ methodName ] = function() {
7419    var timeout = this[ timeoutName ];
7420    clearTimeout( timeout );
7421
7422    var args = arguments;
7423    var _this = this;
7424    this[ timeoutName ] = setTimeout( function() {
7425      method.apply( _this, args );
7426      delete _this[ timeoutName ];
7427    }, threshold );
7428  };
7429};
7430
7431// ----- docReady ----- //
7432
7433utils.docReady = function( callback ) {
7434  var readyState = document.readyState;
7435  if ( readyState == 'complete' || readyState == 'interactive' ) {
7436    // do async to allow for other scripts to run. metafizzy/flickity#441
7437    setTimeout( callback );
7438  } else {
7439    document.addEventListener( 'DOMContentLoaded', callback );
7440  }
7441};
7442
7443// ----- htmlInit ----- //
7444
7445// http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/
7446utils.toDashed = function( str ) {
7447  return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) {
7448    return $1 + '-' + $2;
7449  }).toLowerCase();
7450};
7451
7452var console = window.console;
7453/**
7454 * allow user to initialize classes via [data-namespace] or .js-namespace class
7455 * htmlInit( Widget, 'widgetName' )
7456 * options are parsed from data-namespace-options
7457 */
7458utils.htmlInit = function( WidgetClass, namespace ) {
7459  utils.docReady( function() {
7460    var dashedNamespace = utils.toDashed( namespace );
7461    var dataAttr = 'data-' + dashedNamespace;
7462    var dataAttrElems = document.querySelectorAll( '[' + dataAttr + ']' );
7463    var jsDashElems = document.querySelectorAll( '.js-' + dashedNamespace );
7464    var elems = utils.makeArray( dataAttrElems )
7465      .concat( utils.makeArray( jsDashElems ) );
7466    var dataOptionsAttr = dataAttr + '-options';
7467    var jQuery = window.jQuery;
7468
7469    elems.forEach( function( elem ) {
7470      var attr = elem.getAttribute( dataAttr ) ||
7471        elem.getAttribute( dataOptionsAttr );
7472      var options;
7473      try {
7474        options = attr && JSON.parse( attr );
7475      } catch ( error ) {
7476        // log error, do not initialize
7477        if ( console ) {
7478          console.error( 'Error parsing ' + dataAttr + ' on ' + elem.className +
7479          ': ' + error );
7480        }
7481        return;
7482      }
7483      // initialize
7484      var instance = new WidgetClass( elem, options );
7485      // make available via $().data('namespace')
7486      if ( jQuery ) {
7487        jQuery.data( elem, namespace, instance );
7488      }
7489    });
7490
7491  });
7492};
7493
7494// -----  ----- //
7495
7496return utils;
7497
7498}));
7499
7500/**
7501 * Outlayer Item
7502 */
7503
7504( function( window, factory ) {
7505  // universal module definition
7506  /* jshint strict: false */ /* globals define, module, require */
7507  if ( typeof define == 'function' && define.amd ) {
7508    // AMD - RequireJS
7509    define( 'outlayer/item',[
7510        'ev-emitter/ev-emitter',
7511        'get-size/get-size'
7512      ],
7513      factory
7514    );
7515  } else if ( typeof module == 'object' && module.exports ) {
7516    // CommonJS - Browserify, Webpack
7517    module.exports = factory(
7518      require('ev-emitter'),
7519      require('get-size')
7520    );
7521  } else {
7522    // browser global
7523    window.Outlayer = {};
7524    window.Outlayer.Item = factory(
7525      window.EvEmitter,
7526      window.getSize
7527    );
7528  }
7529
7530}( window, function factory( EvEmitter, getSize ) {
7531'use strict';
7532
7533// ----- helpers ----- //
7534
7535function isEmptyObj( obj ) {
7536  for ( var prop in obj ) {
7537    return false;
7538  }
7539  prop = null;
7540  return true;
7541}
7542
7543// -------------------------- CSS3 support -------------------------- //
7544
7545
7546var docElemStyle = document.documentElement.style;
7547
7548var transitionProperty = typeof docElemStyle.transition == 'string' ?
7549  'transition' : 'WebkitTransition';
7550var transformProperty = typeof docElemStyle.transform == 'string' ?
7551  'transform' : 'WebkitTransform';
7552
7553var transitionEndEvent = {
7554  WebkitTransition: 'webkitTransitionEnd',
7555  transition: 'transitionend'
7556}[ transitionProperty ];
7557
7558// cache all vendor properties that could have vendor prefix
7559var vendorProperties = {
7560  transform: transformProperty,
7561  transition: transitionProperty,
7562  transitionDuration: transitionProperty + 'Duration',
7563  transitionProperty: transitionProperty + 'Property',
7564  transitionDelay: transitionProperty + 'Delay'
7565};
7566
7567// -------------------------- Item -------------------------- //
7568
7569function Item( element, layout ) {
7570  if ( !element ) {
7571    return;
7572  }
7573
7574  this.element = element;
7575  // parent layout class, i.e. Masonry, Isotope, or Packery
7576  this.layout = layout;
7577  this.position = {
7578    x: 0,
7579    y: 0
7580  };
7581
7582  this._create();
7583}
7584
7585// inherit EvEmitter
7586var proto = Item.prototype = Object.create( EvEmitter.prototype );
7587proto.constructor = Item;
7588
7589proto._create = function() {
7590  // transition objects
7591  this._transn = {
7592    ingProperties: {},
7593    clean: {},
7594    onEnd: {}
7595  };
7596
7597  this.css({
7598    position: 'absolute'
7599  });
7600};
7601
7602// trigger specified handler for event type
7603proto.handleEvent = function( event ) {
7604  var method = 'on' + event.type;
7605  if ( this[ method ] ) {
7606    this[ method ]( event );
7607  }
7608};
7609
7610proto.getSize = function() {
7611  this.size = getSize( this.element );
7612};
7613
7614/**
7615 * apply CSS styles to element
7616 * @param {Object} style
7617 */
7618proto.css = function( style ) {
7619  var elemStyle = this.element.style;
7620
7621  for ( var prop in style ) {
7622    // use vendor property if available
7623    var supportedProp = vendorProperties[ prop ] || prop;
7624    elemStyle[ supportedProp ] = style[ prop ];
7625  }
7626};
7627
7628 // measure position, and sets it
7629proto.getPosition = function() {
7630  var style = getComputedStyle( this.element );
7631  var isOriginLeft = this.layout._getOption('originLeft');
7632  var isOriginTop = this.layout._getOption('originTop');
7633  var xValue = style[ isOriginLeft ? 'left' : 'right' ];
7634  var yValue = style[ isOriginTop ? 'top' : 'bottom' ];
7635  var x = parseFloat( xValue );
7636  var y = parseFloat( yValue );
7637  // convert percent to pixels
7638  var layoutSize = this.layout.size;
7639  if ( xValue.indexOf('%') != -1 ) {
7640    x = ( x / 100 ) * layoutSize.width;
7641  }
7642  if ( yValue.indexOf('%') != -1 ) {
7643    y = ( y / 100 ) * layoutSize.height;
7644  }
7645  // clean up 'auto' or other non-integer values
7646  x = isNaN( x ) ? 0 : x;
7647  y = isNaN( y ) ? 0 : y;
7648  // remove padding from measurement
7649  x -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight;
7650  y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom;
7651
7652  this.position.x = x;
7653  this.position.y = y;
7654};
7655
7656// set settled position, apply padding
7657proto.layoutPosition = function() {
7658  var layoutSize = this.layout.size;
7659  var style = {};
7660  var isOriginLeft = this.layout._getOption('originLeft');
7661  var isOriginTop = this.layout._getOption('originTop');
7662
7663  // x
7664  var xPadding = isOriginLeft ? 'paddingLeft' : 'paddingRight';
7665  var xProperty = isOriginLeft ? 'left' : 'right';
7666  var xResetProperty = isOriginLeft ? 'right' : 'left';
7667
7668  var x = this.position.x + layoutSize[ xPadding ];
7669  // set in percentage or pixels
7670  style[ xProperty ] = this.getXValue( x );
7671  // reset other property
7672  style[ xResetProperty ] = '';
7673
7674  // y
7675  var yPadding = isOriginTop ? 'paddingTop' : 'paddingBottom';
7676  var yProperty = isOriginTop ? 'top' : 'bottom';
7677  var yResetProperty = isOriginTop ? 'bottom' : 'top';
7678
7679  var y = this.position.y + layoutSize[ yPadding ];
7680  // set in percentage or pixels
7681  style[ yProperty ] = this.getYValue( y );
7682  // reset other property
7683  style[ yResetProperty ] = '';
7684
7685  this.css( style );
7686  this.emitEvent( 'layout', [ this ] );
7687};
7688
7689proto.getXValue = function( x ) {
7690  var isHorizontal = this.layout._getOption('horizontal');
7691  return this.layout.options.percentPosition && !isHorizontal ?
7692    ( ( x / this.layout.size.width ) * 100 ) + '%' : x + 'px';
7693};
7694
7695proto.getYValue = function( y ) {
7696  var isHorizontal = this.layout._getOption('horizontal');
7697  return this.layout.options.percentPosition && isHorizontal ?
7698    ( ( y / this.layout.size.height ) * 100 ) + '%' : y + 'px';
7699};
7700
7701proto._transitionTo = function( x, y ) {
7702  this.getPosition();
7703  // get current x & y from top/left
7704  var curX = this.position.x;
7705  var curY = this.position.y;
7706
7707  var didNotMove = x == this.position.x && y == this.position.y;
7708
7709  // save end position
7710  this.setPosition( x, y );
7711
7712  // if did not move and not transitioning, just go to layout
7713  if ( didNotMove && !this.isTransitioning ) {
7714    this.layoutPosition();
7715    return;
7716  }
7717
7718  var transX = x - curX;
7719  var transY = y - curY;
7720  var transitionStyle = {};
7721  transitionStyle.transform = this.getTranslate( transX, transY );
7722
7723  this.transition({
7724    to: transitionStyle,
7725    onTransitionEnd: {
7726      transform: this.layoutPosition
7727    },
7728    isCleaning: true
7729  });
7730};
7731
7732proto.getTranslate = function( x, y ) {
7733  // flip cooridinates if origin on right or bottom
7734  var isOriginLeft = this.layout._getOption('originLeft');
7735  var isOriginTop = this.layout._getOption('originTop');
7736  x = isOriginLeft ? x : -x;
7737  y = isOriginTop ? y : -y;
7738  return 'translate3d(' + x + 'px, ' + y + 'px, 0)';
7739};
7740
7741// non transition + transform support
7742proto.goTo = function( x, y ) {
7743  this.setPosition( x, y );
7744  this.layoutPosition();
7745};
7746
7747proto.moveTo = proto._transitionTo;
7748
7749proto.setPosition = function( x, y ) {
7750  this.position.x = parseFloat( x );
7751  this.position.y = parseFloat( y );
7752};
7753
7754// ----- transition ----- //
7755
7756/**
7757 * @param {Object} style - CSS
7758 * @param {Function} onTransitionEnd
7759 */
7760
7761// non transition, just trigger callback
7762proto._nonTransition = function( args ) {
7763  this.css( args.to );
7764  if ( args.isCleaning ) {
7765    this._removeStyles( args.to );
7766  }
7767  for ( var prop in args.onTransitionEnd ) {
7768    args.onTransitionEnd[ prop ].call( this );
7769  }
7770};
7771
7772/**
7773 * proper transition
7774 * @param {Object} args - arguments
7775 *   @param {Object} to - style to transition to
7776 *   @param {Object} from - style to start transition from
7777 *   @param {Boolean} isCleaning - removes transition styles after transition
7778 *   @param {Function} onTransitionEnd - callback
7779 */
7780proto.transition = function( args ) {
7781  // redirect to nonTransition if no transition duration
7782  if ( !parseFloat( this.layout.options.transitionDuration ) ) {
7783    this._nonTransition( args );
7784    return;
7785  }
7786
7787  var _transition = this._transn;
7788  // keep track of onTransitionEnd callback by css property
7789  for ( var prop in args.onTransitionEnd ) {
7790    _transition.onEnd[ prop ] = args.onTransitionEnd[ prop ];
7791  }
7792  // keep track of properties that are transitioning
7793  for ( prop in args.to ) {
7794    _transition.ingProperties[ prop ] = true;
7795    // keep track of properties to clean up when transition is done
7796    if ( args.isCleaning ) {
7797      _transition.clean[ prop ] = true;
7798    }
7799  }
7800
7801  // set from styles
7802  if ( args.from ) {
7803    this.css( args.from );
7804    // force redraw. http://blog.alexmaccaw.com/css-transitions
7805    var h = this.element.offsetHeight;
7806    // hack for JSHint to hush about unused var
7807    h = null;
7808  }
7809  // enable transition
7810  this.enableTransition( args.to );
7811  // set styles that are transitioning
7812  this.css( args.to );
7813
7814  this.isTransitioning = true;
7815
7816};
7817
7818// dash before all cap letters, including first for
7819// WebkitTransform => -webkit-transform
7820function toDashedAll( str ) {
7821  return str.replace( /([A-Z])/g, function( $1 ) {
7822    return '-' + $1.toLowerCase();
7823  });
7824}
7825
7826var transitionProps = 'opacity,' + toDashedAll( transformProperty );
7827
7828proto.enableTransition = function(/* style */) {
7829  // HACK changing transitionProperty during a transition
7830  // will cause transition to jump
7831  if ( this.isTransitioning ) {
7832    return;
7833  }
7834
7835  // make `transition: foo, bar, baz` from style object
7836  // HACK un-comment this when enableTransition can work
7837  // while a transition is happening
7838  // var transitionValues = [];
7839  // for ( var prop in style ) {
7840  //   // dash-ify camelCased properties like WebkitTransition
7841  //   prop = vendorProperties[ prop ] || prop;
7842  //   transitionValues.push( toDashedAll( prop ) );
7843  // }
7844  // munge number to millisecond, to match stagger
7845  var duration = this.layout.options.transitionDuration;
7846  duration = typeof duration == 'number' ? duration + 'ms' : duration;
7847  // enable transition styles
7848  this.css({
7849    transitionProperty: transitionProps,
7850    transitionDuration: duration,
7851    transitionDelay: this.staggerDelay || 0
7852  });
7853  // listen for transition end event
7854  this.element.addEventListener( transitionEndEvent, this, false );
7855};
7856
7857// ----- events ----- //
7858
7859proto.onwebkitTransitionEnd = function( event ) {
7860  this.ontransitionend( event );
7861};
7862
7863proto.onotransitionend = function( event ) {
7864  this.ontransitionend( event );
7865};
7866
7867// properties that I munge to make my life easier
7868var dashedVendorProperties = {
7869  '-webkit-transform': 'transform'
7870};
7871
7872proto.ontransitionend = function( event ) {
7873  // disregard bubbled events from children
7874  if ( event.target !== this.element ) {
7875    return;
7876  }
7877  var _transition = this._transn;
7878  // get property name of transitioned property, convert to prefix-free
7879  var propertyName = dashedVendorProperties[ event.propertyName ] || event.propertyName;
7880
7881  // remove property that has completed transitioning
7882  delete _transition.ingProperties[ propertyName ];
7883  // check if any properties are still transitioning
7884  if ( isEmptyObj( _transition.ingProperties ) ) {
7885    // all properties have completed transitioning
7886    this.disableTransition();
7887  }
7888  // clean style
7889  if ( propertyName in _transition.clean ) {
7890    // clean up style
7891    this.element.style[ event.propertyName ] = '';
7892    delete _transition.clean[ propertyName ];
7893  }
7894  // trigger onTransitionEnd callback
7895  if ( propertyName in _transition.onEnd ) {
7896    var onTransitionEnd = _transition.onEnd[ propertyName ];
7897    onTransitionEnd.call( this );
7898    delete _transition.onEnd[ propertyName ];
7899  }
7900
7901  this.emitEvent( 'transitionEnd', [ this ] );
7902};
7903
7904proto.disableTransition = function() {
7905  this.removeTransitionStyles();
7906  this.element.removeEventListener( transitionEndEvent, this, false );
7907  this.isTransitioning = false;
7908};
7909
7910/**
7911 * removes style property from element
7912 * @param {Object} style
7913**/
7914proto._removeStyles = function( style ) {
7915  // clean up transition styles
7916  var cleanStyle = {};
7917  for ( var prop in style ) {
7918    cleanStyle[ prop ] = '';
7919  }
7920  this.css( cleanStyle );
7921};
7922
7923var cleanTransitionStyle = {
7924  transitionProperty: '',
7925  transitionDuration: '',
7926  transitionDelay: ''
7927};
7928
7929proto.removeTransitionStyles = function() {
7930  // remove transition
7931  this.css( cleanTransitionStyle );
7932};
7933
7934// ----- stagger ----- //
7935
7936proto.stagger = function( delay ) {
7937  delay = isNaN( delay ) ? 0 : delay;
7938  this.staggerDelay = delay + 'ms';
7939};
7940
7941// ----- show/hide/remove ----- //
7942
7943// remove element from DOM
7944proto.removeElem = function() {
7945  this.element.parentNode.removeChild( this.element );
7946  // remove display: none
7947  this.css({ display: '' });
7948  this.emitEvent( 'remove', [ this ] );
7949};
7950
7951proto.remove = function() {
7952  // just remove element if no transition support or no transition
7953  if ( !transitionProperty || !parseFloat( this.layout.options.transitionDuration ) ) {
7954    this.removeElem();
7955    return;
7956  }
7957
7958  // start transition
7959  this.once( 'transitionEnd', function() {
7960    this.removeElem();
7961  });
7962  this.hide();
7963};
7964
7965proto.reveal = function() {
7966  delete this.isHidden;
7967  // remove display: none
7968  this.css({ display: '' });
7969
7970  var options = this.layout.options;
7971
7972  var onTransitionEnd = {};
7973  var transitionEndProperty = this.getHideRevealTransitionEndProperty('visibleStyle');
7974  onTransitionEnd[ transitionEndProperty ] = this.onRevealTransitionEnd;
7975
7976  this.transition({
7977    from: options.hiddenStyle,
7978    to: options.visibleStyle,
7979    isCleaning: true,
7980    onTransitionEnd: onTransitionEnd
7981  });
7982};
7983
7984proto.onRevealTransitionEnd = function() {
7985  // check if still visible
7986  // during transition, item may have been hidden
7987  if ( !this.isHidden ) {
7988    this.emitEvent('reveal');
7989  }
7990};
7991
7992/**
7993 * get style property use for hide/reveal transition end
7994 * @param {String} styleProperty - hiddenStyle/visibleStyle
7995 * @returns {String}
7996 */
7997proto.getHideRevealTransitionEndProperty = function( styleProperty ) {
7998  var optionStyle = this.layout.options[ styleProperty ];
7999  // use opacity
8000  if ( optionStyle.opacity ) {
8001    return 'opacity';
8002  }
8003  // get first property
8004  for ( var prop in optionStyle ) {
8005    return prop;
8006  }
8007};
8008
8009proto.hide = function() {
8010  // set flag
8011  this.isHidden = true;
8012  // remove display: none
8013  this.css({ display: '' });
8014
8015  var options = this.layout.options;
8016
8017  var onTransitionEnd = {};
8018  var transitionEndProperty = this.getHideRevealTransitionEndProperty('hiddenStyle');
8019  onTransitionEnd[ transitionEndProperty ] = this.onHideTransitionEnd;
8020
8021  this.transition({
8022    from: options.visibleStyle,
8023    to: options.hiddenStyle,
8024    // keep hidden stuff hidden
8025    isCleaning: true,
8026    onTransitionEnd: onTransitionEnd
8027  });
8028};
8029
8030proto.onHideTransitionEnd = function() {
8031  // check if still hidden
8032  // during transition, item may have been un-hidden
8033  if ( this.isHidden ) {
8034    this.css({ display: 'none' });
8035    this.emitEvent('hide');
8036  }
8037};
8038
8039proto.destroy = function() {
8040  this.css({
8041    position: '',
8042    left: '',
8043    right: '',
8044    top: '',
8045    bottom: '',
8046    transition: '',
8047    transform: ''
8048  });
8049};
8050
8051return Item;
8052
8053}));
8054
8055/*!
8056 * Outlayer v2.1.1
8057 * the brains and guts of a layout library
8058 * MIT license
8059 */
8060
8061( function( window, factory ) {
8062  'use strict';
8063  // universal module definition
8064  /* jshint strict: false */ /* globals define, module, require */
8065  if ( typeof define == 'function' && define.amd ) {
8066    // AMD - RequireJS
8067    define( 'outlayer/outlayer',[
8068        'ev-emitter/ev-emitter',
8069        'get-size/get-size',
8070        'fizzy-ui-utils/utils',
8071        './item'
8072      ],
8073      function( EvEmitter, getSize, utils, Item ) {
8074        return factory( window, EvEmitter, getSize, utils, Item);
8075      }
8076    );
8077  } else if ( typeof module == 'object' && module.exports ) {
8078    // CommonJS - Browserify, Webpack
8079    module.exports = factory(
8080      window,
8081      require('ev-emitter'),
8082      require('get-size'),
8083      require('fizzy-ui-utils'),
8084      require('./item')
8085    );
8086  } else {
8087    // browser global
8088    window.Outlayer = factory(
8089      window,
8090      window.EvEmitter,
8091      window.getSize,
8092      window.fizzyUIUtils,
8093      window.Outlayer.Item
8094    );
8095  }
8096
8097}( window, function factory( window, EvEmitter, getSize, utils, Item ) {
8098'use strict';
8099
8100// ----- vars ----- //
8101
8102var console = window.console;
8103var jQuery = window.jQuery;
8104var noop = function() {};
8105
8106// -------------------------- Outlayer -------------------------- //
8107
8108// globally unique identifiers
8109var GUID = 0;
8110// internal store of all Outlayer intances
8111var instances = {};
8112
8113
8114/**
8115 * @param {Element, String} element
8116 * @param {Object} options
8117 * @constructor
8118 */
8119function Outlayer( element, options ) {
8120  var queryElement = utils.getQueryElement( element );
8121  if ( !queryElement ) {
8122    if ( console ) {
8123      console.error( 'Bad element for ' + this.constructor.namespace +
8124        ': ' + ( queryElement || element ) );
8125    }
8126    return;
8127  }
8128  this.element = queryElement;
8129  // add jQuery
8130  if ( jQuery ) {
8131    this.$element = jQuery( this.element );
8132  }
8133
8134  // options
8135  this.options = utils.extend( {}, this.constructor.defaults );
8136  this.option( options );
8137
8138  // add id for Outlayer.getFromElement
8139  var id = ++GUID;
8140  this.element.outlayerGUID = id; // expando
8141  instances[ id ] = this; // associate via id
8142
8143  // kick it off
8144  this._create();
8145
8146  var isInitLayout = this._getOption('initLayout');
8147  if ( isInitLayout ) {
8148    this.layout();
8149  }
8150}
8151
8152// settings are for internal use only
8153Outlayer.namespace = 'outlayer';
8154Outlayer.Item = Item;
8155
8156// default options
8157Outlayer.defaults = {
8158  containerStyle: {
8159    position: 'relative'
8160  },
8161  initLayout: true,
8162  originLeft: true,
8163  originTop: true,
8164  resize: true,
8165  resizeContainer: true,
8166  // item options
8167  transitionDuration: '0.4s',
8168  hiddenStyle: {
8169    opacity: 0,
8170    transform: 'scale(0.001)'
8171  },
8172  visibleStyle: {
8173    opacity: 1,
8174    transform: 'scale(1)'
8175  }
8176};
8177
8178var proto = Outlayer.prototype;
8179// inherit EvEmitter
8180utils.extend( proto, EvEmitter.prototype );
8181
8182/**
8183 * set options
8184 * @param {Object} opts
8185 */
8186proto.option = function( opts ) {
8187  utils.extend( this.options, opts );
8188};
8189
8190/**
8191 * get backwards compatible option value, check old name
8192 */
8193proto._getOption = function( option ) {
8194  var oldOption = this.constructor.compatOptions[ option ];
8195  return oldOption && this.options[ oldOption ] !== undefined ?
8196    this.options[ oldOption ] : this.options[ option ];
8197};
8198
8199Outlayer.compatOptions = {
8200  // currentName: oldName
8201  initLayout: 'isInitLayout',
8202  horizontal: 'isHorizontal',
8203  layoutInstant: 'isLayoutInstant',
8204  originLeft: 'isOriginLeft',
8205  originTop: 'isOriginTop',
8206  resize: 'isResizeBound',
8207  resizeContainer: 'isResizingContainer'
8208};
8209
8210proto._create = function() {
8211  // get items from children
8212  this.reloadItems();
8213  // elements that affect layout, but are not laid out
8214  this.stamps = [];
8215  this.stamp( this.options.stamp );
8216  // set container style
8217  utils.extend( this.element.style, this.options.containerStyle );
8218
8219  // bind resize method
8220  var canBindResize = this._getOption('resize');
8221  if ( canBindResize ) {
8222    this.bindResize();
8223  }
8224};
8225
8226// goes through all children again and gets bricks in proper order
8227proto.reloadItems = function() {
8228  // collection of item elements
8229  this.items = this._itemize( this.element.children );
8230};
8231
8232
8233/**
8234 * turn elements into Outlayer.Items to be used in layout
8235 * @param {Array or NodeList or HTMLElement} elems
8236 * @returns {Array} items - collection of new Outlayer Items
8237 */
8238proto._itemize = function( elems ) {
8239
8240  var itemElems = this._filterFindItemElements( elems );
8241  var Item = this.constructor.Item;
8242
8243  // create new Outlayer Items for collection
8244  var items = [];
8245  for ( var i=0; i < itemElems.length; i++ ) {
8246    var elem = itemElems[i];
8247    var item = new Item( elem, this );
8248    items.push( item );
8249  }
8250
8251  return items;
8252};
8253
8254/**
8255 * get item elements to be used in layout
8256 * @param {Array or NodeList or HTMLElement} elems
8257 * @returns {Array} items - item elements
8258 */
8259proto._filterFindItemElements = function( elems ) {
8260  return utils.filterFindElements( elems, this.options.itemSelector );
8261};
8262
8263/**
8264 * getter method for getting item elements
8265 * @returns {Array} elems - collection of item elements
8266 */
8267proto.getItemElements = function() {
8268  return this.items.map( function( item ) {
8269    return item.element;
8270  });
8271};
8272
8273// ----- init & layout ----- //
8274
8275/**
8276 * lays out all items
8277 */
8278proto.layout = function() {
8279  this._resetLayout();
8280  this._manageStamps();
8281
8282  // don't animate first layout
8283  var layoutInstant = this._getOption('layoutInstant');
8284  var isInstant = layoutInstant !== undefined ?
8285    layoutInstant : !this._isLayoutInited;
8286  this.layoutItems( this.items, isInstant );
8287
8288  // flag for initalized
8289  this._isLayoutInited = true;
8290};
8291
8292// _init is alias for layout
8293proto._init = proto.layout;
8294
8295/**
8296 * logic before any new layout
8297 */
8298proto._resetLayout = function() {
8299  this.getSize();
8300};
8301
8302
8303proto.getSize = function() {
8304  this.size = getSize( this.element );
8305};
8306
8307/**
8308 * get measurement from option, for columnWidth, rowHeight, gutter
8309 * if option is String -> get element from selector string, & get size of element
8310 * if option is Element -> get size of element
8311 * else use option as a number
8312 *
8313 * @param {String} measurement
8314 * @param {String} size - width or height
8315 * @private
8316 */
8317proto._getMeasurement = function( measurement, size ) {
8318  var option = this.options[ measurement ];
8319  var elem;
8320  if ( !option ) {
8321    // default to 0
8322    this[ measurement ] = 0;
8323  } else {
8324    // use option as an element
8325    if ( typeof option == 'string' ) {
8326      elem = this.element.querySelector( option );
8327    } else if ( option instanceof HTMLElement ) {
8328      elem = option;
8329    }
8330    // use size of element, if element
8331    this[ measurement ] = elem ? getSize( elem )[ size ] : option;
8332  }
8333};
8334
8335/**
8336 * layout a collection of item elements
8337 * @api public
8338 */
8339proto.layoutItems = function( items, isInstant ) {
8340  items = this._getItemsForLayout( items );
8341
8342  this._layoutItems( items, isInstant );
8343
8344  this._postLayout();
8345};
8346
8347/**
8348 * get the items to be laid out
8349 * you may want to skip over some items
8350 * @param {Array} items
8351 * @returns {Array} items
8352 */
8353proto._getItemsForLayout = function( items ) {
8354  return items.filter( function( item ) {
8355    return !item.isIgnored;
8356  });
8357};
8358
8359/**
8360 * layout items
8361 * @param {Array} items
8362 * @param {Boolean} isInstant
8363 */
8364proto._layoutItems = function( items, isInstant ) {
8365  this._emitCompleteOnItems( 'layout', items );
8366
8367  if ( !items || !items.length ) {
8368    // no items, emit event with empty array
8369    return;
8370  }
8371
8372  var queue = [];
8373
8374  items.forEach( function( item ) {
8375    // get x/y object from method
8376    var position = this._getItemLayoutPosition( item );
8377    // enqueue
8378    position.item = item;
8379    position.isInstant = isInstant || item.isLayoutInstant;
8380    queue.push( position );
8381  }, this );
8382
8383  this._processLayoutQueue( queue );
8384};
8385
8386/**
8387 * get item layout position
8388 * @param {Outlayer.Item} item
8389 * @returns {Object} x and y position
8390 */
8391proto._getItemLayoutPosition = function( /* item */ ) {
8392  return {
8393    x: 0,
8394    y: 0
8395  };
8396};
8397
8398/**
8399 * iterate over array and position each item
8400 * Reason being - separating this logic prevents 'layout invalidation'
8401 * thx @paul_irish
8402 * @param {Array} queue
8403 */
8404proto._processLayoutQueue = function( queue ) {
8405  this.updateStagger();
8406  queue.forEach( function( obj, i ) {
8407    this._positionItem( obj.item, obj.x, obj.y, obj.isInstant, i );
8408  }, this );
8409};
8410
8411// set stagger from option in milliseconds number
8412proto.updateStagger = function() {
8413  var stagger = this.options.stagger;
8414  if ( stagger === null || stagger === undefined ) {
8415    this.stagger = 0;
8416    return;
8417  }
8418  this.stagger = getMilliseconds( stagger );
8419  return this.stagger;
8420};
8421
8422/**
8423 * Sets position of item in DOM
8424 * @param {Outlayer.Item} item
8425 * @param {Number} x - horizontal position
8426 * @param {Number} y - vertical position
8427 * @param {Boolean} isInstant - disables transitions
8428 */
8429proto._positionItem = function( item, x, y, isInstant, i ) {
8430  if ( isInstant ) {
8431    // if not transition, just set CSS
8432    item.goTo( x, y );
8433  } else {
8434    item.stagger( i * this.stagger );
8435    item.moveTo( x, y );
8436  }
8437};
8438
8439/**
8440 * Any logic you want to do after each layout,
8441 * i.e. size the container
8442 */
8443proto._postLayout = function() {
8444  this.resizeContainer();
8445};
8446
8447proto.resizeContainer = function() {
8448  var isResizingContainer = this._getOption('resizeContainer');
8449  if ( !isResizingContainer ) {
8450    return;
8451  }
8452  var size = this._getContainerSize();
8453  if ( size ) {
8454    this._setContainerMeasure( size.width, true );
8455    this._setContainerMeasure( size.height, false );
8456  }
8457};
8458
8459/**
8460 * Sets width or height of container if returned
8461 * @returns {Object} size
8462 *   @param {Number} width
8463 *   @param {Number} height
8464 */
8465proto._getContainerSize = noop;
8466
8467/**
8468 * @param {Number} measure - size of width or height
8469 * @param {Boolean} isWidth
8470 */
8471proto._setContainerMeasure = function( measure, isWidth ) {
8472  if ( measure === undefined ) {
8473    return;
8474  }
8475
8476  var elemSize = this.size;
8477  // add padding and border width if border box
8478  if ( elemSize.isBorderBox ) {
8479    measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight +
8480      elemSize.borderLeftWidth + elemSize.borderRightWidth :
8481      elemSize.paddingBottom + elemSize.paddingTop +
8482      elemSize.borderTopWidth + elemSize.borderBottomWidth;
8483  }
8484
8485  measure = Math.max( measure, 0 );
8486  this.element.style[ isWidth ? 'width' : 'height' ] = measure + 'px';
8487};
8488
8489/**
8490 * emit eventComplete on a collection of items events
8491 * @param {String} eventName
8492 * @param {Array} items - Outlayer.Items
8493 */
8494proto._emitCompleteOnItems = function( eventName, items ) {
8495  var _this = this;
8496  function onComplete() {
8497    _this.dispatchEvent( eventName + 'Complete', null, [ items ] );
8498  }
8499
8500  var count = items.length;
8501  if ( !items || !count ) {
8502    onComplete();
8503    return;
8504  }
8505
8506  var doneCount = 0;
8507  function tick() {
8508    doneCount++;
8509    if ( doneCount == count ) {
8510      onComplete();
8511    }
8512  }
8513
8514  // bind callback
8515  items.forEach( function( item ) {
8516    item.once( eventName, tick );
8517  });
8518};
8519
8520/**
8521 * emits events via EvEmitter and jQuery events
8522 * @param {String} type - name of event
8523 * @param {Event} event - original event
8524 * @param {Array} args - extra arguments
8525 */
8526proto.dispatchEvent = function( type, event, args ) {
8527  // add original event to arguments
8528  var emitArgs = event ? [ event ].concat( args ) : args;
8529  this.emitEvent( type, emitArgs );
8530
8531  if ( jQuery ) {
8532    // set this.$element
8533    this.$element = this.$element || jQuery( this.element );
8534    if ( event ) {
8535      // create jQuery event
8536      var $event = jQuery.Event( event );
8537      $event.type = type;
8538      this.$element.trigger( $event, args );
8539    } else {
8540      // just trigger with type if no event available
8541      this.$element.trigger( type, args );
8542    }
8543  }
8544};
8545
8546// -------------------------- ignore & stamps -------------------------- //
8547
8548
8549/**
8550 * keep item in collection, but do not lay it out
8551 * ignored items do not get skipped in layout
8552 * @param {Element} elem
8553 */
8554proto.ignore = function( elem ) {
8555  var item = this.getItem( elem );
8556  if ( item ) {
8557    item.isIgnored = true;
8558  }
8559};
8560
8561/**
8562 * return item to layout collection
8563 * @param {Element} elem
8564 */
8565proto.unignore = function( elem ) {
8566  var item = this.getItem( elem );
8567  if ( item ) {
8568    delete item.isIgnored;
8569  }
8570};
8571
8572/**
8573 * adds elements to stamps
8574 * @param {NodeList, Array, Element, or String} elems
8575 */
8576proto.stamp = function( elems ) {
8577  elems = this._find( elems );
8578  if ( !elems ) {
8579    return;
8580  }
8581
8582  this.stamps = this.stamps.concat( elems );
8583  // ignore
8584  elems.forEach( this.ignore, this );
8585};
8586
8587/**
8588 * removes elements to stamps
8589 * @param {NodeList, Array, or Element} elems
8590 */
8591proto.unstamp = function( elems ) {
8592  elems = this._find( elems );
8593  if ( !elems ){
8594    return;
8595  }
8596
8597  elems.forEach( function( elem ) {
8598    // filter out removed stamp elements
8599    utils.removeFrom( this.stamps, elem );
8600    this.unignore( elem );
8601  }, this );
8602};
8603
8604/**
8605 * finds child elements
8606 * @param {NodeList, Array, Element, or String} elems
8607 * @returns {Array} elems
8608 */
8609proto._find = function( elems ) {
8610  if ( !elems ) {
8611    return;
8612  }
8613  // if string, use argument as selector string
8614  if ( typeof elems == 'string' ) {
8615    elems = this.element.querySelectorAll( elems );
8616  }
8617  elems = utils.makeArray( elems );
8618  return elems;
8619};
8620
8621proto._manageStamps = function() {
8622  if ( !this.stamps || !this.stamps.length ) {
8623    return;
8624  }
8625
8626  this._getBoundingRect();
8627
8628  this.stamps.forEach( this._manageStamp, this );
8629};
8630
8631// update boundingLeft / Top
8632proto._getBoundingRect = function() {
8633  // get bounding rect for container element
8634  var boundingRect = this.element.getBoundingClientRect();
8635  var size = this.size;
8636  this._boundingRect = {
8637    left: boundingRect.left + size.paddingLeft + size.borderLeftWidth,
8638    top: boundingRect.top + size.paddingTop + size.borderTopWidth,
8639    right: boundingRect.right - ( size.paddingRight + size.borderRightWidth ),
8640    bottom: boundingRect.bottom - ( size.paddingBottom + size.borderBottomWidth )
8641  };
8642};
8643
8644/**
8645 * @param {Element} stamp
8646**/
8647proto._manageStamp = noop;
8648
8649/**
8650 * get x/y position of element relative to container element
8651 * @param {Element} elem
8652 * @returns {Object} offset - has left, top, right, bottom
8653 */
8654proto._getElementOffset = function( elem ) {
8655  var boundingRect = elem.getBoundingClientRect();
8656  var thisRect = this._boundingRect;
8657  var size = getSize( elem );
8658  var offset = {
8659    left: boundingRect.left - thisRect.left - size.marginLeft,
8660    top: boundingRect.top - thisRect.top - size.marginTop,
8661    right: thisRect.right - boundingRect.right - size.marginRight,
8662    bottom: thisRect.bottom - boundingRect.bottom - size.marginBottom
8663  };
8664  return offset;
8665};
8666
8667// -------------------------- resize -------------------------- //
8668
8669// enable event handlers for listeners
8670// i.e. resize -> onresize
8671proto.handleEvent = utils.handleEvent;
8672
8673/**
8674 * Bind layout to window resizing
8675 */
8676proto.bindResize = function() {
8677  window.addEventListener( 'resize', this );
8678  this.isResizeBound = true;
8679};
8680
8681/**
8682 * Unbind layout to window resizing
8683 */
8684proto.unbindResize = function() {
8685  window.removeEventListener( 'resize', this );
8686  this.isResizeBound = false;
8687};
8688
8689proto.onresize = function() {
8690  this.resize();
8691};
8692
8693utils.debounceMethod( Outlayer, 'onresize', 100 );
8694
8695proto.resize = function() {
8696  // don't trigger if size did not change
8697  // or if resize was unbound. See #9
8698  if ( !this.isResizeBound || !this.needsResizeLayout() ) {
8699    return;
8700  }
8701
8702  this.layout();
8703};
8704
8705/**
8706 * check if layout is needed post layout
8707 * @returns Boolean
8708 */
8709proto.needsResizeLayout = function() {
8710  var size = getSize( this.element );
8711  // check that this.size and size are there
8712  // IE8 triggers resize on body size change, so they might not be
8713  var hasSizes = this.size && size;
8714  return hasSizes && size.innerWidth !== this.size.innerWidth;
8715};
8716
8717// -------------------------- methods -------------------------- //
8718
8719/**
8720 * add items to Outlayer instance
8721 * @param {Array or NodeList or Element} elems
8722 * @returns {Array} items - Outlayer.Items
8723**/
8724proto.addItems = function( elems ) {
8725  var items = this._itemize( elems );
8726  // add items to collection
8727  if ( items.length ) {
8728    this.items = this.items.concat( items );
8729  }
8730  return items;
8731};
8732
8733/**
8734 * Layout newly-appended item elements
8735 * @param {Array or NodeList or Element} elems
8736 */
8737proto.appended = function( elems ) {
8738  var items = this.addItems( elems );
8739  if ( !items.length ) {
8740    return;
8741  }
8742  // layout and reveal just the new items
8743  this.layoutItems( items, true );
8744  this.reveal( items );
8745};
8746
8747/**
8748 * Layout prepended elements
8749 * @param {Array or NodeList or Element} elems
8750 */
8751proto.prepended = function( elems ) {
8752  var items = this._itemize( elems );
8753  if ( !items.length ) {
8754    return;
8755  }
8756  // add items to beginning of collection
8757  var previousItems = this.items.slice(0);
8758  this.items = items.concat( previousItems );
8759  // start new layout
8760  this._resetLayout();
8761  this._manageStamps();
8762  // layout new stuff without transition
8763  this.layoutItems( items, true );
8764  this.reveal( items );
8765  // layout previous items
8766  this.layoutItems( previousItems );
8767};
8768
8769/**
8770 * reveal a collection of items
8771 * @param {Array of Outlayer.Items} items
8772 */
8773proto.reveal = function( items ) {
8774  this._emitCompleteOnItems( 'reveal', items );
8775  if ( !items || !items.length ) {
8776    return;
8777  }
8778  var stagger = this.updateStagger();
8779  items.forEach( function( item, i ) {
8780    item.stagger( i * stagger );
8781    item.reveal();
8782  });
8783};
8784
8785/**
8786 * hide a collection of items
8787 * @param {Array of Outlayer.Items} items
8788 */
8789proto.hide = function( items ) {
8790  this._emitCompleteOnItems( 'hide', items );
8791  if ( !items || !items.length ) {
8792    return;
8793  }
8794  var stagger = this.updateStagger();
8795  items.forEach( function( item, i ) {
8796    item.stagger( i * stagger );
8797    item.hide();
8798  });
8799};
8800
8801/**
8802 * reveal item elements
8803 * @param {Array}, {Element}, {NodeList} items
8804 */
8805proto.revealItemElements = function( elems ) {
8806  var items = this.getItems( elems );
8807  this.reveal( items );
8808};
8809
8810/**
8811 * hide item elements
8812 * @param {Array}, {Element}, {NodeList} items
8813 */
8814proto.hideItemElements = function( elems ) {
8815  var items = this.getItems( elems );
8816  this.hide( items );
8817};
8818
8819/**
8820 * get Outlayer.Item, given an Element
8821 * @param {Element} elem
8822 * @param {Function} callback
8823 * @returns {Outlayer.Item} item
8824 */
8825proto.getItem = function( elem ) {
8826  // loop through items to get the one that matches
8827  for ( var i=0; i < this.items.length; i++ ) {
8828    var item = this.items[i];
8829    if ( item.element == elem ) {
8830      // return item
8831      return item;
8832    }
8833  }
8834};
8835
8836/**
8837 * get collection of Outlayer.Items, given Elements
8838 * @param {Array} elems
8839 * @returns {Array} items - Outlayer.Items
8840 */
8841proto.getItems = function( elems ) {
8842  elems = utils.makeArray( elems );
8843  var items = [];
8844  elems.forEach( function( elem ) {
8845    var item = this.getItem( elem );
8846    if ( item ) {
8847      items.push( item );
8848    }
8849  }, this );
8850
8851  return items;
8852};
8853
8854/**
8855 * remove element(s) from instance and DOM
8856 * @param {Array or NodeList or Element} elems
8857 */
8858proto.remove = function( elems ) {
8859  var removeItems = this.getItems( elems );
8860
8861  this._emitCompleteOnItems( 'remove', removeItems );
8862
8863  // bail if no items to remove
8864  if ( !removeItems || !removeItems.length ) {
8865    return;
8866  }
8867
vendor: 38,285 bytes, lines 8868-10291
8868  removeItems.forEach( function( item ) {
8869    item.remove();
8870    // remove item from collection
8871    utils.removeFrom( this.items, item );
8872  }, this );
8873};
8874
8875// ----- destroy ----- //
8876
8877// remove and disable Outlayer instance
8878proto.destroy = function() {
8879  // clean up dynamic styles
8880  var style = this.element.style;
8881  style.height = '';
8882  style.position = '';
8883  style.width = '';
8884  // destroy items
8885  this.items.forEach( function( item ) {
8886    item.destroy();
8887  });
8888
8889  this.unbindResize();
8890
8891  var id = this.element.outlayerGUID;
8892  delete instances[ id ]; // remove reference to instance by id
8893  delete this.element.outlayerGUID;
8894  // remove data for jQuery
8895  if ( jQuery ) {
8896    jQuery.removeData( this.element, this.constructor.namespace );
8897  }
8898
8899};
8900
8901// -------------------------- data -------------------------- //
8902
8903/**
8904 * get Outlayer instance from element
8905 * @param {Element} elem
8906 * @returns {Outlayer}
8907 */
8908Outlayer.data = function( elem ) {
8909  elem = utils.getQueryElement( elem );
8910  var id = elem && elem.outlayerGUID;
8911  return id && instances[ id ];
8912};
8913
8914
8915// -------------------------- create Outlayer class -------------------------- //
8916
8917/**
8918 * create a layout class
8919 * @param {String} namespace
8920 */
8921Outlayer.create = function( namespace, options ) {
8922  // sub-class Outlayer
8923  var Layout = subclass( Outlayer );
8924  // apply new options and compatOptions
8925  Layout.defaults = utils.extend( {}, Outlayer.defaults );
8926  utils.extend( Layout.defaults, options );
8927  Layout.compatOptions = utils.extend( {}, Outlayer.compatOptions  );
8928
8929  Layout.namespace = namespace;
8930
8931  Layout.data = Outlayer.data;
8932
8933  // sub-class Item
8934  Layout.Item = subclass( Item );
8935
8936  // -------------------------- declarative -------------------------- //
8937
8938  utils.htmlInit( Layout, namespace );
8939
8940  // -------------------------- jQuery bridge -------------------------- //
8941
8942  // make into jQuery plugin
8943  if ( jQuery && jQuery.bridget ) {
8944    jQuery.bridget( namespace, Layout );
8945  }
8946
8947  return Layout;
8948};
8949
8950function subclass( Parent ) {
8951  function SubClass() {
8952    Parent.apply( this, arguments );
8953  }
8954
8955  SubClass.prototype = Object.create( Parent.prototype );
8956  SubClass.prototype.constructor = SubClass;
8957
8958  return SubClass;
8959}
8960
8961// ----- helpers ----- //
8962
8963// how many milliseconds are in each unit
8964var msUnits = {
8965  ms: 1,
8966  s: 1000
8967};
8968
8969// munge time-like parameter into millisecond number
8970// '0.4s' -> 40
8971function getMilliseconds( time ) {
8972  if ( typeof time == 'number' ) {
8973    return time;
8974  }
8975  var matches = time.match( /(^\d*\.?\d*)(\w*)/ );
8976  var num = matches && matches[1];
8977  var unit = matches && matches[2];
8978  if ( !num.length ) {
8979    return 0;
8980  }
8981  num = parseFloat( num );
8982  var mult = msUnits[ unit ] || 1;
8983  return num * mult;
8984}
8985
8986// ----- fin ----- //
8987
8988// back in global
8989Outlayer.Item = Item;
8990
8991return Outlayer;
8992
8993}));
8994
8995/**
8996 * Isotope Item
8997**/
8998
8999( function( window, factory ) {
9000  // universal module definition
9001  /* jshint strict: false */ /*globals define, module, require */
9002  if ( typeof define == 'function' && define.amd ) {
9003    // AMD
9004    define( 'isotope-layout/js/item',[
9005        'outlayer/outlayer'
9006      ],
9007      factory );
9008  } else if ( typeof module == 'object' && module.exports ) {
9009    // CommonJS
9010    module.exports = factory(
9011      require('outlayer')
9012    );
9013  } else {
9014    // browser global
9015    window.Isotope = window.Isotope || {};
9016    window.Isotope.Item = factory(
9017      window.Outlayer
9018    );
9019  }
9020
9021}( window, function factory( Outlayer ) {
9022'use strict';
9023
9024// -------------------------- Item -------------------------- //
9025
9026// sub-class Outlayer Item
9027function Item() {
9028  Outlayer.Item.apply( this, arguments );
9029}
9030
9031var proto = Item.prototype = Object.create( Outlayer.Item.prototype );
9032
9033var _create = proto._create;
9034proto._create = function() {
9035  // assign id, used for original-order sorting
9036  this.id = this.layout.itemGUID++;
9037  _create.call( this );
9038  this.sortData = {};
9039};
9040
9041proto.updateSortData = function() {
9042  if ( this.isIgnored ) {
9043    return;
9044  }
9045  // default sorters
9046  this.sortData.id = this.id;
9047  // for backward compatibility
9048  this.sortData['original-order'] = this.id;
9049  this.sortData.random = Math.random();
9050  // go thru getSortData obj and apply the sorters
9051  var getSortData = this.layout.options.getSortData;
9052  var sorters = this.layout._sorters;
9053  for ( var key in getSortData ) {
9054    var sorter = sorters[ key ];
9055    this.sortData[ key ] = sorter( this.element, this );
9056  }
9057};
9058
9059var _destroy = proto.destroy;
9060proto.destroy = function() {
9061  // call super
9062  _destroy.apply( this, arguments );
9063  // reset display, #741
9064  this.css({
9065    display: ''
9066  });
9067};
9068
9069return Item;
9070
9071}));
9072
9073/**
9074 * Isotope LayoutMode
9075 */
9076
9077( function( window, factory ) {
9078  // universal module definition
9079  /* jshint strict: false */ /*globals define, module, require */
9080  if ( typeof define == 'function' && define.amd ) {
9081    // AMD
9082    define( 'isotope-layout/js/layout-mode',[
9083        'get-size/get-size',
9084        'outlayer/outlayer'
9085      ],
9086      factory );
9087  } else if ( typeof module == 'object' && module.exports ) {
9088    // CommonJS
9089    module.exports = factory(
9090      require('get-size'),
9091      require('outlayer')
9092    );
9093  } else {
9094    // browser global
9095    window.Isotope = window.Isotope || {};
9096    window.Isotope.LayoutMode = factory(
9097      window.getSize,
9098      window.Outlayer
9099    );
9100  }
9101
9102}( window, function factory( getSize, Outlayer ) {
9103  'use strict';
9104
9105  // layout mode class
9106  function LayoutMode( isotope ) {
9107    this.isotope = isotope;
9108    // link properties
9109    if ( isotope ) {
9110      this.options = isotope.options[ this.namespace ];
9111      this.element = isotope.element;
9112      this.items = isotope.filteredItems;
9113      this.size = isotope.size;
9114    }
9115  }
9116
9117  var proto = LayoutMode.prototype;
9118
9119  /**
9120   * some methods should just defer to default Outlayer method
9121   * and reference the Isotope instance as `this`
9122  **/
9123  var facadeMethods = [
9124    '_resetLayout',
9125    '_getItemLayoutPosition',
9126    '_manageStamp',
9127    '_getContainerSize',
9128    '_getElementOffset',
9129    'needsResizeLayout',
9130    '_getOption'
9131  ];
9132
9133  facadeMethods.forEach( function( methodName ) {
9134    proto[ methodName ] = function() {
9135      return Outlayer.prototype[ methodName ].apply( this.isotope, arguments );
9136    };
9137  });
9138
9139  // -----  ----- //
9140
9141  // for horizontal layout modes, check vertical size
9142  proto.needsVerticalResizeLayout = function() {
9143    // don't trigger if size did not change
9144    var size = getSize( this.isotope.element );
9145    // check that this.size and size are there
9146    // IE8 triggers resize on body size change, so they might not be
9147    var hasSizes = this.isotope.size && size;
9148    return hasSizes && size.innerHeight != this.isotope.size.innerHeight;
9149  };
9150
9151  // ----- measurements ----- //
9152
9153  proto._getMeasurement = function() {
9154    this.isotope._getMeasurement.apply( this, arguments );
9155  };
9156
9157  proto.getColumnWidth = function() {
9158    this.getSegmentSize( 'column', 'Width' );
9159  };
9160
9161  proto.getRowHeight = function() {
9162    this.getSegmentSize( 'row', 'Height' );
9163  };
9164
9165  /**
9166   * get columnWidth or rowHeight
9167   * segment: 'column' or 'row'
9168   * size 'Width' or 'Height'
9169  **/
9170  proto.getSegmentSize = function( segment, size ) {
9171    var segmentName = segment + size;
9172    var outerSize = 'outer' + size;
9173    // columnWidth / outerWidth // rowHeight / outerHeight
9174    this._getMeasurement( segmentName, outerSize );
9175    // got rowHeight or columnWidth, we can chill
9176    if ( this[ segmentName ] ) {
9177      return;
9178    }
9179    // fall back to item of first element
9180    var firstItemSize = this.getFirstItemSize();
9181    this[ segmentName ] = firstItemSize && firstItemSize[ outerSize ] ||
9182      // or size of container
9183      this.isotope.size[ 'inner' + size ];
9184  };
9185
9186  proto.getFirstItemSize = function() {
9187    var firstItem = this.isotope.filteredItems[0];
9188    return firstItem && firstItem.element && getSize( firstItem.element );
9189  };
9190
9191  // ----- methods that should reference isotope ----- //
9192
9193  proto.layout = function() {
9194    this.isotope.layout.apply( this.isotope, arguments );
9195  };
9196
9197  proto.getSize = function() {
9198    this.isotope.getSize();
9199    this.size = this.isotope.size;
9200  };
9201
9202  // -------------------------- create -------------------------- //
9203
9204  LayoutMode.modes = {};
9205
9206  LayoutMode.create = function( namespace, options ) {
9207
9208    function Mode() {
9209      LayoutMode.apply( this, arguments );
9210    }
9211
9212    Mode.prototype = Object.create( proto );
9213    Mode.prototype.constructor = Mode;
9214
9215    // default options
9216    if ( options ) {
9217      Mode.options = options;
9218    }
9219
9220    Mode.prototype.namespace = namespace;
9221    // register in Isotope
9222    LayoutMode.modes[ namespace ] = Mode;
9223
9224    return Mode;
9225  };
9226
9227  return LayoutMode;
9228
9229}));
9230
9231/*!
9232 * Masonry v4.2.1
9233 * Cascading grid layout library
9234 * https://masonry.desandro.com
9235 * MIT License
9236 * by David DeSandro
9237 */
9238
9239( function( window, factory ) {
9240  // universal module definition
9241  /* jshint strict: false */ /*globals define, module, require */
9242  if ( typeof define == 'function' && define.amd ) {
9243    // AMD
9244    define( 'masonry-layout/masonry',[
9245        'outlayer/outlayer',
9246        'get-size/get-size'
9247      ],
9248      factory );
9249  } else if ( typeof module == 'object' && module.exports ) {
9250    // CommonJS
9251    module.exports = factory(
9252      require('outlayer'),
9253      require('get-size')
9254    );
9255  } else {
9256    // browser global
9257    window.Masonry = factory(
9258      window.Outlayer,
9259      window.getSize
9260    );
9261  }
9262
9263}( window, function factory( Outlayer, getSize ) {
9264
9265
9266
9267// -------------------------- masonryDefinition -------------------------- //
9268
9269  // create an Outlayer layout class
9270  var Masonry = Outlayer.create('masonry');
9271  // isFitWidth -> fitWidth
9272  Masonry.compatOptions.fitWidth = 'isFitWidth';
9273
9274  var proto = Masonry.prototype;
9275
9276  proto._resetLayout = function() {
9277    this.getSize();
9278    this._getMeasurement( 'columnWidth', 'outerWidth' );
9279    this._getMeasurement( 'gutter', 'outerWidth' );
9280    this.measureColumns();
9281
9282    // reset column Y
9283    this.colYs = [];
9284    for ( var i=0; i < this.cols; i++ ) {
9285      this.colYs.push( 0 );
9286    }
9287
9288    this.maxY = 0;
9289    this.horizontalColIndex = 0;
9290  };
9291
9292  proto.measureColumns = function() {
9293    this.getContainerWidth();
9294    // if columnWidth is 0, default to outerWidth of first item
9295    if ( !this.columnWidth ) {
9296      var firstItem = this.items[0];
9297      var firstItemElem = firstItem && firstItem.element;
9298      // columnWidth fall back to item of first element
9299      this.columnWidth = firstItemElem && getSize( firstItemElem ).outerWidth ||
9300        // if first elem has no width, default to size of container
9301        this.containerWidth;
9302    }
9303
9304    var columnWidth = this.columnWidth += this.gutter;
9305
9306    // calculate columns
9307    var containerWidth = this.containerWidth + this.gutter;
9308    var cols = containerWidth / columnWidth;
9309    // fix rounding errors, typically with gutters
9310    var excess = columnWidth - containerWidth % columnWidth;
9311    // if overshoot is less than a pixel, round up, otherwise floor it
9312    var mathMethod = excess && excess < 1 ? 'round' : 'floor';
9313    cols = Math[ mathMethod ]( cols );
9314    this.cols = Math.max( cols, 1 );
9315  };
9316
9317  proto.getContainerWidth = function() {
9318    // container is parent if fit width
9319    var isFitWidth = this._getOption('fitWidth');
9320    var container = isFitWidth ? this.element.parentNode : this.element;
9321    // check that this.size and size are there
9322    // IE8 triggers resize on body size change, so they might not be
9323    var size = getSize( container );
9324    this.containerWidth = size && size.innerWidth;
9325  };
9326
9327  proto._getItemLayoutPosition = function( item ) {
9328    item.getSize();
9329    // how many columns does this brick span
9330    var remainder = item.size.outerWidth % this.columnWidth;
9331    var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil';
9332    // round if off by 1 pixel, otherwise use ceil
9333    var colSpan = Math[ mathMethod ]( item.size.outerWidth / this.columnWidth );
9334    colSpan = Math.min( colSpan, this.cols );
9335    // use horizontal or top column position
9336    var colPosMethod = this.options.horizontalOrder ?
9337      '_getHorizontalColPosition' : '_getTopColPosition';
9338    var colPosition = this[ colPosMethod ]( colSpan, item );
9339    // position the brick
9340    var position = {
9341      x: this.columnWidth * colPosition.col,
9342      y: colPosition.y
9343    };
9344    // apply setHeight to necessary columns
9345    var setHeight = colPosition.y + item.size.outerHeight;
9346    var setMax = colSpan + colPosition.col;
9347    for ( var i = colPosition.col; i < setMax; i++ ) {
9348      this.colYs[i] = setHeight;
9349    }
9350
9351    return position;
9352  };
9353
9354  proto._getTopColPosition = function( colSpan ) {
9355    var colGroup = this._getTopColGroup( colSpan );
9356    // get the minimum Y value from the columns
9357    var minimumY = Math.min.apply( Math, colGroup );
9358
9359    return {
9360      col: colGroup.indexOf( minimumY ),
9361      y: minimumY,
9362    };
9363  };
9364
9365  /**
9366   * @param {Number} colSpan - number of columns the element spans
9367   * @returns {Array} colGroup
9368   */
9369  proto._getTopColGroup = function( colSpan ) {
9370    if ( colSpan < 2 ) {
9371      // if brick spans only one column, use all the column Ys
9372      return this.colYs;
9373    }
9374
9375    var colGroup = [];
9376    // how many different places could this brick fit horizontally
9377    var groupCount = this.cols + 1 - colSpan;
9378    // for each group potential horizontal position
9379    for ( var i = 0; i < groupCount; i++ ) {
9380      colGroup[i] = this._getColGroupY( i, colSpan );
9381    }
9382    return colGroup;
9383  };
9384
9385  proto._getColGroupY = function( col, colSpan ) {
9386    if ( colSpan < 2 ) {
9387      return this.colYs[ col ];
9388    }
9389    // make an array of colY values for that one group
9390    var groupColYs = this.colYs.slice( col, col + colSpan );
9391    // and get the max value of the array
9392    return Math.max.apply( Math, groupColYs );
9393  };
9394
9395  // get column position based on horizontal index. #873
9396  proto._getHorizontalColPosition = function( colSpan, item ) {
9397    var col = this.horizontalColIndex % this.cols;
9398    var isOver = colSpan > 1 && col + colSpan > this.cols;
9399    // shift to next row if item can't fit on current row
9400    col = isOver ? 0 : col;
9401    // don't let zero-size items take up space
9402    var hasSize = item.size.outerWidth && item.size.outerHeight;
9403    this.horizontalColIndex = hasSize ? col + colSpan : this.horizontalColIndex;
9404
9405    return {
9406      col: col,
9407      y: this._getColGroupY( col, colSpan ),
9408    };
9409  };
9410
9411  proto._manageStamp = function( stamp ) {
9412    var stampSize = getSize( stamp );
9413    var offset = this._getElementOffset( stamp );
9414    // get the columns that this stamp affects
9415    var isOriginLeft = this._getOption('originLeft');
9416    var firstX = isOriginLeft ? offset.left : offset.right;
9417    var lastX = firstX + stampSize.outerWidth;
9418    var firstCol = Math.floor( firstX / this.columnWidth );
9419    firstCol = Math.max( 0, firstCol );
9420    var lastCol = Math.floor( lastX / this.columnWidth );
9421    // lastCol should not go over if multiple of columnWidth #425
9422    lastCol -= lastX % this.columnWidth ? 0 : 1;
9423    lastCol = Math.min( this.cols - 1, lastCol );
9424    // set colYs to bottom of the stamp
9425
9426    var isOriginTop = this._getOption('originTop');
9427    var stampMaxY = ( isOriginTop ? offset.top : offset.bottom ) +
9428      stampSize.outerHeight;
9429    for ( var i = firstCol; i <= lastCol; i++ ) {
9430      this.colYs[i] = Math.max( stampMaxY, this.colYs[i] );
9431    }
9432  };
9433
9434  proto._getContainerSize = function() {
9435    this.maxY = Math.max.apply( Math, this.colYs );
9436    var size = {
9437      height: this.maxY
9438    };
9439
9440    if ( this._getOption('fitWidth') ) {
9441      size.width = this._getContainerFitWidth();
9442    }
9443
9444    return size;
9445  };
9446
9447  proto._getContainerFitWidth = function() {
9448    var unusedCols = 0;
9449    // count unused columns
9450    var i = this.cols;
9451    while ( --i ) {
9452      if ( this.colYs[i] !== 0 ) {
9453        break;
9454      }
9455      unusedCols++;
9456    }
9457    // fit container to columns that have been used
9458    return ( this.cols - unusedCols ) * this.columnWidth - this.gutter;
9459  };
9460
9461  proto.needsResizeLayout = function() {
9462    var previousWidth = this.containerWidth;
9463    this.getContainerWidth();
9464    return previousWidth != this.containerWidth;
9465  };
9466
9467  return Masonry;
9468
9469}));
9470
9471/*!
9472 * Masonry layout mode
9473 * sub-classes Masonry
9474 * https://masonry.desandro.com
9475 */
9476
9477( function( window, factory ) {
9478  // universal module definition
9479  /* jshint strict: false */ /*globals define, module, require */
9480  if ( typeof define == 'function' && define.amd ) {
9481    // AMD
9482    define( 'isotope-layout/js/layout-modes/masonry',[
9483        '../layout-mode',
9484        'masonry-layout/masonry'
9485      ],
9486      factory );
9487  } else if ( typeof module == 'object' && module.exports ) {
9488    // CommonJS
9489    module.exports = factory(
9490      require('../layout-mode'),
9491      require('masonry-layout')
9492    );
9493  } else {
9494    // browser global
9495    factory(
9496      window.Isotope.LayoutMode,
9497      window.Masonry
9498    );
9499  }
9500
9501}( window, function factory( LayoutMode, Masonry ) {
9502'use strict';
9503
9504// -------------------------- masonryDefinition -------------------------- //
9505
9506  // create an Outlayer layout class
9507  var MasonryMode = LayoutMode.create('masonry');
9508
9509  var proto = MasonryMode.prototype;
9510
9511  var keepModeMethods = {
9512    _getElementOffset: true,
9513    layout: true,
9514    _getMeasurement: true
9515  };
9516
9517  // inherit Masonry prototype
9518  for ( var method in Masonry.prototype ) {
9519    // do not inherit mode methods
9520    if ( !keepModeMethods[ method ] ) {
9521      proto[ method ] = Masonry.prototype[ method ];
9522    }
9523  }
9524
9525  var measureColumns = proto.measureColumns;
9526  proto.measureColumns = function() {
9527    // set items, used if measuring first item
9528    this.items = this.isotope.filteredItems;
9529    measureColumns.call( this );
9530  };
9531
9532  // point to mode options for fitWidth
9533  var _getOption = proto._getOption;
9534  proto._getOption = function( option ) {
9535    if ( option == 'fitWidth' ) {
9536      return this.options.isFitWidth !== undefined ?
9537        this.options.isFitWidth : this.options.fitWidth;
9538    }
9539    return _getOption.apply( this.isotope, arguments );
9540  };
9541
9542  return MasonryMode;
9543
9544}));
9545
9546/**
9547 * fitRows layout mode
9548 */
9549
9550( function( window, factory ) {
9551  // universal module definition
9552  /* jshint strict: false */ /*globals define, module, require */
9553  if ( typeof define == 'function' && define.amd ) {
9554    // AMD
9555    define( 'isotope-layout/js/layout-modes/fit-rows',[
9556        '../layout-mode'
9557      ],
9558      factory );
9559  } else if ( typeof exports == 'object' ) {
9560    // CommonJS
9561    module.exports = factory(
9562      require('../layout-mode')
9563    );
9564  } else {
9565    // browser global
9566    factory(
9567      window.Isotope.LayoutMode
9568    );
9569  }
9570
9571}( window, function factory( LayoutMode ) {
9572'use strict';
9573
9574var FitRows = LayoutMode.create('fitRows');
9575
9576var proto = FitRows.prototype;
9577
9578proto._resetLayout = function() {
9579  this.x = 0;
9580  this.y = 0;
9581  this.maxY = 0;
9582  this._getMeasurement( 'gutter', 'outerWidth' );
9583};
9584
9585proto._getItemLayoutPosition = function( item ) {
9586  item.getSize();
9587
9588  var itemWidth = item.size.outerWidth + this.gutter;
9589  // if this element cannot fit in the current row
9590  var containerWidth = this.isotope.size.innerWidth + this.gutter;
9591  if ( this.x !== 0 && itemWidth + this.x > containerWidth ) {
9592    this.x = 0;
9593    this.y = this.maxY;
9594  }
9595
9596  var position = {
9597    x: this.x,
9598    y: this.y
9599  };
9600
9601  this.maxY = Math.max( this.maxY, this.y + item.size.outerHeight );
9602  this.x += itemWidth;
9603
9604  return position;
9605};
9606
9607proto._getContainerSize = function() {
9608  return { height: this.maxY };
9609};
9610
9611return FitRows;
9612
9613}));
9614
9615/**
9616 * vertical layout mode
9617 */
9618
9619( function( window, factory ) {
9620  // universal module definition
9621  /* jshint strict: false */ /*globals define, module, require */
9622  if ( typeof define == 'function' && define.amd ) {
9623    // AMD
9624    define( 'isotope-layout/js/layout-modes/vertical',[
9625        '../layout-mode'
9626      ],
9627      factory );
9628  } else if ( typeof module == 'object' && module.exports ) {
9629    // CommonJS
9630    module.exports = factory(
9631      require('../layout-mode')
9632    );
9633  } else {
9634    // browser global
9635    factory(
9636      window.Isotope.LayoutMode
9637    );
9638  }
9639
9640}( window, function factory( LayoutMode ) {
9641'use strict';
9642
9643var Vertical = LayoutMode.create( 'vertical', {
9644  horizontalAlignment: 0
9645});
9646
9647var proto = Vertical.prototype;
9648
9649proto._resetLayout = function() {
9650  this.y = 0;
9651};
9652
9653proto._getItemLayoutPosition = function( item ) {
9654  item.getSize();
9655  var x = ( this.isotope.size.innerWidth - item.size.outerWidth ) *
9656    this.options.horizontalAlignment;
9657  var y = this.y;
9658  this.y += item.size.outerHeight;
9659  return { x: x, y: y };
9660};
9661
9662proto._getContainerSize = function() {
9663  return { height: this.y };
9664};
9665
9666return Vertical;
9667
9668}));
9669
9670/*!
9671 * Isotope v3.0.6
9672 *
9673 * Licensed GPLv3 for open source use
9674 * or Isotope Commercial License for commercial use
9675 *
9676 * https://isotope.metafizzy.co
9677 * Copyright 2010-2018 Metafizzy
9678 */
9679
9680( function( window, factory ) {
9681  // universal module definition
9682  /* jshint strict: false */ /*globals define, module, require */
9683  if ( typeof define == 'function' && define.amd ) {
9684    // AMD
9685    define( [
9686        'outlayer/outlayer',
9687        'get-size/get-size',
9688        'desandro-matches-selector/matches-selector',
9689        'fizzy-ui-utils/utils',
9690        'isotope-layout/js/item',
9691        'isotope-layout/js/layout-mode',
9692        // include default layout modes
9693        'isotope-layout/js/layout-modes/masonry',
9694        'isotope-layout/js/layout-modes/fit-rows',
9695        'isotope-layout/js/layout-modes/vertical'
9696      ],
9697      function( Outlayer, getSize, matchesSelector, utils, Item, LayoutMode ) {
9698        return factory( window, Outlayer, getSize, matchesSelector, utils, Item, LayoutMode );
9699      });
9700  } else if ( typeof module == 'object' && module.exports ) {
9701    // CommonJS
9702    module.exports = factory(
9703      window,
9704      require('outlayer'),
9705      require('get-size'),
9706      require('desandro-matches-selector'),
9707      require('fizzy-ui-utils'),
9708      require('isotope-layout/js/item'),
9709      require('isotope-layout/js/layout-mode'),
9710      // include default layout modes
9711      require('isotope-layout/js/layout-modes/masonry'),
9712      require('isotope-layout/js/layout-modes/fit-rows'),
9713      require('isotope-layout/js/layout-modes/vertical')
9714    );
9715  } else {
9716    // browser global
9717    window.Isotope = factory(
9718      window,
9719      window.Outlayer,
9720      window.getSize,
9721      window.matchesSelector,
9722      window.fizzyUIUtils,
9723      window.Isotope.Item,
9724      window.Isotope.LayoutMode
9725    );
9726  }
9727
9728}( window, function factory( window, Outlayer, getSize, matchesSelector, utils,
9729  Item, LayoutMode ) {
9730
9731
9732
9733// -------------------------- vars -------------------------- //
9734
9735var jQuery = window.jQuery;
9736
9737// -------------------------- helpers -------------------------- //
9738
9739var trim = String.prototype.trim ?
9740  function( str ) {
9741    return str.trim();
9742  } :
9743  function( str ) {
9744    return str.replace( /^\s+|\s+$/g, '' );
9745  };
9746
9747// -------------------------- isotopeDefinition -------------------------- //
9748
9749  // create an Outlayer layout class
9750  var Isotope = Outlayer.create( 'isotope', {
9751    layoutMode: 'masonry',
9752    isJQueryFiltering: true,
9753    sortAscending: true
9754  });
9755
9756  Isotope.Item = Item;
9757  Isotope.LayoutMode = LayoutMode;
9758
9759  var proto = Isotope.prototype;
9760
9761  proto._create = function() {
9762    this.itemGUID = 0;
9763    // functions that sort items
9764    this._sorters = {};
9765    this._getSorters();
9766    // call super
9767    Outlayer.prototype._create.call( this );
9768
9769    // create layout modes
9770    this.modes = {};
9771    // start filteredItems with all items
9772    this.filteredItems = this.items;
9773    // keep of track of sortBys
9774    this.sortHistory = [ 'original-order' ];
9775    // create from registered layout modes
9776    for ( var name in LayoutMode.modes ) {
9777      this._initLayoutMode( name );
9778    }
9779  };
9780
9781  proto.reloadItems = function() {
9782    // reset item ID counter
9783    this.itemGUID = 0;
9784    // call super
9785    Outlayer.prototype.reloadItems.call( this );
9786  };
9787
9788  proto._itemize = function() {
9789    var items = Outlayer.prototype._itemize.apply( this, arguments );
9790    // assign ID for original-order
9791    for ( var i=0; i < items.length; i++ ) {
9792      var item = items[i];
9793      item.id = this.itemGUID++;
9794    }
9795    this._updateItemsSortData( items );
9796    return items;
9797  };
9798
9799
9800  // -------------------------- layout -------------------------- //
9801
9802  proto._initLayoutMode = function( name ) {
9803    var Mode = LayoutMode.modes[ name ];
9804    // set mode options
9805    // HACK extend initial options, back-fill in default options
9806    var initialOpts = this.options[ name ] || {};
9807    this.options[ name ] = Mode.options ?
9808      utils.extend( Mode.options, initialOpts ) : initialOpts;
9809    // init layout mode instance
9810    this.modes[ name ] = new Mode( this );
9811  };
9812
9813
9814  proto.layout = function() {
9815    // if first time doing layout, do all magic
9816    if ( !this._isLayoutInited && this._getOption('initLayout') ) {
9817      this.arrange();
9818      return;
9819    }
9820    this._layout();
9821  };
9822
9823  // private method to be used in layout() & magic()
9824  proto._layout = function() {
9825    // don't animate first layout
9826    var isInstant = this._getIsInstant();
9827    // layout flow
9828    this._resetLayout();
9829    this._manageStamps();
9830    this.layoutItems( this.filteredItems, isInstant );
9831
9832    // flag for initalized
9833    this._isLayoutInited = true;
9834  };
9835
9836  // filter + sort + layout
9837  proto.arrange = function( opts ) {
9838    // set any options pass
9839    this.option( opts );
9840    this._getIsInstant();
9841    // filter, sort, and layout
9842
9843    // filter
9844    var filtered = this._filter( this.items );
9845    this.filteredItems = filtered.matches;
9846
9847    this._bindArrangeComplete();
9848
9849    if ( this._isInstant ) {
9850      this._noTransition( this._hideReveal, [ filtered ] );
9851    } else {
9852      this._hideReveal( filtered );
9853    }
9854
9855    this._sort();
9856    this._layout();
9857  };
9858  // alias to _init for main plugin method
9859  proto._init = proto.arrange;
9860
9861  proto._hideReveal = function( filtered ) {
9862    this.reveal( filtered.needReveal );
9863    this.hide( filtered.needHide );
9864  };
9865
9866  // HACK
9867  // Don't animate/transition first layout
9868  // Or don't animate/transition other layouts
9869  proto._getIsInstant = function() {
9870    var isLayoutInstant = this._getOption('layoutInstant');
9871    var isInstant = isLayoutInstant !== undefined ? isLayoutInstant :
9872      !this._isLayoutInited;
9873    this._isInstant = isInstant;
9874    return isInstant;
9875  };
9876
9877  // listen for layoutComplete, hideComplete and revealComplete
9878  // to trigger arrangeComplete
9879  proto._bindArrangeComplete = function() {
9880    // listen for 3 events to trigger arrangeComplete
9881    var isLayoutComplete, isHideComplete, isRevealComplete;
9882    var _this = this;
9883    function arrangeParallelCallback() {
9884      if ( isLayoutComplete && isHideComplete && isRevealComplete ) {
9885        _this.dispatchEvent( 'arrangeComplete', null, [ _this.filteredItems ] );
9886      }
9887    }
9888    this.once( 'layoutComplete', function() {
9889      isLayoutComplete = true;
9890      arrangeParallelCallback();
9891    });
9892    this.once( 'hideComplete', function() {
9893      isHideComplete = true;
9894      arrangeParallelCallback();
9895    });
9896    this.once( 'revealComplete', function() {
9897      isRevealComplete = true;
9898      arrangeParallelCallback();
9899    });
9900  };
9901
9902  // -------------------------- filter -------------------------- //
9903
9904  proto._filter = function( items ) {
9905    var filter = this.options.filter;
9906    filter = filter || '*';
9907    var matches = [];
9908    var hiddenMatched = [];
9909    var visibleUnmatched = [];
9910
9911    var test = this._getFilterTest( filter );
9912
9913    // test each item
9914    for ( var i=0; i < items.length; i++ ) {
9915      var item = items[i];
9916      if ( item.isIgnored ) {
9917        continue;
9918      }
9919      // add item to either matched or unmatched group
9920      var isMatched = test( item );
9921      // item.isFilterMatched = isMatched;
9922      // add to matches if its a match
9923      if ( isMatched ) {
9924        matches.push( item );
9925      }
9926      // add to additional group if item needs to be hidden or revealed
9927      if ( isMatched && item.isHidden ) {
9928        hiddenMatched.push( item );
9929      } else if ( !isMatched && !item.isHidden ) {
9930        visibleUnmatched.push( item );
9931      }
9932    }
9933
9934    // return collections of items to be manipulated
9935    return {
9936      matches: matches,
9937      needReveal: hiddenMatched,
9938      needHide: visibleUnmatched
9939    };
9940  };
9941
9942  // get a jQuery, function, or a matchesSelector test given the filter
9943  proto._getFilterTest = function( filter ) {
9944    if ( jQuery && this.options.isJQueryFiltering ) {
9945      // use jQuery
9946      return function( item ) {
9947        return jQuery( item.element ).is( filter );
9948      };
9949    }
9950    if ( typeof filter == 'function' ) {
9951      // use filter as function
9952      return function( item ) {
9953        return filter( item.element );
9954      };
9955    }
9956    // default, use filter as selector string
9957    return function( item ) {
9958      return matchesSelector( item.element, filter );
9959    };
9960  };
9961
9962  // -------------------------- sorting -------------------------- //
9963
9964  /**
9965   * @params {Array} elems
9966   * @public
9967   */
9968  proto.updateSortData = function( elems ) {
9969    // get items
9970    var items;
9971    if ( elems ) {
9972      elems = utils.makeArray( elems );
9973      items = this.getItems( elems );
9974    } else {
9975      // update all items if no elems provided
9976      items = this.items;
9977    }
9978
9979    this._getSorters();
9980    this._updateItemsSortData( items );
9981  };
9982
9983  proto._getSorters = function() {
9984    var getSortData = this.options.getSortData;
9985    for ( var key in getSortData ) {
9986      var sorter = getSortData[ key ];
9987      this._sorters[ key ] = mungeSorter( sorter );
9988    }
9989  };
9990
9991  /**
9992   * @params {Array} items - of Isotope.Items
9993   * @private
9994   */
9995  proto._updateItemsSortData = function( items ) {
9996    // do not update if no items
9997    var len = items && items.length;
9998
9999    for ( var i=0; len && i < len; i++ ) {
10000      var item = items[i];
10001      item.updateSortData();
10002    }
10003  };
10004
10005  // ----- munge sorter ----- //
10006
10007  // encapsulate this, as we just need mungeSorter
10008  // other functions in here are just for munging
10009  var mungeSorter = ( function() {
10010    // add a magic layer to sorters for convienent shorthands
10011    // `.foo-bar` will use the text of .foo-bar querySelector
10012    // `[foo-bar]` will use attribute
10013    // you can also add parser
10014    // `.foo-bar parseInt` will parse that as a number
10015    function mungeSorter( sorter ) {
10016      // if not a string, return function or whatever it is
10017      if ( typeof sorter != 'string' ) {
10018        return sorter;
10019      }
10020      // parse the sorter string
10021      var args = trim( sorter ).split(' ');
10022      var query = args[0];
10023      // check if query looks like [an-attribute]
10024      var attrMatch = query.match( /^\[(.+)\]$/ );
10025      var attr = attrMatch && attrMatch[1];
10026      var getValue = getValueGetter( attr, query );
10027      // use second argument as a parser
10028      var parser = Isotope.sortDataParsers[ args[1] ];
10029      // parse the value, if there was a parser
10030      sorter = parser ? function( elem ) {
10031        return elem && parser( getValue( elem ) );
10032      } :
10033      // otherwise just return value
10034      function( elem ) {
10035        return elem && getValue( elem );
10036      };
10037
10038      return sorter;
10039    }
10040
10041    // get an attribute getter, or get text of the querySelector
10042    function getValueGetter( attr, query ) {
10043      // if query looks like [foo-bar], get attribute
10044      if ( attr ) {
10045        return function getAttribute( elem ) {
10046          return elem.getAttribute( attr );
10047        };
10048      }
10049
10050      // otherwise, assume its a querySelector, and get its text
10051      return function getChildText( elem ) {
10052        var child = elem.querySelector( query );
10053        return child && child.textContent;
10054      };
10055    }
10056
10057    return mungeSorter;
10058  })();
10059
10060  // parsers used in getSortData shortcut strings
10061  Isotope.sortDataParsers = {
10062    'parseInt': function( val ) {
10063      return parseInt( val, 10 );
10064    },
10065    'parseFloat': function( val ) {
10066      return parseFloat( val );
10067    }
10068  };
10069
10070  // ----- sort method ----- //
10071
10072  // sort filteredItem order
10073  proto._sort = function() {
10074    if ( !this.options.sortBy ) {
10075      return;
10076    }
10077    // keep track of sortBy History
10078    var sortBys = utils.makeArray( this.options.sortBy );
10079    if ( !this._getIsSameSortBy( sortBys ) ) {
10080      // concat all sortBy and sortHistory, add to front, oldest goes in last
10081      this.sortHistory = sortBys.concat( this.sortHistory );
10082    }
10083    // sort magic
10084    var itemSorter = getItemSorter( this.sortHistory, this.options.sortAscending );
10085    this.filteredItems.sort( itemSorter );
10086  };
10087
10088  // check if sortBys is same as start of sortHistory
10089  proto._getIsSameSortBy = function( sortBys ) {
10090    for ( var i=0; i < sortBys.length; i++ ) {
10091      if ( sortBys[i] != this.sortHistory[i] ) {
10092        return false;
10093      }
10094    }
10095    return true;
10096  };
10097
10098  // returns a function used for sorting
10099  function getItemSorter( sortBys, sortAsc ) {
10100    return function sorter( itemA, itemB ) {
10101      // cycle through all sortKeys
10102      for ( var i = 0; i < sortBys.length; i++ ) {
10103        var sortBy = sortBys[i];
10104        var a = itemA.sortData[ sortBy ];
10105        var b = itemB.sortData[ sortBy ];
10106        if ( a > b || a < b ) {
10107          // if sortAsc is an object, use the value given the sortBy key
10108          var isAscending = sortAsc[ sortBy ] !== undefined ? sortAsc[ sortBy ] : sortAsc;
10109          var direction = isAscending ? 1 : -1;
10110          return ( a > b ? 1 : -1 ) * direction;
10111        }
10112      }
10113      return 0;
10114    };
10115  }
10116
10117  // -------------------------- methods -------------------------- //
10118
10119  // get layout mode
10120  proto._mode = function() {
10121    var layoutMode = this.options.layoutMode;
10122    var mode = this.modes[ layoutMode ];
10123    if ( !mode ) {
10124      // TODO console.error
10125      throw new Error( 'No layout mode: ' + layoutMode );
10126    }
10127    // HACK sync mode's options
10128    // any options set after init for layout mode need to be synced
10129    mode.options = this.options[ layoutMode ];
10130    return mode;
10131  };
10132
10133  proto._resetLayout = function() {
10134    // trigger original reset layout
10135    Outlayer.prototype._resetLayout.call( this );
10136    this._mode()._resetLayout();
10137  };
10138
10139  proto._getItemLayoutPosition = function( item  ) {
10140    return this._mode()._getItemLayoutPosition( item );
10141  };
10142
10143  proto._manageStamp = function( stamp ) {
10144    this._mode()._manageStamp( stamp );
10145  };
10146
10147  proto._getContainerSize = function() {
10148    return this._mode()._getContainerSize();
10149  };
10150
10151  proto.needsResizeLayout = function() {
10152    return this._mode().needsResizeLayout();
10153  };
10154
10155  // -------------------------- adding & removing -------------------------- //
10156
10157  // HEADS UP overwrites default Outlayer appended
10158  proto.appended = function( elems ) {
10159    var items = this.addItems( elems );
10160    if ( !items.length ) {
10161      return;
10162    }
10163    // filter, layout, reveal new items
10164    var filteredItems = this._filterRevealAdded( items );
10165    // add to filteredItems
10166    this.filteredItems = this.filteredItems.concat( filteredItems );
10167  };
10168
10169  // HEADS UP overwrites default Outlayer prepended
10170  proto.prepended = function( elems ) {
10171    var items = this._itemize( elems );
10172    if ( !items.length ) {
10173      return;
10174    }
10175    // start new layout
10176    this._resetLayout();
10177    this._manageStamps();
10178    // filter, layout, reveal new items
10179    var filteredItems = this._filterRevealAdded( items );
10180    // layout previous items
10181    this.layoutItems( this.filteredItems );
10182    // add to items and filteredItems
10183    this.filteredItems = filteredItems.concat( this.filteredItems );
10184    this.items = items.concat( this.items );
10185  };
10186
10187  proto._filterRevealAdded = function( items ) {
10188    var filtered = this._filter( items );
10189    this.hide( filtered.needHide );
10190    // reveal all new items
10191    this.reveal( filtered.matches );
10192    // layout new items, no transition
10193    this.layoutItems( filtered.matches, true );
10194    return filtered.matches;
10195  };
10196
10197  /**
10198   * Filter, sort, and layout newly-appended item elements
10199   * @param {Array or NodeList or Element} elems
10200   */
10201  proto.insert = function( elems ) {
10202    var items = this.addItems( elems );
10203    if ( !items.length ) {
10204      return;
10205    }
10206    // append item elements
10207    var i, item;
10208    var len = items.length;
10209    for ( i=0; i < len; i++ ) {
10210      item = items[i];
10211      this.element.appendChild( item.element );
10212    }
10213    // filter new stuff
10214    var filteredInsertItems = this._filter( items ).matches;
10215    // set flag
10216    for ( i=0; i < len; i++ ) {
10217      items[i].isLayoutInstant = true;
10218    }
10219    this.arrange();
10220    // reset flag
10221    for ( i=0; i < len; i++ ) {
10222      delete items[i].isLayoutInstant;
10223    }
10224    this.reveal( filteredInsertItems );
10225  };
10226
10227  var _remove = proto.remove;
10228  proto.remove = function( elems ) {
10229    elems = utils.makeArray( elems );
10230    var removeItems = this.getItems( elems );
10231    // do regular thing
10232    _remove.call( this, elems );
10233    // bail if no items to remove
10234    var len = removeItems && removeItems.length;
10235    // remove elems from filteredItems
10236    for ( var i=0; len && i < len; i++ ) {
10237      var item = removeItems[i];
10238      // remove item from collection
10239      utils.removeFrom( this.filteredItems, item );
10240    }
10241  };
10242
10243  proto.shuffle = function() {
10244    // update random sortData
10245    for ( var i=0; i < this.items.length; i++ ) {
10246      var item = this.items[i];
10247      item.sortData.random = Math.random();
10248    }
10249    this.options.sortBy = 'random';
10250    this._sort();
10251    this._layout();
10252  };
10253
10254  /**
10255   * trigger fn without transition
10256   * kind of hacky to have this in the first place
10257   * @param {Function} fn
10258   * @param {Array} args
10259   * @returns ret
10260   * @private
10261   */
10262  proto._noTransition = function( fn, args ) {
10263    // save transitionDuration before disabling
10264    var transitionDuration = this.options.transitionDuration;
10265    // disable transition
10266    this.options.transitionDuration = 0;
10267    // do it
10268    var returnValue = fn.apply( this, args );
10269    // re-enable transition for reveal
10270    this.options.transitionDuration = transitionDuration;
10271    return returnValue;
10272  };
10273
10274  // ----- helper methods ----- //
10275
10276  /**
10277   * getter method for getting filtered item elements
10278   * @returns {Array} elems - collection of item elements
10279   */
10280  proto.getFilteredItemElements = function() {
10281    return this.filteredItems.map( function( item ) {
10282      return item.element;
10283    });
10284  };
10285
10286  // -----  ----- //
10287
10288  return Isotope;
10289
10290}));
10291
10292/*!
10293 * Packery layout mode PACKAGED v2.0.1
10294 * sub-classes Packery
10295 */
10296
10297/**
10298 * Rect
10299 * low-level utility class for basic geometry
10300 */
10301
10302( function( window, factory ) {
10303  // universal module definition
10304  /* jshint strict: false */ /* globals define, module */
10305  if ( typeof define == 'function' && define.amd ) {
10306    // AMD
10307    define( 'packery/js/rect',factory );
10308  } else if ( typeof module == 'object' && module.exports ) {
10309    // CommonJS
10310    module.exports = factory();
10311  } else {
10312    // browser global
10313    window.Packery = window.Packery || {};
10314    window.Packery.Rect = factory();
10315  }
10316
10317}( window, function factory() {
10318
10319
10320// -------------------------- Rect -------------------------- //
10321
10322function Rect( props ) {
10323  // extend properties from defaults
10324  for ( var prop in Rect.defaults ) {
10325    this[ prop ] = Rect.defaults[ prop ];
10326  }
10327
10328  for ( prop in props ) {
10329    this[ prop ] = props[ prop ];
10330  }
10331
10332}
10333
10334Rect.defaults = {
10335  x: 0,
10336  y: 0,
10337  width: 0,
10338  height: 0
10339};
10340
10341var proto = Rect.prototype;
10342
10343/**
10344 * Determines whether or not this rectangle wholly encloses another rectangle or point.
10345 * @param {Rect} rect
10346 * @returns {Boolean}
10347**/
10348proto.contains = function( rect ) {
10349  // points don't have width or height
10350  var otherWidth = rect.width || 0;
10351  var otherHeight = rect.height || 0;
10352  return this.x <= rect.x &&
10353    this.y <= rect.y &&
10354    this.x + this.width >= rect.x + otherWidth &&
10355    this.y + this.height >= rect.y + otherHeight;
10356};
10357
10358/**
10359 * Determines whether or not the rectangle intersects with another.
10360 * @param {Rect} rect
10361 * @returns {Boolean}
10362**/
10363proto.overlaps = function( rect ) {
10364  var thisRight = this.x + this.width;
10365  var thisBottom = this.y + this.height;
10366  var rectRight = rect.x + rect.width;
10367  var rectBottom = rect.y + rect.height;
10368
10369  // http://stackoverflow.com/a/306332
10370  return this.x < rectRight &&
10371    thisRight > rect.x &&
10372    this.y < rectBottom &&
10373    thisBottom > rect.y;
10374};
10375
10376/**
10377 * @param {Rect} rect - the overlapping rect
10378 * @returns {Array} freeRects - rects representing the area around the rect
10379**/
10380proto.getMaximalFreeRects = function( rect ) {
10381
10382  // if no intersection, return false
10383  if ( !this.overlaps( rect ) ) {
10384    return false;
10385  }
10386
10387  var freeRects = [];
10388  var freeRect;
10389
10390  var thisRight = this.x + this.width;
10391  var thisBottom = this.y + this.height;
10392  var rectRight = rect.x + rect.width;
10393  var rectBottom = rect.y + rect.height;
10394
10395  // top
10396  if ( this.y < rect.y ) {
10397    freeRect = new Rect({
10398      x: this.x,
10399      y: this.y,
10400      width: this.width,
10401      height: rect.y - this.y
10402    });
10403    freeRects.push( freeRect );
10404  }
10405
10406  // right
10407  if ( thisRight > rectRight ) {
10408    freeRect = new Rect({
10409      x: rectRight,
10410      y: this.y,
10411      width: thisRight - rectRight,
10412      height: this.height
10413    });
10414    freeRects.push( freeRect );
10415  }
10416
10417  // bottom
10418  if ( thisBottom > rectBottom ) {
10419    freeRect = new Rect({
10420      x: this.x,
10421      y: rectBottom,
10422      width: this.width,
10423      height: thisBottom - rectBottom
10424    });
10425    freeRects.push( freeRect );
10426  }
10427
10428  // left
10429  if ( this.x < rect.x ) {
10430    freeRect = new Rect({
10431      x: this.x,
10432      y: this.y,
10433      width: rect.x - this.x,
10434      height: this.height
10435    });
10436    freeRects.push( freeRect );
10437  }
10438
10439  return freeRects;
10440};
10441
10442proto.canFit = function( rect ) {
10443  return this.width >= rect.width && this.height >= rect.height;
10444};
10445
10446return Rect;
10447
10448}));
10449
10450/**
10451 * Packer
10452 * bin-packing algorithm
10453 */
10454
10455( function( window, factory ) {
10456  // universal module definition
10457  /* jshint strict: false */ /* globals define, module, require */
10458  if ( typeof define == 'function' && define.amd ) {
10459    // AMD
10460    define( 'packery/js/packer',[ './rect' ], factory );
10461  } else if ( typeof module == 'object' && module.exports ) {
10462    // CommonJS
10463    module.exports = factory(
10464      require('./rect')
10465    );
10466  } else {
10467    // browser global
10468    var Packery = window.Packery = window.Packery || {};
10469    Packery.Packer = factory( Packery.Rect );
10470  }
10471
10472}( window, function factory( Rect ) {
10473
10474
10475// -------------------------- Packer -------------------------- //
10476
10477/**
10478 * @param {Number} width
10479 * @param {Number} height
10480 * @param {String} sortDirection
10481 *   topLeft for vertical, leftTop for horizontal
10482 */
10483function Packer( width, height, sortDirection ) {
10484  this.width = width || 0;
10485  this.height = height || 0;
10486  this.sortDirection = sortDirection || 'downwardLeftToRight';
10487
10488  this.reset();
10489}
10490
10491var proto = Packer.prototype;
10492
10493proto.reset = function() {
10494  this.spaces = [];
10495
10496  var initialSpace = new Rect({
10497    x: 0,
10498    y: 0,
10499    width: this.width,
10500    height: this.height
10501  });
10502
10503  this.spaces.push( initialSpace );
10504  // set sorter
10505  this.sorter = sorters[ this.sortDirection ] || sorters.downwardLeftToRight;
10506};
10507
10508// change x and y of rect to fit with in Packer's available space
10508s
10509proto.pack = function( rect ) {
10510  for ( var i=0; i < this.spaces.length; i++ ) {
10511    var space = this.spaces[i];
10512    if ( space.canFit( rect ) ) {
10513      this.placeInSpace( rect, space );
10514      break;
10515    }
10516  }
10517};
10518
10519proto.columnPack = function( rect ) {
10520  for ( var i=0; i < this.spaces.length; i++ ) {
10521    var space = this.spaces[i];
10522    var canFitInSpaceColumn = space.x <= rect.x &&
10523      space.x + space.width >= rect.x + rect.width &&
10524      space.height >= rect.height - 0.01; // fudge number for rounding error
10525    if ( canFitInSpaceColumn ) {
10526      rect.y = space.y;
10527      this.placed( rect );
10528      break;
10529    }
10530  }
10531};
10532
10533proto.rowPack = function( rect ) {
10534  for ( var i=0; i < this.spaces.length; i++ ) {
10535    var space = this.spaces[i];
10536    var canFitInSpaceRow = space.y <= rect.y &&
10537      space.y + space.height >= rect.y + rect.height &&
10538      space.width >= rect.width - 0.01; // fudge number for rounding error
10539    if ( canFitInSpaceRow ) {
10540      rect.x = space.x;
10541      this.placed( rect );
10542      break;
10543    }
10544  }
10545};
10546
10547proto.placeInSpace = function( rect, space ) {
10548  // place rect in space
10549  rect.x = space.x;
10550  rect.y = space.y;
10551
10552  this.placed( rect );
10553};
10554
10555// update spaces with placed rect
10556proto.placed = function( rect ) {
10557  // update spaces
10558  var revisedSpaces = [];
10559  for ( var i=0; i < this.spaces.length; i++ ) {
10560    var space = this.spaces[i];
10561    var newSpaces = space.getMaximalFreeRects( rect );
10562    // add either the original space or the new spaces to the revised spaces
10563    if ( newSpaces ) {
10564      revisedSpaces.push.apply( revisedSpaces, newSpaces );
10565    } else {
10566      revisedSpaces.push( space );
10567    }
10568  }
10569
10570  this.spaces = revisedSpaces;
10571
10572  this.mergeSortSpaces();
10573};
10574
10575proto.mergeSortSpaces = function() {
10576  // remove redundant spaces
10577  Packer.mergeRects( this.spaces );
10578  this.spaces.sort( this.sorter );
10579};
10580
10581// add a space back
10582proto.addSpace = function( rect ) {
10583  this.spaces.push( rect );
10584  this.mergeSortSpaces();
10585};
10586
10587// -------------------------- utility functions -------------------------- //
10588
10589/**
10590 * Remove redundant rectangle from array of rectangles
10591 * @param {Array} rects: an array of Rects
10592 * @returns {Array} rects: an array of Rects
10593**/
10594Packer.mergeRects = function( rects ) {
10595  var i = 0;
10596  var rect = rects[i];
10597
10598  rectLoop:
10599  while ( rect ) {
10600    var j = 0;
10601    var compareRect = rects[ i + j ];
10602
10603    while ( compareRect ) {
10604      if  ( compareRect == rect ) {
10605        j++; // next
10606      } else if ( compareRect.contains( rect ) ) {
10607        // remove rect
10608        rects.splice( i, 1 );
10609        rect = rects[i]; // set next rect
10610        continue rectLoop; // bail on compareLoop
10611      } else if ( rect.contains( compareRect ) ) {
10612        // remove compareRect
10613        rects.splice( i + j, 1 );
10614      } else {
10615        j++;
10616      }
10617      compareRect = rects[ i + j ]; // set next compareRect
10618    }
10619    i++;
10620    rect = rects[i];
10621  }
10622
10623  return rects;
10624};
10625
10626
10627// -------------------------- sorters -------------------------- //
10628
10629// functions for sorting rects in order
10630var sorters = {
10631  // top down, then left to right
10632  downwardLeftToRight: function( a, b ) {
10633    return a.y - b.y || a.x - b.x;
10634  },
10635  // left to right, then top down
10636  rightwardTopToBottom: function( a, b ) {
10637    return a.x - b.x || a.y - b.y;
10638  }
10639};
10640
10641
10642// --------------------------  -------------------------- //
10643
10644return Packer;
10645
10646}));
10647
10648/**
10649 * Packery Item Element
10650**/
10651
10652( function( window, factory ) {
10653  // universal module definition
10654  /* jshint strict: false */ /* globals define, module, require */
10655  if ( typeof define == 'function' && define.amd ) {
10656    // AMD
10657    define( 'packery/js/item',[
10658        'outlayer/outlayer',
10659        './rect'
10660      ],
10661      factory );
10662  } else if ( typeof module == 'object' && module.exports ) {
10663    // CommonJS
10664    module.exports = factory(
10665      require('outlayer'),
10666      require('./rect')
10667    );
10668  } else {
10669    // browser global
10670    window.Packery.Item = factory(
10671      window.Outlayer,
10672      window.Packery.Rect
10673    );
10674  }
10675
10676}( window, function factory( Outlayer, Rect ) {
10677
10678
10679// -------------------------- Item -------------------------- //
10680
10681var docElemStyle = document.documentElement.style;
10682
10683var transformProperty = typeof docElemStyle.transform == 'string' ?
10684  'transform' : 'WebkitTransform';
10685
10686// sub-class Item
10687var Item = function PackeryItem() {
10688  Outlayer.Item.apply( this, arguments );
10689};
10690
10691var proto = Item.prototype = Object.create( Outlayer.Item.prototype );
10692
10693var __create = proto._create;
10694proto._create = function() {
10695  // call default _create logic
10696  __create.call( this );
10697  this.rect = new Rect();
10698};
10699
10700var _moveTo = proto.moveTo;
10701proto.moveTo = function( x, y ) {
10702  // don't shift 1px while dragging
10703  var dx = Math.abs( this.position.x - x );
10704  var dy = Math.abs( this.position.y - y );
10705
10706  var canHackGoTo = this.layout.dragItemCount && !this.isPlacing &&
10707    !this.isTransitioning && dx < 1 && dy < 1;
10708  if ( canHackGoTo ) {
10709    this.goTo( x, y );
10710    return;
10711  }
10712  _moveTo.apply( this, arguments );
10713};
10714
10715// -------------------------- placing -------------------------- //
10716
10717proto.enablePlacing = function() {
10718  this.removeTransitionStyles();
10719  // remove transform property from transition
10720  if ( this.isTransitioning && transformProperty ) {
10721    this.element.style[ transformProperty ] = 'none';
10722  }
10723  this.isTransitioning = false;
10724  this.getSize();
10725  this.layout._setRectSize( this.element, this.rect );
10726  this.isPlacing = true;
10727};
10728
10729proto.disablePlacing = function() {
10730  this.isPlacing = false;
10731};
10732
10733// -----  ----- //
10734
10735// remove element from DOM
10736proto.removeElem = function() {
10737  this.element.parentNode.removeChild( this.element );
10738  // add space back to packer
10739  this.layout.packer.addSpace( this.rect );
10740  this.emitEvent( 'remove', [ this ] );
10741};
10742
10743// ----- dropPlaceholder ----- //
10744
10745proto.showDropPlaceholder = function() {
10746  var dropPlaceholder = this.dropPlaceholder;
10747  if ( !dropPlaceholder ) {
10748    // create dropPlaceholder
10749    dropPlaceholder = this.dropPlaceholder = document.createElement('div');
10750    dropPlaceholder.className = 'packery-drop-placeholder';
10751    dropPlaceholder.style.position = 'absolute';
10752  }
10753
10754  dropPlaceholder.style.width = this.size.width + 'px';
10755  dropPlaceholder.style.height = this.size.height + 'px';
10756  this.positionDropPlaceholder();
10757  this.layout.element.appendChild( dropPlaceholder );
10758};
10759
10760proto.positionDropPlaceholder = function() {
10761  this.dropPlaceholder.style[ transformProperty ] = 'translate(' +
10762    this.rect.x + 'px, ' + this.rect.y + 'px)';
10763};
10764
10765proto.hideDropPlaceholder = function() {
10766  this.layout.element.removeChild( this.dropPlaceholder );
10767};
10768
10769// -----  ----- //
10770
10771return Item;
10772
10773}));
10774
10775/*!
10776 * Packery v2.0.0
10777 * Gapless, draggable grid layouts
10778 *
10779 * Licensed GPLv3 for open source use
10780 * or Packery Commercial License for commercial use
10781 *
10782 * http://packery.metafizzy.co
10783 * Copyright 2016 Metafizzy
10784 */
10785
10786( function( window, factory ) {
10787  // universal module definition
10788  /* jshint strict: false */ /* globals define, module, require */
10789  if ( typeof define == 'function' && define.amd ) {
10790    // AMD
10791    define( 'packery/js/packery',[
10792        'get-size/get-size',
10793        'outlayer/outlayer',
10794        './rect',
10795        './packer',
10796        './item'
10797      ],
10798      factory );
10799  } else if ( typeof module == 'object' && module.exports ) {
10800    // CommonJS
10801    module.exports = factory(
10802      require('get-size'),
10803      require('outlayer'),
10804      require('./rect'),
10805      require('./packer'),
10806      require('./item')
10807    );
10808  } else {
10809    // browser global
10810    window.Packery = factory(
10811      window.getSize,
10812      window.Outlayer,
10813      window.Packery.Rect,
10814      window.Packery.Packer,
10815      window.Packery.Item
10816    );
10817  }
10818
10819}( window, function factory( getSize, Outlayer, Rect, Packer, Item ) {
10820
10821
10822// ----- Rect ----- //
10823
10824// allow for pixel rounding errors IE8-IE11 & Firefox; #227
10825Rect.prototype.canFit = function( rect ) {
10826  return this.width >= rect.width - 1 && this.height >= rect.height - 1;
10827};
10828
10829// -------------------------- Packery -------------------------- //
10830
10831// create an Outlayer layout class
10832var Packery = Outlayer.create('packery');
10833Packery.Item = Item;
10834
10835var proto = Packery.prototype;
10836
10837proto._create = function() {
10838  // call super
10839  Outlayer.prototype._create.call( this );
10840
10841  // initial properties
10842  this.packer = new Packer();
10843  // packer for drop targets
10844  this.shiftPacker = new Packer();
10845  this.isEnabled = true;
10846
10847  this.dragItemCount = 0;
10848
10849  // create drag handlers
10850  var _this = this;
10851  this.handleDraggabilly = {
10852    dragStart: function() {
10853      _this.itemDragStart( this.element );
10854    },
10855    dragMove: function() {
10856      _this.itemDragMove( this.element, this.position.x, this.position.y );
10857    },
10858    dragEnd: function() {
10859      _this.itemDragEnd( this.element );
10860    }
10861  };
10862
10863  this.handleUIDraggable = {
10864    start: function handleUIDraggableStart( event, ui ) {
10865      // HTML5 may trigger dragstart, dismiss HTML5 dragging
10866      if ( !ui ) {
10867        return;
10868      }
10869      _this.itemDragStart( event.currentTarget );
10870    },
10871    drag: function handleUIDraggableDrag( event, ui ) {
10872      if ( !ui ) {
10873        return;
10874      }
10875      _this.itemDragMove( event.currentTarget, ui.position.left, ui.position.top );
10876    },
10877    stop: function handleUIDraggableStop( event, ui ) {
10878      if ( !ui ) {
10879        return;
10880      }
10881      _this.itemDragEnd( event.currentTarget );
10882    }
10883  };
10884
10885};
10886
10887
10888// ----- init & layout ----- //
10889
10890/**
10891 * logic before any new layout
10892 */
10893proto._resetLayout = function() {
10894  this.getSize();
10895
10896  this._getMeasurements();
10897
10898  // reset packer
10899  var width, height, sortDirection;
10900  // packer settings, if horizontal or vertical
10901  if ( this._getOption('horizontal') ) {
10902    width = Infinity;
10903    height = this.size.innerHeight + this.gutter;
10904    sortDirection = 'rightwardTopToBottom';
10905  } else {
10906    width = this.size.innerWidth + this.gutter;
10907    height = Infinity;
10908    sortDirection = 'downwardLeftToRight';
10909  }
10910
10911  this.packer.width = this.shiftPacker.width = width;
10912  this.packer.height = this.shiftPacker.height = height;
10913  this.packer.sortDirection = this.shiftPacker.sortDirection = sortDirection;
10914
10915  this.packer.reset();
10916
10917  // layout
10918  this.maxY = 0;
10919  this.maxX = 0;
10920};
10921
10922/**
10923 * update columnWidth, rowHeight, & gutter
10924 * @private
10925 */
10926proto._getMeasurements = function() {
10927  this._getMeasurement( 'columnWidth', 'width' );
10928  this._getMeasurement( 'rowHeight', 'height' );
10929  this._getMeasurement( 'gutter', 'width' );
10930};
10931
10932proto._getItemLayoutPosition = function( item ) {
10933  this._setRectSize( item.element, item.rect );
10934  if ( this.isShifting || this.dragItemCount > 0 ) {
10935    var packMethod = this._getPackMethod();
10936    this.packer[ packMethod ]( item.rect );
10937  } else {
10938    this.packer.pack( item.rect );
10939  }
10940
10941  this._setMaxXY( item.rect );
10942  return item.rect;
10943};
10944
10945proto.shiftLayout = function() {
10946  this.isShifting = true;
10947  this.layout();
10948  delete this.isShifting;
10949};
10950
10951proto._getPackMethod = function() {
10952  return this._getOption('horizontal') ? 'rowPack' : 'columnPack';
10953};
10954
10955
10956/**
10957 * set max X and Y value, for size of container
10958 * @param {Packery.Rect} rect
10959 * @private
10960 */
10961proto._setMaxXY = function( rect ) {
10962  this.maxX = Math.max( rect.x + rect.width, this.maxX );
10963  this.maxY = Math.max( rect.y + rect.height, this.maxY );
10964};
10965
10966/**
10967 * set the width and height of a rect, applying columnWidth and rowHeight
10968 * @param {Element} elem
10969 * @param {Packery.Rect} rect
10970 */
10971proto._setRectSize = function( elem, rect ) {
10972  var size = getSize( elem );
10973  var w = size.outerWidth;
10974  var h = size.outerHeight;
10975  // size for columnWidth and rowHeight, if available
10976  // only check if size is non-zero, #177
10977  if ( w || h ) {
10978    w = this._applyGridGutter( w, this.columnWidth );
10979    h = this._applyGridGutter( h, this.rowHeight );
10980  }
10981  // rect must fit in packer
10982  rect.width = Math.min( w, this.packer.width );
10983  rect.height = Math.min( h, this.packer.height );
10984};
10985
10986/**
10987 * fits item to columnWidth/rowHeight and adds gutter
10988 * @param {Number} measurement - item width or height
10989 * @param {Number} gridSize - columnWidth or rowHeight
10990 * @returns measurement
10991 */
10992proto._applyGridGutter = function( measurement, gridSize ) {
10993  // just add gutter if no gridSize
10994  if ( !gridSize ) {
10995    return measurement + this.gutter;
10996  }
10997  gridSize += this.gutter;
10998  // fit item to columnWidth/rowHeight
10999  var remainder = measurement % gridSize;
11000  var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil';
11001  measurement = Math[ mathMethod ]( measurement / gridSize ) * gridSize;
11002  return measurement;
11003};
11004
11005proto._getContainerSize = function() {
11006  if ( this._getOption('horizontal') ) {
11007    return {
11008      width: this.maxX - this.gutter
11009    };
11010  } else {
11011    return {
11012      height: this.maxY - this.gutter
11013    };
11014  }
11015};
11016
11017
11018// -------------------------- stamp -------------------------- //
11019
11020/**
11021 * makes space for element
11022 * @param {Element} elem
11023 */
11024proto._manageStamp = function( elem ) {
11025
11026  var item = this.getItem( elem );
11027  var rect;
11028  if ( item && item.isPlacing ) {
11029    rect = item.rect;
11030  } else {
11031    var offset = this._getElementOffset( elem );
11032    rect = new Rect({
11033      x: this._getOption('originLeft') ? offset.left : offset.right,
11034      y: this._getOption('originTop') ? offset.top : offset.bottom
11035    });
11036  }
11037
11038  this._setRectSize( elem, rect );
11039  // save its space in the packer
11040  this.packer.placed( rect );
11041  this._setMaxXY( rect );
11042};
11043
11044// -------------------------- methods -------------------------- //
11045
11046function verticalSorter( a, b ) {
11047  return a.position.y - b.position.y || a.position.x - b.position.x;
11048}
11049
11050function horizontalSorter( a, b ) {
11051  return a.position.x - b.position.x || a.position.y - b.position.y;
11052}
11053
11054proto.sortItemsByPosition = function() {
11055  var sorter = this._getOption('horizontal') ? horizontalSorter : verticalSorter;
11056  this.items.sort( sorter );
11057};
11058
11059/**
11060 * Fit item element in its current position
11061 * Packery will position elements around it
11062 * useful for expanding elements
11063 *
11064 * @param {Element} elem
11065 * @param {Number} x - horizontal destination position, optional
11066 * @param {Number} y - vertical destination position, optional
11067 */
11068proto.fit = function( elem, x, y ) {
11069  var item = this.getItem( elem );
11070  if ( !item ) {
11071    return;
11072  }
11073
11074  // stamp item to get it out of layout
11075  this.stamp( item.element );
11076  // set placing flag
11077  item.enablePlacing();
11078  this.updateShiftTargets( item );
11079  // fall back to current position for fitting
11080  x = x === undefined ? item.rect.x: x;
11081  y = y === undefined ? item.rect.y: y;
11082  // position it best at its destination
11083  this.shift( item, x, y );
11084  this._bindFitEvents( item );
11085  item.moveTo( item.rect.x, item.rect.y );
11086  // layout everything else
11087  this.shiftLayout();
11088  // return back to regularly scheduled programming
11089  this.unstamp( item.element );
11090  this.sortItemsByPosition();
11091  item.disablePlacing();
11092};
11093
11094/**
11095 * emit event when item is fit and other items are laid out
11096 * @param {Packery.Item} item
11097 * @private
11098 */
11099proto._bindFitEvents = function( item ) {
11100  var _this = this;
11101  var ticks = 0;
11102  function onLayout() {
11103    ticks++;
11104    if ( ticks != 2 ) {
11105      return;
11106    }
11107    _this.dispatchEvent( 'fitComplete', null, [ item ] );
11108  }
11109  // when item is laid out
11110  item.once( 'layout', onLayout );
11111  // when all items are laid out
11112  this.once( 'layoutComplete', onLayout );
11113};
11114
11115// -------------------------- resize -------------------------- //
11116
11117// debounced, layout on resize
11118proto.resize = function() {
11119  // don't trigger if size did not change
11120  // or if resize was unbound. See #285, outlayer#9
11121  if ( !this.isResizeBound || !this.needsResizeLayout() ) {
11122    return;
11123  }
11124
11125  if ( this.options.shiftPercentResize ) {
11126    this.resizeShiftPercentLayout();
11127  } else {
11128    this.layout();
11129  }
11130};
11131
11132/**
11133 * check if layout is needed post layout
11134 * @returns Boolean
11135 */
11136proto.needsResizeLayout = function() {
11137  var size = getSize( this.element );
11138  var innerSize = this._getOption('horizontal') ? 'innerHeight' : 'innerWidth';
11139  return size[ innerSize ] != this.size[ innerSize ];
11140};
11141
11142proto.resizeShiftPercentLayout = function() {
11143  var items = this._getItemsForLayout( this.items );
11144
11145  var isHorizontal = this._getOption('horizontal');
11146  var coord = isHorizontal ? 'y' : 'x';
11147  var measure = isHorizontal ? 'height' : 'width';
11148  var segmentName = isHorizontal ? 'rowHeight' : 'columnWidth';
11149  var innerSize = isHorizontal ? 'innerHeight' : 'innerWidth';
11150
11151  // proportional re-align items
11152  var previousSegment = this[ segmentName ];
11153  previousSegment = previousSegment && previousSegment + this.gutter;
11154
11155  if ( previousSegment ) {
11156    this._getMeasurements();
11157    var currentSegment = this[ segmentName ] + this.gutter;
11158    items.forEach( function( item ) {
11159      var seg = Math.round( item.rect[ coord ] / previousSegment );
11160      item.rect[ coord ] = seg * currentSegment;
11161    });
11162  } else {
11163    var currentSize = getSize( this.element )[ innerSize ] + this.gutter;
11164    var previousSize = this.packer[ measure ];
11165    items.forEach( function( item ) {
11166      item.rect[ coord ] = ( item.rect[ coord ] / previousSize ) * currentSize;
11167    });
11168  }
11169
11170  this.shiftLayout();
11171};
11172
11173// -------------------------- drag -------------------------- //
11174
11175/**
11176 * handle an item drag start event
11177 * @param {Element} elem
11178 */
11179proto.itemDragStart = function( elem ) {
11180  if ( !this.isEnabled ) {
11181    return;
11182  }
11183  this.stamp( elem );
11184  // this.ignore( elem );
11185  var item = this.getItem( elem );
11186  if ( !item ) {
11187    return;
11188  }
11189
11190  item.enablePlacing();
11191  item.showDropPlaceholder();
11192  this.dragItemCount++;
11193  this.updateShiftTargets( item );
11194};
11195
11196proto.updateShiftTargets = function( dropItem ) {
11197  this.shiftPacker.reset();
11198
11199  // pack stamps
11200  this._getBoundingRect();
11201  var isOriginLeft = this._getOption('originLeft');
11202  var isOriginTop = this._getOption('originTop');
11203  this.stamps.forEach( function( stamp ) {
11204    // ignore dragged item
11205    var item = this.getItem( stamp );
11206    if ( item && item.isPlacing ) {
11207      return;
11208    }
11209    var offset = this._getElementOffset( stamp );
11210    var rect = new Rect({
11211      x: isOriginLeft ? offset.left : offset.right,
11212      y: isOriginTop ? offset.top : offset.bottom
11213    });
11214    this._setRectSize( stamp, rect );
11215    // save its space in the packer
11216    this.shiftPacker.placed( rect );
11217  }, this );
11218
11219  // reset shiftTargets
11220  var isHorizontal = this._getOption('horizontal');
11221  var segmentName = isHorizontal ? 'rowHeight' : 'columnWidth';
11222  var measure = isHorizontal ? 'height' : 'width';
11223
11224  this.shiftTargetKeys = [];
11225  this.shiftTargets = [];
11226  var boundsSize;
11227  var segment = this[ segmentName ];
11228  segment = segment && segment + this.gutter;
11229
11230  if ( segment ) {
11231    var segmentSpan = Math.ceil( dropItem.rect[ measure ] / segment );
11232    var segs = Math.floor( ( this.shiftPacker[ measure ] + this.gutter ) / segment );
11233    boundsSize = ( segs - segmentSpan ) * segment;
11234    // add targets on top
11235    for ( var i=0; i < segs; i++ ) {
11236      this._addShiftTarget( i * segment, 0, boundsSize );
11237    }
11238  } else {
11239    boundsSize = ( this.shiftPacker[ measure ] + this.gutter ) - dropItem.rect[ measure ];
11240    this._addShiftTarget( 0, 0, boundsSize );
11241  }
11242
11243  // pack each item to measure where shiftTargets are
11244  var items = this._getItemsForLayout( this.items );
11245  var packMethod = this._getPackMethod();
11246  items.forEach( function( item ) {
11247    var rect = item.rect;
11248    this._setRectSize( item.element, rect );
11249    this.shiftPacker[ packMethod ]( rect );
11250
11251    // add top left corner
11252    this._addShiftTarget( rect.x, rect.y, boundsSize );
11253    // add bottom left / top right corner
11254    var cornerX = isHorizontal ? rect.x + rect.width : rect.x;
11255    var cornerY = isHorizontal ? rect.y : rect.y + rect.height;
11256    this._addShiftTarget( cornerX, cornerY, boundsSize );
11257
11258    if ( segment ) {
11259      // add targets for each column on bottom / row on right
11260      var segSpan = Math.round( rect[ measure ] / segment );
11261      for ( var i=1; i < segSpan; i++ ) {
11262        var segX = isHorizontal ? cornerX : rect.x + segment * i;
11263        var segY = isHorizontal ? rect.y + segment * i : cornerY;
11264        this._addShiftTarget( segX, segY, boundsSize );
11265      }
11266    }
11267  }, this );
11268
11269};
11270
11271proto._addShiftTarget = function( x, y, boundsSize ) {
11272  var checkCoord = this._getOption('horizontal') ? y : x;
11273  if ( checkCoord !== 0 && checkCoord > boundsSize ) {
11274    return;
11275  }
11276  // create string for a key, easier to keep track of what targets
11277  var key = x + ',' + y;
11278  var hasKey = this.shiftTargetKeys.indexOf( key ) != -1;
11279  if ( hasKey ) {
11280    return;
11281  }
11282  this.shiftTargetKeys.push( key );
11283  this.shiftTargets.push({ x: x, y: y });
11284};
11285
11286// -------------------------- drop -------------------------- //
11287
11288proto.shift = function( item, x, y ) {
11289  var shiftPosition;
11290  var minDistance = Infinity;
11291  var position = { x: x, y: y };
11292  this.shiftTargets.forEach( function( target ) {
11293    var distance = getDistance( target, position );
11294    if ( distance < minDistance ) {
11295      shiftPosition = target;
11296      minDistance = distance;
11297    }
11298  });
11299  item.rect.x = shiftPosition.x;
11300  item.rect.y = shiftPosition.y;
11301};
11302
11303function getDistance( a, b ) {
11304  var dx = b.x - a.x;
11305  var dy = b.y - a.y;
11306  return Math.sqrt( dx * dx + dy * dy );
11307}
11308
11309// -------------------------- drag move -------------------------- //
11310
11311var DRAG_THROTTLE_TIME = 120;
11312
11313/**
11314 * handle an item drag move event
11315 * @param {Element} elem
11316 * @param {Number} x - horizontal change in position
11317 * @param {Number} y - vertical change in position
11318 */
11319proto.itemDragMove = function( elem, x, y ) {
11320  var item = this.isEnabled && this.getItem( elem );
11321  if ( !item ) {
11322    return;
11323  }
11324
11325  x -= this.size.paddingLeft;
11326  y -= this.size.paddingTop;
11327
11328  var _this = this;
11329  function onDrag() {
11330    _this.shift( item, x, y );
11331    item.positionDropPlaceholder();
11332    _this.layout();
11333  }
11334
11335  // throttle
11336  var now = new Date();
11337  if ( this._itemDragTime && now - this._itemDragTime < DRAG_THROTTLE_TIME ) {
11338    clearTimeout( this.dragTimeout );
11339    this.dragTimeout = setTimeout( onDrag, DRAG_THROTTLE_TIME );
11340  } else {
11341    onDrag();
11342    this._itemDragTime = now;
11343  }
11344};
11345
11346// -------------------------- drag end -------------------------- //
11347
11348/**
11349 * handle an item drag end event
11350 * @param {Element} elem
11351 */
11352proto.itemDragEnd = function( elem ) {
11353  var item = this.isEnabled && this.getItem( elem );
11354  if ( !item ) {
11355    return;
11356  }
11357
11358  clearTimeout( this.dragTimeout );
11359  item.element.classList.add('is-positioning-post-drag');
11360
11361  var completeCount = 0;
11362  var _this = this;
11363  function onDragEndLayoutComplete() {
11364    completeCount++;
11365    if ( completeCount != 2 ) {
11366      return;
11367    }
11368    // reset drag item
11369    item.element.classList.remove('is-positioning-post-drag');
11370    item.hideDropPlaceholder();
11371    _this.dispatchEvent( 'dragItemPositioned', null, [ item ] );
11372  }
11373
11374  item.once( 'layout', onDragEndLayoutComplete );
11375  this.once( 'layoutComplete', onDragEndLayoutComplete );
11376  item.moveTo( item.rect.x, item.rect.y );
11377  this.layout();
11378  this.dragItemCount = Math.max( 0, this.dragItemCount - 1 );
11379  this.sortItemsByPosition();
11380  item.disablePlacing();
11381  this.unstamp( item.element );
11382};
11383
11384/**
11385 * binds Draggabilly events
11386 * @param {Draggabilly} draggie
11387 */
11388proto.bindDraggabillyEvents = function( draggie ) {
11389  this._bindDraggabillyEvents( draggie, 'on' );
11390};
11391
11392proto.unbindDraggabillyEvents = function( draggie ) {
11393  this._bindDraggabillyEvents( draggie, 'off' );
11394};
11395
11396proto._bindDraggabillyEvents = function( draggie, method ) {
11397  var handlers = this.handleDraggabilly;
11398  draggie[ method ]( 'dragStart', handlers.dragStart );
11399  draggie[ method ]( 'dragMove', handlers.dragMove );
11400  draggie[ method ]( 'dragEnd', handlers.dragEnd );
11401};
11402
11403/**
11404 * binds jQuery UI Draggable events
11405 * @param {jQuery} $elems
11406 */
11407proto.bindUIDraggableEvents = function( $elems ) {
11408  this._bindUIDraggableEvents( $elems, 'on' );
11409};
11410
11411proto.unbindUIDraggableEvents = function( $elems ) {
11412  this._bindUIDraggableEvents( $elems, 'off' );
11413};
11414
11415proto._bindUIDraggableEvents = function( $elems, method ) {
11416  var handlers = this.handleUIDraggable;
11417  $elems
11418    [ method ]( 'dragstart', handlers.start )
11419    [ method ]( 'drag', handlers.drag )
11420    [ method ]( 'dragstop', handlers.stop );
11421};
11422
11423// ----- destroy ----- //
11424
11425var _destroy = proto.destroy;
11426proto.destroy = function() {
11427  _destroy.apply( this, arguments );
11428  // disable flag; prevent drag events from triggering. #72
11429  this.isEnabled = false;
11430};
11431
11432// -----  ----- //
11433
11434Packery.Rect = Rect;
11435Packery.Packer = Packer;
11436
11437return Packery;
11438
11439}));
11440
11441/*!
11442 * Packery layout mode v2.0.1
11443 * sub-classes Packery
11444 */
11445
11446/*jshint browser: true, strict: true, undef: true, unused: true */
11447
11448( function( window, factory ) {
11449
11450  // universal module definition
11451  if ( typeof define == 'function' && define.amd ) {
11452    // AMD
11453    define( [
11454        'isotope-layout/js/layout-mode',
11455        'packery/js/packery'
11456      ],
11457      factory );
11458  } else if ( typeof module == 'object' && module.exports ) {
11459    // CommonJS
11460    module.exports = factory(
11461      require('isotope-layout/js/layout-mode'),
11462      require('packery')
11463    );
11464  } else {
11465    // browser global
11466    factory(
11467      window.Isotope.LayoutMode,
11468      window.Packery
11469    );
11470  }
11471
11472}( window, function factor( LayoutMode, Packery ) {
11473
11474
11475  // create an Outlayer layout class
11476  var PackeryMode = LayoutMode.create('packery');
11477  var proto = PackeryMode.prototype;
11478
11479  var keepModeMethods = {
11480    _getElementOffset: true,
11481    _getMeasurement: true
11482  };
11483
11484  // inherit Packery prototype
11485  for ( var method in Packery.prototype ) {
11486    // do not inherit mode methods
11487    if ( !keepModeMethods[ method ] ) {
11488      proto[ method ] = Packery.prototype[ method ];
11489    }
11490  }
11491
11492  // set packer in _resetLayout
11493  var _resetLayout = proto._resetLayout;
11494  proto._resetLayout = function() {
11495    this.packer = this.packer || new Packery.Packer();
11496    this.shiftPacker = this.shiftPacker || new Packery.Packer();
11497    _resetLayout.apply( this, arguments );
11498  };
11499
11500  var _getItemLayoutPosition = proto._getItemLayoutPosition;
11501  proto._getItemLayoutPosition = function( item ) {
11502    // set packery rect
11503    item.rect = item.rect || new Packery.Rect();
11504    return _getItemLayoutPosition.call( this, item );
11505  };
11506
11507  // needsResizeLayout for vertical or horizontal
11508  var _needsResizeLayout = proto.needsResizeLayout;
11509  proto.needsResizeLayout = function() {
11510    if ( this._getOption('horizontal') ) {
11511      return this.needsVerticalResizeLayout();
11512    } else {
11513      return _needsResizeLayout.call( this );
11514    }
11515  };
11516
11517  // point to mode options for horizontal
11518  var _getOption = proto._getOption;
11519  proto._getOption = function( option ) {
11520    if ( option == 'horizontal' ) {
11521      return this.options.isHorizontal !== undefined ?
11522        this.options.isHorizontal : this.options.horizontal;
11523    }
11524    return _getOption.apply( this.isotope, arguments );
11525  };
11526
11527  return PackeryMode;
11528
11529}));
11530
11531/*!
11532 * cellsByRows layout mode for Isotope
11533 * v1.1.3
11534 * http://isotope.metafizzy.co/layout-modes/cellsbyrow.html
11535 */
11536
11537/*jshint browser: true, devel: false, strict: true, undef: true, unused: true */
11538
11539( function( window, factory ) {
11540  // universal module definition
11541  /* jshint strict: false */ /*globals define, module, require */
11542  if ( typeof define === 'function' && define.amd ) {
11543    // AMD
11544    define( [
11545        'isotope/js/layout-mode'
11546      ],
11547      factory );
11548  } else if ( typeof exports === 'object' ) {
11549    // CommonJS
11550    module.exports = factory(
11551      require('isotope-layout/js/layout-mode')
11552    );
11553  } else {
11554    // browser global
11555    factory(
11556      window.Isotope.LayoutMode
11557    );
11558  }
11559
11560}( window, function factory( LayoutMode ) {
11561  'use strict';
11562
11563  var CellsByRow = LayoutMode.create( 'cellsByRow' );
11564  var proto = CellsByRow.prototype;
11565
11566  proto._resetLayout = function() {
11567    // reset properties
11568    this.itemIndex = 0;
11569    // measurements
11570    this.getColumnWidth();
11571    this.getRowHeight();
11572    // set cols
11573    this.cols = Math.floor( this.isotope.size.innerWidth / this.columnWidth );
11574    this.cols = Math.max( this.cols, 1 );
11575  };
11576
11577  proto._getItemLayoutPosition = function( item ) {
11578    item.getSize();
11579    var col = this.itemIndex % this.cols;
11580    var row = Math.floor( this.itemIndex / this.cols );
11581    // center item within cell
11582    var x = ( col + 0.5 ) * this.columnWidth - item.size.outerWidth / 2;
11583    var y = ( row + 0.5 ) * this.rowHeight - item.size.outerHeight / 2;
11584    this.itemIndex++;
11585    return { x: x, y: y };
11586  };
11587
11588  proto._getContainerSize = function() {
11589    return {
11590      height: Math.ceil( this.itemIndex / this.cols ) * this.rowHeight
11591    };
11592  };
11593
11594  return CellsByRow;
11595
11596}));
11597/*global jQuery: true */
11598
11599/*!
11600   --------------------------------
11601   Infinite Scroll
11602   --------------------------------
11603   + https://github.com/paulirish/infinite-scroll
11604   + version 2.1.0
11605   + Copyright 2011/12 Paul Irish & Luke Shumard
11606   + Licensed under the MIT license
11607
11608   + Documentation: http://infinite-scroll.com/
11609*/
11610
11611// Uses AMD or browser globals to create a jQuery plugin.
11612(function (factory) {
11613	if (typeof define === 'function' && define.amd) {
11614		// AMD. Register as an anonymous module.
11615		define(['jquery'], factory);
11616	} else {
11617		// Browser globals
11618		factory(jQuery);
11619	}
11620}(function ($, undefined) {
11621	'use strict';
11622
11623	$.infinitescroll = function infscr(options, callback, element) {
11624		this.element = $(element);
11625
11626		// Flag the object in the event of a failed creation
11627		if (!this._create(options, callback)) {
11628			this.failed = true;
11629		}
11630	};
11631
11632	$.infinitescroll.defaults = {
11633		loading: {
11634			finished: undefined,
11635			finishedMsg: "<em>Congratulations, you've reached the end of the internet.</em>",
11636			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
11636MzExnbRvQ2Sy7vN0zvVtNfU2tLY3rPgLdnDvca4VQS/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
11636iqpQpZ4apwSwRtjqrB3muoF9BboaXKmshlqWqsWiGt2wphJkQbAU5hoCACH5BAUKABsALAcABADOAAsAAAX/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',
11637			msg: null,
11638			msgText: '<em>Loading the next set of posts...</em>',
11639			selector: null,
11640			speed: 'fast',
11641			start: undefined
11642		},
11643		state: {
11644			isDuringAjax: false,
11645			isInvalidPage: false,
11646			isDestroyed: false,
11647			isDone: false, // For when it goes all the way through the archive.
11648			isPaused: false,
11649			isBeyondMaxPage: false,
11650			currPage: 1
11651		},
11652		debug: false,
11653		behavior: undefined,
11654		binder: $(window), // used to cache the selector
11655		nextSelector: 'div.navigation a:first',
11656		navSelector: 'div.navigation',
11657		contentSelector: null, // rename to pageFragment
11658		extraScrollPx: 150,
11659		itemSelector: 'div.post',
11660		animate: false,
11661		pathParse: undefined,
11662		dataType: 'html',
11663		appendCallback: true,
11664		bufferPx: 40,
11665		errorCallback: function () { },
11666		infid: 0, //Instance ID
11667		pixelsFromNavToBottom: undefined,
11668		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
11669		prefill: false, // When the document is smaller than the window, load data until the document is larger or links are exhausted
11670		maxPage: undefined // to manually control maximum page (when maxPage is undefined, maximum page limitation is not work)
11671	};
11672
11673	$.infinitescroll.prototype = {
11674
11675		/*
11676			----------------------------
11677			Private methods
11678			----------------------------
11679			*/
11680
11681		// Bind or unbind from scroll
11682		_binding: function infscr_binding(binding) {
11683
11684			var instance = this,
11685				opts = instance.options;
11686
11687			opts.v = '2.0b2.120520';
11688
11689			// if behavior is defined and this function is extended, call that instead of default
11690			if (!!opts.behavior && this['_binding_' + opts.behavior] !== undefined) {
11691				this['_binding_' + opts.behavior].call(this);
11692				return;
11693			}
11694
11695			if (binding !== 'bind' && binding !== 'unbind') {
11696				this._debug('Binding value  ' + binding + ' not valid');
11697				return false;
11698			}
11699
11700			if (binding === 'unbind') {
11701				(this.options.binder).unbind('smartscroll.infscr.' + instance.options.infid);
11702			} else {
11703				(this.options.binder)[binding]('smartscroll.infscr.' + instance.options.infid, function () {
11704					instance.scroll();
11705				});
11706			}
11707
11708			this._debug('Binding', binding);
11709		},
11710
11711		// Fundamental aspects of the plugin are initialized
11712		_create: function infscr_create(options, callback) {
11713
11714			// Add custom options to defaults
11715			var opts = $.extend(true, {}, $.infinitescroll.defaults, options);
11716			this.options = opts;
11717			var $window = $(window);
11718			var instance = this;
11719
11720			// Validate selectors
11721			if (!instance._validate(options)) {
11722				return false;
11723			}
11724
11725			// Validate page fragment path
11726			var path = $(opts.nextSelector).attr('href');
11727			if (!path) {
11728				this._debug('Navigation selector not found');
11729				return false;
11730			}
11731
11732			// Set the path to be a relative URL from root.
11733			opts.path = opts.path || this._determinepath(path);
11734
11735			// contentSelector is 'page fragment' option for .load() / .ajax() calls
11736			opts.contentSelector = opts.contentSelector || this.element;
11737
11738			// loading.selector - if we want to place the load message in a specific selector, defaulted to the contentSelector
11739			opts.loading.selector = opts.loading.selector || opts.contentSelector;
11740
11741			// Define loading.msg
11742			opts.loading.msg = opts.loading.msg || $('<div id="infscr-loading"><img alt="Loading..." src="' + opts.loading.img + '" /><div>' + opts.loading.msgText + '</div></div>');
11743
11744			// Preload loading.img
11745			(new Image()).src = opts.loading.img;
11746
11747			// distance from nav links to bottom
11748			// computed as: height of the document + top offset of container - top offset of nav link
11749			if (opts.pixelsFromNavToBottom === undefined) {
11750				opts.pixelsFromNavToBottom = $(document).height() - $(opts.navSelector).offset().top;
11751				this._debug('pixelsFromNavToBottom: ' + opts.pixelsFromNavToBottom);
11752			}
11753
11754			var self = this;
11755
11756			// determine loading.start actions
11757			opts.loading.start = opts.loading.start || function () {
11758				$(opts.navSelector).hide();
11759				opts.loading.msg
11760					.appendTo(opts.loading.selector)
11761					.show(opts.loading.speed, $.proxy(function () {
11762						this.beginAjax(opts);
11763					}, self));
11764			};
11765
11766			// determine loading.finished actions
11767			opts.loading.finished = opts.loading.finished || function () {
11768				if (!opts.state.isBeyondMaxPage)
11769					opts.loading.msg.fadeOut(opts.loading.speed);
11770			};
11771
11772			// callback loading
11773			opts.callback = function (instance, data, url) {
11774				if (!!opts.behavior && instance['_callback_' + opts.behavior] !== undefined) {
11775					instance['_callback_' + opts.behavior].call($(opts.contentSelector)[0], data, url);
11776				}
11777
11778				if (callback) {
11779					callback.call($(opts.contentSelector)[0], data, opts, url);
11780				}
11781
11782				if (opts.prefill) {
11783					$window.bind('resize.infinite-scroll', instance._prefill);
11784				}
11785			};
11786
11787			if (options.debug) {
11788				// Tell IE9 to use its built-in console
11789				if (Function.prototype.bind && (typeof console === 'object' || typeof console === 'function') && typeof console.log === 'object') {
11790					['log', 'info', 'warn', 'error', 'assert', 'dir', 'clear', 'profile', 'profileEnd']
11791						.forEach(function (method) {
11792							console[method] = this.call(console[method], console);
11793						}, Function.prototype.bind);
11794				}
11795			}
11796
11797			this._setup();
11798
11799			// Setups the prefill method for use
11800			if (opts.prefill) {
11801				this._prefill();
11802			}
11803
11804			// Return true to indicate successful creation
11805			return true;
11806		},
11807
11808		_prefill: function infscr_prefill() {
11809			var instance = this;
11810			var $window = $(window);
11811
11812			function needsPrefill() {
11813				return ($(instance.options.contentSelector).height() <= $window.height());
11814			}
11815
11816			this._prefill = function () {
11817				if (needsPrefill()) {
11818					instance.scroll();
11819				}
11820
11821				$window.bind('resize.infinite-scroll', function () {
11822					if (needsPrefill()) {
11823						$window.unbind('resize.infinite-scroll');
11824						instance.scroll();
11825					}
11826				});
11827			};
11828
11829			// Call self after setting up the new function
11830			this._prefill();
11831		},
11832
11833		// Console log wrapper
11834		_debug: function infscr_debug() {
11835			if (true !== this.options.debug) {
11836				return;
11837			}
11838
11839			if (typeof console !== 'undefined' && typeof console.log === 'function') {
11840				// Modern browsers
11841				// Single argument, which is a string
11842				if ((Array.prototype.slice.call(arguments)).length === 1 && typeof Array.prototype.slice.call(arguments)[0] === 'string') {
11843					console.log((Array.prototype.slice.call(arguments)).toString());
11844				} else {
11845					console.log(Array.prototype.slice.call(arguments));
11846				}
11847			} else if (!Function.prototype.bind && typeof console !== 'undefined' && typeof console.log === 'object') {
11848				// IE8
11849				Function.prototype.call.call(console.log, console, Array.prototype.slice.call(arguments));
11850			}
11851		},
11852
11853		// find the number to increment in the path.
11854		_determinepath: function infscr_determinepath(path) {
11855
11856			var opts = this.options;
11857
11858			// if behavior is defined and this function is extended, call that instead of default
11859			if (!!opts.behavior && this['_determinepath_' + opts.behavior] !== undefined) {
11860				return this['_determinepath_' + opts.behavior].call(this, path);
11861			}
11862
11863			var url = new URL(path);
11864			var pathname = url.pathname;
11865			var hasNumber = /\d/.test(pathname);
11866
11867			if (!!opts.pathParse) {
11868				this._debug('pathParse manual');
11869				return opts.pathParse(path, this.options.state.currPage + 1);
11870            } else if (hasNumber && path.match(/(\?|\&)(upage=)(\d+)/)) {
11871				var parts = path.split(/(\?|\&)(upage=)(\d+)/);
11872				return [parts[0] + parts[1] + parts[2], parts[4]];
11873            } else if (path.match(/^(.*?)\b2\b(.*?$)/)) {
11874				path = path.match(/^(.*?)\b2\b(.*?$)/).slice(1);
11875
11876                // if there is any 2 in the url at all.
11877            } else if (path.match(/^(.*?)2(.*?$)/)) {
11878                // page= is used in django:
11879                // http://www.infinite-scroll.com/changelog/comment-page-1/#comment-127
11880                if (path.match(/^(.*?page=)2(\/.*|$)/)) {
11881                    path = path.match(/^(.*?page=)2(\/.*|$)/).slice(1);
11882                    return path;
11883                }
11884
11885                path = path.match(/^(.*?)2(.*?$)/).slice(1);
11886
11887            } else {
11888                // page= is used in drupal too but second page is page=1 not page=2:
11889                // thx Jerod Fritz, vladikoff
11890                if (path.match(/^(.*?page=)1(\/.*|$)/)) {
11891                    path = path.match(/^(.*?page=)1(\/.*|$)/).slice(1);
11892                    return path;
11893                } else {
11894                    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.");
11895                    // Get rid of isInvalidPage to allow permalink to state
11896                    opts.state.isInvalidPage = true;  //prevent it from running on this page.
11897                }
11898            }
11899            this._debug('determinePath', path);
11900            return path;
11901
11902        },
11903
11904        // Custom error
11905        _error: function infscr_error(xhr) {
11906
11907            var opts = this.options;
11908
11909            // if behavior is defined and this function is extended, call that instead of default
11910            if (!!opts.behavior && this['_error_'+opts.behavior] !== undefined) {
11911                this['_error_'+opts.behavior].call(this,xhr);
11912                return;
11913            }
11914
11915            if (xhr !== 'destroy' && xhr !== 'end') {
11916                xhr = 'unknown';
11917            }
11918
11919            this._debug('Error', xhr);
11920
11921            if (xhr === 'end' || opts.state.isBeyondMaxPage) {
11922                this._showdonemsg();
11923            }
11924
11925            opts.state.isDone = true;
11926            opts.state.currPage = 1; // if you need to go back to this instance
11927            opts.state.isPaused = false;
11928            opts.state.isBeyondMaxPage = false;
11929            this._binding('unbind');
11930
11931        },
11932
11933        // Load Callback
11934        _loadcallback: function infscr_loadcallback(box, data, url) {
11935            var opts = this.options,
11936            callback = this.options.callback, // GLOBAL OBJECT FOR CALLBACK
11937            result = (opts.state.isDone) ? 'done' : (!opts.appendCallback) ? 'no-append' : 'append',
11938            frag;
11939
11940            // if behavior is defined and this function is extended, call that instead of default
11941            if (!!opts.behavior && this['_loadcallback_'+opts.behavior] !== undefined) {
11942                this['_loadcallback_'+opts.behavior].call(this,box,data);
11943                return;
11944            }
11945
11946            switch (result) {
11947                case 'done':
11948                    this._showdonemsg();
11949                    return false;
11950
11951                case 'no-append':
11952                    if (opts.dataType === 'html') {
11953                        data = '<div>' + data + '</div>';
11954                        data = $(data).find(opts.itemSelector);
11955                    }
11956
11957                    // if it didn't return anything
11958                    if (data.length === 0) {
11959                        return this._error('end');
11960                    }
11961
11962                    break;
11963
11964                case 'append':
11965                    var children = box.children();
11966                    // if it didn't return anything
11967                    if (children.length === 0) {
11968                        return this._error('end');
11969                    }
11970
11971                    // use a documentFragment because it works when content is going into a table or UL
11972                    frag = document.createDocumentFragment();
11973                    while (box[0].firstChild) {
11974                        frag.appendChild(box[0].firstChild);
11975                    }
11976
11977                    this._debug('contentSelector', $(opts.contentSelector)[0]);
11978                    $(opts.contentSelector)[0].appendChild(frag);
11979                    // previously, we would pass in the new DOM element as context for the callback
11980                    // however we're now using a documentfragment, which doesn't have parents or children,
11981                    // so the context is the contentContainer guy, and we pass in an array
11982                    // of the elements collected as the first argument.
11983
11984                    data = children.get();
11985                    break;
11986            }
11987
11988            // loadingEnd function
11989            opts.loading.finished.call($(opts.contentSelector)[0],opts);
11990
11991            // smooth scroll to ease in the new content
11992            if (opts.animate) {
11993                var scrollTo = $(window).scrollTop() + $(opts.loading.msg).height() + opts.extraScrollPx + 'px';
11994                $('html,body').animate({ scrollTop: scrollTo }, 800, function () { opts.state.isDuringAjax = false; });
11995            }
11996
11997            if (!opts.animate) {
11998                // once the call is done, we can allow it again.
11999                opts.state.isDuringAjax = false;
12000            }
12001
12002            callback(this, data, url);
12003
12004            if (opts.prefill) {
12005                this._prefill();
12006            }
12007        },
12008
12009        _nearbottom: function infscr_nearbottom() {
12010
12011            var opts = this.options,
12012            pixelsFromWindowBottomToBottom = 0 + $(document).height() - (opts.binder.scrollTop()) - $(window).height();
12013
12014            // if behavior is defined and this function is extended, call that instead of default
12015            if (!!opts.behavior && this['_nearbottom_'+opts.behavior] !== undefined) {
12016                return this['_nearbottom_'+opts.behavior].call(this);
12017            }
12018
12019            this._debug('math:', pixelsFromWindowBottomToBottom, opts.pixelsFromNavToBottom);
12020
12021            // if distance remaining in the scroll (including buffer) is less than the orignal nav to bottom....
12022            return (pixelsFromWindowBottomToBottom - opts.bufferPx < opts.pixelsFromNavToBottom);
12023
12024        },
12025
12026        // Pause / temporarily disable plugin from firing
12027        _pausing: function infscr_pausing(pause) {
12028
12029            var opts = this.options;
12030
12031            // if behavior is defined and this function is extended, call that instead of default
12032            if (!!opts.behavior && this['_pausing_'+opts.behavior] !== undefined) {
12033                this['_pausing_'+opts.behavior].call(this,pause);
12034                return;
12035            }
12036
12037            // If pause is not 'pause' or 'resume', toggle it's value
12038            if (pause !== 'pause' && pause !== 'resume' && pause !== null) {
12039                this._debug('Invalid argument. Toggling pause value instead');
12040            }
12041
12042            pause = (pause && (pause === 'pause' || pause === 'resume')) ? pause : 'toggle';
12043
12044            switch (pause) {
12045                case 'pause':
12046                    opts.state.isPaused = true;
12047                break;
12048
12049                case 'resume':
12050                    opts.state.isPaused = false;
12051                break;
12052
12053                case 'toggle':
12054                    opts.state.isPaused = !opts.state.isPaused;
12055                break;
12056            }
12057
12058            this._debug('Paused', opts.state.isPaused);
12059            return false;
12060
12061        },
12062
12063        // Behavior is determined
12064        // If the behavior option is undefined, it will set to default and bind to scroll
12065        _setup: function infscr_setup() {
12066
12067            var opts = this.options;
12068
12069            // if behavior is defined and this function is extended, call that instead of default
12070            if (!!opts.behavior && this['_setup_'+opts.behavior] !== undefined) {
12071                this['_setup_'+opts.behavior].call(this);
12072                return;
12073            }
12074
12075            this._binding('bind');
12076
12077            return false;
12078
12079        },
12080
12081        // Show done message
12082        _showdonemsg: function infscr_showdonemsg() {
12083
12084            var opts = this.options;
12085
12086            // if behavior is defined and this function is extended, call that instead of default
12087            if (!!opts.behavior && this['_showdonemsg_'+opts.behavior] !== undefined) {
12088                this['_showdonemsg_'+opts.behavior].call(this);
12089                return;
12090            }
12091
12092            opts.loading.msg
12093            .find('img')
12094            .hide()
12095            .parent()
12096            .find('div').html(opts.loading.finishedMsg).animate({ opacity: 1 }, 2000, function () {
12097                $(this).parent().fadeOut(opts.loading.speed);
12098            });
12099
12100            // user provided callback when done
12101            opts.errorCallback.call($(opts.contentSelector)[0],'done');
12102        },
12103
12104        // grab each selector option and see if any fail
12105        _validate: function infscr_validate(opts) {
12106            for (var key in opts) {
12107                if (key.indexOf && key.indexOf('Selector') > -1 && $(opts[key]).length === 0) {
12108                    this._debug('Your ' + key + ' found no elements.');
12109                    return false;
12110                }
12111            }
12112
12113            return true;
12114        },
12115
12116        /*
12117            ----------------------------
12118            Public methods
12119            ----------------------------
12120            */
12121
12122        // Bind to scroll
12123        bind: function infscr_bind() {
12124            this._binding('bind');
12125        },
12126
12127        // Destroy current instance of plugin
12128        destroy: function infscr_destroy() {
12129            this.options.state.isDestroyed = true;
12130            this.options.loading.finished();
12131            return this._error('destroy');
12132        },
12133
12134        // Set pause value to false
12135        pause: function infscr_pause() {
12136            this._pausing('pause');
12137        },
12138
12139        // Set pause value to false
12140        resume: function infscr_resume() {
12141            this._pausing('resume');
12142        },
12143
12144        beginAjax: function infscr_ajax(opts) {
12145            var instance = this,
12146                path = opts.path,
12147                box, desturl, method, condition;
12148
12149			// increment the URL bit. e.g. /page/3/
12150            opts.state.currPage++;
12151
12152            // Manually control maximum page
12153            if ( opts.maxPage !== undefined && opts.state.currPage > opts.maxPage ){
12154                opts.state.isBeyondMaxPage = true;
12155                this.destroy();
12156                return;
12157            }
12158
12159            // if we're dealing with a table we can't use DIVs
12160            box = $(opts.contentSelector).is('table, tbody') ? $('<tbody/>') : $('<div/>');
12161
12162			desturl = (typeof path === 'function') ? path(opts.state.currPage) : path.join(opts.state.currPage);
12163
12164            instance._debug('heading into ajax', desturl);
12165
12166            method = (opts.dataType === 'html' || opts.dataType === 'json' ) ? opts.dataType : 'html+callback';
12167            if (opts.appendCallback && opts.dataType === 'html') {
12168                method += '+callback';
12169            }
12170
12171            switch (method) {
12172                case 'html+callback':
12173                    instance._debug('Using HTML via .load() method');
12174                    box.load(desturl + ' ' + opts.itemSelector, undefined, function infscr_ajax_callback(responseText) {
12175                        instance._loadcallback(box, responseText, desturl);
12176                    });
12177
12178                    break;
12179
12180                case 'html':
12181                    instance._debug('Using ' + (method.toUpperCase()) + ' via $.ajax() method');
12182                    $.ajax({
12183                        // params
12184                        url: desturl,
12185                        dataType: opts.dataType,
12186                        complete: function infscr_ajax_callback(jqXHR, textStatus) {
12187                            condition = (typeof (jqXHR.isResolved) !== 'undefined') ? (jqXHR.isResolved()) : (textStatus === 'success' || textStatus === 'notmodified');
12188                            if (condition) {
12189                                instance._loadcallback(box, jqXHR.responseText, desturl);
12190                            } else {
12191                                instance._error('end');
12192                            }
12193                        }
12194                    });
12195
12196                    break;
12197                case 'json':
12198                    instance._debug('Using ' + (method.toUpperCase()) + ' via $.ajax() method');
12199                    $.ajax({
12200                        dataType: 'json',
12201                        type: 'GET',
12202                        url: desturl,
12203                        success: function (data, textStatus, jqXHR) {
12204                            condition = (typeof (jqXHR.isResolved) !== 'undefined') ? (jqXHR.isResolved()) : (textStatus === 'success' || textStatus === 'notmodified');
12205                            if (opts.appendCallback) {
12206                                // if appendCallback is true, you must defined template in options.
12207                                // note that data passed into _loadcallback is already an html (after processed in opts.template(data)).
12208                                if (opts.template !== undefined) {
12209                                    var theData = opts.template(data);
12210                                    box.append(theData);
12211                                    if (condition) {
12212                                        instance._loadcallback(box, theData);
12213                                    } else {
12214                                        instance._error('end');
12215                                    }
12216                                } else {
12217                                    instance._debug('template must be defined.');
12218                                    instance._error('end');
12219                                }
12220                            } else {
12221                                // if appendCallback is false, we will pass in the JSON object. you should handle it yourself in your callback.
12222                                if (condition) {
12223                                    instance._loadcallback(box, data, desturl);
12224                                } else {
12225                                    instance._error('end');
12226                                }
12227                            }
12228                        },
12229                        error: function() {
12230                            instance._debug('JSON ajax request failed.');
12231                            instance._error('end');
12232                        }
12233                    });
12234
12235                    break;
12236            }
12237        },
12238
12239        // Retrieve next set of content items
12240        retrieve: function infscr_retrieve(pageNum) {
12241            pageNum = pageNum || null;
12242
12243            var instance = this,
12244            opts = instance.options;
12245
12246            // if behavior is defined and this function is extended, call that instead of default
12247            if (!!opts.behavior && this['retrieve_'+opts.behavior] !== undefined) {
12248                this['retrieve_'+opts.behavior].call(this,pageNum);
12249                return;
12250            }
12251
12252            // for manual triggers, if destroyed, get out of here
12253            if (opts.state.isDestroyed) {
12254                this._debug('Instance is destroyed');
12255                return false;
12256            }
12257
12258            // we dont want to fire the ajax multiple times
12259            opts.state.isDuringAjax = true;
12260
12261            opts.loading.start.call($(opts.contentSelector)[0],opts);
12262        },
12263
12264        // Check to see next page is needed
12265        scroll: function infscr_scroll() {
12266
12267            var opts = this.options,
12268            state = opts.state;
12269
12270            // if behavior is defined and this function is extended, call that instead of default
12271            if (!!opts.behavior && this['scroll_'+opts.behavior] !== undefined) {
12272                this['scroll_'+opts.behavior].call(this);
12273                return;
12274            }
12275
12276            if (state.isDuringAjax || state.isInvalidPage || state.isDone || state.isDestroyed || state.isPaused) {
12277                return;
12278            }
12279
12280            if (!this._nearbottom()) {
12281                return;
12282            }
12283
12284            this.retrieve();
12285
12286        },
12287
12288        // Toggle pause value
12289        toggle: function infscr_toggle() {
12290            this._pausing();
12291        },
12292
12293        // Unbind from scroll
12294        unbind: function infscr_unbind() {
12295            this._binding('unbind');
12296        },
12297
12298        // update options
12299        update: function infscr_options(key) {
12300            if ($.isPlainObject(key)) {
12301                this.options = $.extend(true,this.options,key);
12302            }
12303        }
12304    };
12305
12306
12307    /*
12308        ----------------------------
12309        Infinite Scroll function
12310        ----------------------------
12311
12312        Borrowed logic from the following...
12313
12314        jQuery UI
12315        - https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.widget.js
12316
12317        jCarousel
12318        - https://github.com/jsor/jcarousel/blob/master/lib/jquery.jcarousel.js
12319
12320        Masonry
12321        - https://github.com/desandro/masonry/blob/master/jquery.masonry.js
12322
12323*/
12324
12325    $.fn.infinitescroll = function infscr_init(options, callback) {
12326
12327
12328        var thisCall = typeof options;
12329
12330        switch (thisCall) {
12331
12332            // method
12333            case 'string':
12334                var args = Array.prototype.slice.call(arguments, 1);
12335
12336                this.each(function () {
12337                    var instance = $.data(this, 'infinitescroll');
12338
12339                    if (!instance) {
12340                        // not setup yet
12341                        // return $.error('Method ' + options + ' cannot be called until Infinite Scroll is setup');
12342                        return false;
12343                    }
12344
12345                    if (!$.isFunction(instance[options]) || options.charAt(0) === '_') {
12346                        // return $.error('No such method ' + options + ' for Infinite Scroll');
12347                        return false;
12348                    }
12349
12350                    // no errors!
12351                    instance[options].apply(instance, args);
12352                });
12353
12354            break;
12355
12356            // creation
12357            case 'object':
12358
12359                this.each(function () {
12360
12361                var instance = $.data(this, 'infinitescroll');
12362
12363                if (instance) {
12364
12365                    // update options of current instance
12366                    instance.update(options);
12367
12368                } else {
12369
12370                    // initialize new instance
12371                    instance = new $.infinitescroll(options, callback, this);
12372
12373                    // don't attach if instantiation failed
12374                    if (!instance.failed) {
12375                        $.data(this, 'infinitescroll', instance);
12376                    }
12377
12378                }
12379
12380            });
12381
12382            break;
12383
12384        }
12385
12386        return this;
12387    };
12388
12389
12390
12391    /*
12392     * smartscroll: debounced scroll event for jQuery *
12393     * https://github.com/lukeshumard/smartscroll
12394     * Based on smartresize by @louis_remi: https://github.com/lrbabe/jquery.smartresize.js *
12395     * Copyright 2011 Louis-Remi & Luke Shumard * Licensed under the MIT license. *
12396     */
12397
12398    var event = $.event,
12399    scrollTimeout;
12400
12401    event.special.smartscroll = {
12402        setup: function () {
12403            $(this).bind('scroll', event.special.smartscroll.handler);
12404        },
12405        teardown: function () {
12406            $(this).unbind('scroll', event.special.smartscroll.handler);
12407        },
12408        handler: function (event, execAsap) {
12409            // Save the context
12410            var context = this,
12411            args = arguments;
12412
12413            // set correct event type
12414            event.type = 'smartscroll';
12415
12416            if (scrollTimeout) { clearTimeout(scrollTimeout); }
12417            scrollTimeout = setTimeout(function () {
12418                $(context).trigger('smartscroll', args);
12419            }, execAsap === 'execAsap' ? 0 : 100);
12420        }
12421    };
12422
12423    $.fn.smartscroll = function (fn) {
12424        return fn ? this.bind('smartscroll', fn) : this.trigger('smartscroll', ['execAsap']);
12425    };
12426
12427}));
12428
12429/*!
12430Waypoints - 4.0.1
12431Copyright © 2011-2016 Caleb Troughton
12432Licensed under the MIT license.
12433https://github.com/imakewebthings/waypoints/blob/master/licenses.txt
12434*/
12435(function() {
12436  'use strict'
12437
12438  var keyCounter = 0
12439  var allWaypoints = {}
12440
12441  /* http://imakewebthings.com/waypoints/api/waypoint */
12442  function Waypoint(options) {
12443    if (!options) {
12444      throw new Error('No options passed to Waypoint constructor')
12445    }
12446    if (!options.element) {
12447      throw new Error('No element option passed to Waypoint constructor')
12448    }
12449    if (!options.handler) {
12450      throw new Error('No handler option passed to Waypoint constructor')
12451    }
12452
12453    this.key = 'waypoint-' + keyCounter
12454    this.options = Waypoint.Adapter.extend({}, Waypoint.defaults, options)
12455    this.element = this.options.element
12456    this.adapter = new Waypoint.Adapter(this.element)
12457    this.callback = options.handler
12458    this.axis = this.options.horizontal ? 'horizontal' : 'vertical'
12459    this.enabled = this.options.enabled
12460    this.triggerPoint = null
12461    this.group = Waypoint.Group.findOrCreate({
12462      name: this.options.group,
12463      axis: this.axis
12464    })
12465    this.context = Waypoint.Context.findOrCreateByElement(this.options.context)
12466
12467    if (Waypoint.offsetAliases[this.options.offset]) {
12468      this.options.offset = Waypoint.offsetAliases[this.options.offset]
12469    }
12470    this.group.add(this)
12471    this.context.add(this)
12472    allWaypoints[this.key] = this
12473    keyCounter += 1
12474  }
12475
12476  /* Private */
12477  Waypoint.prototype.queueTrigger = function(direction) {
12478    this.group.queueTrigger(this, direction)
12479  }
12480
12481  /* Private */
12482  Waypoint.prototype.trigger = function(args) {
12483    if (!this.enabled) {
12484      return
12485    }
12486    if (this.callback) {
12487      this.callback.apply(this, args)
12488    }
12489  }
12490
12491  /* Public */
12492  /* http://imakewebthings.com/waypoints/api/destroy */
12493  Waypoint.prototype.destroy = function() {
12494    this.context.remove(this)
12495    this.group.remove(this)
12496    delete allWaypoints[this.key]
12497  }
12498
12499  /* Public */
12500  /* http://imakewebthings.com/waypoints/api/disable */
12501  Waypoint.prototype.disable = function() {
12502    this.enabled = false
12503    return this
12504  }
12505
12506  /* Public */
12507  /* http://imakewebthings.com/waypoints/api/enable */
12508  Waypoint.prototype.enable = function() {
12509    this.context.refresh()
12510    this.enabled = true
12511    return this
12512  }
12513
12514  /* Public */
12515  /* http://imakewebthings.com/waypoints/api/next */
12516  Waypoint.prototype.next = function() {
12517    return this.group.next(this)
12518  }
12519
12520  /* Public */
12521  /* http://imakewebthings.com/waypoints/api/previous */
12522  Waypoint.prototype.previous = function() {
12523    return this.group.previous(this)
12524  }
12525
12526  /* Private */
12527  Waypoint.invokeAll = function(method) {
12528    var allWaypointsArray = []
12529    for (var waypointKey in allWaypoints) {
12530      allWaypointsArray.push(allWaypoints[waypointKey])
12531    }
12532    for (var i = 0, end = allWaypointsArray.length; i < end; i++) {
12533      allWaypointsArray[i][method]()
12534    }
12535  }
12536
12537  /* Public */
12538  /* http://imakewebthings.com/waypoints/api/destroy-all */
12539  Waypoint.destroyAll = function() {
12540    Waypoint.invokeAll('destroy')
12541  }
12542
12543  /* Public */
12544  /* http://imakewebthings.com/waypoints/api/disable-all */
12545  Waypoint.disableAll = function() {
12546    Waypoint.invokeAll('disable')
12547  }
12548
12549  /* Public */
12550  /* http://imakewebthings.com/waypoints/api/enable-all */
12551  Waypoint.enableAll = function() {
12552    Waypoint.Context.refreshAll()
12553    for (var waypointKey in allWaypoints) {
12554      allWaypoints[waypointKey].enabled = true
12555    }
12556    return this
12557  }
12558
12559  /* Public */
12560  /* http://imakewebthings.com/waypoints/api/refresh-all */
12561  Waypoint.refreshAll = function() {
12562    Waypoint.Context.refreshAll()
12563  }
12564
12565  /* Public */
12566  /* http://imakewebthings.com/waypoints/api/viewport-height */
12567  Waypoint.viewportHeight = function() {
12568    return window.innerHeight || document.documentElement.clientHeight
12569  }
12570
12571  /* Public */
12572  /* http://imakewebthings.com/waypoints/api/viewport-width */
12573  Waypoint.viewportWidth = function() {
12574    return document.documentElement.clientWidth
12575  }
12576
12577  Waypoint.adapters = []
12578
12579  Waypoint.defaults = {
12580    context: window,
12581    continuous: true,
12582    enabled: true,
12583    group: 'default',
12584    horizontal: false,
12585    offset: 0
12586  }
12587
12588  Waypoint.offsetAliases = {
12589    'bottom-in-view': function() {
12590      return this.context.innerHeight() - this.adapter.outerHeight()
12591    },
12592    'right-in-view': function() {
12593      return this.context.innerWidth() - this.adapter.outerWidth()
12594    }
12595  }
12596
12597  window.Waypoint = Waypoint
12598}())
12599;(function() {
12600  'use strict'
12601
12602  function requestAnimationFrameShim(callback) {
12603    window.setTimeout(callback, 1000 / 60)
12604  }
12605
12606  var keyCounter = 0
12607  var contexts = {}
12608  var Waypoint = window.Waypoint
12609  var oldWindowLoad = window.onload
12610
12611  /* http://imakewebthings.com/waypoints/api/context */
12612  function Context(element) {
12613    this.element = element
12614    this.Adapter = Waypoint.Adapter
12615    this.adapter = new this.Adapter(element)
12616    this.key = 'waypoint-context-' + keyCounter
12617    this.didScroll = false
12618    this.didResize = false
12619    this.oldScroll = {
12620      x: this.adapter.scrollLeft(),
12621      y: this.adapter.scrollTop()
12622    }
12623    this.waypoints = {
12624      vertical: {},
12625      horizontal: {}
12626    }
12627
12628    element.waypointContextKey = this.key
12629    contexts[element.waypointContextKey] = this
12630    keyCounter += 1
12631    if (!Waypoint.windowContext) {
12632      Waypoint.windowContext = true
12633      Waypoint.windowContext = new Context(window)
12634    }
12635
12636    this.createThrottledScrollHandler()
12637    this.createThrottledResizeHandler()
12638  }
12639
12640  /* Private */
12641  Context.prototype.add = function(waypoint) {
12642    var axis = waypoint.options.horizontal ? 'horizontal' : 'vertical'
12643    this.waypoints[axis][waypoint.key] = waypoint
12644    this.refresh()
12645  }
12646
12647  /* Private */
12648  Context.prototype.checkEmpty = function() {
12649    var horizontalEmpty = this.Adapter.isEmptyObject(this.waypoints.horizontal)
12650    var verticalEmpty = this.Adapter.isEmptyObject(this.waypoints.vertical)
12651    var isWindow = this.element == this.element.window
12652    if (horizontalEmpty && verticalEmpty && !isWindow) {
12653      this.adapter.off('.waypoints')
12654      delete contexts[this.key]
12655    }
12656  }
12657
12658  /* Private */
12659  Context.prototype.createThrottledResizeHandler = function() {
12660    var self = this
12661
12662    function resizeHandler() {
12663      self.handleResize()
12664      self.didResize = false
12665    }
12666
12667    this.adapter.on('resize.waypoints', function() {
12668      if (!self.didResize) {
12669        self.didResize = true
12670        Waypoint.requestAnimationFrame(resizeHandler)
12671      }
12672    })
12673  }
12674
12675  /* Private */
12676  Context.prototype.createThrottledScrollHandler = function() {
12677    var self = this
12678    function scrollHandler() {
12679      self.handleScroll()
12680      self.didScroll = false
12681    }
12682
12683    this.adapter.on('scroll.waypoints', function() {
12684      if (!self.didScroll || Waypoint.isTouch) {
12685        self.didScroll = true
12686        Waypoint.requestAnimationFrame(scrollHandler)
12687      }
12688    })
12689  }
12690
12691  /* Private */
12692  Context.prototype.handleResize = function() {
12693    Waypoint.Context.refreshAll()
12694  }
12695
12696  /* Private */
12697  Context.prototype.handleScroll = function() {
12698    var triggeredGroups = {}
12699    var axes = {
12700      horizontal: {
12701        newScroll: this.adapter.scrollLeft(),
12702        oldScroll: this.oldScroll.x,
12703        forward: 'right',
12704        backward: 'left'
12705      },
12706      vertical: {
12707        newScroll: this.adapter.scrollTop(),
12708        oldScroll: this.oldScroll.y,
12709        forward: 'down',
12710        backward: 'up'
12711      }
12712    }
12713
12714    for (var axisKey in axes) {
12715      var axis = axes[axisKey]
12716      var isForward = axis.newScroll > axis.oldScroll
12717      var direction = isForward ? axis.forward : axis.backward
12718
12719      for (var waypointKey in this.waypoints[axisKey]) {
12720        var waypoint = this.waypoints[axisKey][waypointKey]
12721        if (waypoint.triggerPoint === null) {
12722          continue
12723        }
12724        var wasBeforeTriggerPoint = axis.oldScroll < waypoint.triggerPoint
12725        var nowAfterTriggerPoint = axis.newScroll >= waypoint.triggerPoint
12726        var crossedForward = wasBeforeTriggerPoint && nowAfterTriggerPoint
12727        var crossedBackward = !wasBeforeTriggerPoint && !nowAfterTriggerPoint
12728        if (crossedForward || crossedBackward) {
12729          waypoint.queueTrigger(direction)
12730          triggeredGroups[waypoint.group.id] = waypoint.group
12731        }
12732      }
12733    }
12734
12735    for (var groupKey in triggeredGroups) {
12736      triggeredGroups[groupKey].flushTriggers()
12737    }
12738
12739    this.oldScroll = {
12740      x: axes.horizontal.newScroll,
12741      y: axes.vertical.newScroll
12742    }
12743  }
12744
12745  /* Private */
12746  Context.prototype.innerHeight = function() {
12747    /*eslint-disable eqeqeq */
12748    if (this.element == this.element.window) {
12749      return Waypoint.viewportHeight()
12750    }
12751    /*eslint-enable eqeqeq */
12752    return this.adapter.innerHeight()
12753  }
12754
12755  /* Private */
12756  Context.prototype.remove = function(waypoint) {
12757    delete this.waypoints[waypoint.axis][waypoint.key]
12758    this.checkEmpty()
12759  }
12760
12761  /* Private */
12762  Context.prototype.innerWidth = function() {
12763    /*eslint-disable eqeqeq */
12764    if (this.element == this.element.window) {
12765      return Waypoint.viewportWidth()
12766    }
12767    /*eslint-enable eqeqeq */
12768    return this.adapter.innerWidth()
12769  }
12770
12771  /* Public */
12772  /* http://imakewebthings.com/waypoints/api/context-destroy */
12773  Context.prototype.destroy = function() {
12774    var allWaypoints = []
12775    for (var axis in this.waypoints) {
12776      for (var waypointKey in this.waypoints[axis]) {
12777        allWaypoints.push(this.waypoints[axis][waypointKey])
12778      }
12779    }
12780    for (var i = 0, end = allWaypoints.length; i < end; i++) {
12781      allWaypoints[i].destroy()
12782    }
12783  }
12784
12785  /* Public */
12786  /* http://imakewebthings.com/waypoints/api/context-refresh */
12787  Context.prototype.refresh = function() {
12788    /*eslint-disable eqeqeq */
12789    var isWindow = this.element == this.element.window
12790    /*eslint-enable eqeqeq */
12791    var contextOffset = isWindow ? undefined : this.adapter.offset()
12792    var triggeredGroups = {}
12793    var axes
12794
12795    this.handleScroll()
12796    axes = {
12797      horizontal: {
12798        contextOffset: isWindow ? 0 : contextOffset.left,
12799        contextScroll: isWindow ? 0 : this.oldScroll.x,
12800        contextDimension: this.innerWidth(),
12801        oldScroll: this.oldScroll.x,
12802        forward: 'right',
12803        backward: 'left',
12804        offsetProp: 'left'
12805      },
12806      vertical: {
12807        contextOffset: isWindow ? 0 : contextOffset.top,
12808        contextScroll: isWindow ? 0 : this.oldScroll.y,
12809        contextDimension: this.innerHeight(),
12810        oldScroll: this.oldScroll.y,
12811        forward: 'down',
12812        backward: 'up',
12813        offsetProp: 'top'
12814      }
12815    }
12816
12817    for (var axisKey in axes) {
12818      var axis = axes[axisKey]
12819      for (var waypointKey in this.waypoints[axisKey]) {
12820        var waypoint = this.waypoints[axisKey][waypointKey]
12821        var adjustment = waypoint.options.offset
12822        var oldTriggerPoint = waypoint.triggerPoint
12823        var elementOffset = 0
12824        var freshWaypoint = oldTriggerPoint == null
12825        var contextModifier, wasBeforeScroll, nowAfterScroll
12826        var triggeredBackward, triggeredForward
12827
12828        if (waypoint.element !== waypoint.element.window) {
12829          elementOffset = waypoint.adapter.offset()[axis.offsetProp]
12830        }
12831
12832        if (typeof adjustment === 'function') {
12833          adjustment = adjustment.apply(waypoint)
12834        }
12835        else if (typeof adjustment === 'string') {
12836          adjustment = parseFloat(adjustment)
12837          if (waypoint.options.offset.indexOf('%') > - 1) {
12838            adjustment = Math.ceil(axis.contextDimension * adjustment / 100)
12839          }
12840        }
12841
12842        contextModifier = axis.contextScroll - axis.contextOffset
12843        waypoint.triggerPoint = Math.floor(elementOffset + contextModifier - adjustment)
12844        wasBeforeScroll = oldTriggerPoint < axis.oldScroll
12845        nowAfterScroll = waypoint.triggerPoint >= axis.oldScroll
12846        triggeredBackward = wasBeforeScroll && nowAfterScroll
12847        triggeredForward = !wasBeforeScroll && !nowAfterScroll
12848
12849        if (!freshWaypoint && triggeredBackward) {
12850          waypoint.queueTrigger(axis.backward)
12851          triggeredGroups[waypoint.group.id] = waypoint.group
12852        }
12853        else if (!freshWaypoint && triggeredForward) {
12854          waypoint.queueTrigger(axis.forward)
12855          triggeredGroups[waypoint.group.id] = waypoint.group
12856        }
12857        else if (freshWaypoint && axis.oldScroll >= waypoint.triggerPoint) {
12858          waypoint.queueTrigger(axis.forward)
12859          triggeredGroups[waypoint.group.id] = waypoint.group
12860        }
12861      }
12862    }
12863
12864    Waypoint.requestAnimationFrame(function() {
12865      for (var groupKey in triggeredGroups) {
12866        triggeredGroups[groupKey].flushTriggers()
12867      }
12868    })
12869
12870    return this
12871  }
12872
12873  /* Private */
12874  Context.findOrCreateByElement = function(element) {
12875    return Context.findByElement(element) || new Context(element)
12876  }
12877
12878  /* Private */
12879  Context.refreshAll = function() {
12880    for (var contextId in contexts) {
12881      contexts[contextId].refresh()
12882    }
12883  }
12884
12885  /* Public */
12886  /* http://imakewebthings.com/waypoints/api/context-find-by-element */
12887  Context.findByElement = function(element) {
12888    return contexts[element.waypointContextKey]
12889  }
12890
12891  window.onload = function() {
12892    if (oldWindowLoad) {
12893      oldWindowLoad()
12894    }
12895    Context.refreshAll()
12896  }
12897
12898
12899  Waypoint.requestAnimationFrame = function(callback) {
12900    var requestFn = window.requestAnimationFrame ||
12901      window.mozRequestAnimationFrame ||
12902      window.webkitRequestAnimationFrame ||
12903      requestAnimationFrameShim
12904    requestFn.call(window, callback)
12905  }
12906  Waypoint.Context = Context
12907}())
12908;(function() {
12909  'use strict'
12910
12911  function byTriggerPoint(a, b) {
12912    return a.triggerPoint - b.triggerPoint
12913  }
12914
12915  function byReverseTriggerPoint(a, b) {
12916    return b.triggerPoint - a.triggerPoint
12917  }
12918
12919  var groups = {
12920    vertical: {},
12921    horizontal: {}
12922  }
12923  var Waypoint = window.Waypoint
12924
12925  /* http://imakewebthings.com/waypoints/api/group */
12926  function Group(options) {
12927    this.name = options.name
12928    this.axis = options.axis
12929    this.id = this.name + '-' + this.axis
12930    this.waypoints = []
12931    this.clearTriggerQueues()
12932    groups[this.axis][this.name] = this
12933  }
12934
12935  /* Private */
12936  Group.prototype.add = function(waypoint) {
12937    this.waypoints.push(waypoint)
12938  }
12939
12940  /* Private */
12941  Group.prototype.clearTriggerQueues = function() {
12942    this.triggerQueues = {
12943      up: [],
12944      down: [],
12945      left: [],
12946      right: []
12947    }
12948  }
12949
12950  /* Private */
12951  Group.prototype.flushTriggers = function() {
12952    for (var direction in this.triggerQueues) {
12953      var waypoints = this.triggerQueues[direction]
12954      var reverse = direction === 'up' || direction === 'left'
12955      waypoints.sort(reverse ? byReverseTriggerPoint : byTriggerPoint)
12956      for (var i = 0, end = waypoints.length; i < end; i += 1) {
12957        var waypoint = waypoints[i]
12958        if (waypoint.options.continuous || i === waypoints.length - 1) {
12959          waypoint.trigger([direction])
12960        }
12961      }
12962    }
12963    this.clearTriggerQueues()
12964  }
12965
12966  /* Private */
12967  Group.prototype.next = function(waypoint) {
12968    this.waypoints.sort(byTriggerPoint)
12969    var index = Waypoint.Adapter.inArray(waypoint, this.waypoints)
12970    var isLast = index === this.waypoints.length - 1
12971    return isLast ? null : this.waypoints[index + 1]
12972  }
12973
12974  /* Private */
12975  Group.prototype.previous = function(waypoint) {
12976    this.waypoints.sort(byTriggerPoint)
12977    var index = Waypoint.Adapter.inArray(waypoint, this.waypoints)
12978    return index ? this.waypoints[index - 1] : null
12979  }
12980
12981  /* Private */
12982  Group.prototype.queueTrigger = function(waypoint, direction) {
12983    this.triggerQueues[direction].push(waypoint)
12984  }
12985
12986  /* Private */
12987  Group.prototype.remove = function(waypoint) {
12988    var index = Waypoint.Adapter.inArray(waypoint, this.waypoints)
12989    if (index > -1) {
12990      this.waypoints.splice(index, 1)
12991    }
12992  }
12993
12994  /* Public */
12995  /* http://imakewebthings.com/waypoints/api/first */
12996  Group.prototype.first = function() {
12997    return this.waypoints[0]
12998  }
12999
13000  /* Public */
13001  /* http://imakewebthings.com/waypoints/api/last */
13002  Group.prototype.last = function() {
13003    return this.waypoints[this.waypoints.length - 1]
13004  }
13005
13006  /* Private */
13007  Group.findOrCreate = function(options) {
13008    return groups[options.axis][options.name] || new Group(options)
13009  }
13010
13011  Waypoint.Group = Group
13012}())
13013;(function() {
13014  'use strict'
13015
13016  var $ = window.jQuery
13017  var Waypoint = window.Waypoint
13018
13019  function JQueryAdapter(element) {
13020    this.$element = $(element)
13021  }
13022
13023  $.each([
13024    'innerHeight',
13025    'innerWidth',
13026    'off',
13027    'offset',
13028    'on',
13029    'outerHeight',
13030    'outerWidth',
13031    'scrollLeft',
13032    'scrollTop'
13033  ], function(i, method) {
13034    JQueryAdapter.prototype[method] = function() {
13035      var args = Array.prototype.slice.call(arguments)
13036      return this.$element[method].apply(this.$element, args)
13037    }
13038  })
13039
13040  $.each([
13041    'extend',
13042    'inArray',
13043    'isEmptyObject'
13044  ], function(i, method) {
13045    JQueryAdapter[method] = $[method]
13046  })
13047
13048  Waypoint.adapters.push({
13049    name: 'jquery',
13050    Adapter: JQueryAdapter
13051  })
13052  Waypoint.Adapter = JQueryAdapter
13053}())
13054;(function() {
13055  'use strict'
13056
13057  var Waypoint = window.Waypoint
13058
13059  function createExtension(framework) {
13060    return function() {
13061      var waypoints = []
13062      var overrides = arguments[0]
13063
13064      if (framework.isFunction(arguments[0])) {
13065        overrides = framework.extend({}, arguments[1])
13066        overrides.handler = arguments[0]
13067      }
13068
13069      this.each(function() {
13070        var options = framework.extend({}, overrides, {
13071          element: this
13072        })
13073        if (typeof options.context === 'string') {
13074          options.context = framework(this).closest(options.context)[0]
13075        }
13076        waypoints.push(new Waypoint(options))
13077      })
13078
13079      return waypoints
13080    }
13081  }
13082
13083  if (window.jQuery) {
13084    window.jQuery.fn.waypoint = createExtension(window.jQuery)
13085  }
13086  if (window.Zepto) {
13087    window.Zepto.fn.waypoint = createExtension(window.Zepto)
13088  }
13089}())
13090;
13091/*!
13092Waypoints Inview Shortcut - 4.0.1
13093Copyright © 2011-2016 Caleb Troughton
13094Licensed under the MIT license.
13095https://github.com/imakewebthings/waypoints/blob/master/licenses.txt
13096*/
13097(function() {
13098  'use strict'
13099
13100  function noop() {}
13101
13102  var Waypoint = window.Waypoint
13103
13104  /* http://imakewebthings.com/waypoints/shortcuts/inview */
13105  function Inview(options) {
13106    this.options = Waypoint.Adapter.extend({}, Inview.defaults, options)
13107    this.axis = this.options.horizontal ? 'horizontal' : 'vertical'
13108    this.waypoints = []
13109    this.element = this.options.element
13110    this.createWaypoints()
13111  }
13112
13113  /* Private */
13114  Inview.prototype.createWaypoints = function() {
13115    var configs = {
13116      vertical: [{
13117        down: 'enter',
13118        up: 'exited',
13119        offset: '100%'
13120      }, {
13121        down: 'entered',
13122        up: 'exit',
13123        offset: 'bottom-in-view'
13124      }, {
13125        down: 'exit',
13126        up: 'entered',
13127        offset: 0
13128      }, {
13129        down: 'exited',
13130        up: 'enter',
13131        offset: function() {
13132          return -this.adapter.outerHeight()
13133        }
13134      }],
13135      horizontal: [{
13136        right: 'enter',
13137        left: 'exited',
13138        offset: '100%'
13139      }, {
13140        right: 'entered',
13141        left: 'exit',
13142        offset: 'right-in-view'
13143      }, {
13144        right: 'exit',
13145        left: 'entered',
13146        offset: 0
13147      }, {
13148        right: 'exited',
13149        left: 'enter',
13150        offset: function() {
13151          return -this.adapter.outerWidth()
13152        }
13153      }]
13154    }
13155
13156    for (var i = 0, end = configs[this.axis].length; i < end; i++) {
13157      var config = configs[this.axis][i]
13158      this.createWaypoint(config)
13159    }
13160  }
13161
13162  /* Private */
13163  Inview.prototype.createWaypoint = function(config) {
13164    var self = this
13165    this.waypoints.push(new Waypoint({
13166      context: this.options.context,
13167      element: this.options.element,
13168      enabled: this.options.enabled,
13169      handler: (function(config) {
13170        return function(direction) {
13171          self.options[config[direction]].call(self, direction)
13172        }
13173      }(config)),
13174      offset: config.offset,
13175      horizontal: this.options.horizontal
13176    }))
13177  }
13178
13179  /* Public */
13180  Inview.prototype.destroy = function() {
13181    for (var i = 0, end = this.waypoints.length; i < end; i++) {
13182      this.waypoints[i].destroy()
13183    }
13184    this.waypoints = []
13185  }
13186
13187  Inview.prototype.disable = function() {
13188    for (var i = 0, end = this.waypoints.length; i < end; i++) {
13189      this.waypoints[i].disable()
13190    }
13191  }
13192
13193  Inview.prototype.enable = function() {
13194    for (var i = 0, end = this.waypoints.length; i < end; i++) {
13195      this.waypoints[i].enable()
13196    }
13197  }
13198
13199  Inview.defaults = {
13200    context: window,
13201    enabled: true,
13202    enter: noop,
13203    entered: noop,
13204    exit: noop,
13205    exited: noop
13206  }
13207
13208  Waypoint.Inview = Inview
13209}())
13210;
13211
13212/*
13213 * SmartMenus jQuery v0.9.6
13214 * http://www.smartmenus.org/
13215 *
13216 * Copyright 2014 Vasil Dinkov, Vadikom Web Ltd.
13217 * http://vadikom.com/
13218 *
13219 * Released under the MIT license:
13220 * http://www.opensource.org/licenses/MIT
13221 */
13222
13223(function($) {
13224
13225	var menuTrees = [],
13226		IE = !!window.createPopup, // we need to detect it, unfortunately
13227		IElt9 = IE && !document.defaultView,
13228		IElt8 = IE && !document.querySelector,
13229		IE6 = IE && typeof document.documentElement.currentStyle.minWidth == 'undefined',
13230		mouse = false, // optimize for touch by default - we will detect for mouse input
13231		mouseDetectionEnabled = false;
13232
13233	// Handle detection for mouse input (i.e. desktop browsers, tablets with a mouse, etc.)
13234	function initMouseDetection(disable) {
13235		if (!mouseDetectionEnabled && !disable) {
13236			// if we get two consecutive mousemoves within 2 pixels from each other and within 300ms, we assume a real mouse/cursor is present
13237			// 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)
13238			var firstTime = true,
13239				lastMove = null;
13240			$(document).bind({
13241				'mousemove.smartmenus_mouse': function(e) {
13242					var thisMove = { x: e.pageX, y: e.pageY, timeStamp: new Date().getTime() };
13243					if (lastMove) {
13244						var deltaX = Math.abs(lastMove.x - thisMove.x),
13245							deltaY = Math.abs(lastMove.y - thisMove.y);
13246	 					if ((deltaX > 0 || deltaY > 0) && deltaX <= 2 && deltaY <= 2 && thisMove.timeStamp - lastMove.timeStamp <= 300) {
13247							mouse = true;
13248							// 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
13249							if (firstTime) {
13250								var $a = $(e.target).closest('a');
13251								if ($a.is('a')) {
13252									$.each(menuTrees, function() {
13253										if ($.contains(this.$root[0], $a[0])) {
13254											this.itemEnter({ currentTarget: $a[0] });
13255											return false;
13256										}
13257									});
13258								}
13259								firstTime = false;
13260							}
13261						}
13262					}
13263					lastMove = thisMove;
13264				},
13265				'touchstart.smartmenus_mouse pointerover.smartmenus_mouse MSPointerOver.smartmenus_mouse': function(e) {
13266					if (!/^(4|mouse|pen)$/.test(e.originalEvent.pointerType)) {
13267						mouse = false;
13268					}
13269				}
13270			});
13271			mouseDetectionEnabled = true;
13272		} else if (mouseDetectionEnabled && disable) {
13273			$(document).unbind('.smartmenus_mouse');
13274			mouseDetectionEnabled = false;
13275		}
13276	};
13277
13278	$.SmartMenus = function(elm, options) {
13279		this.$root = $(elm);
13280		this.opts = options;
13281		this.rootId = ''; // internal
13282		this.$subArrow = null;
13283		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)
13284		this.activatedItems = []; // stores last activated A's for each level
13285		this.visibleSubMenus = []; // stores visible sub menus UL's
13286		this.showTimeout = 0;
13287		this.hideTimeout = 0;
13288		this.scrollTimeout = 0;
13289		this.clickActivated = false;
13290		this.zIndexInc = 0;
13291		this.$firstLink = null; // we'll use these for some tests
13292		this.$firstSub = null; // at runtime so we'll cache them
13293		this.disabled = false;
13294		this.$disableOverlay = null;
13295		this.init();
13296	};
13297
13298	$.extend($.SmartMenus, {
13299		hideAll: function() {
13300			$.each(menuTrees, function() {
13301				this.menuHideAll();
13302			});
13303		},
13304		destroy: function() {
13305			while (menuTrees.length) {
13306				menuTrees[0].destroy();
13307			}
13308			initMouseDetection(true);
13309		},
13310		prototype: {
13311			init: function(refresh) {
13312				var self = this;
13313
13314				if (!refresh) {
13315					menuTrees.push(this);
13316
13317					this.rootId = (new Date().getTime() + Math.random() + '').replace(/\D/g, '');
13318
13319					if (this.$root.hasClass('sm-rtl')) {
13320						this.opts.rightToLeftSubMenus = true;
13321					}
13322
13323					// init root (main menu)
13324					this.$root
13325						.data('smartmenus', this)
13326						.attr('data-smartmenus-id', this.rootId)
13327						.dataSM('level', 1)
13328						.bind({
13329							'mouseover.smartmenus focusin.smartmenus': $.proxy(this.rootOver, this),
13330							'mouseout.smartmenus focusout.smartmenus': $.proxy(this.rootOut, this)
13331						})
13332						.delegate('a, div.logo-container', {
13333							'mouseenter.smartmenus': $.proxy(this.itemEnter, this),
13334							'mouseleave.smartmenus': $.proxy(this.itemLeave, this),
13335							'mousedown.smartmenus': $.proxy(this.itemDown, this),
13336							'focus.smartmenus': $.proxy(this.itemFocus, this),
13337							'blur.smartmenus': $.proxy(this.itemBlur, this),
13338							'click.smartmenus': $.proxy(this.itemClick, this),
13339							'touchend.smartmenus': $.proxy(this.itemTouchEnd, this)
13340						});
13341
13342					var eNamespace = '.smartmenus' + this.rootId;
13343					// hide menus on tap or click outside the root UL
13344					if (this.opts.hideOnClick) {
13345							$(document).on('touchstart' + eNamespace, $.proxy(this.docTouchStart, this))
13346								.on('touchmove' + eNamespace, $.proxy(this.docTouchMove, this))
13347								.on('touchend' + eNamespace, $.proxy(this.docTouchEnd, this))
13348								// for Opera Mobile < 11.5, webOS browser, etc. we'll check click too
13349								.on('click' + eNamespace, $.proxy(this.docClick, this));
13350					}
13351					// hide sub menus on resize
13352					$(window).on('resize' + eNamespace + ' orientationchange' + eNamespace, $.proxy(this.winResize, this));
13353					var $vmenu = $('body.vmenu .vmenu-container');
13354					if ( ! $vmenu.length && UNCODE.wwidth > UNCODE.mediaQuery ) {
13355						$(window).on('scroll' + eNamespace + ' orientationchange' + eNamespace, $.proxy(this.winResize, this));
13356					}
13357
13358					if (this.opts.subIndicators) {
13359						this.$subArrow = $('<span/>').addClass('sub-arrow');
13360						if (this.opts.subIndicatorsText) {
13361							this.$subArrow.html(this.opts.subIndicatorsText);
13362						}
13363					}
13364
13365					// make sure mouse detection is enabled
13366					initMouseDetection();
13367				}
13368
13369				// init sub menus
13370				this.$firstSub = this.$root.find('ul').each(function() { self.menuInit($(this)); }).eq(0);
13371
13372				this.$firstLink = this.$root.find('a').eq(0);
13373
13374				// find current item
13375				if (this.opts.markCurrentItem) {
13376					var reDefaultDoc = /(index|default)\.[^#\?\/]*/i,
13377						reHash = /#.*/,
13378						locHref = window.location.href.replace(reDefaultDoc, ''),
13379						locHrefNoHash = locHref.replace(reHash, '');
13380					this.$root.find('a').each(function() {
13381						var href = this.href.replace(reDefaultDoc, ''),
13382							$this = $(this);
13383						if (href == locHref || href == locHrefNoHash) {
13384							$this.addClass('current');
13385							if (self.opts.markCurrentTree) {
13386								$this.parents('li').each(function() {
13387									var $this = $(this);
13388									if ($this.dataSM('sub')) {
13389										$this.children('a').addClass('current');
13390									}
13391								});
13392							}
13393						}
13394					});
13395				}
13396			},
13397			destroy: function() {
13398				this.menuHideAll();
13399				this.$root
13400					.removeData('smartmenus')
13401					.removeAttr('data-smartmenus-id')
13402					.removeDataSM('level')
13403					.unbind('.smartmenus')
13404					.undelegate('.smartmenus');
13405				var eNamespace = '.smartmenus' + this.rootId;
13406				$(document).unbind(eNamespace);
13407				$(window).unbind(eNamespace);
13408				if (this.opts.subIndicators) {
13409					this.$subArrow = null;
13410				}
13411				var self = this;
13412				$.each(this.subMenus, function() {
13413					if (this.hasClass('mega-menu')) {
13414						this.find('ul').removeDataSM('in-mega');
13415					}
13416					if (this.dataSM('shown-before')) {
13417						if (IElt8) {
13418							this.children().css({ styleFloat: '', width: '' });
13419						}
13420						if (self.opts.subMenusMinWidth || self.opts.subMenusMaxWidth) {
13421							if (!IE6) {
13422								this.css({ width: '', minWidth: '', maxWidth: '' }).removeClass('sm-nowrap');
13423							} else {
13424								this.css({ width: '', overflowX: '', overflowY: '' }).children().children('a').css('white-space', '');
13425							}
13426						}
13427						if (this.dataSM('scroll-arrows')) {
13428							this.dataSM('scroll-arrows').remove();
13429						}
13430						this.css({ zIndex: '', top: '', left: '', marginLeft: '', marginTop: '', display: '' });
13431					}
13432					if (self.opts.subIndicators) {
13433						this.dataSM('parent-a').removeClass('has-submenu').children('span.sub-arrow').remove();
13434					}
13435					this.removeDataSM('shown-before')
13436						.removeDataSM('ie-shim')
13437						.removeDataSM('scroll-arrows')
13438						.removeDataSM('parent-a')
13439						.removeDataSM('level')
13440						.removeDataSM('beforefirstshowfired')
13441						.parent().removeDataSM('sub');
13442				});
13443				if (this.opts.markCurrentItem) {
13444					this.$root.find('a.current').removeClass('current');
13445				}
13446				this.$root = null;
13447				this.$firstLink = null;
13448				this.$firstSub = null;
13449				if (this.$disableOverlay) {
13450					this.$disableOverlay.remove();
13451					this.$disableOverlay = null;
13452				}
13453				menuTrees.splice($.inArray(this, menuTrees), 1);
13454			},
13455			disable: function(noOverlay) {
13456				if (!this.disabled) {
13457					this.menuHideAll();
13458					// display overlay over the menu to prevent interaction
13459					if (!noOverlay && !this.opts.isPopup && this.$root.is(':visible')) {
13460						var pos = this.$root.offset();
13461						this.$disableOverlay = $('<div class="sm-jquery-disable-overlay"/>').css({
13462							position: 'absolute',
13463							top: pos.top,
13464							left: pos.left,
13465							width: this.$root.outerWidth(),
13466							height: this.$root.outerHeight(),
13467							zIndex: this.getStartZIndex() + 1,
13468							opacity: 0
13469						}).appendTo(document.body);
13470					}
13471					this.disabled = true;
13472				}
13473			},
13474			docClick: function(e) {
13475				// hide on any click outside the menu or on a menu link
13476				if (this.visibleSubMenus.length && !$.contains(this.$root[0], e.target) || $(e.target).is('a')) {
13477					this.menuHideAll($(e.target));
13478				}
13479			},
13480			docTouchEnd: function(e) {
13481				if (!this.lastTouch) {
13482					return;
13483				}
13484				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))) {
13485					if (this.hideTimeout) {
13486						clearTimeout(this.hideTimeout);
13487						this.hideTimeout = 0;
13488					}
13489					// hide with a delay to prevent triggering accidental unwanted click on some page element
13490					var self = this;
13491					this.hideTimeout = setTimeout(function() { self.menuHideAll($(e.target)); }, 350);
13492				}
13493				this.lastTouch = null;
13494			},
13495			docTouchMove: function(e) {
13496				if (!this.lastTouch) {
13497					return;
13498				}
13499				var touchPoint = e.originalEvent.touches[0];
13500				this.lastTouch.x2 = touchPoint.pageX;
13501				this.lastTouch.y2 = touchPoint.pageY;
13502			},
13503			docTouchStart: function(e) {
13504				var touchPoint = e.originalEvent.touches[0];
13505				this.lastTouch = { x1: touchPoint.pageX, y1: touchPoint.pageY, target: touchPoint.target };
13506			},
13507			enable: function() {
13508				if (this.disabled) {
13509					if (this.$disableOverlay) {
13510						this.$disableOverlay.remove();
13511						this.$disableOverlay = null;
13512					}
13513					this.disabled = false;
13514				}
13515			},
13516			getHeight: function($elm) {
13517				return this.getOffset($elm, true);
13518			},
13519			// returns precise width/height float values in IE9+, FF4+, recent WebKit
13520			// http://vadikom.com/dailies/offsetwidth-offsetheight-useless-in-ie9-firefox4/
13521			getOffset: function($elm, height) {
13522				var old,
13523					$win = $(window),
13524					winW = $win.width();
13525				if ($elm.css('display') == 'none') {
13526					old = { position: $elm[0].style.position, visibility: $elm[0].style.visibility };
13527					$elm.css({ position: 'absolute', visibility: 'hidden' }).show();
13528					if ( 
13529						($('body').hasClass('menu-mobile-off-canvas') && winW < 960 && $elm.closest('.main-menu-container').length)
13530						||
13531						(( $('body').hasClass('vmenu-offcanvas-overlay') || $('body').hasClass('vmenu') ) && winW >= 960 && $elm.closest('.main-menu-container').length && !$elm.closest('.menu-horizontal-inner').length)
13532					) {
13533						$elm.closest('li').addClass('smartmenu-open-item');
13534					}
13535				}
13536				var defaultView = $elm[0].ownerDocument.defaultView,
13537					compStyle = defaultView && defaultView.getComputedStyle && defaultView.getComputedStyle($elm[0], null),
13538					val = compStyle && parseFloat(compStyle[height ? 'height' : 'width']);
13539				if (val) {
13540					val += parseFloat(compStyle[height ? 'paddingTop' : 'paddingLeft'])
13541	 					+ parseFloat(compStyle[height ? 'paddingBottom' : 'paddingRight'])
13542	 					+ parseInt(compStyle[height ? 'borderTopWidth' : 'borderLeftWidth'])
13543	 					+ parseInt(compStyle[height ? 'borderBottomWidth' : 'borderRightWidth']);
13544				} else {
13545					val = height ? $elm[0].offsetHeight : $elm[0].offsetWidth;
13546				}
13547				if (old) {
13548					$elm.hide().css(old);
13549				}
13550				return val;
13551			},
13552			getWidth: function($elm) {
13553				return this.getOffset($elm);
13554			},
13555			getStartZIndex: function() {
13556				var zIndex = parseInt(this.$root.css('z-index'));
13557				return !isNaN(zIndex) ? zIndex : 1;
13558			},
13559			handleEvents: function() {
13560				return !this.disabled && this.isCSSOn();
13561			},
13562			handleItemEvents: function($a) {
13563				return this.handleEvents() && !this.isLinkInMegaMenu($a);
13564			},
13565			isCollapsible: function() {
13566				return this.$firstSub.css('position') == 'static';
13567			},
13568			isCSSOn: function() {
13569				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';
13570			},
13571			isFixed: function() {
13572				return this.$root.css('position') == 'fixed';
13573			},
13574			isLinkInMegaMenu: function($a) {
13575				return !$a.parent().parent().dataSM('level');
13576			},
13577			isTouchMode: function() {
13578				return !mouse || this.isCollapsible();
13579			},
13580			itemActivate: function($a) {
13581				var $li = $a.parent(),
13582					$ul = $li.parent(),
13583					level = $ul.dataSM('level');
13584				// 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
13585				if (level > 1 && (!this.activatedItems[level - 2] || this.activatedItems[level - 2][0] != $ul.dataSM('parent-a')[0])) {
13586					var self = this;
13587					$($ul.parentsUntil('[data-smartmenus-id]', 'ul').get().reverse()).add($ul).each(function() {
13588						self.itemActivate($(this).dataSM('parent-a'));
13589					});
13590				}
13591				// hide any visible deeper level sub menus
13592				if (this.visibleSubMenus.length > level) {
13593					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--) {
13594						//if ( !this.visibleSubMenus[i].closest('.menu-accordion').length ) {
13595							this.menuHide(this.visibleSubMenus[i]);
13596						//}
13597					}
13598				}
13599				// save new active item and sub menu for this level
13600				this.activatedItems[level - 1] = $a;
13601				this.visibleSubMenus[level - 1] = $ul;
13602				if (this.$root.triggerHandler('activate.smapi', $a[0]) === false) {
13603					return;
13604				}
13605				// show the sub menu if this item has one
13606				var $sub = $li.dataSM('sub');
13607				if ($sub && (this.isTouchMode() || (!this.opts.showOnClick || this.clickActivated))) {
13608					this.menuShow($sub);
13609				}
13610			},
13611			itemBlur: function(e) {
13612				var $a = $(e.currentTarget);
13613				if (!this.handleItemEvents($a)) {
13614					return;
13615				}
13616				this.$root.triggerHandler('blur.smapi', $a[0]);
13617			},
13618			itemClick: function(e) {
13619				var $a = $(e.currentTarget);
13620
13621				if (!this.handleItemEvents($a)) {
13622					return;
13623				}
13624				$a.removeDataSM('mousedown');
13625				if (this.$root.triggerHandler('click.smapi', $a[0]) === false) {
13626					return false;
13627				}
13628				var $sub = $a.parent().dataSM('sub');
13629				if (this.isTouchMode()) {
13630					// undo fix: prevent the address bar on iPhone from sliding down when expanding a sub menu
13631					if ($a.dataSM('href')) {
13632						$a.attr('href', $a.dataSM('href')).removeDataSM('href');
13633					}
13634					// if the sub is not visible
13635					if ($sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) {
13636						// try to activate the item and show the sub
13637						this.itemActivate($a);
13638						// if "itemActivate" showed the sub, prevent the click so that the link is not loaded
13639						// 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
13640						if ($sub.is(':visible')) {
13641							return false;
13642						}
13643					}
13644				} else if (this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 && $sub) {
13645					this.clickActivated = true;
13646					this.menuShow($sub);
13647					return false;
13648				}
13649				if ($a.hasClass('disabled')) {
13650					return false;
13651				}
13652				if (this.$root.triggerHandler('select.smapi', $a[0]) === false) {
13653					return false;
13654				}
13655			},
13656			itemDown: function(e) {
13657				var $a = $(e.currentTarget);
13658				if (!this.handleItemEvents($a)) {
13659					return;
13660				}
13661				$a.dataSM('mousedown', true);
13662			},
13663			itemEnter: function(e) {
13664				var $a = $(e.currentTarget);
13665				if (!this.handleItemEvents($a)) {
13666					return;
13667				}
13668				if (!this.isTouchMode()) {
13669					if (this.showTimeout) {
13670						clearTimeout(this.showTimeout);
13671						this.showTimeout = 0;
13672					}
13673					var self = this;
13674					this.showTimeout = setTimeout(function() { self.itemActivate($a); }, this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 ? 1 : this.opts.showTimeout);
13675				}
13676				this.$root.triggerHandler('mouseenter.smapi', $a[0]);
13677			},
13678			itemFocus: function(e) {
13679				var $a = $(e.currentTarget);
13680				if (!this.handleItemEvents($a)) {
13681					return;
13682				}
13683				// 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
13684				if ((!this.isTouchMode() || !$a.dataSM('mousedown')) && (!this.activatedItems.length || this.activatedItems[this.activatedItems.length - 1][0] != $a[0])) {
13685					this.itemActivate($a);
13686				}
13687				this.$root.triggerHandler('focus.smapi', $a[0]);
13688			},
13689			itemLeave: function(e) {
13690				var $a = $(e.currentTarget);
13691				if (!this.handleItemEvents($a)) {
13692					return;
13693				}
13694				if (!this.isTouchMode()) {
13695					if ($a[0].blur) {
13696						$a[0].blur();
13697					}
13698					if (this.showTimeout) {
13699						clearTimeout(this.showTimeout);
13700						this.showTimeout = 0;
13701					}
13702				}
13703				$a.removeDataSM('mousedown');
13704				this.$root.triggerHandler('mouseleave.smapi', $a[0]);
13705			},
13706			itemTouchEnd: function(e) {
13707				var $a = $(e.currentTarget);
13708				if (!this.handleItemEvents($a)) {
13709					return;
13710				}
13711				// prevent the address bar on iPhone from sliding down when expanding a sub menu
13712				var $sub = $a.parent().dataSM('sub');
13713				if ($a.attr('href').charAt(0) !== '#' && $sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) {
13714					$a.dataSM('href', $a.attr('href'));
13715					$a.attr('href', '#');
13716				}
13717			},
13718			menuFixLayout: function($ul) {
13719				// fixes a menu that is being shown for the first time
13720				if (!$ul.dataSM('shown-before')) {
13721					$ul.hide().dataSM('shown-before', true);
13722					// fix the layout of the items in IE<8
13723					if (IElt8) {
13724						$ul.children().css({ styleFloat: 'left', width: '100%' });
13725					}
13726				}
13727			},
13728			menuHide: function($sub) {
13729				if (this.$root.triggerHandler('beforehide.smapi', $sub[0]) === false) {
13730					return;
13731				}
13732				$sub.stop(true, true);
13733				if ($sub.is(':visible')) {
13734					var complete = function() {
13735						// unset z-index
13736						if (IElt9) {
13737							$sub.parent().css('z-index', '');
13738						} else {
13739							$sub.css('z-index', '');
13740						}
13741					};
13742					// if sub is collapsible (mobile view)
13743					if (this.isCollapsible()) {
13744						if (this.opts.collapsibleHideFunction) {
13745							this.opts.collapsibleHideFunction.call(this, $sub, complete);
13746						} else {
13747							$sub.hide(this.opts.collapsibleHideDuration, complete);
13748						}
13749					} else {
13750						if (this.opts.hideFunction) {
13751							this.opts.hideFunction.call(this, $sub, complete);
13752						} else {
13753							$sub.hide(this.opts.hideDuration, complete);
13754						}
13755					}
13756					// remove IE iframe shim
13757					if ($sub.dataSM('ie-shim')) {
13758						$sub.dataSM('ie-shim').remove();
13759					}
13760					// deactivate scrolling if it is activated for this sub
13761					if ($sub.dataSM('scroll')) {
13762						$sub.unbind('.smartmenus_scroll').removeDataSM('scroll').dataSM('scroll-arrows').hide();
13763					}
13764					// unhighlight parent item
13765					$sub.dataSM('parent-a').removeClass('highlighted');
13766					var level = $sub.dataSM('level');
13767					this.activatedItems.splice(level - 1, 1);
13768					this.visibleSubMenus.splice(level - 1, 1);
13769					this.$root.triggerHandler('hide.smapi', $sub[0]);
13770				}
13771			},
13772			menuHideAll: function($item) {
13773				if ($item != undefined && $item.parent().hasClass('menu-item') && !$item.parent().hasClass('menu-item-has-children')) return;
13774				var $win = $(window),
13775					winW = $win.width();
13776				if (this.showTimeout) {
13777					clearTimeout(this.showTimeout);
13778					this.showTimeout = 0;
13779				}
13780				// hide all subs
13781				for (var i = this.visibleSubMenus.length - 1; i > 0; i--) {
13782					if ( this.visibleSubMenus[i].closest('.smartmenu-open-item').length ) {
13783						if ( $item != undefined && $item.closest('.smartmenu-open-item').length ) {
13784							this.menuHide(this.visibleSubMenus[i]);
13785							$(this.visibleSubMenus[i]).closest('.smartmenu-open-item').removeClass('smartmenu-open-item');
13786						} else {
13787							return;
13788						}
13789					} else {
13790						//if ( !this.visibleSubMenus[i].closest('.menu-accordion').length ) {
13791							this.menuHide(this.visibleSubMenus[i]);
13792						//}
13793					}
13794				}
13795				// hide root if it's popup
13796				if (this.opts.isPopup) {
13797					this.$root.stop(true, true);
13798					if (this.$root.is(':visible')) {
13799						if (this.opts.hideFunction) {
13800							this.opts.hideFunction.call(this, this.$root);
13801						} else {
13802							this.$root.hide(this.opts.hideDuration);
13803						}
13804						// remove IE iframe shim
13805						if (this.$root.dataSM('ie-shim')) {
13806							this.$root.dataSM('ie-shim').remove();
13807						}
13808					}
13809				}
13810				this.activatedItems = [];
13811				this.visibleSubMenus = [];
13812				this.clickActivated = false;
13813				// reset z-index increment
13814				this.zIndexInc = 0;
13815			},
13816			menuIframeShim: function($ul) {
13817				// create iframe shim for the menu
13818				if (IE && this.opts.overlapControlsInIE && !$ul.dataSM('ie-shim')) {
13819					$ul.dataSM('ie-shim', $('<iframe/>').attr({ src: 'javascript:0', tabindex: -9 })
13820						.css({ position: 'absolute', top: 'auto', left: '0', opacity: 0, border: '0' })
13821					);
13822				}
13823			},
13824			menuInit: function($ul) {
13825				if (!$ul.dataSM('in-mega')) {
13826					this.subMenus.push($ul);
13827					// mark UL's in mega drop downs (if any) so we can neglect them
13828					if ($ul.hasClass('mega-menu')) {
13829						$ul.find('ul').dataSM('in-mega', true);
13830					}
13831					// get level (much faster than, for example, using parentsUntil)
13832					var level = 2,
13833						par = $ul[0];
13834					while (par != null && par.parentNode != null && ( par = par.parentNode.parentNode) != this.$root[0]) {
13835						level++;
13836					}
13837					// cache stuff
13838					$ul.dataSM('parent-a', $ul.prevAll('a').eq(-1))
13839						.dataSM('level', level)
13840						.parent().dataSM('sub', $ul);
13841					// add sub indicator to parent item
13842					if (this.opts.subIndicators) {
13843						$ul.dataSM('parent-a').addClass('has-submenu')[this.opts.subIndicatorsPos](this.$subArrow.clone());
13844					}
13845				}
13846			},
13847			menuPosition: function($sub) {
13848				var fixIE = $('html.ie').length;
13849				// if (fixIE) {
13850				// 	var $rowParent = $($sub).closest('.main-menu-container');
13851				// 	$rowParent.height($rowParent.height());
13852				// }
13853				var $a = $sub.dataSM('parent-a'),
13854					$li = $sub.parent(),
13855					$ul = $sub.parent().parent(),
13856					// $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'),
13857					$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'),
13858					level = $sub.dataSM('level'),
13859					subW = this.getWidth($sub),
13860					subH = this.getHeight($sub),
13861					itemOffset = $a.offset(),
13862					itemX = itemOffset.left,
13863					itemY = itemOffset.top,
13864					itemW = this.getWidth($a),
13865					itemH = this.getHeight($a),
13866					$win = $(window),
13867					winX = $win.scrollLeft(),
13868					winY = $win.scrollTop(),
13869					winW = $win.width(),
13870					winH = $win.height(),
13871					containerW = $container.width(),
13872					containerOffsetX = containerW + ((winW - containerW) / 2),
13873					horizontalParent = $ul.hasClass('sm') && !$ul.hasClass('sm-vertical'),
13874					subOffsetX = level == 2 ? this.opts.mainMenuSubOffsetX : this.opts.subMenusSubOffsetX,
13875					subOffsetY = level == 2 ? this.opts.mainMenuSubOffsetY : this.opts.subMenusSubOffsetY,
13876					x, y, leftPos;
13877
13878				if (horizontalParent) {
13879					x = this.opts.rightToLeftSubMenus ? itemW - subW - subOffsetX : subOffsetX;
13880					y = this.opts.bottomToTopSubMenus ? -subH - subOffsetY : itemH + subOffsetY;
13881				} else {
13882					x = this.opts.rightToLeftSubMenus ? subOffsetX - subW : subW - subOffsetX;
13883					y = this.opts.bottomToTopSubMenus ? itemH - subOffsetY - subH : subOffsetY;
13884				}
13885				if (this.opts.keepInViewport && !this.isCollapsible()) {
13886					if (this.isFixed()) {
13887						itemX -= winX;
13888						itemY -= winY;
13889						winX = winY = 0;
13890					}
13891					var absX = itemX + x,
13892						absY = itemY + y;
13893					if (this.opts.rightToLeftSubMenus && absX < winX) {
13894						x = horizontalParent ? winX - absX + x : itemW - subOffsetX;
13895					} else if (!this.opts.rightToLeftSubMenus && absX + subW > winX + containerOffsetX ) {
13896						x = horizontalParent ? winX + containerOffsetX - subW - absX + x : subOffsetX - subW;
13897					}
13898					if (!horizontalParent) {
13899						if (subH < winH && absY + subH > winY + winH) {
13900							y += winY + winH - subH - absY;
13901						} else if (subH >= winH || absY < winY) {
13902							y += winY - absY;
13903						}
13904					}
13905					// do we need scrolling?
13906					// 0.49 added for the sake of IE9/FF4+ where we might be dealing with float numbers for "subH"
13907					if (mouse && (horizontalParent && (absY + subH > winY + winH + 0.49 || absY < winY) || !horizontalParent && subH > winH + 0.49)) {
13908						var self = this;
13909						if (!$sub.dataSM('scroll-arrows')) {
13910							$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]])
13911								.bind({
13912									mouseenter: function() { self.menuScroll($sub, $(this).hasClass('scroll-up')); },
13913									mouseleave: function(e) {
13914										self.menuScrollStop($sub);
13915										self.menuScrollOut($sub, e);
13916									},
13917									'mousewheel DOMMouseScroll': function(e) { e.preventDefault(); }
13918								})
13919								.insertAfter($sub)
13920							);
13921						}
13922						// bind events to show/hide arrows on hover and save scrolling data for this sub
13923						var vportY = winY - (itemY + itemH);
13924						$sub.dataSM('scroll', {
13925								vportY: vportY,
13926								subH: subH,
13927								winH: winH,
13928								step: 1
13929							})
13930							.bind({
13931								'mouseover.smartmenus_scroll': function(e) { self.menuScrollOver($sub, e); },
13932								'mouseout.smartmenus_scroll': function(e) { self.menuScrollOut($sub, e); },
13933								'mousewheel.smartmenus_scroll DOMMouseScroll.smartmenus_scroll': function(e) { self.menuScrollMousewheel($sub, e); }
13934							})
13935							.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
13935StartZIndex() + this.zIndexInc })
13936							.eq(0).css('margin-top', vportY).end()
13937							.eq(1).css('margin-top', vportY + winH - this.getHeight($sub.dataSM('scroll-arrows').eq(1))).end()
13938							.eq(horizontalParent && this.opts.bottomToTopSubMenus ? 0 : 1).show();
13939					}
13940				}
13941				if ( !$sub.closest('.menu-accordion').length ) {
13942					var rightPos = 'auto';
13943					if ( $sub.closest('.grid-filters').length ) {
13944						if ( $sub.closest('.text-right').length ) {
13945							leftPos = '0px';
13946							rightPos = 'auto';
13947						} else {
13948							leftPos = 'auto';
13949							rightPos = '0px';
13950						}
13951						x = 0;
13952					} else {
13953						if ( $sub.hasClass('mega-menu-inner') ) {
13954							$sub.css({ width: containerW});
13955							leftPos = -1 * (parseFloat($sub.closest('ul.menu-smart').offset().left) - parseFloat($sub.closest('.row-menu').offset().left));
13956							if ( ! $('body').hasClass('megamenu-side-to-side') ) {
13957								leftPos += parseFloat($sub.closest('.row-menu-inner').css('paddingLeft'));
13958							}
13959							x = 0;
13960						} else {
13961							leftPos = (level > 2 ? $li.position().left - parseFloat($li.closest('ul').css('paddingLeft')) : $li.position().left ) + 'px';
13962							x = (level > 2 && x >= 0) ? x + 1 : x - 1;
13963						}
13964					}
13965				}
13966
13967				// $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) });
13968				$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) });
13969				// IE iframe shim
13970				this.menuIframeShim($sub);
13971				if ($sub.dataSM('ie-shim')) {
13972					$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) });
13973				}
13974			},
13975			menuScroll: function($sub, up, wheel) {
13976				var y = parseFloat($sub.css('margin-top')),
13977					scroll = $sub.dataSM('scroll'),
13978					navH = $('.navbar-main').outerHeight(),
13979					end = scroll.vportY + (up ? navH + 54 : scroll.winH - scroll.subH),
13980					step = wheel || !this.opts.scrollAccelerate ? this.opts.scrollStep : Math.floor($sub.dataSM('scroll').step);
13981				$sub.add($sub.dataSM('ie-shim')).css('margin-top', Math.abs(end - y) > step ? y + (up ? step : -step) : end);
13982				y = parseFloat($sub.css('margin-top'));
13983				// show opposite arrow if appropriate
13984				if (up && y + scroll.subH > scroll.vportY + scroll.winH || !up && y < scroll.vportY) {
13985					$sub.dataSM('scroll-arrows').eq(up ? 1 : 0).show();
13986				}
13987				// accelerate when not using mousewheel to scroll
13988				if (!wheel && this.opts.scrollAccelerate && $sub.dataSM('scroll').step < this.opts.scrollStep) {
13989					$sub.dataSM('scroll').step += 0.5;
13990				}
13991				// "y" and "end" might be float numbers in IE9/FF4+ so this weird way to check is used
13992				if (Math.abs(y - end) < 1) {
13993					$sub.dataSM('scroll-arrows').eq(up ? 0 : 1).hide();
13994					$sub.dataSM('scroll').step = 1;
13995				} else if (!wheel) {
13996					var self = this;
13997					this.scrollTimeout = setTimeout(function() { self.menuScroll($sub, up); }, this.opts.scrollInterval);
13998				}
13999			},
14000			menuScrollMousewheel: function($sub, e) {
14001				var $closestSub = $(e.target).closest('ul');
14002				while ($closestSub.dataSM('in-mega')) {
14003					$closestSub = $closestSub.parent().closest('ul');
14004				}
14005				if ($closestSub[0] == $sub[0]) {
14006					var up = (e.originalEvent.wheelDelta || -e.originalEvent.detail) > 0;
14007					if ($sub.dataSM('scroll-arrows').eq(up ? 0 : 1).is(':visible')) {
14008						this.menuScroll($sub, up, true);
14009					}
14010				}
14011				if ( ! $sub.hasClass('mega-menu-inner') ) {
14012					e.preventDefault();
14013				}
14014			},
14015			menuScrollOut: function($sub, e) {
14016				var reClass = /^scroll-(up|down)/,
14017					$closestSub = $(e.relatedTarget).closest('ul');
14018				while ($closestSub.dataSM('in-mega')) {
14019					$closestSub = $closestSub.parent().closest('ul');
14020				}
14021				if (!reClass.test((e.relatedTarget || '').className) && ($sub[0] != e.relatedTarget && !$.contains($sub[0], e.relatedTarget) || $closestSub[0] != $sub[0])) {
14022					$sub.dataSM('scroll-arrows').css('visibility', 'hidden');
14023				}
14024			},
14025			menuScrollOver: function($sub, e) {
14026				var reClass = /^scroll-(up|down)/,
14027					$closestSub = $(e.target).closest('ul');
14028				while ($closestSub.dataSM('in-mega')) {
14029					$closestSub = $closestSub.parent().closest('ul');
14030				}
14031				if (!reClass.test(e.target.className) && $closestSub[0] == $sub[0]) {
14032					$sub.dataSM('scroll-arrows').css('visibility', 'visible');
14033				}
14034			},
14035			menuScrollStop: function($sub) {
14036				if (this.scrollTimeout) {
14037					clearTimeout(this.scrollTimeout);
14038					this.scrollTimeout = 0;
14039					$sub.dataSM('scroll').step = 1;
14040				}
14041			},
14042			menuShow: function($sub) {
14043				if (!$sub.dataSM('beforefirstshowfired')) {
14044					$sub.dataSM('beforefirstshowfired', true);
14045					if (this.$root.triggerHandler('beforefirstshow.smapi', $sub[0]) === false) {
14046						return;
14047					}
14048				}
14049				if (this.$root.triggerHandler('beforeshow.smapi', $sub[0]) === false) {
14050					return;
14051				}
14052				this.menuFixLayout($sub);
14053				$sub.stop(true, true);
14054				if (!$sub.is(':visible')) {
14055					$sub.css({
14056						'visibility': 'visible',
14057						'pointer-events': 'auto',
14058					});
14059					// set z-index - for IE < 9 set it to the parent LI
14060					var zIndex = this.getStartZIndex() + (++this.zIndexInc);
14061					if (IElt9) {
14062						$sub.parent().css('z-index', zIndex);
14063					} else {
14064						$sub.css('z-index', zIndex);
14065					}
14066					// highlight parent item
14067					if (this.opts.keepHighlighted || this.isCollapsible()) {
14068						if ($sub.dataSM('parent-a').attr('data-type') != 'title')
14069							$sub.dataSM('parent-a').addClass('highlighted');
14070					}
14071					// min/max-width fix - no way to rely purely on CSS as all UL's are nested
14072					if (this.opts.subMenusMinWidth || this.opts.subMenusMaxWidth) {
14073						if (!IElt8) {
14074							$sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap');
14075							if (this.opts.subMenusMinWidth) {
14076							 	$sub.css('min-width', this.opts.subMenusMinWidth);
14077							}
14078							if (this.opts.subMenusMaxWidth) {
14079							 	var noMaxWidth = this.getWidth($sub);
14080							 	if ( ! $sub.hasClass('mega-menu-inner') ) {
14081								 	$sub.css('max-width', this.opts.subMenusMaxWidth);
14082							 	}
14083								if (noMaxWidth > this.getWidth($sub)) {
14084									$sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth);
14085								}
14086							}
14087						// IE6,7
14088 						} else {
14089							$sub.children().css('styleFloat', 'none');
14090							if (IE6) {
14091								$sub.width(this.opts.subMenusMinWidth ? this.opts.subMenusMinWidth : 1)
14092									.children().children('a').css('white-space', 'nowrap');
14093							} else { // IE7
14094								$sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap');
14095								if (this.opts.subMenusMinWidth) {
14096									$sub.css('min-width', this.opts.subMenusMinWidth);
14097								}
14098							}
14099							if (this.opts.subMenusMaxWidth) {
14100								var noMaxWidth = $sub.width();
14101								if (IE6) {
14102							 		var maxWidth = $sub.css({ width: this.opts.subMenusMaxWidth, overflowX: 'hidden', overflowY: 'hidden' }).width();
14103									if (noMaxWidth > maxWidth) {
14104										$sub.css({ width: maxWidth, overflowX: 'visible', overflowY: 'visible' }).children().children('a').css('white-space', '');
14105									} else {
14106										$sub.css({ width: noMaxWidth, overflowX: 'visible', overflowY: 'visible' });
14107									}
14108								} else { // IE7
14109								 	if ( ! $sub.hasClass('mega-menu-inner') ) {
14110									 	$sub.css('max-width', this.opts.subMenusMaxWidth);
14111								 	}
14112									if (noMaxWidth > $sub.width()) {
14113										$sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth);
14114									} else {
14115										$sub.width(noMaxWidth);
14116									}
14117								}
14118							} else {
14119							 	$sub.width($sub.width());
14120							}
14121							$sub.children().css('styleFloat', 'left');
14122						}
14123					}
14124					if ( $sub.hasClass('mega-menu-inner') && $('body').hasClass('scrollable-megamenu') && UNCODE.wwidth > UNCODE.mediaQuery ) {
14125						var $nav = $('.navbar-main'),
14126							navH = 0,
14127							navTop = 0,
14128							$vmenu = $('body.vmenu .vmenu-container, body.menu-overlay .vmenu-container, body.menu-offcanvas .vmenu-container');
14129						if ( $nav.length && typeof $nav[0] !== 'undefined' ) {
14130							var navRect = $nav[0].getBoundingClientRect();
14131							navH = navRect.height;
14132							navTop = navRect.top;
14133						}
14134						if ( ! $vmenu.length ) {
14135							$sub.css({ maxHeight: UNCODE.wheight - navH });
14136						}
14137					}
14138					this.menuPosition($sub);
14139					// insert IE iframe shim
14140					if ($sub.dataSM('ie-shim')) {
14141						$sub.dataSM('ie-shim').insertBefore($sub);
14142					}
14143					var complete = function() {
14144						// fix: "overflow: hidden;" is not reset on animation complete in jQuery < 1.9.0 in Chrome when global "box-sizing: border-box;" is used
14145						$sub.css('overflow', '');
14146					};
14147					// if sub is collapsible (mobile view)
14148					if (this.isCollapsible()) {
14149						if (this.opts.collapsibleShowFunction) {
14150							this.opts.collapsibleShowFunction.call(this, $sub, complete);
14151						} else {
14152							$sub.show(this.opts.collapsibleShowDuration, complete);
14153						}
14154					} else {
14155						if (this.opts.showFunction) {
14156							this.opts.showFunction.call(this, $sub, complete);
14157						} else {
14158							$sub.show(this.opts.showDuration, complete);
14159						}
14160					}
14161					// save new sub menu for this level
14162					this.visibleSubMenus[$sub.dataSM('level') - 1] = $sub;
14163					this.$root.triggerHandler('show.smapi', $sub[0]);
14164				}
14165			},
14166			popupHide: function(noHideTimeout) {
14167				if (this.hideTimeout) {
14168					clearTimeout(this.hideTimeout);
14169					this.hideTimeout = 0;
14170				}
14171				var self = this;
14172				this.hideTimeout = setTimeout(function() {
14173					self.menuHideAll();
14174				}, noHideTimeout ? 1 : this.opts.hideTimeout);
14175			},
14176			popupShow: function(left, top) {
14177				if (!this.opts.isPopup) {
14178					alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.');
14179					return;
14180				}
14181				if (this.hideTimeout) {
14182					clearTimeout(this.hideTimeout);
14183					this.hideTimeout = 0;
14184				}
14185				this.menuFixLayout(this.$root);
14186				this.$root.stop(true, true);
14187				if (!this.$root.is(':visible')) {
14188					this.$root.css({ left: left, top: top });
14189					// IE iframe shim
14190					this.menuIframeShim(this.$root);
14191					if (this.$root.dataSM('ie-shim')) {
14192						this.$root.dataSM('ie-shim').css({ zIndex: this.$root.css('z-index'), width: this.getWidth(this.$root), height: this.getHeight(this.$root), left
14192: left, top: top }).insertBefore(this.$root);
14193					}
14194					// show menu
14195					if (this.opts.showFunction) {
14196						this.opts.showFunction.call(this, this.$root);
14197					} else {
14198						this.$root.show(this.opts.showDuration);
14199					}
14200					this.visibleSubMenus[0] = this.$root;
14201				}
14202			},
14203			refresh: function() {
14204				this.menuHideAll();
14205				this.$root.find('ul').each(function() {
14206						var $this = $(this);
14207						if ($this.dataSM('scroll-arrows')) {
14208							$this.dataSM('scroll-arrows').remove();
14209						}
14210					})
14211					.removeDataSM('in-mega')
14212					.removeDataSM('shown-before')
14213					.removeDataSM('ie-shim')
14214					.removeDataSM('scroll-arrows')
14215					.removeDataSM('parent-a')
14216					.removeDataSM('level')
14217					.removeDataSM('beforefirstshowfired');
14218				this.$root.find('a.has-submenu').removeClass('has-submenu')
14219					.parent().removeDataSM('sub');
14220				if (this.opts.subIndicators) {
14221					this.$root.find('span.sub-arrow').remove();
14222				}
14223				if (this.opts.markCurrentItem) {
14224					this.$root.find('a.current').removeClass('current');
14225				}
14226				this.subMenus = [];
14227				this.init(true);
14228			},
14229			rootOut: function(e) {
14230				if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) {
14231					return;
14232				}
14233				if (this.hideTimeout) {
14234					clearTimeout(this.hideTimeout);
14235					this.hideTimeout = 0;
14236				}
14237				if (!this.opts.showOnClick || !this.opts.hideOnClick) {
14238					var self = this;
14239					this.hideTimeout = setTimeout(function() { self.menuHideAll(); }, this.opts.hideTimeout);
14240				}
14241			},
14242			rootOver: function(e) {
14243				if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) {
14244					return;
14245				}
14246				if (this.hideTimeout) {
14247					clearTimeout(this.hideTimeout);
14248					this.hideTimeout = 0;
14249				}
14250			},
14251			winResize: function(e) {
14252				if (!this.handleEvents()) {
14253					// we still need to resize the disable overlay if it's visible
14254					if (this.$disableOverlay) {
14255						var pos = this.$root.offset();
14256	 					this.$disableOverlay.css({
14257							top: pos.top,
14258							left: pos.left,
14259							width: this.$root.outerWidth(),
14260							height: this.$root.outerHeight()
14261						});
14262					}
14263					return;
14264				}
14265				// hide sub menus on resize - on mobile do it only on orientation change
14266				if (!this.isCollapsible() && (!('onorientationchange' in window) || e.type == 'orientationchange')) {
14267					if (this.activatedItems.length) {
14268						this.activatedItems[this.activatedItems.length - 1][0].blur();
14269					}
14270					this.menuHideAll();
14271				}
14272			}
14273		}
14274	});
14275
14276	$.fn.dataSM = function(key, val) {
14277		if (val) {
14278			return this.data(key + '_smartmenus', val);
14279		}
14280		return this.data(key + '_smartmenus');
14281	}
14282
14283	$.fn.removeDataSM = function(key) {
14284		return this.removeData(key + '_smartmenus');
14285	}
14286
14287	$.fn.smartmenus = function(options) {
14288		if (typeof options == 'string') {
14289			var args = arguments,
14290				method = options;
14291			Array.prototype.shift.call(args);
14292			return this.each(function() {
14293				var smartmenus = $(this).data('smartmenus');
14294				if (smartmenus && smartmenus[method]) {
14295					smartmenus[method].apply(smartmenus, args);
14296				}
14297			});
14298		}
14299		var opts = $.extend({}, $.fn.smartmenus.defaults, options);
14300		return this.each(function() {
14301			new $.SmartMenus(this, opts);
14302		});
14303	}
14304
14305	// default settings
14306	$.fn.smartmenus.defaults = {
14307		isPopup:		false,		// is this a popup menu (can be shown via the popupShow/popupHide methods) or a permanent menu bar
14308		mainMenuSubOffsetX:	0,		// pixels offset from default position
14309		mainMenuSubOffsetY:	0,		// pixels offset from default position
14310		subMenusSubOffsetX:	0,		// pixels offset from default position
14311		subMenusSubOffsetY:	0,		// pixels offset from default position
14312		subMenusMinWidth:	false, //'10em',		// min-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored
14313		subMenusMaxWidth:	false, //'20em',		// max-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored
14314		subIndicators: 		true,		// create sub menu indicators - creates a SPAN and inserts it in the A
14315		subIndicatorsPos: 	'prepend',	// position of the SPAN relative to the menu item content ('prepend', 'append')
14316		subIndicatorsText:	'+',		// [optionally] add text in the SPAN (e.g. '+') (you may want to check the CSS for the sub indicators too)
14317		scrollStep: 		30,		// pixels step when scrolling long sub menus that do not fit in the viewport height
14318		scrollInterval:		30,		// interval between each scrolling step
14319		scrollAccelerate:	true,		// accelerate scrolling or use a fixed step
14320		showTimeout:		250,		// timeout before showing the sub menus
14321		hideTimeout:		500,		// timeout before hiding the sub menus
14322		showDuration:		0,		// duration for show animation - set to 0 for no animation - matters only if showFunction:null
14323		showFunction:		null,		// custom function to use when showing a sub menu (the default is the jQuery 'show')
14324							// don't forget to call complete() at the end of whatever you do
14325							// e.g.: function($ul, complete) { $ul.fadeIn(250, complete); }
14326		hideDuration:		0,		// duration for hide animation - set to 0 for no animation - matters only if hideFunction:null
14327		hideFunction:		function($ul, complete) { $ul.fadeOut(200, complete); },	// custom function to use when hiding a sub menu (the default is the jQuery 'hide')
14328							// don't forget to call complete() at the end of whatever you do
14329							// e.g.: function($ul, complete) { $ul.fadeOut(250, complete); }
14330		collapsibleShowDuration:0,		// duration for show animation for collapsible sub menus - matters only if collapsibleShowFunction:null
14331		collapsibleShowFunction:function($ul, complete) { $ul.slideDown(200, complete); },	// custom function to use when showing a collapsible sub menu
14332							// (i.e. when mobile styles are used to make the sub menus collapsible)
14333		collapsibleHideDuration:0,		// duration for hide animation for collapsible sub menus - matters only if collapsibleHideFunction:null
14334		collapsibleHideFunction:function($ul, complete) { $ul.slideUp(200, complete); },	// custom function to use when hiding a collapsible sub menu
14335							// (i.e. when mobile styles are used to make the sub menus collapsible)
14336		showOnClick:		false,		// show the first-level sub menus onclick instead of onmouseover (matters only for mouse input)
14337		hideOnClick:		true,		// hide the sub menus on click/tap anywhere on the page
14338		keepInViewport:		true,		// reposition the sub menus if needed to make sure they always appear inside the viewport
14339		keepHighlighted:	true,		// keep all ancestor items of the current sub menu highlighted (adds the 'highlighted' class to the A's)
14340		markCurrentItem:	false,		// automatically add the 'current' class to the A element of the item linking to the current URL
14341		markCurrentTree:	true,		// add the 'current' class also to the A elements of all ancestor items of the current item
14342		rightToLeftSubMenus:	false,		// right to left display of the sub menus (check the CSS for the sub indicators' position)
14343		bottomToTopSubMenus:	false,		// bottom to top display of the sub menus
14344		overlapControlsInIE:	true		// make sure sub menus appear on top of special OS controls in IE (i.e. SELECT, OBJECT, EMBED, etc.)
14345	};
14346
14347})(jQuery);
14348/*
14349 * jQuery Easing v1.4.1 - http://gsgd.co.uk/sandbox/jquery/easing/
14350 * Open source under the BSD License.
14351 * Copyright © 2008 George McGinley Smith
14352 * All rights reserved.
14353 * https://raw.github.com/gdsmith/jquery.easing/master/LICENSE
14354*/
14355
14356/* globals jQuery, define, module, require */
14357(function (factory) {
14358	if (typeof define === "function" && define.amd) {
14359		define(['jquery'], function ($) {
14360			return factory($);
14361		});
14362	} else if (typeof module === "object" && typeof module.exports === "object") {
14363		module.exports = factory(require('jquery'));
14364	} else {
14365		factory(jQuery);
14366	}
14367})(function($){
14368
14369	// Preserve the original jQuery "swing" easing as "jswing"
14370	if (typeof $.easing !== 'undefined') {
14371		$.easing['jswing'] = $.easing['swing'];
14372	}
14373
14374	var pow = Math.pow,
14375		sqrt = Math.sqrt,
14376		sin = Math.sin,
14377		cos = Math.cos,
14378		PI = Math.PI,
14379		c1 = 1.70158,
14380		c2 = c1 * 1.525,
14381		c3 = c1 + 1,
14382		c4 = ( 2 * PI ) / 3,
14383		c5 = ( 2 * PI ) / 4.5;
14384
14385	// x is the fraction of animation progress, in the range 0..1
14386	function bounceOut(x) {
14387		var n1 = 7.5625,
14388			d1 = 2.75;
14389		if ( x < 1/d1 ) {
14390			return n1*x*x;
14391		} else if ( x < 2/d1 ) {
14392			return n1*(x-=(1.5/d1))*x + .75;
14393		} else if ( x < 2.5/d1 ) {
14394			return n1*(x-=(2.25/d1))*x + .9375;
14395		} else {
14396			return n1*(x-=(2.625/d1))*x + .984375;
14397		}
14398	}
14399
14400	$.extend( $.easing, {
14401		def: 'easeOutQuad',
14402		swing: function (x) {
14403			return $.easing[$.easing.def](x);
14404		},
14405		easeInQuad: function (x) {
14406			return x * x;
14407		},
14408		easeOutQuad: function (x) {
14409			return 1 - ( 1 - x ) * ( 1 - x );
14410		},
14411		easeInOutQuad: function (x) {
14412			return x < 0.5 ?
14413				2 * x * x :
14414				1 - pow( -2 * x + 2, 2 ) / 2;
14415		},
14416		easeInCubic: function (x) {
14417			return x * x * x;
14418		},
14419		easeOutCubic: function (x) {
14420			return 1 - pow( 1 - x, 3 );
14421		},
14422		easeInOutCubic: function (x) {
14423			return x < 0.5 ?
14424				4 * x * x * x :
14425				1 - pow( -2 * x + 2, 3 ) / 2;
14426		},
14427		easeInQuart: function (x) {
14428			return x * x * x * x;
14429		},
14430		easeOutQuart: function (x) {
14431			return 1 - pow( 1 - x, 4 );
14432		},
14433		easeInOutQuart: function (x) {
14434			return x < 0.5 ?
14435				8 * x * x * x * x :
14436				1 - pow( -2 * x + 2, 4 ) / 2;
14437		},
14438		easeInQuint: function (x) {
14439			return x * x * x * x * x;
14440		},
14441		easeOutQuint: function (x) {
14442			return 1 - pow( 1 - x, 5 );
14443		},
14444		easeInOutQuint: function (x) {
14445			return x < 0.5 ?
14446				16 * x * x * x * x * x :
14447				1 - pow( -2 * x + 2, 5 ) / 2;
14448		},
14449		easeInSine: function (x) {
14450			return 1 - cos( x * PI/2 );
14451		},
14452		easeOutSine: function (x) {
14453			return sin( x * PI/2 );
14454		},
14455		easeInOutSine: function (x) {
14456			return -( cos( PI * x ) - 1 ) / 2;
14457		},
14458		easeInExpo: function (x) {
14459			return x === 0 ? 0 : pow( 2, 10 * x - 10 );
14460		},
14461		easeOutExpo: function (x) {
14462			return x === 1 ? 1 : 1 - pow( 2, -10 * x );
14463		},
14464		easeInOutExpo: function (x) {
14465			return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ?
14466				pow( 2, 20 * x - 10 ) / 2 :
14467				( 2 - pow( 2, -20 * x + 10 ) ) / 2;
14468		},
14469		easeInCirc: function (x) {
14470			return 1 - sqrt( 1 - pow( x, 2 ) );
14471		},
14472		easeOutCirc: function (x) {
14473			return sqrt( 1 - pow( x - 1, 2 ) );
14474		},
14475		easeInOutCirc: function (x) {
14476			return x < 0.5 ?
14477				( 1 - sqrt( 1 - pow( 2 * x, 2 ) ) ) / 2 :
14478				( sqrt( 1 - pow( -2 * x + 2, 2 ) ) + 1 ) / 2;
14479		},
14480		easeInElastic: function (x) {
14481			return x === 0 ? 0 : x === 1 ? 1 :
14482				-pow( 2, 10 * x - 10 ) * sin( ( x * 10 - 10.75 ) * c4 );
14483		},
14484		easeOutElastic: function (x) {
14485			return x === 0 ? 0 : x === 1 ? 1 :
14486				pow( 2, -10 * x ) * sin( ( x * 10 - 0.75 ) * c4 ) + 1;
14487		},
14488		easeInOutElastic: function (x) {
14489			return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ?
14490				-( pow( 2, 20 * x - 10 ) * sin( ( 20 * x - 11.125 ) * c5 )) / 2 :
14491				pow( 2, -20 * x + 10 ) * sin( ( 20 * x - 11.125 ) * c5 ) / 2 + 1;
14492		},
14493		easeInBack: function (x) {
14494			return c3 * x * x * x - c1 * x * x;
14495		},
14496		easeOutBack: function (x) {
14497			return 1 + c3 * pow( x - 1, 3 ) + c1 * pow( x - 1, 2 );
14498		},
14499		easeInOutBack: function (x) {
14500			return x < 0.5 ?
14501				( pow( 2 * x, 2 ) * ( ( c2 + 1 ) * 2 * x - c2 ) ) / 2 :
14502				( pow( 2 * x - 2, 2 ) *( ( c2 + 1 ) * ( x * 2 - 2 ) + c2 ) + 2 ) / 2;
14503		},
14504		easeInBounce: function (x) {
14505			return 1 - bounceOut( 1 - x );
14506		},
14507		easeOutBounce: bounceOut,
14508		easeInOutBounce: function (x) {
14509			return x < 0.5 ?
14510				( 1 - bounceOut( 1 - 2 * x ) ) / 2 :
14511				( 1 + bounceOut( 2 * x - 1 ) ) / 2;
14512		}
14513	});
14514	return $;
14515});
14516
14517/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net)
14518 * Licensed under the MIT License (LICENSE.txt).
14519 *
14520 * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
14521 * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
14522 * Thanks to: Seamus Leahy for adding deltaX and deltaY
14523 *
14524 * Version: 3.0.6
14525 *
14526 * Requires: 1.2.2+
14527 */
14528(function($) {
14529    var types = ['DOMMouseScroll', 'mousewheel'];
14530    if ($.event.fixHooks) {
14531        for (var i = types.length; i;) {
14532            $.event.fixHooks[types[--i]] = $.event.mouseHooks;
14533        }
14534    }
14535    $.event.special.mousewheel = {
14536        setup: function() {
14537            if (this.addEventListener) {
14538                for (var i = types.length; i;) {
14539                    this.addEventListener(types[--i], handler, false);
14540                }
14541            } else {
14542                this.onmousewheel = handler;
14543            }
14544        },
14545        teardown: function() {
14546            if (this.removeEventListener) {
14547                for (var i = types.length; i;) {
14548                    this.removeEventListener(types[--i], handler, false);
14549                }
14550            } else {
14551                this.onmousewheel = null;
14552            }
14553        }
14554    };
14555    $.fn.extend({
14556        mousewheel: function(fn) {
14557            return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");
14558        },
14559        unmousewheel: function(fn) {
14560            return this.unbind("mousewheel", fn);
14561        }
14562    });
14563
14564    function handler(event) {
14565        var orgEvent = event || window.event,
14566            args = [].slice.call(arguments, 1),
14567            delta = 0,
14568            returnValue = true,
14569            deltaX = 0,
14570            deltaY = 0;
14571        event = $.event.fix(orgEvent);
14572        event.type = "mousewheel";
14573        // Old school scrollwheel delta
14574        if (orgEvent.wheelDelta) {
14575            delta = orgEvent.wheelDelta / 120;
14576        }
14577        if (orgEvent.detail) {
14578            delta = -orgEvent.detail / 3;
14579        }
14580        // New school multidimensional scroll (touchpads) deltas
14581        deltaY = delta;
14582        // Gecko
14583        if (orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS) {
14584            deltaY = 0;
14585            deltaX = -1 * delta;
14586        }
14587        // Webkit
14588        if (orgEvent.wheelDeltaY !== undefined) {
14589            deltaY = orgEvent.wheelDeltaY / 120;
14590        }
14591        if (orgEvent.wheelDeltaX !== undefined) {
14592            deltaX = -1 * orgEvent.wheelDeltaX / 120;
14593        }
14594        // Add event and delta to the front of the arguments
14595        args.unshift(event, delta, deltaX, deltaY);
14596        return ($.event.dispatch || $.event.handle).apply(this, args);
14597    }
14598})(jQuery);
14599/**
14600 * jQuery iLightBox - Revolutionary Lightbox Plugin
14601 * http://www.ilightbox.net/
14602 *
14603 * @version: 2.2.4 - October 14, 2017
14604 *
14605 * @author: iProDev (Hemn Chawroka)
14606 *          http://www.iprodev.com/
14607 *
14608 */
14609(function($, window, undefined) {
14610
14611	var extensions = {
14612			flash: ['swf'],
14613			image: ['bmp', 'gif', 'jpeg', 'jpg', 'png', 'tiff', 'tif', 'jfif', 'jpe', 'webp'],
14614			iframe: ['asp', 'aspx', 'cgi', 'cfm', 'htm', 'html', 'jsp', 'php', 'pl', 'php3', 'php4', 'php5', 'phtml', 'rb', 'rhtml', 'shtml', 'txt'],
14615			video: ['avi', 'mov', 'mpg', 'mpeg', 'movie', 'mp4', 'webm', 'ogv', 'ogg', '3gp', 'm4v']
14616		},
14617
14618		// Global DOM elements
14619		$win = $(window),
14620		$doc = $(document),
14621
14622		// Support indicators
14623		browser,
14624		transform,
14625		gpuAcceleration,
14626		fullScreenApi = '',
14627		userAgent = navigator.userAgent || navigator.vendor || window.opera,
14628        supportTouch = "ontouchstart" in window || navigator.msMaxTouchPoints || (navigator.maxTouchPoints && navigator.userAgent.indexOf('Windows') > -1),
14629        ishybrid = navigator.maxTouchPoints && navigator.userAgent.indexOf('Windows') > -1,
14630        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)),
14631
14632		// Events
14633		clickEvent = ishybrid ? "itap.iLightBox click.iLightBox" : supportTouch ? "itap.iLightBox" : "click.iLightBox",
14634		touchStartEvent = ishybrid ? "touchstart.iLightBox mousedown.iLightBox" : supportTouch ? "touchstart.iLightBox" : "mousedown.iLightBox",
14635		touchStopEvent = ishybrid ? "touchend.iLightBox mouseup.iLightBox" : supportTouch ? "touchend.iLightBox" : "mouseup.iLightBox",
14636		touchMoveEvent = ishybrid ? "touchmove.iLightBox mousemove.iLightBox" : supportTouch ? "touchmove.iLightBox" : "mousemove.iLightBox",
14637
14638		// Math shorthands
14639		abs = Math.abs,
14640		sqrt = Math.sqrt,
14641		round = Math.round,
14642		max = Math.max,
14643		min = Math.min,
14644		floor = Math.floor,
14645		random = Math.random,
14646
14647		pluginspages = {
14648			quicktime: 'http://www.apple.com/quicktime/download',
14649			flash: 'http://www.adobe.com/go/getflash'
14650		},
14651
14652		iLightBox = function(el, options, items, instant) {
14653			var iL = this;
14654
14655			iL.options = options,
14656				iL.selector = options.selector || el,
14657				iL.context = document,
14658				iL.instant = instant;
14659
14660			if (items.length < 1) iL.attachItems();
14661			else iL.items = items;
14662
14663			iL.vars = {
14664				total: iL.items.length,
14665				start: 0,
14666				current: null,
14667				next: null,
14668				prev: null,
14669				BODY: $('body'),
14670				loadRequests: 0,
14671				overlay: $('<div class="ilightbox-overlay"></div>'),
14672				loader: $('<div class="ilightbox-loader"><div></div></div>'),
14673				toolbar: $('<div class="ilightbox-toolbar"></div>'),
14674				innerToolbar: $('<div class="ilightbox-inner-toolbar"></div>'),
14675				title: $('<div class="ilightbox-title"></div>'),
14676				closeButton: $('<a class="ilightbox-close" title="' + iL.options.text.close + '"></a>'),
14677				fullScreenButton: $('<a class="ilightbox-fullscreen" title="' + iL.options.text.enterFullscreen + '"></a>'),
14678				innerPlayButton: $('<a class="ilightbox-play" title="' + iL.options.text.slideShow + '"></a>'),
14679				innerNextButton: $('<a class="ilightbox-next-button" title="' + iL.options.text.next + '"></a>'),
14680				innerPrevButton: $('<a class="ilightbox-prev-button" title="' + iL.options.text.previous + '"></a>'),
14681				holder: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + '" ondragstart="return false;"><div class="ilightbox-container"></div></div>'),
14682				nextPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-next" ondragstart="return false;"><div class="ilightbox-container"></div></div>'),
14683				prevPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-prev" ondragstart="return false;"><div class="ilightbox-container"></div></div>'),
14684				nextButton: $('<a class="ilightbox-button ilightbox-next-button" ondragstart="return false;" title="' + iL.options.text.next + '"><span></span></a>'),
14685				prevButton: $('<a class="ilightbox-button ilightbox-prev-button" ondragstart="return false;" title="' + iL.options.text.previous + '"><span></span></a>'),
14686				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>'),
14687				thumbs: false,
14688				nextLock: false,
14689				prevLock: false,
14690				hashLock: false,
14691				isMobile: false,
14692				mobileMaxWidth: 980,
14693				isInFullScreen: false,
14694				isSwipe: false,
14695				mouseID: 0,
14696				cycleID: 0,
14697				isPaused: 0,
14698				captionHeight: 39,
14699			};
14700
14701			// Hideable elements with mousemove event
14702			iL.vars.hideableElements = iL.vars.nextButton.add(iL.vars.prevButton);
14703
14704			iL.normalizeItems();
14705
14706			//Check necessary plugins
14707			iL.availPlugins();
14708
14709			//Set startFrom
14710			iL.options.startFrom = (iL.options.startFrom > 0 && iL.options.startFrom >= iL.vars.total) ? iL.vars.total - 1 : iL.options.startFrom;
14711
14712			//If randomStart
14713			iL.options.startFrom = (iL.options.randomStart) ? floor(random() * iL.vars.total) : iL.options.startFrom;
14714			iL.vars.start = iL.options.startFrom;
14715
14716			if (instant) iL.instantCall();
14717			else iL.patchItemsEvents();
14718
14719			if (iL.options.linkId) {
14720				iL.hashChangeHandler();
14721				$win.iLightBoxHashChange(function() {
14722					iL.hashChangeHandler();
14723				});
14724			}
14725
14726			if (supportTouch) {
14727				var RegExp = /(click|mouseenter|mouseleave|mouseover|mouseout)/ig,
14728					replace = "itap";
14729				iL.options.caption.show = iL.options.caption.show.replace(RegExp, replace),
14730					iL.options.caption.hide = iL.options.caption.hide.replace(RegExp, replace),
14731					iL.options.social.show = iL.options.social.show.replace(RegExp, replace),
14732					iL.options.social.hide = iL.options.social.hide.replace(RegExp, replace);
14733			}
14734
14735			if (iL.options.controls.arrows || $(window).width() < UNCODE.mediaQuery) {
14736				$.extend(iL.options.styles, {
14737					nextOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4,
14738					prevOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4,
14739					nextOpacity: 0,
14740					prevOpacity: 0
14741				});
14742			}
14743		};
14744
14745	//iLightBox helpers
14746	iLightBox.prototype = {
14747		showLoader: function() {
14748			var iL = this;
14749			iL.vars.loadRequests += 1;
14750			if (iL.options.path.toLowerCase() == "horizontal") iL.vars.loader.addClass('ilightbox-show').stop().animate({
14751				//top: '-30px'
14752				opacity: '1'
14753			}, iL.options.show.speed, 'easeOutCirc');
14754			else iL.vars.loader.addClass('ilightbox-show').stop().animate({
14755				//left: '-30px'
14756				opacity: '1'
14757			}, iL.options.show.speed, 'easeOutCirc');
14758		},
14759
14760		hideLoader: function() {
14761			var iL = this;
14762			iL.vars.loadRequests -= 1;
14763			iL.vars.loadRequests = (iL.vars.loadRequests < 0) ? 0 : iL.vars.loadRequests;
14764			if (iL.options.path.toLowerCase() == "horizontal") {
14765				if (iL.vars.loadRequests <= 0) iL.vars.loader.removeClass('ilightbox-show').stop().animate({
14766					//top: '-192px'
14767					opacity: '0'
14768				}, iL.options.show.speed, 'easeInCirc');
14769			} else {
14770				if (iL.vars.loadRequests <= 0) iL.vars.loader.removeClass('ilightbox-show').stop().animate({
14771					//left: '-192px'
14772					opacity: '0'
14773				}, iL.options.show.speed, 'easeInCirc');
14774			}
14775		},
14776
14777		createUI: function() {
14778			var iL = this;
14779
14780			iL.ui = {
14781				currentElement: iL.vars.holder,
14782				nextElement: iL.vars.nextPhoto,
14783				prevElement: iL.vars.prevPhoto,
14784				currentItem: iL.vars.current,
14785				nextItem: iL.vars.next,
14786				prevItem: iL.vars.prev,
14787				hide: function() {
14788					iL.closeAction();
14789				},
14790				refresh: function() {
14791					(arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto();
14792				},
14793				fullscreen: function() {
14794					iL.fullScreenAction();
14795				}
14796			};
14797		},
14798
14799		attachItems: function() {
14800			var iL = this,
14801				itemsObject = new Array(),
14802				items = new Array();
14803
14804			$(iL.selector, iL.context).each(function() {
14805				var t = $(this),
14806					URL = t.attr(iL.options.attr) || null,
14807					options = t.data("options") && eval("({" + t.data("options") + "})") || {},
14808					caption = t.data('caption'),
14809					title = t.data('title'),
14810					type = t.data('type') || getTypeByExtension(URL),
14811					clone = t.data('lbox-clone') || false;
14812
14813				//Uncode addition ##START##
14814				if (type === false) {
14815					return;
14816				}
14817				//Uncode addition ##END##
14818
14819				if (t.data('lbox-clone') != undefined) return;
14820
14821				//Uncode addition ##START##
14822				if ( typeof t.attr('data-album') != 'undefined' && t.attr('data-album') != '' ) {
14823					var ALBUM_URLS = JSON.parse(t.attr('data-album')),
14824						URL_i,
14825						URLS_LENGHT = ALBUM_URLS.length;
14826
14827					for (URL_i = 0; URL_i < URLS_LENGHT; URL_i++) {
14828						if ( typeof ALBUM_URLS[URL_i].url !== 'undefined' && ALBUM_URLS[URL_i].url != '' ) {
14829							var item_opts = 'width:' + ALBUM_URLS[URL_i].width + ',height:' + ALBUM_URLS[URL_i].height + ',thumbnail: \'' + ALBUM_URLS[URL_i].thumbnail + '\'';
14830							item_opts = item_opts && eval("({" + item_opts + "})") || {},
14831							items.push({
14832								URL: ALBUM_URLS[URL_i].url,
14833								caption: ALBUM_URLS[URL_i].caption,
14834								title: ALBUM_URLS[URL_i].title,
14835								type: getTypeByExtension(ALBUM_URLS[URL_i].url),
14836								options: item_opts,
14837								clone: clone
14838							});
14839							var newT = t;
14840							newT.attr('href',ALBUM_URLS[URL_i].url);
14841							if (!iL.instant) itemsObject.push(newT);
14842						}
14843					}
14844				} else {
14845				//Uncode addition ##END##
14846					items.push({
14847						URL: URL,
14848						caption: caption,
14849						title: title,
14850						type: type,
14851						options: options,
14852						clone: clone
14853					});
14854				}
14855
14856
14857				if (iL.vars != undefined) iL.vars.total = items.length;
14858
14859				if (!iL.instant) itemsObject.push(t);
14860			});
14861
14862			iL.items = items,
14863				iL.itemsObject = itemsObject;
14864
14865		},
14866
14867		normalizeItems: function() {
14868			var iL = this,
14869				newItems = new Array();
14870
14871			$.each(iL.items, function(key, val) {
14872
14873				if (typeof val == "string") val = {
14874					url: val
14875				};
14876
14877				var URL = val.url || val.URL || null,
14878					options = val.options || {},
14879					caption = val.caption || null,
14880					title = val.title || null,
14881					type = (val.type) ? val.type.toLowerCase() : getTypeByExtension(URL),
14882					ext = (typeof URL != 'object') ? getExtension(URL) : '';
14883
14884				options.thumbnail = options.thumbnail || ((type == "image") ? URL : null),
14885				options.videoType = options.videoType || null,
14886				options.skin = options.skin || iL.options.skin,
14887				options.width = options.width || null,
14888				options.height = options.height || null,
14889				options.mousewheel = (typeof options.mousewheel != 'undefined') ? options.mousewheel : true,
14890				options.swipe = (typeof options.swipe != 'undefined') ? options.swipe : true,
14891				options.social = (typeof options.social != 'undefined') ? options.social : iL.options.social.buttons && $.extend({}, {}, iL.options.social.buttons);
14892
14893				if (type == "video") {
14894					options.html5video = (typeof options.html5video != 'undefined') ? options.html5video : {};
14895
14896					options.html5video.webm = options.html5video.webm || options.html5video.WEBM || null;
14897					options.html5video.controls = (typeof options.html5video.controls != 'undefined') ? options.html5video.controls : "controls";
14898					options.html5video.preload = options.html5video.preload || "metadata";
14899					options.html5video.autoplay = (typeof options.html5video.autoplay != 'undefined') ? options.html5video.autoplay : false;
14900					//UNCODE addition
14901					options.html5video.loop = (typeof options.html5video.loop != 'undefined') ? options.html5video.loop : false;
14902				}
14903
14904				if (!options.width || !options.height) {
14905					if (type == "video") options.width = 1280, options.height = 720;
14906					else if (type == "iframe") options.width = '100%', options.height = '90%';
14907					else if (type == "flash") options.width = 1280, options.height = 720;
14908				}
14909
14910				delete val.url;
14911				val.index = key;
14912				val.URL = URL;
14913				val.caption = caption;
14914				val.title = title;
14915				val.type = type;
14916				val.options = options;
14917				val.ext = ext;
14918
14919				newItems.push(val);
14920			});
14921
14922			iL.items = newItems;
14923		},
14924
14925		instantCall: function() {
14926			var iL = this,
14927				key = iL.vars.start;
14928
14929			iL.vars.current = key;
14930			iL.vars.next = (iL.items[key + 1]) ? key + 1 : null;
14931			iL.vars.prev = (iL.items[key - 1]) ? key - 1 : null;
14932
14933			iL.addContents();
14934			iL.patchEvents();
14935		},
14936
14937		addContents: function() {
14938			var iL = this,
14939				vars = iL.vars,
14940				opts = iL.options,
14941				viewport = getViewport(),
14942				path = opts.path.toLowerCase(),
14943				recognizingItems = vars.total > 0 && iL.items.filter(function(e, i, arr) {
14944					return ['image', 'flash', 'video'].indexOf(e.type) === -1 && typeof e.recognized === 'undefined' && (opts.smartRecognition || e.options.smartRecognition);
14945				}),
14946				needRecognition = recognizingItems.length > 0;
14947
14948			if (opts.mobileOptimizer && !opts.innerToolbar)
14949				vars.isMobile = viewport.width <= vars.mobileMaxWidth;
14950
14951			vars.overlay.addClass(opts.skin).hide().css('opacity', opts.overlay.opacity);
14952
14953			if (opts.linkId)
14954				vars.overlay[0].setAttribute('linkid', opts.linkId);
14955
14956			//Add Toolbar Buttons
14957			if (opts.controls.toolbar) {
14958				vars.toolbar.addClass(opts.skin).append(vars.closeButton);
14959				if (opts.controls.fullscreen)
14960					vars.toolbar.append(vars.fullScreenButton);
14961				if (opts.controls.slideshow)
14962					vars.toolbar.append(vars.innerPlayButton);
14963				if (vars.total > 1)
14964					vars.toolbar.append(vars.innerPrevButton).append(vars.innerNextButton);
14965			}
14966
14967			//Append elements to body
14968			vars.BODY.addClass('ilightbox-noscroll').append(vars.overlay).append(vars.loader).append(vars.holder).append(vars.nextPhoto).append(vars.prevPhoto);
14969
14970			if (!opts.innerToolbar)
14971				vars.BODY.append(vars.toolbar);
14972			if (opts.controls.arrows)
14973				vars.BODY.append(vars.nextButton).append(vars.prevButton);
14974
14975			if (opts.controls.thumbnail && vars.total > 1) {
14976				vars.BODY.append(vars.thumbnails);
14977				vars.thumbnails.addClass(opts.skin).addClass('ilightbox-' + path);
14978				$('div.ilightbox-thumbnails-grid', vars.thumbnails).empty();
14979				vars.thumbs = true;
14980			}
14981
14982			//Configure loader and arrows
14983			var loaderCss = (opts.path.toLowerCase() == "horizontal") ? {
14984				left: parseInt((viewport.width / 2) - (vars.loader.outerWidth() / 2))
14985			} : {
14986				top: parseInt((viewport.height / 2) - (vars.loader.outerHeight() / 2))
14987			};
14988			vars.loader.addClass(opts.skin).css(loaderCss);
14989			vars.nextButton.add(vars.prevButton).addClass(opts.skin);
14990			if (path == "horizontal")
14991				vars.loader.add(vars.nextButton).add(vars.prevButton).addClass('horizontal');
14992
14993			// Configure arrow buttons
14994			vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile');
14995
14996			if (!opts.infinite) {
14997				vars.prevButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
14998
14999				if (vars.current == 0)
15000					vars.prevButton.add(vars.innerPrevButton).addClass('disabled');
15001				if (vars.current >= vars.total - 1)
15002					vars.nextButton.add(vars.innerNextButton).addClass('disabled');
15003			}
15004
15005			if (opts.show.effect) {
15006				vars.overlay.stop().fadeIn(opts.show.speed);
15007				vars.toolbar.stop().fadeIn(opts.show.speed);
15008			} else {
15009				vars.overlay.show();
15010				vars.toolbar.show();
15011			}
15012
15013			var length = recognizingItems.length;
15014			if (needRecognition) {
15015				iL.showLoader();
15016
15017				$.each(recognizingItems, function(key, val) {
15018					var resultFnc = function(result) {
15019							var key = -1,
15020								filter = iL.items.filter(function(e, i, arr) {
15021									if (e.URL == result.url)
15022										key = i;
15023
15024									return e.URL == result.url;
15025								}),
15026								self = iL.items[key];
15027
15028							if (result)
15029								$.extend(true, self, {
15030									URL: result.source,
15031									type: result.type,
15032									recognized: true,
15033									options: {
15034										html5video: result.html5video,
15035										width: (result.type == "image") ? 0 : (result.width || self.width),
15036										height: (result.type == "image") ? 0 : (result.height || self.height),
15037										thumbnail: self.options.thumbnail || result.thumbnail
15038									}
15039								});
15040
15041							length--;
15042
15043							if (length == 0) {
15044								iL.hideLoader();
15045
15046								vars.dontGenerateThumbs = false;
15047								iL.generateThumbnails();
15048
15049								if (opts.show.effect)
15050									setTimeout(function() {
15051										iL.generateBoxes();
15052									}, opts.show.speed);
15053								else
15054									iL.generateBoxes();
15055							}
15056						};
15057
15058					iL.ogpRecognition(this, resultFnc);
15059				});
15060			}
15061			else {
15062				if (opts.show.effect)
15063					setTimeout(function() {
15064						iL.generateBoxes();
15065					}, opts.show.speed);
15066				else
15067					iL.generateBoxes();
15068			}
15069
15070			iL.createUI();
15071
15072			window.iLightBox = {
15073				close: function() {
15074					iL.closeAction();
15075				},
15076				fullscreen: function() {
15077					iL.fullScreenAction();
15078				},
15079				moveNext: function() {
15080					iL.moveTo('next');
15081				},
15082				movePrev: function() {
15083					iL.moveTo('prev');
15084				},
15085				goTo: function(index) {
15086					iL.goTo(index);
15087				},
15088				refresh: function() {
15089					iL.refresh();
15090				},
15091				reposition: function() {
15092					(arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto();
15093				},
15094				setOption: function(options) {
15095					iL.setOption(options);
15096				},
15097				destroy: function() {
15098					iL.closeAction();
15099					iL.dispatchItemsEvents();
15100				}
15101			};
15102
15103			if (opts.linkId) {
15104				vars.hashLock = true;
15105				window.location.hash = opts.linkId + '/' + vars.current;
15106				setTimeout(function() {
15107					vars.hashLock = false;
15108				}, 55);
15109			}
15110
15111			if (!opts.slideshow.startPaused) {
15112				iL.resume();
15113				vars.innerPlayButton.removeClass('ilightbox-play').addClass('ilightbox-pause');
15114			}
15115
15116			//Trigger the onOpen callback
15117			if (typeof iL.options.callback.onOpen == 'function') iL.options.callback.onOpen.call(iL);
15118		},
15119
15120		loadContent: function(obj, opt, speed) {
15121			var iL = this,
15122				holder, item;
15123
15124			iL.createUI();
15125
15126			obj.speed = speed || iL.options.effects.loadedFadeSpeed;
15127
15128			if (opt == 'current') {
15129				if (!obj.options.mousewheel) iL.vars.lockWheel = true;
15130				else iL.vars.lockWheel = false;
15131
15132				if (!obj.options.swipe) iL.vars.lockSwipe = true;
15133				else iL.vars.lockSwipe = false;
15134			}
15135
15136			switch (opt) {
15137				case 'current':
15138					holder = iL.vars.holder, item = iL.vars.current;
15139					break;
15140				case 'next':
15141					holder = iL.vars.nextPhoto, item = iL.vars.next;
15142					break;
15143				case 'prev':
15144					holder = iL.vars.prevPhoto, item = iL.vars.prev;
15145					break;
15146			}
15147
15148			holder.removeAttr('style class').addClass('ilightbox-holder' + (supportTouch ? ' supportTouch' : '')).addClass(obj.options.skin);
15149			$('div.ilightbox-inner-toolbar', holder).remove();
15150
15151			if (obj.title || iL.options.innerToolbar) {
15152				var innerToolbar = iL.vars.innerToolbar.clone();
15153				if (obj.title && iL.options.show.title) {
15154					var title = iL.vars.title.clone();
15155					title.empty().html(obj.title);
15156					innerToolbar.append(title);
15157				}
15158				if (iL.options.innerToolbar) {
15159					innerToolbar.append((iL.vars.total > 1) ? iL.vars.toolbar.clone() : iL.vars.toolbar);
15160				}
15161				holder.prepend(innerToolbar);
15162			}
15163
15164			//console.warn('loadContent', arguments);
15165
15166			iL.loadSwitcher(obj, holder, item, opt);
15167		},
15168
15169		loadSwitcher: function(obj, holder, item, opt) {
15170			var iL = this,
15171				opts = iL.options,
15172				api = {
15173					element: holder,
15174					position: item
15175				};
15176
15177			switch (obj.type) {
15178				case 'image':
15179					//Trigger the onBeforeLoad callback
15180					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
15181					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
15182
15183					iL.loadImage(obj.URL, function(img) {
15184						//Trigger the onAfterLoad callback
15185						if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
15186						if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
15187
15188						var width = (img) ? img.width : 400,
15189							height = (img) ? img.height : 200;
15190
15191						holder.data({
15192							naturalWidth: width,
15193							naturalHeight: height
15194						});
15195
15196						$('div.ilightbox-container', holder).empty().append((img) ? '<img src="' + obj.URL + '" class="ilightbox-image" />' : '<span class="ilightbox-alert">' + opts.errors.loadImage + '</span>');
15197
15198						//Trigger the onRender callback
15199						if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
15200						if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
15201
15202						iL.configureHolder(obj, opt, holder);
15203					});
15204
15205					break;
15206
15207				case 'video':
15208					holder.data({
15209						naturalWidth: obj.options.width,
15210						naturalHeight: obj.options.height
15211					});
15212
15213					if (opt === 'current') {
15214						iL.addContent(holder, obj);
15215
15216						//Trigger the onRender callback
15217						if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
15218						if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
15219					} else {
15220						$('div.ilightbox-container', holder).empty();
15221					}
15222
15223					iL.configureHolder(obj, opt, holder);
15224
15225					break;
15226
15227				case 'iframe':
15228					//iL.showLoader();
15229					holder.data({
15230						naturalWidth: obj.options.width,
15231						naturalHeight: obj.options.height
15232					});
15233
15234					iL.configureHolder(obj, opt, holder);
15235
15236					if (opt === 'current') {
15237						var el = iL.addContent(holder, obj);
15238
15239						//Trigger the onRender callback
15240						if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
15241						if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
15242
15243						//Trigger the onBeforeLoad callback
15244						if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
15245						if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
15246
15247						el.bind('load', function() {
15248							//Trigger the onAfterLoad callback
15249							if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
15250							if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
15251
15252							//iL.hideLoader();
15253							el.unbind('load');
15254						});
15255					} else {
15256						$('div.ilightbox-container', holder).empty();
15257					}
15258
15259					break;
15260
15261				case 'inline':
15262					var el = $(obj.URL),
15263						content = iL.addContent(holder, obj),
15264						images = findImageInElement(holder);
15265
15266					holder.data({
15267						naturalWidth: (iL.items[item].options.width || el.outerWidth()),
15268						naturalHeight: (iL.items[item].options.height || el.outerHeight())
15269					});
15270					content.children().eq(0).show();
15271
15272					//Trigger the onRender callback
15273					if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
15274					if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
15275
15276					//Trigger the onBeforeLoad callback
15277					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
15278					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
15279
15280					iL.loadImage(images, function() {
15281						//Trigger the onAfterLoad callback
15282						if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
15283						if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
15284
15285						iL.configureHolder(obj, opt, holder);
15286					});
15287
15288					break;
15289
15290				case 'flash':
15291					var el = iL.addContent(holder, obj);
15292
15293					holder.data({
15294						naturalWidth: (iL.items[item].options.width || el.outerWidth()),
15295						naturalHeight: (iL.items[item].options.height || el.outerHeight())
15296					});
15297
15298					//Trigger the onRender callback
15299					if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
15300					if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
15301
15302					iL.configureHolder(obj, opt, holder);
15303
15304					break;
15305
15306				case 'ajax':
15307					var ajax = obj.options.ajax || {};
15308					//Trigger the onBeforeLoad callback
15309					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
15310					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
15311
15312					iL.showLoader();
15313					$.ajax({
15314						url: obj.URL || opts.ajaxSetup.url,
15315						data: ajax.data || null,
15316						dataType: ajax.dataType || "html",
15317						type: ajax.type || opts.ajaxSetup.type,
15318						cache: ajax.cache || opts.ajaxSetup.cache,
15319						crossDomain: ajax.crossDomain || opts.ajaxSetup.crossDomain,
15320						global: ajax.global || opts.ajaxSetup.global,
15321						ifModified: ajax.ifModified || opts.ajaxSetup.ifModified,
15322						username: ajax.username || opts.ajaxSetup.username,
15323						password: ajax.password || opts.ajaxSetup.password,
15324						beforeSend: ajax.beforeSend || opts.ajaxSetup.beforeSend,
15325						complete: ajax.complete || opts.ajaxSetup.complete,
15326						success: function(data, textStatus, jqXHR) {
15327							iL.hideLoader();
15328
15329							var el = $(data),
15330								container = $('div.ilightbox-container', holder),
15331								elWidth = iL.items[item].options.width || parseInt(el[0].getAttribute('width')),
15332								elHeight = iL.items[item].options.height || parseInt(el[0].getAttribute('height')),
15333								css = (el[0].getAttribute('width') && el[0].getAttribute('height')) ? {
15334									'overflow': 'hidden'
15335								} : {};
15336
15337							container.empty().append($('<div class="ilightbox-wrapper"></div>').css(css).html(el));
15338							holder.show().data({
15339								naturalWidth: (elWidth || container.outerWidth()),
15340								naturalHeight: (elHeight || container.outerHeight())
15341							}).hide();
15342
15343							//Trigger the onRender callback
15344							if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
15345							if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
15346
15347							var images = findImageInElement(holder);
15348							iL.loadImage(images, function() {
15349								//Trigger the onAfterLoad callback
15350								if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
15351								if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
15352
15353								iL.configureHolder(obj, opt, holder);
15354							});
15355
15356							opts.ajaxSetup.success(data, textStatus, jqXHR);
15357							if (typeof ajax.success == 'function') ajax.success(data, textStatus, jqXHR);
15358						},
15359						error: function(jqXHR, textStatus, errorThrown) {
15360							//Trigger the onAfterLoad callback
15361							if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
15362							if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
15363
15364							iL.hideLoader();
15365							$('div.ilightbox-container', holder).empty().append('<span class="ilightbox-alert">' + opts.errors.loadContents + '</span>');
15366							iL.configureHolder(obj, opt, holder);
15367
15368							opts.ajaxSetup.error(jqXHR, textStatus, errorThrown);
15369							if (typeof ajax.error == 'function') ajax.error(jqXHR, textStatus, errorThrown);
15370						}
15371					});
15372
15373					break;
15374
15375				case 'html':
15376					var object = obj.URL,
15377						el
15378					container = $('div.ilightbox-container', holder);
15379
15380					if (object[0].nodeName) el = object.clone();
15381					else {
15382						var dom = $(object);
15383						if (dom.selector) el = $('<div>' + dom + '</div>');
15384						else el = dom;
15385					}
15386
15387					var elWidth = iL.items[item].options.width || parseInt(el.attr('width')),
15388						elHeight = iL.items[item].options.height || parseInt(el.attr('height'));
15389
15390					iL.addContent(holder, obj);
15391
15392					el.appendTo(document.documentElement).hide();
15393
15394					//Trigger the onRender callback
15395					if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
15396					if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
15397
15398					var images = findImageInElement(holder);
15399
15400					//Trigger the onBeforeLoad callback
15401					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
15402					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
15403
15404					iL.loadImage(images, function() {
15405						//Trigger the onAfterLoad callback
15406						if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
15407						if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
15408
15409						holder.show().data({
15410							naturalWidth: (elWidth || container.outerWidth()),
15411							naturalHeight: (elHeight || container.outerHeight())
15412						}).hide();
15413						el.remove();
15414
15415						iL.configureHolder(obj, opt, holder);
15416					});
15417
15418					break;
15419			}
15420		},
15421
15422		configureHolder: function(obj, opt, holder) {
15423			var iL = this,
15424				vars = iL.vars,
15425				opts = iL.options;
15426
15427			if (opt != "current")(opt == "next") ? holder.addClass('ilightbox-next') : holder.addClass('ilightbox-prev');
15428
15429			if (opt == "current")
15430				var item = vars.current;
15431			else if (opt == "next")
15432				var opacity = opts.styles.nextOpacity,
15433					item = vars.next;
15434			else
15435				var opacity = opts.styles.prevOpacity,
15436					item = vars.prev;
15437
15438			var api = {
15439				element: holder,
15440				position: item
15441			};
15442
15443			iL.items[item].options.width = iL.items[item].options.width || 0,
15444			iL.items[item].options.height = iL.items[item].options.height || 0;
15445
15446			if (opt == "current") {
15447				if (opts.show.effect) holder.css(transform, gpuAcceleration).fadeIn(obj.speed, function() {
15448					holder.css(transform, '');
15449					if (obj.caption) {
15450						iL.setCaption(obj, holder);
15451						var caption = $('div.ilightbox-caption', holder),
15452							percent = parseInt((caption.outerHeight() / holder.outerHeight()) * 100);
15453						if (opts.caption.start & percent <= 50) caption.fadeIn(opts.effects.fade
15453Speed);
15454					}
15455
15456					var social = obj.options.social;
15457					if (social) {
15458						iL.setSocial(social, obj.URL, holder);
15459						if (opts.social.start) $('div.ilightbox-social', holder).fadeIn(opts.effects.fadeSpeed);
15460					}
15461
15462					//Generate thumbnails
15463					iL.generateThumbnails();
15464
15465					//Trigger the onShow callback
15466					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
15467					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
15468				});
15469				else {
15470					holder.show();
15471
15472					//Generate thumbnails
15473					iL.generateThumbnails();
15474
15475					//Trigger the onShow callback
15476					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
15477					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
15478				}
15479			} else {
15480				if (opts.show.effect) holder.fadeTo(obj.speed, opacity, function() {
15481					if (opt == "next") vars.nextLock = false;
15482					else vars.prevLock = false;
15483
15484					//Generate thumbnails
15485					iL.generateThumbnails();
15486
15487					//Trigger the onShow callback
15488					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
15489					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
15490				});
15491				else {
15492					holder.css({
15493						opacity: opacity
15494					}).show();
15495					if (opt == "next") vars.nextLock = false;
15496					else vars.prevLock = false;
15497
15498					//Generate thumbnails
15499					iL.generateThumbnails();
15500
15501					//Trigger the onShow callback
15502					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
15503					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
15504				}
15505			}
15506
15507			setTimeout(function() {
15508				iL.repositionPhoto();
15509			}, 0);
15510		},
15511
15512		generateBoxes: function() {
15513			var iL = this,
15514				vars = iL.vars,
15515				opts = iL.options;
15516
15517			if (opts.infinite && vars.total >= 3) {
15518				if (vars.current == vars.total - 1) vars.next = 0;
15519				if (vars.current == 0) vars.prev = vars.total - 1;
15520			} else opts.infinite = false;
15521
15522			//UNCODE addition
15523			if ( typeof iL.items[vars.current] == 'undefined' )
15524				vars.current = 0;
15525
15526			iL.loadContent(iL.items[vars.current], 'current', opts.show.speed);
15527
15528			if (iL.items[vars.next]) iL.loadContent(iL.items[vars.next], 'next', opts.show.speed);
15529			if (iL.items[vars.prev]) iL.loadContent(iL.items[vars.prev], 'prev', opts.show.speed);
15530		},
15531
15532		generateThumbnails: function() {
15533			var iL = this,
15534				vars = iL.vars,
15535				opts = iL.options,
15536				timeOut = null;
15537
15538			if (vars.thumbs && !iL.vars.dontGenerateThumbs) {
15539				var thumbnails = vars.thumbnails,
15540					container = $('div.ilightbox-thumbnails-container', thumbnails),
15541					grid = $('div.ilightbox-thumbnails-grid', container),
15542					i = 0;
15543
15544				grid.removeAttr('style').empty();
15545
15546				$.each(iL.items, function(key, val) {
15547					var isActive = (vars.current == key) ? 'ilightbox-active' : '',
15548						opacity = (vars.current == key) ? opts.thumbnails.activeOpacity : opts.thumbnails.normalOpacity,
15549						thumb = val.options.thumbnail,
15550						thumbnail = $('<div class="ilightbox-thumbnail"></div>'),
15551						icon = $('<div class="ilightbox-thumbnail-icon"></div>');
15552
15553					thumbnail.css({
15554						opacity: 0
15555					}).addClass(isActive);
15556
15557					if ((val.type == "video" || val.type == "flash") && typeof val.options.icon == 'undefined') {
15558						icon.addClass('ilightbox-thumbnail-video');
15559						thumbnail.append(icon);
15560					} else if (val.options.icon) {
15561						icon.addClass('ilightbox-thumbnail-' + val.options.icon);
15562						thumbnail.append(icon);
15563					}
15564
15565					if (thumb) iL.loadImage(thumb, function(img) {
15566						i++;
15567						if (img) thumbnail.data({
15568							naturalWidth: img.width,
15569							naturalHeight: img.height
15570						}).append('<img src="' + thumb + '" border="0" />');
15571						else thumbnail.data({
15572							naturalWidth: opts.thumbnails.maxWidth,
15573							naturalHeight: opts.thumbnails.maxHeight
15574						});
15575
15576						clearTimeout(timeOut);
15577						timeOut = setTimeout(function() {
15578							iL.positionThumbnails(thumbnails, container, grid);
15579						}, 20);
15580						setTimeout(function() {
15581							thumbnail.fadeTo(opts.effects.loadedFadeSpeed, opacity);
15582						}, i * 20);
15583					});
15584
15585					grid.append(thumbnail);
15586				});
15587				iL.vars.dontGenerateThumbs = true;
15588			}
15589		},
15590
15591		positionThumbnails: function(thumbnails, container, grid) {
15592			var iL = this,
15593				vars = iL.vars,
15594				opts = iL.options,
15595				viewport = getViewport(),
15596				path = opts.path.toLowerCase();
15597
15598			if (!thumbnails) thumbnails = vars.thumbnails;
15599			if (!container) container = $('div.ilightbox-thumbnails-container', thumbnails);
15600			if (!grid) grid = $('div.ilightbox-thumbnails-grid', container);
15601
15602			var thumbs = $('.ilightbox-thumbnail', grid),
15603				widthAvail = (path == 'horizontal') ? viewport.width - opts.styles.pageOffsetX : thumbs.eq(0).outerWidth() - opts.styles.pageOffsetX,
15604				heightAvail = (path == 'horizontal') ? thumbs.eq(0).outerHeight() - opts.styles.pageOffsetY : viewport.height - opts.styles.pageOffsetY,
15605				gridWidth = (path == 'horizontal') ? 0 : widthAvail,
15606				gridHeight = (path == 'horizontal') ? heightAvail : 0,
15607				active = $('.ilightbox-active', grid),
15608				gridCss = {},
15609				css = {};
15610
15611			if (arguments.length < 3) {
15612				thumbs.css({
15613					opacity: opts.thumbnails.normalOpacity
15614				});
15615				active.css({
15616					opacity: opts.thumbnails.activeOpacity
15617				});
15618			}
15619
15620			thumbs.each(function(i) {
15621				var t = $(this),
15622					data = t.data(),
15623					width = (path == 'horizontal') ? 0 : opts.thumbnails.maxWidth;
15624				height = (path == 'horizontal') ? opts.thumbnails.maxHeight : 0;
15625				dims = iL.getNewDimenstions(width, height, data.naturalWidth, data.naturalHeight, true);
15626
15627				t.css({
15628					width: dims.width,
15629					height: dims.height
15630				});
15631				if (path == 'horizontal') t.css({
15632					'float': 'left'
15633				});
15634
15635				(path == 'horizontal') ? (
15636					gridWidth += t.outerWidth()
15637				) : (
15638					gridHeight += t.outerHeight()
15639				);
15640			});
15641
15642			gridCss = {
15643				width: gridWidth,
15644				height: gridHeight
15645			};
15646
15647			grid.css(gridCss);
15648
15649			gridCss = {};
15650
15651			var gridOffset = grid.offset(),
15652				activeOffset = (active.length) ? active.offset() : {
15653					top: parseInt(heightAvail / 2),
15654					left: parseInt(widthAvail / 2)
15655				};
15656
15657			gridOffset.top = (gridOffset.top - $doc.scrollTop()),
15658				gridOffset.left = (gridOffset.left - $doc.scrollLeft()),
15659				activeOffset.top = (activeOffset.top - gridOffset.top - $doc.scrollTop()),
15660				activeOffset.left = (activeOffset.left - gridOffset.left - $doc.scrollLeft());
15661
15662			(path == 'horizontal') ? (
15663				gridCss.top = 0,
15664				gridCss.left = parseInt((widthAvail / 2) - activeOffset.left - (active.outerWidth() / 2))
15665			) : (
15666				gridCss.top = parseInt(((heightAvail / 2) - activeOffset.top - (active.outerHeight() / 2))),
15667				gridCss.left = 0
15668			);
15669
15670			if (arguments.length < 3) grid.stop().animate(gridCss, opts.effects.repositionSpeed, 'easeOutCirc');
15671			else grid.css(gridCss);
15672		},
15673
15674		loadImage: function(image, callback) {
15675			if (!$.isArray(image)) image = [image];
15676
15677			var iL = this,
15678				length = image.length;
15679
15680			if (length > 0) {
15681				iL.showLoader();
15682				$.each(image, function(index, value) {
15683					var img = new Image();
15684					img.onload = function() {
15685						length -= 1;
15686						if (length == 0) {
15687							iL.hideLoader();
15688							callback(img);
15689						}
15690					};
15691					img.onerror = img.onabort = function() {
15692						length -= 1;
15693						if (length == 0) {
15694							iL.hideLoader();
15695							callback(false);
15696						}
15697					};
15698					img.src = image[index];
15699				});
15700			} else callback(false);
15701		},
15702
15703		patchItemsEvents: function() {
15704			var iL = this,
15705				vars = iL.vars,
15706				clickEvent = ishybrid ? "itap.iL click.iL" : supportTouch ? "itap.iL" : "click.iL",
15707				vEvent = ishybrid ? "click.iL itap.iL" : supportTouch ? "click.iL" : "itap.iL";
15708
15709			if (iL.context && iL.selector) {
15710				var $items = $(iL.selector, iL.context);
15711
15712				$(iL.context).on(clickEvent, iL.selector, function() {
15713					var $this = $(this),
15714						//UNCODE addition
15715						key = typeof $(this).data('lb-index') !== '' && $(this).closest('.owl-item').length ? $(this).data('lb-index') : $items.index($this);
15716					if (UNCODE.isMobile) {
15717						var isCarousel = $this.closest('.owl-carousel');
15718						if (isCarousel.length) {
15719							if (isCarousel.hasClass('owl-translating')) return false;
15720						}
15721					}
15722
15723					vars.current = key;
15724					vars.next = iL.items[key + 1] ? key + 1 : null;
15725					vars.prev = iL.items[key - 1] ? key - 1 : null;
15726
15727					//UNCODE addition
15728					if ( vars.BODY.hasClass('fp-slide-scrolling') )
15729						return false;
15730
15731					iL.addContents();
15732					iL.patchEvents();
15733
15734					return false;
15735				}).on(vEvent, iL.selector, function() {
15736					return false;
15737				});
15738			} else
15739				$.each(iL.itemsObject, function(key, val) {
15740					val.on(clickEvent, function() {
15741						vars.current = key;
15742						vars.next = iL.items[key + 1] ? key + 1 : null;
15743						vars.prev = iL.items[key - 1] ? key - 1 : null;
15744
15745						iL.addContents();
15746						iL.patchEvents();
15747
15748						return false;
15749					}).on(vEvent, function() {
15750						return false;
15751					});
15752				});
15753		},
15754
15755		dispatchItemsEvents: function() {
15756			var iL = this,
15757				vars = iL.vars,
15758				opts = iL.options;
15759
15760			if (iL.context && iL.selector)
15761				$(iL.context).off('.iL', iL.selector);
15762			else
15763				$.each(iL.itemsObject, function(key, val) {
15764					val.off('.iL');
15765				});
15766		},
15767
15768		refresh: function() {
15769			var iL = this;
15770
15771			iL.dispatchItemsEvents();
15772			iL.attachItems();
15773			iL.normalizeItems();
15774			iL.patchItemsEvents();
15775		},
15776
15777		patchEvents: function() {
15778			var iL = this,
15779				vars = iL.vars,
15780				opts = iL.options,
15781				path = opts.path.toLowerCase(),
15782				holders = $('.ilightbox-holder'),
15783				fullscreenEvent = fullScreenApi.fullScreenEventName + '.iLightBox',
15784				durationThreshold = 1000,
15785				horizontalDistanceThreshold =
15786				verticalDistanceThreshold = 100,
15787				buttonsArray = [vars.nextButton[0], vars.prevButton[0], vars.nextButton[0].firstChild, vars.prevButton[0].firstChild];
15788
15789			$win.bind('resize.iLightBox', function() {
15790				var viewport = getViewport();
15791
15792				if (opts.mobileOptimizer && !opts.innerToolbar) vars.isMobile = viewport.width <= vars.mobileMaxWidth;
15793				vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile');
15794
15795				iL.repositionPhoto(null);
15796				if (supportTouch) {
15797					clearTimeout(vars.setTime);
15798					vars.setTime = setTimeout(function() {
15799						var scrollTop = getScrollXY().y;
15800						window.scrollTo(0, scrollTop - 30);
15801						window.scrollTo(0, scrollTop + 30);
15802						window.scrollTo(0, scrollTop);
15803					}, 2000);
15804				}
15805				if (vars.thumbs) iL.positionThumbnails();
15806			}).bind('keydown.iLightBox', function(event) {
15807				if (opts.controls.keyboard) {
15808					switch (event.keyCode) {
15809						case 13:
15810							if (event.shiftKey && opts.keyboard.shift_enter) iL.fullScreenAction();
15811							break;
15812						case 27:
15813							if (opts.keyboard.esc) iL.closeAction();
15814							break;
15815						case 37:
15816							if (opts.keyboard.left && !vars.lockKey) iL.moveTo('prev');
15817							break;
15818						case 38:
15819							if (opts.keyboard.up && !vars.lockKey) iL.moveTo('prev');
15820							break;
15821						case 39:
15822							if (opts.keyboard.right && !vars.lockKey) iL.moveTo('next');
15823							break;
15824						case 40:
15825							if (opts.keyboard.down && !vars.lockKey) iL.moveTo('next');
15826							break;
15827					}
15828				}
15829			});
15830
15831			if (fullScreenApi.supportsFullScreen) $win.bind(fullscreenEvent, function() {
15832				iL.doFullscreen();
15833			});
15834
15835			var holderEventsArr = [opts.caption.show + '.iLightBox', opts.caption.hide + '.iLightBox', opts.social.show + '.iLightBox', opts.social.hide + '.iLightBox'].filter(function(e, i, arr) {
15836					return arr.lastIndexOf(e) === i;
15837				}),
15838				holderEvents = "";
15839
15840			$.each(holderEventsArr, function(key, val) {
15841				if (key != 0) holderEvents += ' ';
15842				holderEvents += val;
15843			});
15844
15845			$doc.on(clickEvent, '.ilightbox-overlay', function() {
15846				if (opts.overlay.blur) iL.closeAction();
15847			}).on(clickEvent, '.ilightbox-next, .ilightbox-next-button', function() {
15848				iL.moveTo('next');
15849			}).on(clickEvent, '.ilightbox-prev, .ilightbox-prev-button', function() {
15850				iL.moveTo('prev');
15851			}).on(clickEvent, '.ilightbox-thumbnail', function() {
15852				var t = $(this),
15853					thumbs = $('.ilightbox-thumbnail', vars.thumbnails),
15854					index = thumbs.index(t);
15855
15856				if (index != vars.current) iL.goTo(index);
15857			}).on(holderEvents, '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) {
15858				var caption = $('div.ilightbox-caption', vars.holder),
15859					social = $('div.ilightbox-social', vars.holder),
15860					fadeSpeed = opts.effects.fadeSpeed;
15861
15862				if (vars.nextLock || vars.prevLock) {
15863					if (e.type == opts.caption.show && !caption.is(':visible')) caption.fadeIn(fadeSpeed);
15864					else if (e.type == opts.caption.hide && caption.is(':visible')) caption.fadeOut(fadeSpeed);
15865
15866					if (e.type == opts.social.show && !social.is(':visible')) social.fadeIn(fadeSpeed);
15867					else if (e.type == opts.social.hide && social.is(':visible')) social.fadeOut(fadeSpeed);
15868				} else {
15869					if (e.type == opts.caption.show && !caption.is(':visible')) caption.stop().fadeIn(fadeSpeed);
15870					else if (e.type == opts.caption.hide && caption.is(':visible')) caption.stop().fadeOut(fadeSpeed);
15871
15872					if (e.type == opts.social.show && !social.is(':visible')) social.stop().fadeIn(fadeSpeed);
15873					else if (e.type == opts.social.hide && social.is(':visible')) social.stop().fadeOut(fadeSpeed);
15874				}
15875			}).on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-wrapper', function(e) {
15876				if (e.type == 'mouseenter') vars.lockWheel = true;
15877				else vars.lockWheel = false;
15878			}).on(clickEvent, '.ilightbox-toolbar a.ilightbox-close, .ilightbox-toolbar a.ilightbox-fullscreen, .ilightbox-toolbar a.ilightbox-play, .ilightbox-toolbar a.ilightbox-pause', function() {
15879				var t = $(this);
15880
15881				if (t.hasClass('ilightbox-fullscreen')) iL.fullScreenAction();
15882				else if (t.hasClass('ilightbox-play')) {
15883					iL.resume();
15884					t.addClass('ilightbox-pause').removeClass('ilightbox-play');
15885				} else if (t.hasClass('ilightbox-pause')) {
15886					iL.pause();
15887					t.addClass('ilightbox-play').removeClass('ilightbox-pause');
15888				} else iL.closeAction();
15889			}).on(touchMoveEvent, '.ilightbox-overlay, .ilightbox-thumbnails-container', function(e) {
15890				// prevent scrolling
15891				e.preventDefault();
15892			});
15893
15894			function mouseMoveHandler(e) {
15895				if (!vars.isMobile) {
15896					if (!vars.mouseID) {
15897						vars.hideableElements.show();
15898					}
15899
15900					vars.mouseID = clearTimeout(vars.mouseID);
15901
15902					if (buttonsArray.indexOf(e.target) === -1)
15903						vars.mouseID = setTimeout(function() {
15904							vars.hideableElements.hide();
15905							vars.mouseID = clearTimeout(vars.mouseID);
15906						}, 3000);
15907				}
15908			}
15909
15910			if (opts.controls.arrows && !supportTouch) $doc.on('mousemove.iLightBox', mouseMoveHandler);
15911
15912			if (opts.controls.slideshow && opts.slideshow.pauseOnHover) $doc.on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) {
15913				if (e.type == 'mouseenter' && vars.cycleID) iL.pause();
15914				else if (e.type == 'mouseleave' && vars.isPaused) iL.resume();
15915			});
15916
15917			var switchers = $('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails'),
15918				delay = false;
15919
15920			if (opts.controls.mousewheel) switchers.on('mousewheel.iLightBox', function(event, delta) {
15921				event.preventDefault();
15922				if (delay) return;
15923				delay = true;
15924				if (!vars.lockWheel) {
15925					event.preventDefault();
15926					if (delta < 0) {
15927						iL.moveTo('next');
15928					} else if (delta > 0) {
15929						iL.moveTo('prev');
15930					}
15931				}
15932				setTimeout(function(){
15933					delay = false;
15934				}, 2000);
15935			});
15936
15937			if (opts.controls.swipe) holders.on(touchStartEvent, function(event) {
15938				if (vars.nextLock || vars.prevLock || vars.total == 1 || vars.lockSwipe) return;
15939
15940				vars.BODY.addClass('ilightbox-closedhand');
15941
15942				var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event,
15943					scrollTop = $doc.scrollTop(),
15944					scrollLeft = $doc.scrollLeft(),
15945					offsets = [
15946						holders.eq(0).offset(),
15947						holders.eq(1).offset(),
15948						holders.eq(2).offset()
15949					],
15950					offSet = [{
15951						top: offsets[0].top - scrollTop,
15952						left: offsets[0].left - scrollLeft
15953					}, {
15954						top: offsets[1].top - scrollTop,
15955						left: offsets[1].left - scrollLeft
15956					}, {
15957						top: offsets[2].top - scrollTop,
15958						left: offsets[2].left - scrollLeft
15959					}],
15960					start = {
15961						time: (new Date()).getTime(),
15962						coords: [data.pageX - scrollLeft, data.pageY - scrollTop]
15963					},
15964					stop;
15965
15966				function moveEachHandler(i) {
15967					var t = $(this),
15968						offset = offSet[i],
15969						scroll = [(start.coords[0] - stop.coords[0]), (start.coords[1] - stop.coords[1])];
15970
15971					t[0].style[path == "horizontal" ? 'left' : 'top'] = (path == "horizontal" ? offset.left - scroll[0] : offset.top - scroll[1]) + 'px';
15972				}
15973
15974				function moveHandler(event) {
15975
15976					if (!start) return;
15977
15978					var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event;
15979
15980					stop = {
15981						time: (new Date()).getTime(),
15982						coords: [data.pageX - scrollLeft, data.pageY - scrollTop]
15983					};
15984
15985					holders.each(moveEachHandler);
15986
15987					// prevent scrolling
15988					event.preventDefault();
15989				}
15990
15991				function repositionHolders() {
15992					holders.each(function() {
15993						var t = $(this),
15994							offset = t.data('offset') || {
15995								top: t.offset().top - scrollTop,
15996								left: t.offset().left - scrollLeft
15997							},
15998							top = offset.top,
15999							left = offset.left;
16000
16001						t.css(transform, gpuAcceleration).stop().animate({
16002							top: top,
16003							left: left
16004						}, 500, 'easeOutCirc', function() {
16005							t.css(transform, '');
16006						});
16007					});
16008				}
16009
16010				holders.bind(touchMoveEvent, moveHandler);
16011				$doc.one(touchStopEvent, function(event) {
16012					holders.unbind(touchMoveEvent, moveHandler);
16013
16014					vars.BODY.removeClass('ilightbox-closedhand');
16015
16016					if (start && stop) {
16017						if (path == "horizontal" && stop.time - start.time < durationThreshold && abs(start.coords[0] - stop.coords[0]) > horizontalDistanceThreshold && abs(start.coords[1] - stop.coords[1]) < verticalDistanceThreshold) {
16018							if (start.coords[0] > stop.coords[0]) {
16019								if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders();
16020								else {
16021									vars.isSwipe = true;
16022									iL.moveTo('next');
16023								}
16024							} else {
16025								if (vars.current == 0 && !opts.infinite) repositionHolders();
16026								else {
16027									vars.isSwipe = true;
16028									iL.moveTo('prev');
16029								}
16030							}
16031						} 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) {
16032							if (start.coords[1] > stop.coords[1]) {
16033								if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders();
16034								else {
16035									vars.isSwipe = true;
16036									iL.moveTo('next');
16037								}
16038							} else {
16039								if (vars.current == 0 && !opts.infinite) repositionHolders();
16040								else {
16041									vars.isSwipe = true;
16042									iL.moveTo('prev');
16043								}
16044							}
16045						} else repositionHolders();
16046					}
16047					start = stop = undefined;
16048				});
16049			});
16050
16051		},
16052
16053		goTo: function(index) {
16054			var iL = this,
16055				vars = iL.vars,
16056				opts = iL.options,
16057				diff = (index - vars.current);
16058
16059			if (opts.infinite) {
16060				if (index == vars.total - 1 && vars.current == 0) diff = -1;
16061				if (vars.current == vars.total - 1 && index == 0) diff = 1;
16062			}
16063
16064			if (diff == 1) iL.moveTo('next');
16065			else if (diff == -1) iL.moveTo('prev');
16066			else {
16067
16068				if (vars.nextLock || vars.prevLock) return false;
16069
16070				//Trigger the onBeforeChange callback
16071				if (typeof opts.callback.onBeforeChange == 'function') opts.callback.onBeforeChange.call(iL, iL.ui);
16072
16073				if (opts.linkId) {
16074					vars.hashLock = true;
16075					window.location.hash = opts.linkId + '/' + index;
16076				}
16077
16078				if (iL.items[index]) {
16079					if (!iL.items[index].options.mousewheel) vars.lockWheel = true;
16080					else iL.vars.lockWheel = false;
16081
16082					if (!iL.items[index].options.swipe) vars.lockSwipe = true;
16083					else vars.lockSwipe = false;
16084				}
16085
16086				$.each([vars.holder, vars.nextPhoto, vars.prevPhoto], function(key, val) {
16087					val.css(transform, gpuAcceleration).fadeOut(opts.effects.loadedFadeSpeed);
16088				});
16089
16090				vars.current = index;
16091				vars.next = index + 1;
16092				vars.prev = index - 1;
16093
16094				iL.createUI();
16095
16096				setTimeout(function() {
16097					iL.generateBoxes();
16098				}, opts.effects.loadedFadeSpeed + 50);
16099
16100				$('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(index).addClass('ilightbox-active');
16101				iL.positionThumbnails();
16102
16103				if (opts.linkId) setTimeout(function() {
16104					vars.hashLock = false;
16105				}, 55);
16106
16107				// Configure arrow buttons
16108				if (!opts.infinite) {
16109					vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
16110
16111					if (vars.current == 0) {
16112						vars.prevButton.add(vars.innerPrevButton).addClass('disabled');
16113					}
16114					if (vars.current >= vars.total - 1) {
16115						vars.nextButton.add(vars.innerNextButton).addClass('disabled');
16116					}
16117				}
16118
16119				// Reset next cycle timeout
16120				iL.resetCycle();
16121
16122				//Trigger the onAfterChange callback
16123				if (typeof opts.callback.onAfterChange == 'function') opts.callback.onAfterChange.call(iL, iL.ui);
16124			}
16125		},
16126
16127		moveTo: function(side) {
16128			var iL = this,
16129				vars = iL.vars,
16130				opts = iL.options,
16131				path = opts.path.toLowerCase(),
16132				viewport = getViewport(),
16133				switchSpeed = opts.effects.switchSpeed;
16134
16135			if (vars.nextLock || vars.prevLock) return false;
16136			else {
16137
16138				var item = (side == "next") ? vars.next : vars.prev;
16139
16140				if (opts.linkId) {
16141					vars.hashLock = true;
16142					window.location.hash = opts.linkId + '/' + item;
16143				}
16144
16145				if (side == "next") {
16146					if (!iL.items[item]) return false;
16147					var firstHolder = vars.nextPhoto,
16148						secondHolder = vars.holder,
16149						lastHolder = vars.prevPhoto,
16150						firstClass = 'ilightbox-prev',
16151						secondClass = 'ilightbox-next';
16152				} else if (side == "prev") {
16153					if (!iL.items[item]) return false;
16154					var firstHolder = vars.prevPhoto,
16155						secondHolder = vars.holder,
16156						lastHolder = vars.nextPhoto,
16157						firstClass = 'ilightbox-next',
16158						secondClass = 'ilightbox-prev';
16159				}
16160
16161				//Trigger the onBeforeChange callback
16162				if (typeof opts.callback.onBeforeChange == 'function')
16163					opts.callback.onBeforeChange.call(iL, iL.ui);
16164
16165				(side == "next") ? vars.nextLock = true: vars.prevLock = true;
16166
16167				var captionFirst = $('div.ilightbox-caption', secondHolder),
16168					socialFirst = $('div.ilightbox-social', secondHolder);
16169
16170				if (captionFirst.length)
16171					captionFirst.stop().fadeOut(switchSpeed, function() {
16172						$(this).remove();
16173					});
16174				if (socialFirst.length)
16175					socialFirst.stop().fadeOut(switchSpeed, function() {
16176						$(this).remove();
16177					});
16178
16179				if (iL.items[item].caption) {
16180					iL.setCaption(iL.items[item], firstHolder);
16181					var caption = $('div.ilightbox-caption', firstHolder),
16182						percent = parseInt((caption.outerHeight() / firstHolder.outerHeight()) * 100);
16183					if (opts.caption.start && percent <= 50) caption.fadeIn(switchSpeed);
16184				}
16185
16186				var social = iL.items[item].options.social;
16187				if (social) {
16188					iL.setSocial(social, iL.items[item].URL, firstHolder);
16189					if (opts.social.start) $('div.ilightbox-social', firstHolder).fadeIn(opts.effects.fadeSpeed);
16190				}
16191
16192				$.each([firstHolder, secondHolder, lastHolder], function(key, val) {
16193					val.removeClass('ilightbox-next ilightbox-prev');
16194				});
16195
16196				var firstOffset = firstHolder.data('offset'),
16197					winW = (viewport.width - (opts.styles.pageOffsetX)),
16198					winH = (viewport.height - (opts.styles.pageOffsetY)),
16199					width = firstOffset.newDims.width,
16200					height = firstOffset.newDims.height,
16201					thumbsOffset = firstOffset.thumbsOffset,
16202					diff = firstOffset.diff,
16203					top = parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)),
16204					left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2));
16205
16206				var secondOffset = secondHolder.data('offset'),
16207					object = secondOffset.object;
16208
16209				/*if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) {
16210					var objRatio = width / height;
16211					height = height - vars.captionHeight;
16212					width = height * objRatio;
16213					top = path == 'horizontal' ? parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)) : top,
16214					left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2));
16215				}*/
16216
16217				firstHolder.show().css(transform, gpuAcceleration).animate({
16218					top: top,
16219					left: left,
16220					opacity: 1
16221				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() {
16222					firstHolder.css(transform, '');
16223				});
16224
16225				$('div.ilightbox-container', firstHolder).animate({
16226					width: width,
16227					height: height
16228				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc');
16229
16230				diff = secondOffset.diff;
16231
16232				width = secondOffset.newDims.width,
16233					height = secondOffset.newDims.height;
16234
16235				width = parseInt(width * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']),
16236					height = parseInt(height * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']),
16237					top = (path == 'horizontal') ? parseInt((winH / 2) - object.offsetY - (height / 2) - diff.H - (thumbsOffset.H / 2)) : parseInt(winH - object.offsetX - diff.H - (thumbsOffset.H / 2));
16238
16239				if (side == 'prev')
16240					left = (path == 'horizontal') ? parseInt(winW - object.offsetX - diff.W - (thumbsOffset.W / 2)) : parseInt((winW / 2) - (width / 2) - diff.W - object.offsetY - (thumbsOffset.W / 2));
16241				else {
16242					top = (path == 'horizontal') ? top : parseInt(object.offsetX - diff.H - height - (thumbsOffset.H / 2)),
16243					left = (path == 'horizontal') ? parseInt(object.offsetX - diff.W - width - (thumbsOffset.W / 2)) : parseInt((winW / 2) - object.offsetY - (width / 2) - diff.W - (thumbsOffset.W / 2));
16244				}
16245
16246				/*if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) {
16247					var objRatio = width / height;
16248					height = height - vars.captionHeight;
16249					width = height * objRatio;
16250					top = path == 'horizontal' ? parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)) : top;
16251				}*/
16252
16253				$('div.ilightbox-container', secondHolder).animate({
16254					width: width,
16255					height: height
16256				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc');
16257
16258				secondHolder.addClass(firstClass).css(transform, gpuAcceleration).animate({
16259					top: top,
16260					left: left,
16261					opacity: opts.styles.prevOpacity,
16262				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() {
16263					secondHolder.css(transform, '');
16264
16265					$('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(item).addClass('ilightbox-active');
16266					iL.positionThumbnails();
16267
16268					if (iL.items[item]) {
16269						if (!iL.items[item].options.mousewheel) vars.lockWheel = true;
16270						else vars.lockWheel = false;
16271
16272						if (!iL.items[item].options.swipe) vars.lockSwipe = true;
16273						else vars.lockSwipe = false;
16274					}
16275
16276					vars.isSwipe = false;
16277
16278					// Remove iframe & video from previous slide
16279					if (['iframe', 'video'].indexOf(iL.items[vars.current].type) !== -1) {
16280						$('div.ilightbox-container', secondHolder).empty();
16281					}
16282
16283					if (side == "next") {
16284						vars.nextPhoto = lastHolder,
16285							vars.prevPhoto = secondHolder,
16286							vars.holder = firstHolder;
16287
16288						vars.nextPhoto.hide();
16289
16290						vars.next = vars.next + 1,
16291							vars.prev = vars.current,
16292							vars.current = vars.current + 1;
16293
16294						if (opts.infinite) {
16295							if (vars.current > vars.total - 1) vars.current = 0;
16296							if (vars.current == vars.total - 1) vars.next = 0;
16297							if (vars.current == 0) vars.prev = vars.total - 1;
16298						}
16299
16300						iL.createUI();
16301
16302						if (!iL.items[vars.next])
16303							vars.nextLock = false;
16304						else
16305							iL.loadContent(iL.items[vars.next], 'next');
16306					} else {
16307						vars.prevPhoto = lastHolder;
16308						vars.nextPhoto = secondHolder;
16309						vars.holder = firstHolder;
16310
16311						vars.prevPhoto.hide();
16312
16313						vars.next = vars.current;
16314						vars.current = vars.prev;
16315						vars.prev = vars.current - 1;
16316
16317						if (opts.infinite) {
16318							if (vars.current == vars.total - 1) vars.next = 0;
16319							if (vars.current == 0) vars.prev = vars.total - 1;
16320						}
16321
16322						iL.createUI();
16323
16324						if (!iL.items[vars.prev])
16325							vars.prevLock = false;
16326						else
16327							iL.loadContent(iL.items[vars.prev], 'prev');
16328					}
16329
16330					// Add iframe & video content for current slide
16331					if (['iframe', 'video'].indexOf(iL.items[vars.current].type) !== -1) {
16332						iL.loadContent(iL.items[vars.current], 'current');
16333					}
16334
16335					if (opts.linkId) setTimeout(function() {
16336						vars.hashLock = false;
16337					}, 55);
16338
16339					// Configure arrow buttons
16340					if (!opts.infinite) {
16341						vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
16342
16343						if (vars.current == 0)
16344							vars.prevButton.add(vars.innerPrevButton).addClass('disabled');
16345						if (vars.current >= vars.total - 1)
16346							vars.nextButton.add(vars.innerNextButton).addClass('disabled');
16347					}
16348
16349					iL.repositionPhoto();
16350
16351					// Reset next cycle timeout
16352					iL.resetCycle();
16353
16354					//Trigger the onAfterChange callback
16355					if (typeof opts.callback.onAfterChange == 'function')
16356						opts.callback.onAfterChange.call(iL, iL.ui);
16357				});
16358
16359				top = (path == 'horizontal') ? getPixel(lastHolder, 'top') : ((side == "next") ? parseInt(-(winH / 2) - lastHolder.outerHeight()) : parseInt(top * 2)),
16360					left = (path == 'horizontal') ? ((side == "next") ? parseInt(-(winW / 2) - lastHolder.outerWidth()) : parseInt(left * 2)) : getPixel(lastHolder, 'left');
16361
16362				lastHolder.css(transform, gpuAcceleration).animate({
16363					top: top,
16364					left: left,
16365					opacity: opts.styles.nextOpacity
16366				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() {
16367					lastHolder.css(transform, '');
16368				}).addClass(secondClass);
16369			}
16370		},
16371
16372		setCaption: function(obj, target) {
16373			var iL = this,
16374				caption = $('<div class="ilightbox-caption"></div>');
16375
16376			if (obj.caption) {
16377				caption.html(obj.caption);
16378				$('div.ilightbox-container', target).append(caption);
16379			}
16380		},
16381
16382		normalizeSocial: function(obj, url) {
16383			var iL = this,
16384				vars = iL.vars,
16385				opts = iL.options,
16386				baseURL = window.location.href;
16387
16388			$.each(obj, function(key, value) {
16389				if (!value)
16390					return true;
16391
16392				var item = key.toLowerCase(),
16393					source, text;
16394
16395				switch (item) {
16396					case 'facebook':
16397						source = "http://www.facebook.com/share.php?v=4&src=bm&u={URL}",
16398							text = "Share on Facebook";
16399						break;
16400					case 'twitter':
16401						source = "http://twitter.com/home?status={URL}",
16402							text = "Share on Twitter";
16403						break;
16404					case 'digg':
16405						source = "http://digg.com/submit?phase=2&url={URL}",
16406							text = "Share on Digg";
16407						break;
16408					case 'reddit':
16409						source = "http://reddit.com/submit?url={URL}",
16410							text = "Share on reddit";
16411						break;
16412				}
16413
16414				obj[key] = {
16415					URL: value.URL && absolutizeURI(baseURL, value.URL) || opts.linkId && window.location.href || typeof url !== 'string' && baseURL || url && absolutizeURI(baseURL, url) || baseURL,
16416					source: value.source || source || value.URL && absolutizeURI(baseURL, value.URL) || url && absolutizeURI(baseURL, url),
16417					text: value.text || text || "Share on " + key,
16418					width: (typeof(value.width) != 'undefined' && !isNaN(value.width)) ? parseInt(value.width) : 640,
16419					height: value.height || 360
16420				};
16421
16422			});
16423
16424			return obj;
16425		},
16426
16427		setSocial: function(obj, url, target) {
16428			var iL = this,
16429				socialBar = $('<div class="ilightbox-social"></div>'),
16430				buttons = '<ul>';
16431
16432			obj = iL.normalizeSocial(obj, url);
16433
16434			$.each(obj, function(key, value) {
16435				var item = key.toLowerCase(),
16436					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, '+'));
16437				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>';
16438			});
16439
16440			buttons += '</ul>';
16441
16442			socialBar.html(buttons);
16443			$('div.ilightbox-container', target).append(socialBar);
16444		},
16445
16446		fullScreenAction: function() {
16447			var iL = this,
16448				vars = iL.vars;
16449
16450			if (fullScreenApi.supportsFullScreen) {
16451				if (fullScreenApi.isFullScreen()) fullScreenApi.cancelFullScreen(document.documentElement);
16452				else fullScreenApi.requestFullScreen(document.documentElement);
16453			} else {
16454				iL.doFullscreen();
16455			}
16456		},
16457
16458		doFullscreen: function() {
16459			var iL = this,
16460				vars = iL.vars,
16461				viewport = getViewport(),
16462				opts = iL.options;
16463
16464			if (opts.fullAlone) {
16465				var currentHolder = vars.holder,
16466					current = iL.items[vars.current],
16467					windowWidth = viewport.width,
16468					windowHeight = viewport.height,
16469					elements = [currentHolder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.overlay, vars.toolbar, vars.thumbnails, vars.loader],
16470					hideElements = [vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails];
16471
16472				if (!vars.isInFullScreen) {
16473					vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = true;
16474					vars.overlay.css({
16475						opacity: 1
16476					});
16477
16478					$.each(hideElements, function(i, element) {
16479						element.hide();
16480					});
16481
16482					vars.fullScreenButton.attr('title', opts.text.exitFullscreen);
16483
16484					if (opts.fullStretchTypes.indexOf(current.type) != -1) currentHolder.data({
16485						naturalWidthOld: currentHolder.data('naturalWidth'),
16486						naturalHeightOld: currentHolder.data('naturalHeight'),
16487						naturalWidth: windowWidth,
16488						naturalHeight: windowHeight
16489					});
16490					else {
16491						var viewport = current.options.fullViewPort || opts.fullViewPort || '',
16492							newWidth = windowWidth,
16493							newHeight = windowHeight,
16494							width = currentHolder.data('naturalWidth'),
16495							height = currentHolder.data('naturalHeight');
16496
16497						if (viewport.toLowerCase() == 'fill') {
16498							newHeight = (newWidth / width) * height;
16499
16500							if (newHeight < windowHeight) {
16501								newWidth = (windowHeight / height) * width,
16502									newHeight = windowHeight;
16503							}
16504						} else if (viewport.toLowerCase() == 'fit') {
16505							var dims = iL.getNewDimenstions(newWidth, newHeight, width, height, true);
16506
16507							newWidth = dims.width,
16508								newHeight = dims.height;
16509						} else if (viewport.toLowerCase() == 'stretch') {
16510							newWidth = newWidth,
16511								newHeight = newHeight;
16512						} else {
16513							var scale = (width > newWidth || height > newHeight) ? true : false,
16514								dims = iL.getNewDimenstions(newWidth, newHeight, width, height, scale);
16515							newWidth = dims.width,
16516								newHeight = dims.height;
16517						}
16518
16519						currentHolder.data({
16520							naturalWidthOld: currentHolder.data('naturalWidth'),
16521							naturalHeightOld: currentHolder.data('naturalHeight'),
16522							naturalWidth: newWidth,
16523							naturalHeight: newHeight
16524						});
16525					}
16526
16527					$.each(elements, function(key, val) {
16528						val.addClass('ilightbox-fullscreen');
16529					});
16530
16531					//Trigger the onEnterFullScreen callback
16532					if (typeof opts.callback.onEnterFullScreen == 'function') opts.callback.onEnterFullScreen.call(iL, iL.ui);
16533				} else {
16534					vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = false;
16535					vars.overlay.css({
16536						opacity: iL.options.overlay.opacity
16537					});
16538
16539					$.each(hideElements, function(i, element) {
16540						element.show();
16541					});
16542
16543					vars.fullScreenButton.attr('title', opts.text.enterFullscreen);
16544
16545					currentHolder.data({
16546						naturalWidth: currentHolder.data('naturalWidthOld'),
16547						naturalHeight: currentHolder.data('naturalHeightOld'),
16548						naturalWidthOld: null,
16549						naturalHeightOld: null
16550					});
16551
16552					$.each(elements, function(key, val) {
16553						val.removeClass('ilightbox-fullscreen');
16554					});
16555
16556					//Trigger the onExitFullScreen callback
16557					if (typeof opts.callback.onExitFullScreen == 'function') opts.callback.onExitFullScreen.call(iL, iL.ui);
16558				}
16559			} else {
16560				if (!vars.isInFullScreen) vars.isInFullScreen = true;
16561				else vars.isInFullScreen = false;
16562			}
16563			iL.repositionPhoto(true);
16564		},
16565
16566		closeAction: function() {
16567			var iL = this,
16568				vars = iL.vars,
16569				opts = iL.options;
16570
16571			$win.unbind('.iLightBox');
16572			$doc.off('.iLightBox');
16573
16574			if (vars.isInFullScreen) fullScreenApi.cancelFullScreen(document.documentElement);
16575
16576			$('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails').off('.iLightBox');
16577
16578			if (opts.hide.effect) vars.overlay.stop().fadeOut(opts.hide.speed, function() {
16579				vars.overlay.remove();
16580				vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox');
16581			});
16582			else {
16583				vars.overlay.remove();
16584				vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox');
16585			}
16586
16587			var fadeOuts = [vars.toolbar, vars.holder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails];
16588
16589			$.each(fadeOuts, function(i, element) {
16590				element.removeAttr('style').remove();
16591			});
16592
16593			vars.dontGenerateThumbs = vars.isInFullScreen = false;
16594
16595			window.iLightBox = null;
16596
16597			if (opts.linkId) {
16598				vars.hashLock = true;
16599				removeHash();
16600				setTimeout(function() {
16601					vars.hashLock = false;
16602				}, 55);
16603			}
16604
16605			vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
16606
16607			//Trigger the onHide callback
16608			if (typeof opts.callback.onHide == 'function') opts.callback.onHide.call(iL, iL.ui);
16609		},
16610
16611		repositionPhoto: function() {
16612			var iL = this,
16613				vars = iL.vars,
16614				opts = iL.options,
16615				path = opts.path.toLowerCase(),
16616				viewport = getViewport(),
16617				winWidth = viewport.width,
16618				winHeight = viewport.height;
16619
16620			if (viewport.width < UNCODE.mediaQuery) opts.styles.nextOffsetX = 0;
16621
16622			var thumbsOffsetW = (vars.isInFullScreen && opts.fullAlone || vars.isMobile) ? 0 : ((path == 'horizontal') ? 0 : vars.thumbnails.outerWidth()),
16623				thumbsOffsetH = vars.isMobile ? vars.toolbar.outerHeight() : ((vars.isInFullScreen && opts.fullAlone) ? 0 : ((path == 'horizontal') ? vars.thumbnails.outerHeight() : 0)),
16624				width = (vars.isInFullScreen && opts.fullAlone) ? winWidth : (winWidth - (opts.styles.pageOffsetX)),
16625				height = (vars.isInFullScreen && opts.fullAlone) ? winHeight : (winHeight - (opts.styles.pageOffsetY)),
16626				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,
16627				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)));
16628
16629			var elObject = {
16630				type: 'current',
16631				width: width,
16632				height: height,
16633				item: iL.items[vars.current],
16634				offsetW: offsetW,
16635				offsetH: offsetH,
16636				thumbsOffsetW: thumbsOffsetW,
16637				thumbsOffsetH: thumbsOffsetH,
16638				animate: arguments.length,
16639				holder: vars.holder
16640			};
16641
16642			iL.repositionEl(elObject);
16643
16644			if (iL.items[vars.next]) {
16645				elObject = $.extend(elObject, {
16646					type: 'next',
16647					item: iL.items[vars.next],
16648					offsetX: opts.styles.nextOffsetX,
16649					offsetY: opts.styles.nextOffsetY,
16650					holder: vars.nextPhoto
16651				});
16652
16653				iL.repositionEl(elObject);
16654			}
16655
16656			if (iL.items[vars.prev]) {
16657				elObject = $.extend(elObject, {
16658					type: 'prev',
16659					item: iL.items[vars.prev],
16660					offsetX: opts.styles.nextOffsetX,
16661					offsetY: opts.styles.prevOffsetY,
16662					holder: vars.prevPhoto
16663				});
16664
16665				iL.repositionEl(elObject);
16666			}
16667
16668			var loaderCss = (path == "horizontal") ? {
16669				left: parseInt((width / 2) - (vars.loader.outerWidth() / 2))
16670			} : {
16671				top: parseInt((height / 2) - (vars.loader.outerHeight() / 2))
16672			};
16673			vars.loader.css(loaderCss);
16674		},
16675
16676		repositionEl: function(obj) {
16677			var iL = this,
16678				vars = iL.vars,
16679				opts = iL.options,
16680				path = opts.path.toLowerCase(),
16681				widthAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.width : (obj.width - obj.offsetW)) : (obj.width - obj.offsetW),
16682				heightAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.height : (obj.height - obj.offsetH)) : (obj.height - obj.offsetH),
16683				itemParent = obj.item,
16684				item = obj.item.options,
16685				holder = obj.holder,
16686				offsetX = obj.offsetX || 0,
16687				offsetY = obj.offsetY || 0,
16688				//Uncode change ##START##
16689				toolbarHeight = $('.ilightbox-inner-toolbar', holder).length ? parseInt( $('.ilightbox-inner-toolbar', holder).outerHeight() ) : 0,
16690				//Uncode change ##END##
16691				thumbsOffsetW = obj.thumbsOffsetW,
16692				thumbsOffsetH = obj.thumbsOffsetH;
16693
16694			if (obj.type == 'current') {
16695				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);
16696				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);
16697			} else {
16698				if (typeof item.width == 'number' && item.width) widthAvail = (item.width > widthAvail) ? widthAvail : item.width;
16699				if (typeof item.height == 'number' && item.height) heightAvail = (item.height > heightAvail) ? heightAvail : item.height;
16700			}
16701
16702
16703			//Uncode change ##START##
16704			heightAvail = parseInt(heightAvail - toolbarHeight);
16705			// heightAvail = parseInt(heightAvail - $('.ilightbox-inner-toolbar', holder).outerHeight());
16706			//Uncode change ##END##
16707
16708			var width = (typeof item.width == 'string' && item.width.indexOf('%') != -1) ? percentToValue(parseInt(item.width.replace('%', '')), obj.width) : holder.data('naturalWidth'),
16709				height = (typeof item.height == 'string' && item.height.indexOf('%') != -1) ? percentToValue(parseInt(item.height.replace('%', '')), obj.height) : holder.data('naturalHeight');
16710
16711			var dims = ((typeof item.width == 'string' && item.width.indexOf('%') != -1 || typeof item.height == 'string' && item.height.indexOf('%') != -1) ? {
16712					width: width,
16713					height: height
16714				} : iL.getNewDimenstions(widthAvail, heightAvail, width, height)),
16715				newDims = $.extend({}, dims, {});
16716
16717			if (obj.type == 'prev' || obj.type == 'next')
16718				width = parseInt(dims.width * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale)),
16719				height = parseInt(dims.height * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale));
16720			else
16721				width = dims.width,
16722				height = dims.height;
16723
16724			var widthDiff = parseInt((getPixel(holder, 'padding-left') + getPixel(holder, 'padding-right') + getPixel(holder, 'border-left-width') + getPixel(holder, 'border-right-width')) / 2),
16725				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);
16726
16727			switch (obj.type) {
16728				case 'current':
16729					var top = parseInt((obj.height / 2) - (height / 2) - heightDiff - (thumbsOffsetH / 2)),
16730						left = parseInt((obj.width / 2) - (width / 2) - widthDiff - (thumbsOffsetW / 2));
16731					break;
16732
16733				case 'next':
16734					var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(obj.height - offsetX - heightDiff - (thumbsOffsetH / 2)),
16735						left = (path == 'horizontal') ? parseInt(obj.width - offsetX - widthDiff - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - (width / 2) - widthDiff - offsetY - (thumbsOffsetW / 2));
16736					break;
16737
16738				case 'prev':
16739					var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(offsetX - heightDiff - height - (thumbsOffsetH / 2)),
16740						left = (path == 'horizontal') ? parseInt(offsetX - widthDiff - width - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - offsetY - (width / 2) - widthDiff - (thumbsOffsetW / 2));
16741					break;
16742			}
16743
16744			holder.data('offset', {
16745				top: top,
16746				left: left,
16747				newDims: newDims,
16748				diff: {
16749					W: widthDiff,
16750					H: heightDiff
16751				},
16752				thumbsOffset: {
16753					W: thumbsOffsetW,
16754					H: thumbsOffsetH
16755				},
16756				object: obj
16757			});
16758
16759			var opacityMobile;
16760			if ( isMobile ) {
16761				opacityMobile = {
16762					opacity: 1,
16763					top: top,
16764					left: left
16765				};
16766			} else {
16767				opacityMobile = {
16768					top: top,
16769					left: left
16770				};
16771			}
16772
16773			if (obj.animate > 0 && opts.effects.reposition) {
16774				holder.css(transform, gpuAcceleration).stop().animate(
16775					opacityMobile,
16776					opts.effects.repositionSpeed, 'easeOutCirc', function() {
16777					holder.css(transform, '');
16778				});
16779				$('div.ilightbox-container', holder).stop().animate({
16780					width: width,
16781					height: height
16782				}, opts.effects.repositionSpeed, 'easeOutCirc');
16783				$('div.ilightbox-inner-toolbar', holder).stop().animate({
16784					width: width
16785				}, opts.effects.repositionSpeed, 'easeOutCirc', function() {
16786					$(this).css('overflow', 'visible');
16787				});
16788			} else {
16789				holder.css(opacityMobile);
16790				$('div.ilightbox-container', holder).css({
16791					width: width,
16792					height: height
16793				});
16794				$('div.ilightbox-inner-toolbar', holder).css({
16795					width: width
16796				});
16797			}
16798		},
16799
16800
16801		resume: function(priority) {
16802			var iL = this,
16803				vars = iL.vars,
16804				opts = iL.options;
16805
16806			if (!opts.slideshow.pauseTime || opts.controls.slideshow && vars.total <= 1 || priority < vars.isPaused) {
16807				return;
16808			}
16809
16810			vars.isPaused = 0;
16811
16812			if (vars.cycleID) {
16813				vars.cycleID = clearTimeout(vars.cycleID);
16814			}
16815
16816			vars.cycleID = setTimeout(function() {
16817				if (vars.current == vars.total - 1) iL.goTo(0);
16818				else iL.moveTo('next');
16819			}, opts.slideshow.pauseTime);
16820		},
16821
16822		pause: function(priority) {
16823			var iL = this,
16824				vars = iL.vars,
16825				opts = iL.options;
16826
16827			if (priority < vars.isPaused) {
16828				return;
16829			}
16830
16831			vars.isPaused = priority || 100;
16832
16833			if (vars.cycleID) {
16834				vars.cycleID = clearTimeout(vars.cycleID);
16835			}
16836		},
16837
16838		resetCycle: function() {
16839			var iL = this,
16840				vars = iL.vars,
16841				opts = iL.options;
16842
16843			if (opts.controls.slideshow && vars.cycleID && !vars.isPaused) {
16844				iL.resume();
16845			}
16846		},
16847
16848		getNewDimenstions: function(width, height, width_old, height_old, thumb) {
16849			var iL = this;
16850
16851			if (!width) factor = height / height_old;
16852			else if (!height) factor = width / width_old;
16853			else factor = min(width / width_old, height / height_old);
16854
16855			if (!thumb) {
16856				if (factor > iL.options.maxScale) factor = iL.options.maxScale;
16857				else if (factor < iL.options.minScale) factor = iL.options.minScale;
16858			}
16859
16860			var final_width = (iL.options.keepAspectRatio) ? round(width_old * factor) : width,
16861				final_height = (iL.options.keepAspectRatio) ? round(height_old * factor) : height;
16862
16863			return {
16864				width: final_width,
16865				height: final_height,
16866				ratio: factor
16867			};
16868		},
16869
16870		setOption: function(options) {
16871			var iL = this;
16872
16873			iL.options = $.extend(true, iL.options, options || {});
16874			iL.refresh();
16875		},
16876
16877		availPlugins: function() {
16878			var iL = this,
16879				testEl = document.createElement("video");
16880
16881			iL.plugins = {
16882				flash: !isMobile,
16883				quicktime: (parseInt(PluginDetect.getVersion("QuickTime")) >= 0) ? true : false,
16884				html5H264: !!(testEl.canPlayType && testEl.canPlayType('video/mp4').replace(/no/, '')),
16885				html5WebM: !!(testEl.canPlayType && testEl.canPlayType('video/webm').replace(/no/, '')),
16886				html5Vorbis: !!(testEl.canPlayType && testEl.canPlayType('video/ogg').replace(/no/, '')),
16887				html5QuickTime: !!(testEl.canPlayType && testEl.canPlayType('video/quicktime').replace(/no/, ''))
16888			};
16889		},
16890
16891		addContent: function(element, obj) {
16892			var iL = this,
16893				el;
16894
16895			switch (obj.type) {
16896				case 'video':
16897					var HTML5 = false,
16898						videoType = obj.videoType,
16899						html5video = obj.options.html5video;
16900
16901					if (((videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v') || html5video.h264) && iL.plugins.html5H264)
16902						obj.ext = 'mp4',
16903						obj.URL = html5video.h264 || obj.URL;
16904					else if (html5video.webm && iL.plugins.html5WebM)
16905						obj.ext = 'webm',
16906						obj.URL = html5video.webm || obj.URL;
16907					else if (html5video.ogg && iL.plugins.html5Vorbis)
16908						obj.ext = 'ogv',
16909						obj.URL = html5video.ogg || obj.URL;
16910
16911					if (iL.plugins.html5H264 && (videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v')) HTML5 = true, videoType = "video/mp4";
16912					else if (iL.plugins.html5WebM && (videoType == 'video/webm' || obj.ext == 'webm')) HTML5 = true, videoType = "video/webm";
16913					else if (iL.plugins.html5Vorbis && (videoType == 'video/ogg' || obj.ext == 'ogv')) HTML5 = true, videoType = "video/ogg";
16914					else if (iL.plugins.html5QuickTime && (videoType == 'video/quicktime' || obj.ext == 'mov' || obj.ext == 'qt')) HTML5 = true, videoType = "video/quicktime";
16915
16916					if (HTML5) {
16917						el = $('<video />
16917', {
16918							"width": "100%",
16919							"height": "100%",
16920							"preload": html5video.preload,
16921							"autoplay": html5video.autoplay,
16922							"loop": html5video.loop,
16923							"poster": html5video.poster,
16924							"controls": html5video.controls,
16925							"controlslist": "nodownload"
16926						}).append($('<source />', {
16927							"src": obj.URL,
16928							"type": videoType
16929						}));
16930					} else {
16931						if (!iL.plugins.quicktime) el = $('<span />', {
16932							"class": "ilightbox-alert",
16933							html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.quicktime).replace('{type}', 'QuickTime')
16934						});
16935						else {
16936
16937							el = $('<object />', {
16938								"type": "video/quicktime",
16939								"pluginspage": pluginspages.quicktime
16940							}).attr({
16941								"data": obj.URL,
16942								"width": "100%",
16943								"height": "100%"
16944							}).append($('<param />', {
16945								"name": "src",
16946								"value": obj.URL
16947							})).append($('<param />', {
16948								"name": "autoplay",
16949								"value": "false"
16950							})).append($('<param />', {
16951								"name": "loop",
16952								"value": "false"
16953							})).append($('<param />', {
16954								"name": "scale",
16955								"value": "tofit"
16956							}));
16957
16958							if (browser.msie) el = QT_GenerateOBJECTText(obj.URL, '100%', '100%', '', 'SCALE', 'tofit', 'AUTOPLAY', 'false', 'LOOP', 'false');
16959						}
16960					}
16961
16962					break;
16963
16964				case 'flash':
16965					if (!iL.plugins.flash) el = $('<span />', {
16966						"class": "ilightbox-alert",
16967						html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.flash).replace('{type}', 'Adobe Flash player')
16968					});
16969					else {
16970						var flashvars = "",
16971							i = 0;
16972
16973						if (obj.options.flashvars) $.each(obj.options.flashvars, function(k, v) {
16974							if (i != 0) flashvars += "&";
16975							flashvars += k + "=" + encodeURIComponent(v);
16976							i++;
16977						});
16978						else flashvars = null;
16979
16980						el = $('<embed />').attr({
16981							"type": "application/x-shockwave-flash",
16982							"src": obj.URL,
16983							"width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%",
16984							"height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%",
16985							"quality": "high",
16986							"bgcolor": "#000000",
16987							"play": "true",
16988							"loop": "true",
16989							"menu": "true",
16990							"wmode": "transparent",
16991							"scale": "showall",
16992							"allowScriptAccess": "always",
16993							"allowFullScreen": "true",
16994							"flashvars": flashvars,
16995							"fullscreen": "yes"
16996						});
16997					}
16998
16999					break;
17000
17001				case 'iframe':
17002					el = $('<iframe />').attr({
17003						"width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%",
17004						"height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%",
17005						src: obj.URL,
17006						frameborder: 0,
17007						'hspace': 0,
17008						'vspace': 0,
17009						'scrolling': supportTouch ? 'auto' : 'scroll',
17010						'webkitAllowFullScreen': '',
17011						'mozallowfullscreen': '',
17012						'allowFullScreen': ''
17013					});
17014
17015					break;
17016
17017				case 'inline':
17018					el = $('<div class="ilightbox-wrapper"></div>').html($(obj.URL).clone(true));
17019
17020					break;
17021
17022				case 'html':
17023					var object = obj.URL,
17024						el;
17025
17026					if (object[0].nodeName) {
17027						el = $('<div class="ilightbox-wrapper"></div>').html(object);
17028					} else {
17029						var dom = $(obj.URL),
17030							html = (dom.selector) ? $('<div>' + dom + '</div>') : dom;
17031						el = $('<div class="ilightbox-wrapper"></div>').html(html);
17032					}
17033
17034					break;
17035			}
17036
17037			$('div.ilightbox-container', element).empty().html(el);
17038
17039			// For fixing Chrome about just playing the video for first time
17040			if (el[0].tagName.toLowerCase() === 'video' && browser.webkit) setTimeout(function() {
17041				var src = el[0].currentSrc + '?' + floor(random() * 30000);
17042				el[0].currentSrc = src;
17043				el[0].src = src;
17044			});
17045
17046			return el;
17047		},
17048
17049		ogpRecognition: function(obj, callback) {
17050			var iL = this,
17051				url = obj.URL;
17052
17053			iL.showLoader();
17054			doAjax(url, function(data) {
17055				iL.hideLoader();
17056				if (data) {
17057					var object = new Object();
17058
17059					object.length = false,
17060					object.url = data.url;
17061
17062					if (data.status == 200) {
17063						var result = data.results,
17064							type = result.type,
17065							source = result.source;
17066
17067						object.source = source.src,
17068						object.width = source.width && parseInt(source.width) || 0,
17069						object.height = source.height && parseInt(source.height) || 0,
17070						object.type = type,
17071						object.thumbnail = source.thumbnail || result.images && result.images[0],
17072						object.html5video = result.html5video || {},
17073						object.length = true;
17074
17075						if (source.type == 'application/x-shockwave-flash') object.type = "flash";
17076						else if (source.type.indexOf("video/") != -1) object.type = "video";
17077						else if (source.type.indexOf("/html") != -1) object.type = "iframe";
17078						else if (source.type.indexOf("image/") != -1) object.type = "image";
17079
17080					} else if (typeof data.response != 'undefined')
17081						throw data.response;
17082
17083					callback.call(this, object.length ? object : false);
17084				}
17085			});
17086		},
17087
17088		hashChangeHandler: function(url) {
17089			var iL = this,
17090				vars = iL.vars,
17091				opts = iL.options,
17092				URL = url || window.location.href,
17093				hash = parseURI(URL).hash,
17094				split = hash.split('/'),
17095				index = split[1];
17096
17097			if (vars.hashLock || ('#' + opts.linkId != split[0] && hash.length > 1)) return;
17098
17099			if (index) {
17100				var target = split[1] || 0;
17101				if (iL.items[target]) {
17102					var overlay = $('.ilightbox-overlay');
17103					if (overlay.length && overlay.attr('linkid') == opts.linkId) {
17104						iL.goTo(target);
17105					} else {
17106						iL.itemsObject[target].trigger(ishybrid ? "itap click" : supportTouch ? 'itap' : 'click');
17107						//iL.goTo(target);
17108					}
17109				} else {
17110					var overlay = $('.ilightbox-overlay');
17111					if (overlay.length) iL.closeAction();
17112				}
17113			} else {
17114				var overlay = $('.ilightbox-overlay');
17115				if (overlay.length) iL.closeAction();
17116			}
17117		}
17118	};
17119
17120	/**
17121	 * Parse style to pixels.
17122	 *
17123	 * @param {Object}   $element   jQuery object with element.
17124	 * @param {Property} property   CSS property to get the pixels from.
17125	 *
17126	 * @return {Int}
17127	 */
17128	function getPixel($element, property) {
17129		return parseInt($element.css(property), 10) || 0;
17130	}
17131
17132	/**
17133	 * Make sure that number is within the limits.
17134	 *
17135	 * @param {Number} number
17136	 * @param {Number} min
17137	 * @param {Number} max
17138	 *
17139	 * @return {Number}
17140	 */
17141	function within(number, min, max) {
17142		return number < min ? min : number > max ? max : number;
17143	}
17144
17145	/**
17146	 * Get viewport/window size (width and height).
17147	 *
17148	 * @return {Object}
17149	 */
17150	function getViewport() {
17151		var e = window,
17152			a = 'inner';
17153		if (!('innerWidth' in window)) {
17154			a = 'client';
17155			e = document.documentElement || document.body;
17156		}
17157		return {
17158			width: e[a + 'Width'],
17159			height: e[a + 'Height']
17160		}
17161	}
17162
17163	/**
17164	 * Remove hash tag from the URL
17165	 *
17166	 * @return {Void}
17167	 */
17168	function removeHash() {
17169		var scroll = getScrollXY();
17170
17171		//UNCODE change
17172		// window.location.hash = "";
17173		// history.pushState("", document.title, window.location.pathname + window.location.search);
17174		history.replaceState({}, document.title, window.location.pathname + window.location.search);
17175
17176		// Restore the scroll offset, should be flicker free
17177		window.scrollTo(scroll.x, scroll.y);
17178	}
17179
17180	/**
17181	 * Do the ajax requests with callback.
17182	 *
17183	 * @param {String}   url
17184	 * @param {Function} callback
17185	 *
17186	 * @return {Void}
17187	 */
17188	function doAjax(url, callback) {
17189		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');
17190		$.ajax({
17191			url: url,
17192			dataType: 'jsonp'
17193		});
17194
17195		iLCallback = function(data) {
17196			callback.call(this, data);
17197		};
17198	}
17199
17200	/**
17201	 * Find image from DOM elements
17202	 *
17203	 * @param {Element} element
17204	 *
17205	 * @return {Void}
17206	 */
17207	function findImageInElement(element) {
17208		var elements = $('*', element),
17209			imagesArr = new Array();
17210
17211		elements.each(function() {
17212			var url = "",
17213				element = this;
17214
17215			if ($(element).css("background-image") != "none") {
17216				url = $(element).css("background-image");
17217			} else if (typeof($(element).attr("src")) != "undefined" && element.nodeName.toLowerCase() == "img") {
17218				url = $(element).attr("src");
17219			}
17220
17221			if (url.indexOf("gradient") == -1) {
17222				url = url.replace(/url\(\"/g, "");
17223				url = url.replace(/url\(/g, "");
17224				url = url.replace(/\"\)/g, "");
17225				url = url.replace(/\)/g, "");
17226
17227				var urls = url.split(",");
17228
17229				for (var i = 0; i < urls.length; i++) {
17230					if (urls[i].length > 0 && $.inArray(urls[i], imagesArr) == -1) {
17231						var extra = "";
17232						if (browser.msie && browser.version < 9) {
17233							extra = "?" + floor(random() * 3000);
17234						}
17235						imagesArr.push(urls[i] + extra);
17236					}
17237				}
17238			}
17239		});
17240
17241		return imagesArr;
17242	}
17243
17244	/**
17245	 * Get file extension.
17246	 *
17247	 * @param {String} URL
17248	 *
17249	 * @return {String}
17250	 */
17251	function getExtension(URL) {
17252		if (URL !== null) {
17253			//UNCODE: fix issue to detect media type with query strings
17254			var ext = URL.indexOf('?') !== -1 ? URL.split('?')[0] : URL;
17255			ext = ext.split('.').pop().toLowerCase();
17256
17257			return ext;
17258		}
17259	}
17260
17261	/**
17262	 * Get type via extension.
17263	 *
17264	 * @param {String} URL
17265	 *
17266	 * @return {String}
17267	 */
17268	function getTypeByExtension(URL) {
17269		var type,
17270			ext = getExtension(URL);
17271
17272		//Uncode addition ##START##
17273		if (URL == undefined) {
17274			return false;
17275		}
17276		//Uncode addition ##END##
17277
17278		if (extensions.image.indexOf(ext) !== -1) type = 'image';
17279		else if (extensions.flash.indexOf(ext) !== -1) type = 'flash';
17280		else if (extensions.video.indexOf(ext) !== -1) type = 'video';
17281		else if (ext.substring(0, 1) == "#") type = 'inline'; //Uncode addition
17282		else type = 'iframe';
17283
17284		return type;
17285	}
17286
17287	/**
17288	 * Return value from percent of a number.
17289	 *
17290	 * @param {Number} percent
17291	 * @param {Number} total
17292	 *
17293	 * @return {Number}
17294	 */
17295	function percentToValue(percent, total) {
17296		return parseInt((total / 100) * percent);
17297	}
17298
17299	/**
17300	 * A JavaScript equivalent of PHP’s parse_url.
17301	 *
17302	 * @param {String} url           The URL to parse.
17303	 *
17304	 * @return {Mixed}
17305	 */
17306	function parseURI(url) {
17307		var m = String(url).replace(/^\s+|\s+$/g, '').match(/^([^:\/?#]+:)?(\/\/(?:[^:@]*(?::[^:@]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/);
17308		// authority = '//' + user + ':' + pass '@' + hostname + ':' port
17309		return (m ? {
17310			href: m[0] || '',
17311			protocol: m[1] || '',
17312			authority: m[2] || '',
17313			host: m[3] || '',
17314			hostname: m[4] || '',
17315			port: m[5] || '',
17316			pathname: m[6] || '',
17317			search: m[7] || '',
17318			hash: m[8] || ''
17319		} : null);
17320	}
17321
17322	/**
17323	 * Gets the absolute URI.
17324	 *
17325	 * @param {String} href     The relative URL.
17326	 * @param {String} base     The base URL.
17327	 *
17328	 * @return {String}         The absolute URL.
17329	 */
17330	function absolutizeURI(base, href) { // RFC 3986
17331		var iL = this;
17332
17333		function removeDotSegments(input) {
17334			var output = [];
17335			input.replace(/^(\.\.?(\/|$))+/, '')
17336				.replace(/\/(\.(\/|$))+/g, '/')
17337				.replace(/\/\.\.$/, '/../')
17338				.replace(/\/?[^\/]*/g, function(p) {
17339					if (p === '/..') {
17340						output.pop();
17341					} else {
17342						output.push(p);
17343					}
17344				});
17345			return output.join('').replace(/^\//, input.charAt(0) === '/' ? '/' : '');
17346		}
17347
17348		href = parseURI(href || '');
17349		base = parseURI(base || '');
17350
17351		return !href || !base ? null : (href.protocol || base.protocol) +
17352			(href.protocol || href.authority ? href.authority : base.authority) +
17353			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)) +
17354			(href.protocol || href.authority || href.pathname ? href.search : (href.search || base.search)) +
17355			href.hash;
17356	}
17357
17358	/**
17359	 * A JavaScript equivalent of PHP’s version_compare.
17360	 *
17361	 * @param {String} v1
17362	 * @param {String} v2
17363	 * @param {String} operator
17364	 *
17365	 * @return {Boolean}
17366	 */
17367	function version_compare(v1, v2, operator) {
17368		this.php_js = this.php_js || {};
17369		this.php_js.ENV = this.php_js.ENV || {};
17370		var i = 0,
17371			x = 0,
17372			compare = 0,
17373			vm = {
17374				'dev': -6,
17375				'alpha': -5,
17376				'a': -5,
17377				'beta': -4,
17378				'b': -4,
17379				'RC': -3,
17380				'rc': -3,
17381				'#': -2,
17382				'p': 1,
17383				'pl': 1
17384			},
17385			prepVersion = function(v) {
17386				v = ('' + v).replace(/[_\-+]/g, '.');
17387				v = v.replace(/([^.\d]+)/g, '.$1.').replace(/\.{2,}/g, '.');
17388				return (!v.length ? [-8] : v.split('.'));
17389			},
17390			numVersion = function(v) {
17391				return !v ? 0 : (isNaN(v) ? vm[v] || -7 : parseInt(v, 10));
17392			};
17393		v1 = prepVersion(v1);
17394		v2 = prepVersion(v2);
17395		x = max(v1.length, v2.length);
17396		for (i = 0; i < x; i++) {
17397			if (v1[i] == v2[i]) {
17398				continue;
17399			}
17400			v1[i] = numVersion(v1[i]);
17401			v2[i] = numVersion(v2[i]);
17402			if (v1[i] < v2[i]) {
17403				compare = -1;
17404				break;
17405			} else if (v1[i] > v2[i]) {
17406				compare = 1;
17407				break;
17408			}
17409		}
17410		if (!operator) {
17411			return compare;
17412		}
17413
17414		switch (operator) {
17415			case '>':
17416			case 'gt':
17417				return (compare > 0);
17418			case '>=':
17419			case 'ge':
17420				return (compare >= 0);
17421			case '<=':
17422			case 'le':
17423				return (compare <= 0);
17424			case '==':
17425			case '=':
17426			case 'eq':
17427				return (compare === 0);
17428			case '<>':
17429			case '!=':
17430			case 'ne':
17431				return (compare !== 0);
17432			case '':
17433			case '<':
17434			case 'lt':
17435				return (compare < 0);
17436			default:
17437				return null;
17438		}
17439	}
17440
17441
17442	// Begin the iLightBox plugin
17443	$.fn.iLightBox = function() {
17444
17445		var args = arguments,
17446			opt = ($.isPlainObject(args[0])) ? args[0] : args[1],
17447			items = ($.isArray(args[0]) || typeof args[0] == 'string') ? args[0] : args[1];
17448
17449		if (!opt) opt = {};
17450
17451		// Default options. Play carefully.
17452		var options = $.extend(true, {
17453			attr: 'href',
17454			path: 'vertical',
17455			skin: 'dark',
17456			linkId: false,
17457			infinite: false,
17458			startFrom: 0,
17459			randomStart: false,
17460			keepAspectRatio: true,
17461			maxScale: 1,
17462			minScale: .2,
17463			innerToolbar: false,
17464			smartRecognition: false,
17465			mobileOptimizer: true,
17466			fullAlone: true,
17467			fullViewPort: null,
17468			fullStretchTypes: 'flash, video',
17469			overlay: {
17470				blur: true,
17471				opacity: .85
17472			},
17473			controls: {
17474				arrows: false,
17475				slideshow: false,
17476				toolbar: true,
17477				fullscreen: true,
17478				thumbnail: true,
17479				keyboard: true,
17480				mousewheel: true,
17481				swipe: true
17482			},
17483			keyboard: {
17484				left: true, // previous
17485				right: true, // next
17486				up: true, // previous
17487				down: true, // next
17488				esc: true, // close
17489				shift_enter: true // fullscreen
17490			},
17491			show: {
17492				effect: true,
17493				speed: 300,
17494				title: true
17495			},
17496			hide: {
17497				effect: true,
17498				speed: 300
17499			},
17500			caption: {
17501				start: true,
17502				show: 'mouseenter',
17503				hide: 'mouseleave'
17504			},
17505			social: {
17506				start: true,
17507				show: 'mouseenter',
17508				hide: 'mouseleave',
17509				buttons: false
17510			},
17511			styles: {
17512				pageOffsetX: 0,
17513				pageOffsetY: 0,
17514				nextOffsetX: 45,
17515				nextOffsetY: 0,
17516				nextOpacity: 1,
17517				nextScale: 1,
17518				prevOffsetX: 45,
17519				prevOffsetY: 0,
17520				prevOpacity: 1,
17521				prevScale: 1
17522			},
17523			thumbnails: {
17524				maxWidth: 120,
17525				maxHeight: 80,
17526				normalOpacity: 1,
17527				activeOpacity: .6
17528			},
17529			effects: {
17530				reposition: true,
17531				repositionSpeed: 200,
17532				switchSpeed: 500,
17533				loadedFadeSpeed: 180,
17534				fadeSpeed: 200
17535			},
17536			slideshow: {
17537				pauseTime: 5000,
17538				pauseOnHover: false,
17539				startPaused: true
17540			},
17541			text: {
17542				close: "Press Esc to close",
17543				enterFullscreen: "Enter Fullscreen (Shift+Enter)",
17544				exitFullscreen: "Exit Fullscreen (Shift+Enter)",
17545				slideShow: "Slideshow",
17546				next: "Next",
17547				previous: "Previous"
17548			},
17549			errors: {
17550				loadImage: "An error occurred when trying to load photo.",
17551				loadContents: "An error occurred when trying to load contents.",
17552				missingPlugin: "The content your are attempting to view requires the <a href='{pluginspage}' target='_blank'>{type} plugin<\/a>."
17553			},
17554			ajaxSetup: {
17555				url: '',
17556				beforeSend: function(jqXHR, settings) {},
17557				cache: false,
17558				complete: function(jqXHR, textStatus) {},
17559				crossDomain: false,
17560				error: function(jqXHR, textStatus, errorThrown) {},
17561				success: function(data, textStatus, jqXHR) {},
17562				global: true,
17563				ifModified: false,
17564				username: null,
17565				password: null,
17566				type: 'GET'
17567			},
17568			callback: {}
17569		}, opt);
17570
17571		var instant = ($.isArray(items) || typeof items == 'string') ? true : false;
17572
17573		items = $.isArray(items) ? items : new Array();
17574
17575		if (typeof args[0] == 'string') items[0] = args[0];
17576
17577		if (version_compare($.fn.jquery, '1.8', '>=')) {
17578			var iLB = new iLightBox($(this), options, items, instant);
17579			return {
17580				close: function() {
17581					iLB.closeAction();
17582				},
17583				fullscreen: function() {
17584					iLB.fullScreenAction();
17585				},
17586				moveNext: function() {
17587					iLB.moveTo('next');
17588				},
17589				movePrev: function() {
17590					iLB.moveTo('prev');
17591				},
17592				goTo: function(index) {
17593					iLB.goTo(index);
17594				},
17595				refresh: function() {
17596					iLB.refresh();
17597				},
17598				reposition: function() {
17599					(arguments.length > 0) ? iLB.repositionPhoto(true): iLB.repositionPhoto();
17600				},
17601				setOption: function(options) {
17602					iLB.setOption(options);
17603				},
17604				destroy: function() {
17605					iLB.closeAction();
17606					iLB.dispatchItemsEvents();
17607				}
17608			};
17609		} else {
17610			throw "The jQuery version that was loaded is too old. iLightBox requires jQuery 1.8+";
17611		}
17612
17613	};
17614
17615
17616	$.iLightBox = function() {
17617		return $.fn.iLightBox(arguments[0], arguments[1]);
17618	};
17619
17620	function getScrollXY() {
17621		var scrOfX = 0,
17622			scrOfY = 0;
17623		if (typeof(window.pageYOffset) == 'number') {
17624			//Netscape compliant
17625			scrOfY = window.pageYOffset;
17626			scrOfX = window.pageXOffset;
17627		} else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) {
17628			//DOM compliant
17629			scrOfY = document.body.scrollTop;
17630			scrOfX = document.body.scrollLeft;
17631		} else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
17632			//IE6 standards compliant mode
17633			scrOfY = document.documentElement.scrollTop;
17634			scrOfX = document.documentElement.scrollLeft;
17635		}
17636		return {
17637			x: scrOfX,
17638			y: scrOfY
17639		};
17640	}
17641
17642	(function() {
17643		// add new event shortcuts
17644		$.each(("touchstart touchmove touchend " +
17645			"tap taphold " +
17646			"swipe swipeleft swiperight " +
17647			"scrollstart scrollstop").split(" "), function(i, name) {
17648
17649			$.fn[name] = function(fn) {
17650				return fn ? this.bind(name, fn) : this.trigger(name);
17651			};
17652
17653			// jQuery < 1.8
17654			// if ($.attrFn) {
17655			// 	$.attrFn[name] = true;
17656			// }
17657		});
17658
17659		var tapSettings = {
17660			startEvent: 'touchstart.iTap',
17661			endEvent: 'touchend.iTap'
17662		};
17663
17664		// tap Event:
17665		$.event.special.itap = {
17666			setup: function() {
17667
17668				var self = this,
17669					$self = $(this),
17670					start, stop;
17671
17672				$self.bind(tapSettings.startEvent, function(event) {
17673					start = getScrollXY();
17674
17675					$self.one(tapSettings.endEvent, function(event) {
17676						stop = getScrollXY();
17677
17678						var orgEvent = event || window.event;
17679						event = $.event.fix(orgEvent);
17680						event.type = "itap";
17681
17682						if ((start && stop) && (start.x == stop.x && start.y == stop.y))($.event.dispatch || $.event.handle).call(self, event);
17683
17684						start = stop = undefined;
17685					});
17686				});
17687			},
17688
17689			teardown: function() {
17690				$(this).unbind(tapSettings.startEvent);
17691			}
17692		};
17693	}());
17694
17695
17696	//Fullscreen API
17697	(function() {
17698		fullScreenApi = {
17699				supportsFullScreen: false,
17700				isFullScreen: function() {
17701					return false;
17702				},
17703				requestFullScreen: function() {},
17704				cancelFullScreen: function() {},
17705				fullScreenEventName: '',
17706				prefix: ''
17707			},
17708			browserPrefixes = 'webkit moz o ms khtml'.split(' ');
17709
17710		// check for native support
17711		if (typeof document.cancelFullScreen != 'undefined') {
17712			fullScreenApi.supportsFullScreen = true;
17713		} else {
17714			// check for fullscreen support by vendor prefix
17715			for (var i = 0, il = browserPrefixes.length; i < il; i++) {
17716				fullScreenApi.prefix = browserPrefixes[i];
17717
17718				if (typeof document[fullScreenApi.prefix + 'CancelFullScreen'] != 'undefined') {
17719					fullScreenApi.supportsFullScreen = true;
17720
17721					break;
17722				}
17723			}
17724		}
17725
17726		// update methods to do something useful
17727		if (fullScreenApi.supportsFullScreen) {
17728			fullScreenApi.fullScreenEventName = fullScreenApi.prefix + 'fullscreenchange';
17729
17730			fullScreenApi.isFullScreen = function() {
17731				switch (this.prefix) {
17732					case '':
17733						return document.fullScreen;
17734					case 'webkit':
17735						return document.webkitIsFullScreen;
17736					default:
17737						return document[this.prefix + 'FullScreen'];
17738				}
17739			}
17740			fullScreenApi.requestFullScreen = function(el) {
17741				return (this.prefix === '') ? el.requestFullScreen() : el[this.prefix + 'RequestFullScreen']();
17742			}
17743			fullScreenApi.cancelFullScreen = function(el) {
17744				return (this.prefix === '') ? document.cancelFullScreen() : document[this.prefix + 'CancelFullScreen']();
17745			}
17746		}
17747	}());
17748
17749	// Browser detect
17750	(function() {
17751		function uaMatch(ua) {
17752			ua = ua.toLowerCase();
17753
17754			var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
17755				/(webkit)[ \/]([\w.]+)/.exec(ua) ||
17756				/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
17757				/(msie) ([\w.]+)/.exec(ua) ||
17758				ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || [];
17759
17760			return {
17761				browser: match[1] || "",
17762				version: match[2] || "0"
17763			};
17764		}
17765
17766		var matched = uaMatch(navigator.userAgent);
17767		browser = {};
17768
17769		if (matched.browser) {
17770			browser[matched.browser] = true;
17771			browser.version = matched.version;
17772		}
17773
17774		// Chrome is Webkit, but Webkit is also Safari.
17775		if (browser.chrome) {
17776			browser.webkit = true;
17777		} else if (browser.webkit) {
17778			browser.safari = true;
17779		}
17780	}());
17781
17782	// Feature detects
17783	(function() {
17784		var prefixes = ['', 'webkit', 'moz', 'ms', 'o'];
17785		var el = document.createElement('div');
17786
17787		function testProp(prop) {
17788			for (var p = 0, pl = prefixes.length; p < pl; p++) {
17789				var prefixedProp = prefixes[p] ? prefixes[p] + prop.charAt(0).toUpperCase() + prop.slice(1) : prop;
17790				if (el.style[prefixedProp] !== undefined) {
17791					return prefixedProp;
17792				}
17793			}
17794		}
17795
17796		// Global support indicators
17797		transform = testProp('transform') || '';
17798		gpuAcceleration = testProp('perspective') ? 'translateZ(0) ' : '';
17799	}());
17800
17801
17802	/*
17803		PluginDetect v0.7.9
17804		www.pinlady.net/PluginDetect/license/
17805		[ getVersion onWindowLoaded BetterIE ]
17806		[ Flash QuickTime Shockwave ]
17807	*/
17808	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;
17808d++){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);
17808d.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)}
17808c.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;
17808if(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();
17809
17810	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)};
17811
17812
17813	/*
17814		jQuery hashchange event v1.3
17815		https://github.com/cowboy/jquery-hashchange
17816		Copyright (c) 2010 "Cowboy" Ben Alman
17817		Dual licensed under the MIT and GPL licenses.
17818	*/
17819	(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=
17820	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||
17821	"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;
17821a!==d&&(b.title=k.title,b.open(),e&&b.write('<script>document.domain="'+e+'"\x3c/script>'),b.close(),c.location.hash=a)}}();return h}()})();
17822
17823	if (!Array.prototype.filter) {
17824		Array.prototype.filter = function(fun /*, thisp */ ) {
17825			"use strict";
17826
17827			if (this == null)
17828				throw new TypeError();
17829
17830			var t = Object(this);
17831			var len = t.length >>> 0;
17832			if (typeof fun != "function")
17833				throw new TypeError();
17834
17835			var res = [];
17836			var thisp = arguments[1];
17837			for (var i = 0; i < len; i++) {
17838				if (i in t) {
17839					var val = t[i]; // in case fun mutates this
17840					if (fun.call(thisp, val, i, t))
17841						res.push(val);
17842				}
17843			}
17844
17845			return res;
17846		};
17847	}
17848
17849	if (!Array.prototype.indexOf) {
17850		Array.prototype.indexOf = function(searchElement, fromIndex) {
17851			var k;
17852
17853			if (this == null) {
17854				throw new TypeError('"this" is null or not defined');
17855			}
17856
17857			var O = Object(this);
17858
17859			var len = O.length >>> 0;
17860
17861			if (len === 0) {
17862				return -1;
17863			}
17864
17865			var n = +fromIndex || 0;
17866
17867			if (abs(n) === Infinity) {
17868				n = 0;
17869			}
17870
17871			if (n >= len) {
17872				return -1;
17873			}
17874
17875			k = max(n >= 0 ? n : len - abs(n), 0);
17876
17877			while (k < len) {
17878				var kValue;
17879				if (k in O && O[k] === searchElement) {
17880					return k;
17881				}
17882				k++;
17883			}
17884			return -1;
17885		};
17886	}
17887
17888	if (!Array.prototype.lastIndexOf) {
17889		Array.prototype.lastIndexOf = function(searchElement /*, fromIndex*/ ) {
17890			"use strict";
17891
17892			if (this == null)
17893				throw new TypeError();
17894
17895			var t = Object(this);
17896			var len = t.length >>> 0;
17897			if (len === 0)
17898				return -1;
17899
17900			var n = len;
17901			if (arguments.length > 1) {
17902				n = Number(arguments[1]);
17903				if (n != n)
17904					n = 0;
17905				else if (n != 0 && n != (1 / 0) && n != -(1 / 0))
17906					n = (n > 0 || -1) * floor(abs(n));
17907			}
17908
17909			var k = n >= 0 ? min(n, len - 1) : len - abs(n);
17910
17911			for (; k >= 0; k--) {
17912				if (k in t && t[k] === searchElement)
17913					return k;
17914			}
17915			return -1;
17916		};
17917	}
17918})(jQuery, this);
17919
17920/*!
17921 * lightgallery | 2.5.0 | June 13th 2022
17922 * http://www.lightgalleryjs.com/
17923 * Copyright (c) 2020 Sachin Neravath;
17924 * @license GPLv3
17925 */
17926
17927(function (global, factory) {
17928	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
17929	typeof define === 'function' && define.amd ? define(factory) :
17930	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lightGallery = factory());
17931}(this, (function () { 'use strict';
17932
17933	/*! *****************************************************************************
17934	Copyright (c) Microsoft Corporation.
17935
17936	Permission to use, copy, modify, and/or distribute this software for any
17937	purpose with or without fee is hereby granted.
17938
17939	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
17940	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
17941	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
17942	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
17943	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
17944	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17945	PERFORMANCE OF THIS SOFTWARE.
17946	***************************************************************************** */
17947
17948	var __assign = function() {
17949		__assign = Object.assign || function __assign(t) {
17950			for (var s, i = 1, n = arguments.length; i < n; i++) {
17951				s = arguments[i];
17952				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
17953			}
17954			return t;
17955		};
17956		return __assign.apply(this, arguments);
17957	};
17958
17959	function __spreadArrays() {
17960		for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
17961		for (var r = Array(s), k = 0, i = 0; i < il; i++)
17962			for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
17963				r[k] = a[j];
17964		return r;
17965	}
17966
17967	/**
17968	 * List of lightGallery events
17969	 * All events should be documented here
17970	 * Below interfaces are used to build the website documentations
17971	 * */
17972	var lGEvents = {
17973		afterAppendSlide: 'lgAfterAppendSlide',
17974		init: 'lgInit',
17975		hasVideo: 'lgHasVideo',
17976		containerResize: 'lgContainerResize',
17977		updateSlides: 'lgUpdateSlides',
17978		afterAppendSubHtml: 'lgAfterAppendSubHtml',
17979		beforeOpen: 'lgBeforeOpen',
17980		afterOpen: 'lgAfterOpen',
17981		slideItemLoad: 'lgSlideItemLoad',
17982		beforeSlide: 'lgBeforeSlide',
17983		afterSlide: 'lgAfterSlide',
17984		posterClick: 'lgPosterClick',
17985		dragStart: 'lgDragStart',
17986		dragMove: 'lgDragMove',
17987		dragEnd: 'lgDragEnd',
17988		beforeNextSlide: 'lgBeforeNextSlide',
17989		beforePrevSlide: 'lgBeforePrevSlide',
17990		beforeClose: 'lgBeforeClose',
17991		afterClose: 'lgAfterClose',
17992		rotateLeft: 'lgRotateLeft',
17993		rotateRight: 'lgRotateRight',
17994		flipHorizontal: 'lgFlipHorizontal',
17995		flipVertical: 'lgFlipVertical',
17996		autoplay: 'lgAutoplay',
17997		autoplayStart: 'lgAutoplayStart',
17998		autoplayStop: 'lgAutoplayStop',
17999	};
18000
18001	var lightGalleryCoreSettings = {
18002		mode: 'lg-slide',
18003		easing: 'ease',
18004		speed: 400,
18005		licenseKey: '0000-0000-000-0000',
18006		height: '100%',
18007		width: '100%',
18008		addClass: '',
18009		startClass: 'lg-start-zoom',
18010		backdropDuration: 300,
18011		container: '',
18012		startAnimationDuration: 400,
18013		zoomFromOrigin: true,
18014		hideBarsDelay: 0,
18015		showBarsAfter: 10000,
18016		slideDelay: 0,
18017		supportLegacyBrowser: true,
18018		allowMediaOverlap: false,
18019		videoMaxSize: '1280-720',
18020		loadYouTubePoster: true,
18021		defaultCaptionHeight: 0,
18022		ariaLabelledby: '',
18023		ariaDescribedby: '',
18024		resetScrollPosition: true,
18025		hideScrollbar: false,
18026		closable: true,
18027		swipeToClose: true,
18028		closeOnTap: true,
18029		showCloseIcon: true,
18030		showMaximizeIcon: false,
18031		loop: true,
18032		escKey: true,
18033		keyPress: true,
18034		trapFocus: true,
18035		controls: true,
18036		slideEndAnimation: true,
18037		hideControlOnEnd: false,
vendor: 49,158 bytes, lines 18038-19448
18038		mousewheel: false,
18039		getCaptionFromTitleOrAlt: true,
18040		appendSubHtmlTo: '.lg-sub-html',
18041		subHtmlSelectorRelative: false,
18042		preload: 2,
18043		numberOfSlideItemsInDom: 10,
18044		selector: '',
18045		selectWithin: '',
18046		nextHtml: '',
18047		prevHtml: '',
18048		index: 0,
18049		iframeWidth: '100%',
18050		iframeHeight: '100%',
18051		iframeMaxWidth: '100%',
18052		iframeMaxHeight: '100%',
18053		download: true,
18054		counter: true,
18055		appendCounterTo: '.lg-toolbar',
18056		swipeThreshold: 50,
18057		enableSwipe: true,
18058		enableDrag: true,
18059		dynamic: false,
18060		dynamicEl: [],
18061		extraProps: [],
18062		exThumbImage: '',
18063		isMobile: undefined,
18064		mobileSettings: {
18065			controls: false,
18066			showCloseIcon: false,
18067			download: false,
18068		},
18069		plugins: [],
18070		strings: {
18071			closeGallery: 'Close gallery',
18072			toggleMaximize: 'Toggle maximize',
18073			previousSlide: 'Previous slide',
18074			nextSlide: 'Next slide',
18075			download: 'Download',
18076			playVideo: 'Play video',
18077		},
18078	};
18079
18080	function initLgPolyfills() {
18081		(function () {
18082			if (typeof window.CustomEvent === 'function')
18083				return false;
18084			function CustomEvent(event, params) {
18085				params = params || {
18086					bubbles: false,
18087					cancelable: false,
18088					detail: null,
18089				};
18090				var evt = document.createEvent('CustomEvent');
18091				evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
18092				return evt;
18093			}
18094			window.CustomEvent = CustomEvent;
18095		})();
18096		(function () {
18097			if (!Element.prototype.matches) {
18098				Element.prototype.matches =
18099					Element.prototype.msMatchesSelector ||
18100						Element.prototype.webkitMatchesSelector;
18101			}
18102		})();
18103	}
18104	var lgQuery = /** @class */ (function () {
18105		function lgQuery(selector) {
18106			this.cssVenderPrefixes = [
18107				'TransitionDuration',
18108				'TransitionTimingFunction',
18109				'Transform',
18110				'Transition',
18111			];
18112			this.selector = this._getSelector(selector);
18113			this.firstElement = this._getFirstEl();
18114			return this;
18115		}
18116		lgQuery.generateUUID = function () {
18117			return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
18118				var r = (Math.random() * 16) | 0, v = c == 'x' ? r : (r & 0x3) | 0x8;
18119				return v.toString(16);
18120			});
18121		};
18122		lgQuery.prototype._getSelector = function (selector, context) {
18123			if (context === void 0) { context = document; }
18124			if (typeof selector !== 'string') {
18125				return selector;
18126			}
18127			context = context || document;
18128			var fl = selector.substring(0, 1);
18129			if (fl === '#') {
18130				return context.querySelector(selector);
18131			}
18132			else {
18133				return context.querySelectorAll(selector);
18134			}
18135		};
18136		lgQuery.prototype._each = function (func) {
18137			if (!this.selector) {
18138				return this;
18139			}
18140			if (this.selector.length !== undefined) {
18141				[].forEach.call(this.selector, func);
18142			}
18143			else {
18144				func(this.selector, 0);
18145			}
18146			return this;
18147		};
18148		lgQuery.prototype._setCssVendorPrefix = function (el, cssProperty, value) {
18149			// prettier-ignore
18150			var property = cssProperty.replace(/-([a-z])/gi, function (s, group1) {
18151				return group1.toUpperCase();
18152			});
18153			if (this.cssVenderPrefixes.indexOf(property) !== -1) {
18154				el.style[property.charAt(0).toLowerCase() + property.slice(1)] = value;
18155				el.style['webkit' + property] = value;
18156				el.style['moz' + property] = value;
18157				el.style['ms' + property] = value;
18158				el.style['o' + property] = value;
18159			}
18160			else {
18161				el.style[property] = value;
18162			}
18163		};
18164		lgQuery.prototype._getFirstEl = function () {
18165			if (this.selector && this.selector.length !== undefined) {
18166				return this.selector[0];
18167			}
18168			else {
18169				return this.selector;
18170			}
18171		};
18172		lgQuery.prototype.isEventMatched = function (event, eventName) {
18173			var eventNamespace = eventName.split('.');
18174			return event
18175				.split('.')
18176				.filter(function (e) { return e; })
18177				.every(function (e) {
18178				return eventNamespace.indexOf(e) !== -1;
18179			});
18180		};
18181		lgQuery.prototype.attr = function (attr, value) {
18182			if (value === undefined) {
18183				if (!this.firstElement) {
18184					return '';
18185				}
18186				return this.firstElement.getAttribute(attr);
18187			}
18188			this._each(function (el) {
18189				el.setAttribute(attr, value);
18190			});
18191			return this;
18192		};
18193		lgQuery.prototype.find = function (selector) {
18194			return $LG(this._getSelector(selector, this.selector));
18195		};
18196		lgQuery.prototype.first = function () {
18197			if (this.selector && this.selector.length !== undefined) {
18198				return $LG(this.selector[0]);
18199			}
18200			else {
18201				return $LG(this.selector);
18202			}
18203		};
18204		lgQuery.prototype.eq = function (index) {
18205			return $LG(this.selector[index]);
18206		};
18207		lgQuery.prototype.parent = function () {
18208			return $LG(this.selector.parentElement);
18209		};
18210		lgQuery.prototype.get = function () {
18211			return this._getFirstEl();
18212		};
18213		lgQuery.prototype.removeAttr = function (attributes) {
18214			var attrs = attributes.split(' ');
18215			this._each(function (el) {
18216				attrs.forEach(function (attr) { return el.removeAttribute(attr); });
18217			});
18218			return this;
18219		};
18220		lgQuery.prototype.wrap = function (className) {
18221			if (!this.firstElement) {
18222				return this;
18223			}
18224			var wrapper = document.createElement('div');
18225			wrapper.className = className;
18226			this.firstElement.parentNode.insertBefore(wrapper, this.firstElement);
18227			this.firstElement.parentNode.removeChild(this.firstElement);
18228			wrapper.appendChild(this.firstElement);
18229			return this;
18230		};
18231		lgQuery.prototype.addClass = function (classNames) {
18232			if (classNames === void 0) { classNames = ''; }
18233			this._each(function (el) {
18234				// IE doesn't support multiple arguments
18235				classNames.split(' ').forEach(function (className) {
18236					if (className) {
18237						el.classList.add(className);
18238					}
18239				});
18240			});
18241			return this;
18242		};
18243		lgQuery.prototype.removeClass = function (classNames) {
18244			this._each(function (el) {
18245				// IE doesn't support multiple arguments
18246				classNames.split(' ').forEach(function (className) {
18247					if (className) {
18248						el.classList.remove(className);
18249					}
18250				});
18251			});
18252			return this;
18253		};
18254		lgQuery.prototype.hasClass = function (className) {
18255			if (!this.firstElement) {
18256				return false;
18257			}
18258			return this.firstElement.classList.contains(className);
18259		};
18260		lgQuery.prototype.hasAttribute = function (attribute) {
18261			if (!this.firstElement) {
18262				return false;
18263			}
18264			return this.firstElement.hasAttribute(attribute);
18265		};
18266		lgQuery.prototype.toggleClass = function (className) {
18267			if (!this.firstElement) {
18268				return this;
18269			}
18270			if (this.hasClass(className)) {
18271				this.removeClass(className);
18272			}
18273			else {
18274				this.addClass(className);
18275			}
18276			return this;
18277		};
18278		lgQuery.prototype.css = function (property, value) {
18279			var _this = this;
18280			this._each(function (el) {
18281				_this._setCssVendorPrefix(el, property, value);
18282			});
18283			return this;
18284		};
18285		// Need to pass separate namespaces for separate elements
18286		lgQuery.prototype.on = function (events, listener) {
18287			var _this = this;
18288			if (!this.selector) {
18289				return this;
18290			}
18291			events.split(' ').forEach(function (event) {
18292				if (!Array.isArray(lgQuery.eventListeners[event])) {
18293					lgQuery.eventListeners[event] = [];
18294				}
18295				lgQuery.eventListeners[event].push(listener);
18296				_this.selector.addEventListener(event.split('.')[0], listener);
18297			});
18298			return this;
18299		};
18300		// @todo - test this
18301		lgQuery.prototype.once = function (event, listener) {
18302			var _this = this;
18303			this.on(event, function () {
18304				_this.off(event);
18305				listener(event);
18306			});
18307			return this;
18308		};
18309		lgQuery.prototype.off = function (event) {
18310			var _this = this;
18311			if (!this.selector) {
18312				return this;
18313			}
18314			Object.keys(lgQuery.eventListeners).forEach(function (eventName) {
18315				if (_this.isEventMatched(event, eventName)) {
18316					lgQuery.eventListeners[eventName].forEach(function (listener) {
18317						_this.selector.removeEventListener(eventName.split('.')[0], listener);
18318					});
18319					lgQuery.eventListeners[eventName] = [];
18320				}
18321			});
18322			return this;
18323		};
18324		lgQuery.prototype.trigger = function (event, detail) {
18325			if (!this.firstElement) {
18326				return this;
18327			}
18328			var customEvent = new CustomEvent(event.split('.')[0], {
18329				detail: detail || null,
18330			});
18331			this.firstElement.dispatchEvent(customEvent);
18332			return this;
18333		};
18334		// Does not support IE
18335		lgQuery.prototype.load = function (url) {
18336			var _this = this;
18337			fetch(url)
18338				.then(function (res) { return res.text(); })
18339				.then(function (html) {
18340				_this.selector.innerHTML = html;
18341			});
18342			return this;
18343		};
18344		lgQuery.prototype.html = function (html) {
18345			if (html === undefined) {
18346				if (!this.firstElement) {
18347					return '';
18348				}
18349				return this.firstElement.innerHTML;
18350			}
18351			this._each(function (el) {
18352				el.innerHTML = html;
18353			});
18354			return this;
18355		};
18356		lgQuery.prototype.append = function (html) {
18357			this._each(function (el) {
18358				if (typeof html === 'string') {
18359					el.insertAdjacentHTML('beforeend', html);
18360				}
18361				else {
18362					el.appendChild(html);
18363				}
18364			});
18365			return this;
18366		};
18367		lgQuery.prototype.prepend = function (html) {
18368			this._each(function (el) {
18369				el.insertAdjacentHTML('afterbegin', html);
18370			});
18371			return this;
18372		};
18373		lgQuery.prototype.remove = function () {
18374			this._each(function (el) {
18375				el.parentNode.removeChild(el);
18376			});
18377			return this;
18378		};
18379		lgQuery.prototype.empty = function () {
18380			this._each(function (el) {
18381				el.innerHTML = '';
18382			});
18383			return this;
18384		};
18385		lgQuery.prototype.scrollTop = function (scrollTop) {
18386			if (scrollTop !== undefined) {
18387				document.body.scrollTop = scrollTop;
18388				document.documentElement.scrollTop = scrollTop;
18389				return this;
18390			}
18391			else {
18392				return (window.pageYOffset ||
18393					document.documentElement.scrollTop ||
18394					document.body.scrollTop ||
18395					0);
18396			}
18397		};
18398		lgQuery.prototype.scrollLeft = function (scrollLeft) {
18399			if (scrollLeft !== undefined) {
18400				document.body.scrollLeft = scrollLeft;
18401				document.documentElement.scrollLeft = scrollLeft;
18402				return this;
18403			}
18404			else {
18405				return (window.pageXOffset ||
18406					document.documentElement.scrollLeft ||
18407					document.body.scrollLeft ||
18408					0);
18409			}
18410		};
18411		lgQuery.prototype.offset = function () {
18412			if (!this.firstElement) {
18413				return {
18414					left: 0,
18415					top: 0,
18416				};
18417			}
18418			var rect = this.firstElement.getBoundingClientRect();
18419			var bodyMarginLeft = $LG('body').style().marginLeft;
18420			// Minus body margin - https://stackoverflow.com/questions/30711548/is-getboundingclientrect-left-returning-a-wrong-value
18421			return {
18422				left: rect.left - parseFloat(bodyMarginLeft) + this.scrollLeft(),
18423				top: rect.top + this.scrollTop(),
18424			};
18425		};
18426		lgQuery.prototype.style = function () {
18427			if (!this.firstElement) {
18428				return {};
18429			}
18430			return (this.firstElement.currentStyle ||
18431				window.getComputedStyle(this.firstElement));
18432		};
18433		// Width without padding and border even if box-sizing is used.
18434		lgQuery.prototype.width = function () {
18435			var style = this.style();
18436			return (this.firstElement.clientWidth -
18437				parseFloat(style.paddingLeft) -
18438				parseFloat(style.paddingRight));
18439		};
18440		// Height without padding and border even if box-sizing is used.
18441		lgQuery.prototype.height = function () {
18442			var style = this.style();
18443			return (this.firstElement.clientHeight -
18444				parseFloat(style.paddingTop) -
18445				parseFloat(style.paddingBottom));
18446		};
18447		lgQuery.eventListeners = {};
18448		return lgQuery;
18449	}());
18450	function $LG(selector) {
18451		initLgPolyfills();
18452		return new lgQuery(selector);
18453	}
18454
18455	var defaultDynamicOptions = [
18456		'src',
18457		'sources',
18458		'subHtml',
18459		'subHtmlUrl',
18460		'html',
18461		'video',
18462		'poster',
18463		'slideName',
18464		'responsive',
18465		'srcset',
18466		'sizes',
18467		'iframe',
18468		'downloadUrl',
18469		'download',
18470		'width',
18471		'facebookShareUrl',
18472		'tweetText',
18473		'iframeTitle',
18474		'twitterShareUrl',
18475		'pinterestShareUrl',
18476		'pinterestText',
18477		'fbHtml',
18478		'disqusIdentifier',
18479		'disqusUrl',
18480	];
18481	// Convert html data-attribute to camalcase
18482	function convertToData(attr) {
18483		// FInd a way for lgsize
18484		if (attr === 'href') {
18485			return 'src';
18486		}
18487		attr = attr.replace('data-', '');
18488		attr = attr.charAt(0).toLowerCase() + attr.slice(1);
18489		attr = attr.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); });
18490		return attr;
18491	}
18492	var utils = {
18493		/**
18494		 * get possible width and height from the lgSize attribute. Used for ZoomFromOrigin option
18495		 */
18496		//Uncode edit ##START##
18497		getSize: function (el, container, spacing, defaultLgSize, galleryItem) {
18498		// getSize: function (el, container, spacing, defaultLgSize) {
18499		//Uncode edit ##END##
18500			if (spacing === void 0) { spacing = 0; }
18501			var LGel = $LG(el);
18502			var lgSize = LGel.attr('data-lg-size') || defaultLgSize;
18503			//Uncode edit ##START##
18504			if ( typeof galleryItem.size && galleryItem.size != null ) {
18505				lgSize = galleryItem.size;
18506			}
18507			//Uncode edit ##END##
18508			if (!lgSize) {
18509				return;
18510			}
18511			var isResponsiveSizes = lgSize.split(',');
18512			// if at-least two viewport sizes are available
18513			if (isResponsiveSizes[1]) {
18514				var wWidth = window.innerWidth;
18515				for (var i = 0; i < isResponsiveSizes.length; i++) {
18516					var size_1 = isResponsiveSizes[i];
18517					var responsiveWidth = parseInt(size_1.split('-')[2], 10);
18518					if (responsiveWidth > wWidth) {
18519						lgSize = size_1;
18520						break;
18521					}
18522					// take last item as last option
18523					if (i === isResponsiveSizes.length - 1) {
18524						lgSize = size_1;
18525					}
18526				}
18527			}
18528			var size = lgSize.split('-');
18529			var width = parseInt(size[0], 10);
18530			var height = parseInt(size[1], 10);
18531			var cWidth = container.width();
18532			var cHeight = container.height() - spacing;
18533			var maxWidth = Math.min(cWidth, width);
18534			var maxHeight = Math.min(cHeight, height);
18535			var ratio = Math.min(maxWidth / width, maxHeight / height);
18536			return { width: width * ratio, height: height * ratio };
18537		},
18538		/**
18539		 * @desc Get transform value based on the imageSize. Used for ZoomFromOrigin option
18540		 * @param {jQuery Element}
18541		 * @returns {String} Transform CSS string
18542		 */
18543		getTransform: function (el, container, top, bottom, imageSize) {
18544			if (!imageSize) {
18545				return;
18546			}
18547			var LGel = $LG(el).find('img').first();
18548			if (!LGel.get()) {
18549				return;
18550			}
18551			var containerRect = container.get().getBoundingClientRect();
18552			var wWidth = containerRect.width;
18553			// using innerWidth to include mobile safari bottom bar
18554			var wHeight = container.height() - (top + bottom);
18555			var elWidth = LGel.width();
18556			var elHeight = LGel.height();
18557			var elStyle = LGel.style();
18558			var x = (wWidth - elWidth) / 2 -
18559				LGel.offset().left +
18560				(parseFloat(elStyle.paddingLeft) || 0) +
18561				(parseFloat(elStyle.borderLeft) || 0) +
18562				$LG(window).scrollLeft() +
18563				containerRect.left;
18564			var y = (wHeight - elHeight) / 2 -
18565				LGel.offset().top +
18566				(parseFloat(elStyle.paddingTop) || 0) +
18567				(parseFloat(elStyle.borderTop) || 0) +
18568				$LG(window).scrollTop() +
18569				top;
18570			var scX = elWidth / imageSize.width;
18571			var scY = elHeight / imageSize.height;
18572			var transform = 'translate3d(' +
18573				(x *= -1) +
18574				'px, ' +
18575				(y *= -1) +
18576				'px, 0) scale3d(' +
18577				scX +
18578				', ' +
18579				scY +
18580				', 1)';
18581			return transform;
18582		},
18583		getIframeMarkup: function (iframeWidth, iframeHeight, iframeMaxWidth, iframeMaxHeight, src, iframeTitle) {
18584			var title = iframeTitle ? 'title="' + iframeTitle + '"' : '';
18585			return "<div class=\"lg-video-cont lg-has-iframe\" style=\"width:" + iframeWidth + "; max-width:" + iframeMaxWidth + "; height: " + iframeHeight + "; max-height:" + iframeMaxHeight + "\">\n                    <iframe class=\"lg-object\" frameborder=\"0\" " + title + " src=\"" + src + "\"  allowfullscreen=\"true\"></iframe>\n                </div>";
18586		},
18587		getImgMarkup: function (index, src, altAttr, srcset, sizes, sources) {
18588			var srcsetAttr = srcset ? "srcset=\"" + srcset + "\"" : '';
18589			var sizesAttr = sizes ? "sizes=\"" + sizes + "\"" : '';
18590			var imgMarkup = "<img " + altAttr + " " + srcsetAttr + "  " + sizesAttr + " class=\"lg-object lg-image\" data-index=\"" + index + "\" src=\"" + src + "\" />";
18591			var sourceTag = '';
18592			if (sources) {
18593				var sourceObj = typeof sources === 'string' ? JSON.parse(sources) : sources;
18594				sourceTag = sourceObj.map(function (source) {
18595					var attrs = '';
18596					Object.keys(source).forEach(function (key) {
18597						// Do not remove the first space as it is required to separate the attributes
18598						attrs += " " + key + "=\"" + source[key] + "\"";
18599					});
18600					return "<source " + attrs + "></source>";
18601				});
18602			}
18603			return "" + sourceTag + imgMarkup;
18604		},
18605		// Get src from responsive src
18606		getResponsiveSrc: function (srcItms) {
18607			var rsWidth = [];
18608			var rsSrc = [];
18609			var src = '';
18610			for (var i = 0; i < srcItms.length; i++) {
18611				var _src = srcItms[i].split(' ');
18612				// Manage empty space
18613				if (_src[0] === '') {
18614					_src.splice(0, 1);
18615				}
18616				rsSrc.push(_src[0]);
18617				rsWidth.push(_src[1]);
18618			}
18619			var wWidth = window.innerWidth;
18620			for (var j = 0; j < rsWidth.length; j++) {
18621				if (parseInt(rsWidth[j], 10) > wWidth) {
18622					src = rsSrc[j];
18623					break;
18624				}
18625			}
18626			return src;
18627		},
18628		isImageLoaded: function (img) {
18629			if (!img)
18630				return false;
18631			// During the onload event, IE correctly identifies any images that
18632			// weren’t downloaded as not complete. Others should too. Gecko-based
18633			// browsers act like NS4 in that they report this incorrectly.
18634			if (!img.complete) {
18635				return false;
18636			}
18637			// However, they do have two very useful properties: naturalWidth and
18638			// naturalHeight. These give the true size of the image. If it failed
18639			// to load, either of these should be zero.
18640			if (img.naturalWidth === 0) {
18641				return false;
18642			}
18643			// No other way of checking: assume it’s ok.
18644			return true;
18645		},
18646		getVideoPosterMarkup: function (_poster, dummyImg, videoContStyle, playVideoString, _isVideo) {
18647			var videoClass = '';
18648			if (_isVideo && _isVideo.youtube) {
18649				videoClass = 'lg-has-youtube';
18650			}
18651			else if (_isVideo && _isVideo.vimeo) {
18652				videoClass = 'lg-has-vimeo';
18653			}
18654			else {
18655				videoClass = 'lg-has-html5';
18656			}
18657			return "<div class=\"lg-video-cont " + videoClass + "\" style=\"" + videoContStyle + "\">\n                <div class=\"lg-video-play-button\">\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>";
18658		},
18659		getFocusableElements: function (container) {
18660			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])');
18661			var visibleElements = [].filter.call(elements, function (element) {
18662				var style = window.getComputedStyle(element);
18663				return style.display !== 'none' && style.visibility !== 'hidden';
18664			});
18665			return visibleElements;
18666		},
18667		/**
18668		 * @desc Create dynamic elements array from gallery items when dynamic option is false
18669		 * It helps to avoid frequent DOM interaction
18670		 * and avoid multiple checks for dynamic elments
18671		 *
18672		 * @returns {Array} dynamicEl
18673		 */
18674		getDynamicOptions: function (items, extraProps, getCaptionFromTitleOrAlt, exThumbImage) {
18675			var dynamicElements = [];
18676			var availableDynamicOptions = __spreadArrays(defaultDynamicOptions, extraProps);
18677			[].forEach.call(items, function (item) {
18678				var dynamicEl = {};
18679				for (var i = 0; i < item.attributes.length; i++) {
18680					var attr = item.attributes[i];
18681					if (attr.specified) {
18682						var dynamicAttr = convertToData(attr.name);
18683						var label = '';
18684						if (availableDynamicOptions.indexOf(dynamicAttr) > -1) {
18685							label = dynamicAttr;
18686						}
18687						if (label) {
18688							dynamicEl[label] = attr.value;
18689						}
18690					}
18691				}
18692				var currentItem = $LG(item);
18693				var alt = currentItem.find('img').first().attr('alt');
18694				var title = currentItem.attr('title');
18695				//Uncode edit ##START##
18696				// var thumb = exThumbImage
18697				var thumb = exThumbImage && currentItem.attr(exThumbImage)
18698				//Uncode edit ##END##
18699					? currentItem.attr(exThumbImage)
18700					: currentItem.find('img').first().attr('src');
18701				dynamicEl.thumb = thumb;
18702				//Uncode edit ##START##
18703				if (getCaptionFromTitleOrAlt && !dynamicEl.subHtml) {
18704					// dynamicEl.subHtml = title || alt || '';
18705					dynamicEl.subHtml = title || '';
18706				}
18707				// dynamicEl.alt = alt || title || '';
18708				dynamicEl.alt = title || '';
18709				var inlineType = currentItem.attr('data-type');
18710				dynamicEl.type = inlineType;
18711				//Uncode edit ##END##
18712				dynamicElements.push(dynamicEl);
18713			});
18714			return dynamicElements;
18715		},
18716		isMobile: function () {
18717			return /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
18718		},
18719		/**
18720		 * @desc Check the given src is video
18721		 * @param {String} src
18722		 * @return {Object} video type
18723		 * Ex:{ youtube  :  ["//www.youtube.com/watch?v=c0asJgSyxcY", "c0asJgSyxcY"] }
18724		 *
18725		 * @todo - this information can be moved to dynamicEl to avoid frequent calls
18726		 */
18727		isVideo: function (src, isHTML5VIdeo, index) {
18728			if (!src || src.match(/\.(mp4|m4v|ogg|webm)$/) ) {
18729				if (isHTML5VIdeo) {
18730					return {
18731						html5: true,
18732					};
18733				}
18734				else {
18735					console.warn('lightGallery :- data-src is not provided on slide item ' +
18736						(index + 1) +
18737						'. Please make sure the selector property is properly configured. More info - https://www.lightgalleryjs.com/demos/html-markup/');
18738					return;
18739				}
18740			}
18741			var youtube = src.match(/\/\/(?:www\.)?youtu(?:\.be|be\.com|be-nocookie\.com)\/(?:watch\?v=|embed\/)?([a-z0-9\-\_\%]+)([\&|?][\S]*)*/i);
18742			var vimeo = src.match(/\/\/(?:www\.)?(?:player\.)?vimeo.com\/(?:video\/)?([0-9a-z\-_]+)(.*)?/i);
18743			var wistia = src.match(/https?:\/\/(.+)?(wistia\.com|wi\.st)\/(medias|embed)\/([0-9a-z\-_]+)(.*)/);
18744			if (youtube) {
18745				return {
18746					youtube: youtube,
18747				};
18748			}
18749			else if (vimeo) {
18750				return {
18751					vimeo: vimeo,
18752				};
18753			}
18754			else if (wistia) {
18755				return {
18756					wistia: wistia,
18757				};
18758			}
18759		},
18760	};
18761
18762	// @ref - https://stackoverflow.com/questions/3971841/how-to-resize-images-proportionally-keeping-the-aspect-ratio
18763	// @ref - https://2ality.com/2017/04/setting-up-multi-platform-packages.html
18764	// Unique id for each gallery
18765	var lgId = 0;
18766	var LightGallery = /** @class */ (function () {
18767		function LightGallery(element, options) {
18768			this.lgOpened = false;
18769			this.index = 0;
18770			// lightGallery modules
18771			this.plugins = [];
18772			// false when lightGallery load first slide content;
18773			this.lGalleryOn = false;
18774			// True when a slide animation is in progress
18775			this.lgBusy = false;
18776			this.currentItemsInDom = [];
18777			// Scroll top value before lightGallery is opened
18778			this.prevScrollTop = 0;
18779			this.bodyPaddingRight = 0;
18780			this.isDummyImageRemoved = false;
18781			this.dragOrSwipeEnabled = false;
18782			this.mediaContainerPosition = {
18783				top: 0,
18784				bottom: 0,
18785			};
18786			if (!element) {
18787				return this;
18788			}
18789			lgId++;
18790			this.lgId = lgId;
18791			this.el = element;
18792			this.LGel = $LG(element);
18793			this.generateSettings(options);
18794			this.buildModules();
18795			// When using dynamic mode, ensure dynamicEl is an array
18796			if (this.settings.dynamic &&
18797				this.settings.dynamicEl !== undefined &&
18798				!Array.isArray(this.settings.dynamicEl)) {
18799				throw 'When using dynamic mode, you must also define dynamicEl as an Array.';
18800			}
18801			this.galleryItems = this.getItems();
18802			this.normalizeSettings();
18803			// Gallery items
18804			this.init();
18805			//Uncode edit ##START##
18806			// this.validateLicense();
18807			//Uncode edit ##END##
18808			return this;
18809		}
18810		LightGallery.prototype.generateSettings = function (options) {
18811			// lightGallery settings
18812			this.settings = __assign(__assign({}, lightGalleryCoreSettings), options);
18813			if (this.settings.isMobile &&
18814				typeof this.settings.isMobile === 'function'
18815				? this.settings.isMobile()
18816				: utils.isMobile()) {
18817				var mobileSettings = __assign(__assign({}, this.settings.mobileSettings), this.settings.mobileSettings);
18818				this.settings = __assign(__assign({}, this.settings), mobileSettings);
18819			}
18820		};
18821		LightGallery.prototype.normalizeSettings = function () {
18822			if (this.settings.slideEndAnimation) {
18823				this.settings.hideControlOnEnd = false;
18824			}
18825			if (!this.settings.closable) {
18826				this.settings.swipeToClose = false;
18827			}
18828			// And reset it on close to get the correct value next time
18829			this.zoomFromOrigin = this.settings.zoomFromOrigin;
18830			// At the moment, Zoom from image doesn't support dynamic options
18831			// @todo add zoomFromOrigin support for dynamic images
18832			if (this.settings.dynamic) {
18833				this.zoomFromOrigin = false;
18834			}
18835			if (!this.settings.container) {
18836				this.settings.container = document.body;
18837			}
18838			// settings.preload should not be grater than $item.length
18839			this.settings.preload = Math.min(this.settings.preload, this.galleryItems.length);
18840		};
18841		LightGallery.prototype.init = function () {
18842			var _this = this;
18843			this.addSlideVideoInfo(this.galleryItems);
18844			this.buildStructure();
18845			this.LGel.trigger(lGEvents.init, {
18846				instance: this,
18847			});
18848			if (this.settings.keyPress) {
18849				this.keyPress();
18850			}
18851			setTimeout(function () {
18852				_this.enableDrag();
18853				_this.enableSwipe();
18854				_this.triggerPosterClick();
18855			}, 50);
18856			this.arrow();
18857			if (this.settings.mousewheel) {
18858				this.mousewheel();
18859			}
18860			if (!this.settings.dynamic) {
18861				this.openGalleryOnItemClick();
18862			}
18863		};
18864		LightGallery.prototype.openGalleryOnItemClick = function () {
18865			var _this = this;
18866			var _loop_1 = function (index) {
18867				var element = this_1.items[index];
18868				var $element = $LG(element);
18869				// Using different namespace for click because click event should not unbind if selector is same object('this')
18870				// @todo manage all event listners - should have namespace that represent element
18871				var uuid = lgQuery.generateUUID();
18872				$element
18873					.attr('data-lg-id', uuid)
18874					.on("click.lgcustom-item-" + uuid, function (e) {
18875					e.preventDefault();
18876					var currentItemIndex = _this.settings.index || index;
18877					_this.openGallery(currentItemIndex, element);
18878				});
18879			};
18880			var this_1 = this;
18881			// Using for loop instead of using bubbling as the items can be any html element.
18882			for (var index = 0; index < this.items.length; index++) {
18883				_loop_1(index);
18884			}
18885		};
18886		/**
18887		 * Module constructor
18888		 * Modules are build incrementally.
18889		 * Gallery should be opened only once all the modules are initialized.
18890		 * use moduleBuildTimeout to make sure this
18891		 */
18892		LightGallery.prototype.buildModules = function () {
18893			var _this = this;
18894			this.settings.plugins.forEach(function (plugin) {
18895				_this.plugins.push(new plugin(_this, $LG));
18896			});
18897		};
18898		LightGallery.prototype.validateLicense = function () {
18899			if (!this.settings.licenseKey) {
18900				console.warn('Please provide a valid license key');
18901			}
18902			else if (this.settings.licenseKey === '0000-0000-000-0000') {
18903				console.warn("lightGallery: " + this.settings.licenseKey + " license key is not valid for production use");
18904			}
18905		};
18906		LightGallery.prototype.getSlideItem = function (index) {
18907			return $LG(this.getSlideItemId(index));
18908		};
18909		LightGallery.prototype.getSlideItemId = function (index) {
18910			return "#lg-item-" + this.lgId + "-" + index;
18911		};
18912		LightGallery.prototype.getIdName = function (id) {
18913			return id + "-" + this.lgId;
18914		};
18915		LightGallery.prototype.getElementById = function (id) {
18916			return $LG("#" + this.getIdName(id));
18917		};
18918		LightGallery.prototype.manageSingleSlideClassName = function () {
18919			if (this.galleryItems.length < 2) {
18920				this.outer.addClass('lg-single-item');
18921			}
18922			else {
18923				this.outer.removeClass('lg-single-item');
18924			}
18925		};
18926		LightGallery.prototype.buildStructure = function () {
18927			var _this = this;
18928			var container = this.$container && this.$container.get();
18929			if (container) {
18930				return;
18931			}
18932			var controls = '';
18933			var subHtmlCont = '';
18934			// Create controls
18935			if (this.settings.controls) {
18936				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>";
18937			}
18938			if (this.settings.appendSubHtmlTo !== '.lg-item') {
18939				subHtmlCont =
18940					'<div class="lg-sub-html" role="status" aria-live="polite"></div>';
18941			}
18942			var addClasses = '';
18943			if (this.settings.allowMediaOverlap) {
18944				// Do not remove space before last single quote
18945				addClasses += 'lg-media-overlap ';
18946			}
18947			var ariaLabelledby = this.settings.ariaLabelledby
18948				? 'aria-labelledby="' + this.settings.ariaLabelledby + '"'
18949				: '';
18950			var ariaDescribedby = this.settings.ariaDescribedby
18951				? 'aria-describedby="' + this.settings.ariaDescribedby + '"'
18952				: '';
18953			var containerClassName = "lg-container " + this.settings.addClass + " " + (document.body !== this.settings.container ? 'lg-inline' : '');
18954			var closeIcon = this.settings.closable && this.settings.showCloseIcon
18955				? "<button type=\"button\" aria-label=\"" + this.settings.strings['closeGallery'] + "\" id=\"" + this.getIdName('lg-close') + "\" class=\"lg-close lg-icon\"></button>"
18956				: '';
18957			var maximizeIcon = this.settings.showMaximizeIcon
18958				? "<button type=\"button\" aria-label=\"" + this.settings.strings['toggleMaximize'] + "\" id=\"" + this.getIdName('lg-maximize') + "\" class=\"lg-maximize lg-icon\"></button>"
18959				: '';
18960			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'
18961				? subHtmlCont
18962				: '') + "\n                <div id=\"" + this.getIdName('lg-components') + "\" class=\"lg-components\">\n                    " + (this.settings.appendSubHtmlTo === '.lg-sub-html'
18963				? subHtmlCont
18964				: '') + "\n                </div>\n            </div>\n        </div>\n        ";
18965			$LG(this.settings.container).append(template);
18966			if (document.body !== this.settings.container) {
18967				$LG(this.settings.container).css('position', 'relative');
18968			}
18969			this.outer = this.getElementById('lg-outer');
18970			this.$lgComponents = this.getElementById('lg-components');
18971			this.$backdrop = this.getElementById('lg-backdrop');
18972			this.$container = this.getElementById('lg-container');
18973			this.$inner = this.getElementById('lg-inner');
18974			this.$content = this.getElementById('lg-content');
18975			this.$toolbar = this.getElementById('lg-toolbar');
18976			this.$backdrop.css('transition-duration', this.settings.backdropDuration + 'ms');
18977			var outerClassNames = this.settings.mode + " ";
18978			this.manageSingleSlideClassName();
18979			if (this.settings.enableDrag) {
18980				outerClassNames += 'lg-grab ';
18981			}
18982			this.outer.addClass(outerClassNames);
18983			this.$inner.css('transition-timing-function', this.settings.easing);
18984			this.$inner.css('transition-duration', this.settings.speed + 'ms');
18985			if (this.settings.download) {
18986				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>");
18987			}
18988			this.counter();
18989			$LG(window).on("resize.lg.global" + this.lgId + " orientationchange.lg.global" + this.lgId, function () {
18990				_this.refreshOnResize();
18991			});
18992			this.hideBars();
18993			this.manageCloseGallery();
18994			this.toggleMaximize();
18995			this.initModules();
18996		};
18997		LightGallery.prototype.refreshOnResize = function () {
18998			if (this.lgOpened) {
18999				var currentGalleryItem = this.galleryItems[this.index];
19000				var __slideVideoInfo = currentGalleryItem.__slideVideoInfo;
19001				this.mediaContainerPosition = this.getMediaContainerPosition();
19002				var _a = this.mediaContainerPosition, top_1 = _a.top, bottom = _a.bottom;
19003				//Uncode edit ##START##
19004				this.currentImageSize = utils.getSize(this.items[this.index], this.outer, top_1 + bottom, __slideVideoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
19005				// this.currentImageSize = utils.getSize(this.items[this.index], this.outer, top_1 + bottom, __slideVideoInfo && this.settings.videoMaxSize);
19006				//Uncode edit ##END##
19007				if (__slideVideoInfo) {
19008					this.resizeVideoSlide(this.index, this.currentImageSize);
19009				}
19010				if (this.zoomFromOrigin && !this.isDummyImageRemoved) {
19011					var imgStyle = this.getDummyImgStyles(this.currentImageSize);
19012					this.outer
19013						.find('.lg-current .lg-dummy-img')
19014						.first()
19015						.attr('style', imgStyle);
19016				}
19017				this.LGel.trigger(lGEvents.containerResize);
19018			}
19019		};
19020		LightGallery.prototype.resizeVideoSlide = function (index, imageSize) {
19021			var lgVideoStyle = this.getVideoContStyle(imageSize);
19022			var currentSlide = this.getSlideItem(index);
19023			currentSlide.find('.lg-video-cont').attr('style', lgVideoStyle);
19024		};
19025		/**
19026		 * Update slides dynamically.
19027		 * Add, edit or delete slides dynamically when lightGallery is opened.
19028		 * Modify the current gallery items and pass it via updateSlides method
19029		 * @note
19030		 * - Do not mutate existing lightGallery items directly.
19031		 * - Always pass new list of gallery items
19032		 * - You need to take care of thumbnails outside the gallery if any
19033		 * - user this method only if you want to update slides when the gallery is opened. Otherwise, use `refresh()` method.
19034		 * @param items Gallery items
19035		 * @param index After the update operation, which slide gallery should navigate to
19036		 * @category lGPublicMethods
19037		 * @example
19038		 * const plugin = lightGallery();
19039		 *
19040		 * // Adding slides dynamically
19041		 * let galleryItems = [
19042		 * // Access existing lightGallery items
19043		 * // galleryItems are automatically generated internally from the gallery HTML markup
19044		 * // or directly from galleryItems when dynamic gallery is used
19045		 *   ...plugin.galleryItems,
19046		 *     ...[
19047		 *       {
19048		 *         src: 'img/img-1.png',
19049		 *           thumb: 'img/thumb1.png',
19050		 *         },
19051		 *     ],
19052		 *   ];
19053		 *   plugin.updateSlides(
19054		 *     galleryItems,
19055		 *     plugin.index,
19056		 *   );
19057		 *
19058		 *
19059		 * // Remove slides dynamically
19060		 * galleryItems = JSON.parse(
19061		 *   JSON.stringify(updateSlideInstance.galleryItems),
19062		 * );
19063		 * galleryItems.shift();
19064		 * updateSlideInstance.updateSlides(galleryItems, 1);
19065		 * @see <a href="/demos/update-slides/">Demo</a>
19066		 */
19067		LightGallery.prototype.updateSlides = function (items, index) {
19068			if (this.index > items.length - 1) {
19069				this.index = items.length - 1;
19070			}
19071			if (items.length === 1) {
19072				this.index = 0;
19073			}
19074			if (!items.length) {
19075				this.closeGallery();
19076				return;
19077			}
19078			var currentSrc = this.galleryItems[index].src;
19079			this.galleryItems = items;
19080			this.updateControls();
19081			this.$inner.empty();
19082			this.currentItemsInDom = [];
19083			var _index = 0;
19084			// Find the current index based on source value of the slide
19085			this.galleryItems.some(function (galleryItem, itemIndex) {
19086				if (galleryItem.src === currentSrc) {
19087					_index = itemIndex;
19088					return true;
19089				}
19090				return false;
19091			});
19092			this.currentItemsInDom = this.organizeSlideItems(_index, -1);
19093			this.loadContent(_index, true);
19094			this.getSlideItem(_index).addClass('lg-current');
19095			this.index = _index;
19096			this.updateCurrentCounter(_index);
19097			this.LGel.trigger(lGEvents.updateSlides);
19098		};
19099		// Get gallery items based on multiple conditions
19100		LightGallery.prototype.getItems = function () {
19101			// Gallery items
19102			this.items = [];
19103			if (!this.settings.dynamic) {
19104				if (this.settings.selector === 'this') {
19105					this.items.push(this.el);
19106				}
19107				else if (this.settings.selector) {
19108					if (typeof this.settings.selector === 'string') {
19109						if (this.settings.selectWithin) {
19110							var selectWithin = $LG(this.settings.selectWithin);
19111							this.items = selectWithin
19112								.find(this.settings.selector)
19113								.get();
19114						}
19115						else {
19116							this.items = this.el.querySelectorAll(this.settings.selector);
19117						}
19118					}
19119					else {
19120						this.items = this.settings.selector;
19121					}
19122				}
19123				else {
19124					this.items = this.el.children;
19125				}
19126				return utils.getDynamicOptions(this.items, this.settings.extraProps, this.settings.getCaptionFromTitleOrAlt, this.settings.exThumbImage);
19127			}
19128			else {
19129				return this.settings.dynamicEl || [];
19130			}
19131		};
19132		LightGallery.prototype.shouldHideScrollbar = function () {
19133			return (this.settings.hideScrollbar &&
19134				document.body === this.settings.container);
19135		};
19136		LightGallery.prototype.hideScrollbar = function () {
19137			if (!this.shouldHideScrollbar()) {
19138				return;
19139			}
19140			this.bodyPaddingRight = parseFloat($LG('body').style().paddingRight);
19141			var bodyRect = document.documentElement.getBoundingClientRect();
19142			var scrollbarWidth = window.innerWidth - bodyRect.width;
19143			$LG(document.body).css('padding-right', scrollbarWidth + this.bodyPaddingRight + 'px');
19144			$LG(document.body).addClass('lg-overlay-open');
19145		};
19146		LightGallery.prototype.resetScrollBar = function () {
19147			if (!this.shouldHideScrollbar()) {
19148				return;
19149			}
19150			$LG(document.body).css('padding-right', this.bodyPaddingRight + 'px');
19151			$LG(document.body).removeClass('lg-overlay-open');
19152		};
19153		/**
19154		 * Open lightGallery.
19155		 * Open gallery with specific slide by passing index of the slide as parameter.
19156		 * @category lGPublicMethods
19157		 * @param {Number} index  - index of the slide
19158		 * @param {HTMLElement} element - Which image lightGallery should zoom from
19159		 *
19160		 * @example
19161		 * const $dynamicGallery = document.getElementById('dynamic-gallery-demo');
19162		 * const dynamicGallery = lightGallery($dynamicGallery, {
19163		 *     dynamic: true,
19164		 *     dynamicEl: [
19165		 *         {
19166		 *              src: 'img/1.jpg',
19167		 *              thumb: 'img/thumb-1.jpg',
19168		 *              subHtml: '<h4>Image 1 title</h4><p>Image 1 descriptions.</p>',
19169		 *         },
19170		 *         ...
19171		 *     ],
19172		 * });
19173		 * $dynamicGallery.addEventListener('click', function () {
19174		 *     // Starts with third item.(Optional).
19175		 *     // This is useful if you want use dynamic mode with
19176		 *     // custom thumbnails (thumbnails outside gallery),
19177		 *     dynamicGallery.openGallery(2);
19178		 * });
19179		 *
19180		 */
19181		LightGallery.prototype.openGallery = function (index, element) {
19182			var _this = this;
19183			if (index === void 0) { index = this.settings.index; }
19184			// prevent accidental double execution
19185			if (this.lgOpened)
19186				return;
19187			this.lgOpened = true;
19188			this.outer.removeClass('lg-hide-items');
19189			this.hideScrollbar();
19190			// Add display block, but still has opacity 0
19191			this.$container.addClass('lg-show');
19192			var itemsToBeInsertedToDom = this.getItemsToBeInsertedToDom(index, index);
19193			this.currentItemsInDom = itemsToBeInsertedToDom;
19194			var items = '';
19195			itemsToBeInsertedToDom.forEach(function (item) {
19196				items = items + ("<div id=\"" + item + "\" class=\"lg-item\"></div>");
19197			});
19198			this.$inner.append(items);
19199			this.addHtml(index);
19200			var transform = '';
19201			this.mediaContainerPosition = this.getMediaContainerPosition();
19202			var _a = this.mediaContainerPosition, top = _a.top, bottom = _a.bottom;
19203			if (!this.settings.allowMediaOverlap) {
19204				this.setMediaContainerPosition(top, bottom);
19205			}
19206			var __slideVideoInfo = this.galleryItems[index].__slideVideoInfo;
19207			if (this.zoomFromOrigin && element) {
19208				//Uncode edit ##START##
19209				this.currentImageSize = utils.getSize(element, this.outer, top + bottom, __slideVideoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
19210				// this.currentImageSize = utils.getSize(element, this.outer, top + bottom, __slideVideoInfo && this.settings.videoMaxSize);
19211				//Uncode edit ##END##
19212				transform = utils.getTransform(element, this.outer, top, bottom, this.currentImageSize);
19213			}
19214			if (!this.zoomFromOrigin || !transform) {
19215				this.outer.addClass(this.settings.startClass);
19216				this.getSlideItem(index).removeClass('lg-complete');
19217			}
19218			var timeout = this.settings.zoomFromOrigin
19219				? 100
19220				: this.settings.backdropDuration;
19221			setTimeout(function () {
19222				_this.outer.addClass('lg-components-open');
19223			}, timeout);
19224			this.index = index;
19225			//Uncode edit ##START##
19226			// this.LGel.trigger(lGEvents.beforeOpen);
19227			this.LGel.trigger(lGEvents.beforeOpen, {
19228				galleryItems: this.galleryItems,
19229				items: this.items,
19230				outer: this.outer,
19231			});
19232			//Uncode edit ##END##
19233			// add class lg-current to remove initial transition
19234			this.getSlideItem(index).addClass('lg-current');
19235			this.lGalleryOn = false;
19236			// Store the current scroll top value to scroll back after closing the gallery..
19237			this.prevScrollTop = $LG(window).scrollTop();
19238			setTimeout(function () {
19239				// Need to check both zoomFromOrigin and transform values as we need to set set the
19240				// default opening animation if user missed to add the lg-size attribute
19241				if (_this.zoomFromOrigin && transform) {
19242					var currentSlide_1 = _this.getSlideItem(index);
19243					currentSlide_1.css('transform', transform);
19244					setTimeout(function () {
19245						currentSlide_1
19246							.addClass('lg-start-progress lg-start-end-progress')
19247							.css('transition-duration', _this.settings.startAnimationDuration + 'ms');
19248						_this.outer.addClass('lg-zoom-from-image');
19249					});
19250					setTimeout(function () {
19251						currentSlide_1.css('transform', 'translate3d(0, 0, 0)');
19252					}, 100);
19253				}
19254				setTimeout(function () {
19255					_this.$backdrop.addClass('in');
19256					_this.$container.addClass('lg-show-in');
19257				}, 10);
19258				setTimeout(function () {
19259					if (_this.settings.trapFocus &&
19260						document.body === _this.settings.container) {
19261						_this.trapFocus();
19262					}
19263				}, _this.settings.backdropDuration + 50);
19264				// lg-visible class resets gallery opacity to 1
19265				if (!_this.zoomFromOrigin || !transform) {
19266					setTimeout(function () {
19267						_this.outer.addClass('lg-visible');
19268					}, _this.settings.backdropDuration);
19269				}
19270				// initiate slide function
19271				_this.slide(index, false, false, false);
19272				_this.LGel.trigger(lGEvents.afterOpen);
19273			});
19274			if (document.body === this.settings.container) {
19275				$LG('html').addClass('lg-on');
19276			}
19277		};
19278		/**
19279		 * Note - Changing the position of the media on every slide transition creates a flickering effect.
19280		 * Therefore, The height of the caption is calculated dynamically, only once based on the first slide caption.
19281		 * if you have dynamic captions for each media,
19282		 * you can provide an appropriate height for the captions via allowMediaOverlap option
19283		 */
19284		LightGallery.prototype.getMediaContainerPosition = function () {
19285			if (this.settings.allowMediaOverlap) {
19286				return {
19287					top: 0,
19288					bottom: 0,
19289				};
19290			}
19291			var top = this.$toolbar.get().clientHeight || 0;
19292			var subHtml = this.outer.find('.lg-components .lg-sub-html').get();
19293			var captionHeight = this.settings.defaultCaptionHeight ||
19294				(subHtml && subHtml.clientHeight) ||
19295				0;
19296			var thumbContainer = this.outer.find('.lg-thumb-outer').get();
19297			var thumbHeight = thumbContainer ? thumbContainer.clientHeight : 0;
19298			var bottom = thumbHeight + captionHeight;
19299			//Uncode edit ##START##
19300			bottom = bottom < 55 ? 55 : bottom;
19301			//Uncode edit ##END##
19302			return {
19303				top: top,
19304				bottom: bottom,
19305			};
19306		};
19307		LightGallery.prototype.setMediaContainerPosition = function (top, bottom) {
19308			if (top === void 0) { top = 0; }
19309			if (bottom === void 0) { bottom = 0; }
19310			this.$content.css('top', top + 'px').css('bottom', bottom + 'px');
19311		};
19312		LightGallery.prototype.hideBars = function () {
19313			var _this = this;
19314			// Hide controllers if mouse doesn't move for some period
19315			setTimeout(function () {
19316				_this.outer.removeClass('lg-hide-items');
19317				if (_this.settings.hideBarsDelay > 0) {
19318					_this.outer.on('mousemove.lg click.lg touchstart.lg', function () {
19319						_this.outer.removeClass('lg-hide-items');
19320						clearTimeout(_this.hideBarTimeout);
19321						// Timeout will be cleared on each slide movement also
19322						_this.hideBarTimeout = setTimeout(function () {
19323							_this.outer.addClass('lg-hide-items');
19324						}, _this.settings.hideBarsDelay);
19325					});
19326					_this.outer.trigger('mousemove.lg');
19327				}
19328			}, this.settings.showBarsAfter);
19329		};
19330		LightGallery.prototype.initPictureFill = function ($img) {
19331			if (this.settings.supportLegacyBrowser) {
19332				try {
19333					picturefill({
19334						elements: [$img.get()],
19335					});
19336				}
19337				catch (e) {
19338					console.warn('lightGallery :- If you want srcset or picture tag to be supported for older browser please include picturefil javascript library in your document.');
19339				}
19340			}
19341		};
19342		/**
19343		 *  @desc Create image counter
19344		 *  Ex: 1/10
19345		 */
19346		LightGallery.prototype.counter = function () {
19347			if (this.settings.counter) {
19348				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>";
19349				this.outer.find(this.settings.appendCounterTo).append(counterHtml);
19350			}
19351		};
19352		/**
19353		 *  @desc add sub-html into the slide
19354		 *  @param {Number} index - index of the slide
19355		 */
19356		LightGallery.prototype.addHtml = function (index) {
19357			var subHtml;
19358			var subHtmlUrl;
19359			if (this.galleryItems[index].subHtmlUrl) {
19360				subHtmlUrl = this.galleryItems[index].subHtmlUrl;
19361			}
19362			else {
19363				subHtml = this.galleryItems[index].subHtml;
19364			}
19365			if (!subHtmlUrl) {
19366				if (subHtml) {
19367					// get first letter of sub-html
19368					// if first letter starts with . or # get the html form the jQuery object
19369					var fL = subHtml.substring(0, 1);
19370					if (fL === '.' || fL === '#') {
19371						if (this.settings.subHtmlSelectorRelative &&
19372							!this.settings.dynamic) {
19373							subHtml = $LG(this.items)
19374								.eq(index)
19375								.find(subHtml)
19376								.first()
19377								.html();
19378						}
19379						else {
19380							subHtml = $LG(subHtml).first().html();
19381						}
19382					}
19383				}
19384				else {
19385					subHtml = '';
19386				}
19387			}
19388			if (this.settings.appendSubHtmlTo !== '.lg-item') {
19389				if (subHtmlUrl) {
19390					this.outer.find('.lg-sub-html').load(subHtmlUrl);
19391				}
19392				else {
19393					this.outer.find('.lg-sub-html').html(subHtml);
19394				}
19395			}
19396			else {
19397				var currentSlide = $LG(this.getSlideItemId(index));
19398				if (subHtmlUrl) {
19399					currentSlide.load(subHtmlUrl);
19400				}
19401				else {
19402					currentSlide.append("<div class=\"lg-sub-html\">" + subHtml + "</div>");
19403				}
19404			}
19405			// Add lg-empty-html class if title doesn't exist
19406			if (typeof subHtml !== 'undefined' && subHtml !== null) {
19407				if (subHtml === '') {
19408					this.outer
19409						.find(this.settings.appendSubHtmlTo)
19410						.addClass('lg-empty-html');
19411				}
19412				else {
19413					this.outer
19414						.find(this.settings.appendSubHtmlTo)
19415						.removeClass('lg-empty-html');
19416				}
19417			}
19418			this.LGel.trigger(lGEvents.afterAppendSubHtml, {
19419				index: index,
19420			});
19421		};
19422		/**
19423		 *  @desc Preload slides
19424		 *  @param {Number} index - index of the slide
19425		 * @todo preload not working for the first slide, Also, should work for the first and last slide as well
19426		 */
19427		LightGallery.prototype.preload = function (index) {
19428			for (var i = 1; i <= this.settings.preload; i++) {
19429				if (i >= this.galleryItems.length - index) {
19430					break;
19431				}
19432				this.loadContent(index + i, false);
19433			}
19434			for (var j = 1; j <= this.settings.preload; j++) {
19435				if (index - j < 0) {
19436					break;
19437				}
19438				this.loadContent(index - j, false);
19439			}
19440		};
19441		LightGallery.prototype.getDummyImgStyles = function (imageSize) {
19442			if (!imageSize)
19443				return '';
19444			return "width:" + imageSize.width + "px;\n                margin-left: -" + imageSize.width / 2 + "px;\n                margin-top: -" + imageSize.height / 2 + "px;\n                height:" + imageSize.height + "px";
19445		};
19446		LightGallery.prototype.getVideoContStyle = function (imageSize) {
19447			if (!imageSize)
19448				return '';
19449			return "width:" + imageSize.width + "px;\n                height:" + imageSize.height + "px";
19450		};
19451		LightGallery.prototype.getDummyImageContent = function ($currentSlide, index, alt) {
19452			var $currentItem;
19453			if (!this.settings.dynamic) {
19454				$currentItem = $LG(this.items).eq(index);
19455			}
19456			if ($currentItem) {
19457				var _dummyImgSrc = void 0;
19458				if (!this.settings.exThumbImage) {
19459					_dummyImgSrc = $currentItem.find('img').first().attr('src');
19460				}
19461				else {
19462					_dummyImgSrc = $currentItem.attr(this.settings.exThumbImage);
19463				}
19464				if (!_dummyImgSrc)
19465					return '';
19466				var imgStyle = this.getDummyImgStyles(this.currentImageSize);
19467				var dummyImgContent = "<img " + alt + " style=\"" + imgStyle + "\" class=\"lg-dummy-img\" src=\"" + _dummyImgSrc + "\" />";
19468				$currentSlide.addClass('lg-first-slide');
19469				this.outer.addClass('lg-first-slide-loading');
19470				return dummyImgContent;
19471			}
19472			return '';
19473		};
19474		LightGallery.prototype.setImgMarkup = function (src, $currentSlide, index) {
19475			var currentGalleryItem = this.galleryItems[index];
19476			var alt = currentGalleryItem.alt, srcset = currentGalleryItem.srcset, sizes = currentGalleryItem.sizes, sources = currentGalleryItem.sources;
19477			// Use the thumbnail as dummy image which will be resized to actual image size and
19478			// displayed on top of actual image
19479			var imgContent = '';
19480			var altAttr = alt ? 'alt="' + alt + '"' : '';
19481			if (this.isFirstSlideWithZoomAnimation()) {
19482				imgContent = this.getDummyImageContent($currentSlide, index, altAttr);
19483			}
19484			else {
19485				imgContent = utils.getImgMarkup(index, src, altAttr, srcset, sizes, sources);
19486			}
19487			var imgMarkup = "<picture class=\"lg-img-wrap\"> " + imgContent + "</picture>";
19488			$currentSlide.prepend(imgMarkup);
19489		};
19490		LightGallery.prototype.onSlideObjectLoad = function ($slide, isHTML5VideoWithoutPoster, onLoad, onError) {
19491			var mediaObject = $slide.find('.lg-object').first();
19492			if (utils.isImageLoaded(mediaObject.get()) ||
19493				isHTML5VideoWithoutPoster) {
19494				onLoad();
19495			}
19496			else {
19497				mediaObject.on('load.lg error.lg', function () {
19498					onLoad && onLoad();
19499				});
19500				mediaObject.on('error.lg', function () {
19501					onError && onError();
19502				});
19503			}
19504		};
19505		/**
19506		 *
19507		 * @param $el Current slide item
19508		 * @param index
19509		 * @param delay Delay is 0 except first time
19510		 * @param speed Speed is same as delay, except it is 0 if gallery is opened via hash plugin
19511		 * @param isFirstSlide
19512		 */
19513		LightGallery.prototype.onLgObjectLoad = function (currentSlide, index, delay, speed, isFirstSlide, isHTML5VideoWithoutPoster) {
19514			var _this = this;
19515			//Uncode edit ##START##
19516			var $item = _this.galleryItems[index],
19517				type = $item.type;
19518
19519			if ( typeof $item.src !== 'undefined' ) {
19520				var inline_id = $item.src.replace('#', ''),
19521					$inline = document.getElementById(inline_id),
19522					inline_html;
19523
19524				if ( type === 'inline' && inline_id != null && typeof $inline !== 'undefined' ) {
19525					inline_html = $inline.innerHTML;
19526				} else {
19527					inline_html = '';
19528				}
19529			}
19530			//Uncode edit ##END##
19531			this.onSlideObjectLoad(currentSlide, true, function () {
19532				_this.triggerSlideItemLoad(currentSlide, index, delay, speed, isFirstSlide);
19533			}, function () {
19534				currentSlide.addClass('lg-complete lg-complete_');
19535				//Uncode edit ##START##
19536				// currentSlide.html('<span class="lg-error-msg">Oops... Failed to load content...</span>');
19537				if ( inline_html !== '' ) {
19538					currentSlide.html(inline_html);
19539				} else {
19540					currentSlide.html('<span class="lg-error-msg">Oops... Failed to load content...</span>');
19541				}
19542				//Uncode edit ##END##
19543			});
19544		};
19545		LightGallery.prototype.triggerSlideItemLoad = function ($currentSlide, index, delay, speed, isFirstSlide) {
19546			var _this = this;
19547			var currentGalleryItem = this.galleryItems[index];
19548			// Adding delay for video slides without poster for better performance and user experience
19549			// Videos should start playing once once the gallery is completely loaded
19550			var _speed = isFirstSlide &&
vendor: 3,676 bytes, lines 19551-19639
19551				this.getSlideType(currentGalleryItem) === 'video' &&
19552				!currentGalleryItem.poster
19553				? speed
19554				: 0;
19555			setTimeout(function () {
19556				$currentSlide.addClass('lg-complete lg-complete_');
19557				_this.LGel.trigger(lGEvents.slideItemLoad, {
19558					index: index,
19559					delay: delay || 0,
19560					isFirstSlide: isFirstSlide,
19561				});
19562			}, _speed);
19563		};
19564		LightGallery.prototype.isFirstSlideWithZoomAnimation = function () {
19565			return !!(!this.lGalleryOn &&
19566				this.zoomFromOrigin &&
19567				this.currentImageSize);
19568		};
19569		// Add video slideInfo
19570		LightGallery.prototype.addSlideVideoInfo = function (items) {
19571			var _this = this;
19572			items.forEach(function (element, index) {
19573				element.__slideVideoInfo = utils.isVideo(element.src, !!element.video, index);
19574				if (element.__slideVideoInfo &&
19575					_this.settings.loadYouTubePoster &&
19576					!element.poster &&
19577					element.__slideVideoInfo.youtube) {
19578					element.poster = "//img.youtube.com/vi/" + element.__slideVideoInfo.youtube[1] + "/maxresdefault.jpg";
19579				}
19580			});
19581		};
19582		/**
19583		 *  Load slide content into slide.
19584		 *  This is used to load content into slides that is not visible too
19585		 *  @param {Number} index - index of the slide.
19586		 *  @param {Boolean} rec - if true call loadcontent() function again.
19587		 */
19588		LightGallery.prototype.loadContent = function (index, rec) {
19589			var _this = this;
19590			var currentGalleryItem = this.galleryItems[index];
19591			var $currentSlide = $LG(this.getSlideItemId(index));
19592			var poster = currentGalleryItem.poster, srcset = currentGalleryItem.srcset, sizes = currentGalleryItem.sizes, sources = currentGalleryItem.sources;
19593			var src = currentGalleryItem.src;
19594			var video = currentGalleryItem.video;
19595			var _html5Video = video && typeof video === 'string' ? JSON.parse(video) : video;
19596			if (currentGalleryItem.responsive) {
19597				var srcDyItms = currentGalleryItem.responsive.split(',');
19598				src = utils.getResponsiveSrc(srcDyItms) || src;
19599			}
19600			var videoInfo = currentGalleryItem.__slideVideoInfo;
19601			var lgVideoStyle = '';
19602			var iframe = !!currentGalleryItem.iframe;
19603			var isFirstSlide = !this.lGalleryOn;
19604			// delay for adding complete class. it is 0 except first time.
19605			var delay = 0;
19606			if (isFirstSlide) {
19607				if (this.zoomFromOrigin && this.currentImageSize) {
19608					delay = this.settings.startAnimationDuration + 10;
19609				}
19610				else {
19611					delay = this.settings.backdropDuration + 10;
19612				}
19613			}
19614			if (!$currentSlide.hasClass('lg-loaded')) {
19615				if (videoInfo) {
19616					var _a = this.mediaContainerPosition, top_2 = _a.top, bottom = _a.bottom;
19617					//Uncode edit ##START##
19618					var videoSize = utils.getSize(this.items[index], this.outer, top_2 + bottom, videoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
19619					// var videoSize = utils.getSize(this.items[index], this.outer, top_2 + bottom, videoInfo && this.settings.videoMaxSize);
19620					//Uncode edit ##END##
19621					lgVideoStyle = this.getVideoContStyle(videoSize);
19622				}
19623				if (iframe) {
19624					var markup = utils.getIframeMarkup(this.settings.iframeWidth, this.settings.iframeHeight, this.settings.iframeMaxWidth, this.settings.iframeMaxHeight, src, currentGalleryItem.iframeTitle);
19625					$currentSlide.prepend(markup);
19626				}
19627				else if (poster) {
19628					var dummyImg = '';
19629					var hasStartAnimation = isFirstSlide &&
19630						this.zoomFromOrigin &&
19631						this.currentImageSize;
19632					if (hasStartAnimation) {
19633						dummyImg = this.getDummyImageContent($currentSlide, index, '');
19634					}
19635					var markup = utils.getVideoPosterMarkup(poster, dummyImg || '', lgVideoStyle, this.settings.strings['playVideo'], videoInfo);
19636					$currentSlide.prepend(markup);
19637				}
19638				//Uncode edit ##START##
19639				// else if (videoInfo) {
19640				else if (videoInfo || this.getSlideType(currentGalleryItem) === 'audio') {
19641					if (! _html5Video) {
19642						var markup = "<div class=\"lg-video-cont \" style=\"" + lgVideoStyle + "\"></div>";
19643					}
19644					//Uncode edit ##END##
19645					$currentSlide.prepend(markup);
19646				}
19647				else {
19648					//Uncode edit ##START##
19649					var $item = _this.galleryItems[index],
19650						type = $item.type;
19651
19652					if ( typeof $item.src !== 'undefined' ) {
19653						var inline_id = $item.src.replace('#', ''),
19654							$inline = document.getElementById(inline_id),
19655							inline_html;
19656
19657						if ( type === 'inline' && inline_id != null && typeof $inline !== 'undefined' ) {
19658							inline_html = $inline.innerHTML;
19659						} else {
19660							inline_html = '';
19661						}
19662					}
19663					if ( inline_html !== '' ) {
19664						$currentSlide.html(inline_html);
19665					} else {
19666						this.setImgMarkup(src, $currentSlide, index);
19667						if (srcset || sources) {
19668							var $img = $currentSlide.find('.lg-object');
19669							this.initPictureFill($img);
19670						}
19671					}
19672					/*this.setImgMarkup(src, $currentSlide, index);
19673					if (srcset || sources) {
19674						var $img = $currentSlide.find('.lg-object');
19675						this.initPictureFill($img);
19676					}*/
19677					//Uncode edit ##END##
19678				}
19679				if (poster || videoInfo) {
19680					this.LGel.trigger(lGEvents.hasVideo, {
19681						index: index,
19682						src: src,
19683						html5Video: _html5Video,
19684						hasPoster: !!poster,
19685					});
19686				}
19687				this.LGel.trigger(lGEvents.afterAppendSlide, { index: index });
19688				if (this.lGalleryOn &&
19689					this.settings.appendSubHtmlTo === '.lg-item') {
19690					this.addHtml(index);
19691				}
19692			}
19693			// For first time add some delay for displaying the start animation.
19694			var _speed = 0;
19695			// Do not change the delay value because it is required for zoom plugin.
19696			// If gallery opened from direct url (hash) speed value should be 0
19697			if (delay && !$LG(document.body).hasClass('lg-from-hash')) {
19698				_speed = delay;
19699			}
19700			// Only for first slide and zoomFromOrigin is enabled
19701			if (this.isFirstSlideWithZoomAnimation()) {
19702				setTimeout(function () {
19703					$currentSlide
19704						.removeClass('lg-start-end-progress lg-start-progress')
19705						.removeAttr('style');
19706				}, this.settings.startAnimationDuration + 100);
19707				if (!$currentSlide.hasClass('lg-loaded')) {
19708					setTimeout(function () {
19709						if (_this.getSlideType(currentGalleryItem) === 'image') {
19710							var alt = currentGalleryItem.alt;
19711							var altAttr = alt ? 'alt="' + alt + '"' : '';
19712							$currentSlide
19713								.find('.lg-img-wrap')
19714								.append(utils.getImgMarkup(index, src, altAttr, srcset, sizes, currentGalleryItem.sources));
19715							if (srcset || sources) {
19716								var $img = $currentSlide.find('.lg-object');
19717								_this.initPictureFill($img);
19718							}
19719						}
19720						if (_this.getSlideType(currentGalleryItem) === 'image' ||
19721							(_this.getSlideType(currentGalleryItem) === 'video' &&
19722								poster)) {
19723							_this.onLgObjectLoad($currentSlide, index, delay, _speed, true, false);
19724							// load remaining slides once the slide is completely loaded
19725							_this.onSlideObjectLoad($currentSlide, !!(videoInfo && videoInfo.html5 && !poster), function () {
19726								_this.loadContentOnFirstSlideLoad(index, $currentSlide, _speed);
19727							}, function () {
19728								_this.loadContentOnFirstSlideLoad(index, $currentSlide, _speed);
19729							});
19730						}
19731					}, this.settings.startAnimationDuration + 100);
19732				}
19733			}
19734			// SLide content has been added to dom
19735			$currentSlide.addClass('lg-loaded');
19736			if (!this.isFirstSlideWithZoomAnimation() ||
19737				(this.getSlideType(currentGalleryItem) === 'video' && !poster)) {
19738				//Uncode edit ##START##
19739				// this.onLgObjectLoad($currentSlide, index, delay, _speed, isFirstSlide, !!(videoInfo && videoInfo.html5 && !poster));
19740				this.onLgObjectLoad($currentSlide, index, delay, _speed, isFirstSlide, !!( (videoInfo && videoInfo.html5 && !poster) || this.get
vendor: 31,133 bytes, lines 19740-20664
19740SlideType(currentGalleryItem) === 'audio'));
19741				//Uncode edit ##END##
19742			}
19743			// When gallery is opened once content is loaded (second time) need to add lg-complete class for css styling
19744			if ((!this.zoomFromOrigin || !this.currentImageSize) &&
19745				$currentSlide.hasClass('lg-complete_') &&
19746				!this.lGalleryOn) {
19747				setTimeout(function () {
19748					$currentSlide.addClass('lg-complete');
19749				}, this.settings.backdropDuration);
19750			}
19751			// Content loaded
19752			// Need to set lGalleryOn before calling preload function
19753			this.lGalleryOn = true;
19754			if (rec === true) {
19755				if (!$currentSlide.hasClass('lg-complete_')) {
19756					$currentSlide
19757						.find('.lg-object')
19758						.first()
19759						.on('load.lg error.lg', function () {
19760						_this.preload(index);
19761					});
19762				}
19763				else {
19764					this.preload(index);
19765				}
19766			}
19767		};
19768		/**
19769		 * @desc Remove dummy image content and load next slides
19770		 * Called only for the first time if zoomFromOrigin animation is enabled
19771		 * @param index
19772		 * @param $currentSlide
19773		 * @param speed
19774		 */
19775		LightGallery.prototype.loadContentOnFirstSlideLoad = function (index, $currentSlide, speed) {
19776			var _this = this;
19777			setTimeout(function () {
19778				$currentSlide.find('.lg-dummy-img').remove();
19779				$currentSlide.removeClass('lg-first-slide');
19780				_this.outer.removeClass('lg-first-slide-loading');
19781				_this.isDummyImageRemoved = true;
19782				_this.preload(index);
19783			}, speed + 300);
19784		};
19785		LightGallery.prototype.getItemsToBeInsertedToDom = function (index, prevIndex, numberOfItems) {
19786			var _this = this;
19787			if (numberOfItems === void 0) { numberOfItems = 0; }
19788			var itemsToBeInsertedToDom = [];
19789			// Minimum 2 items should be there
19790			var possibleNumberOfItems = Math.max(numberOfItems, 3);
19791			possibleNumberOfItems = Math.min(possibleNumberOfItems, this.galleryItems.length);
19792			var prevIndexItem = "lg-item-" + this.lgId + "-" + prevIndex;
19793			if (this.galleryItems.length <= 3) {
19794				this.galleryItems.forEach(function (_element, index) {
19795					itemsToBeInsertedToDom.push("lg-item-" + _this.lgId + "-" + index);
19796				});
19797				return itemsToBeInsertedToDom;
19798			}
19799			if (index < (this.galleryItems.length - 1) / 2) {
19800				for (var idx = index; idx > index - possibleNumberOfItems / 2 && idx >= 0; idx--) {
19801					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + idx);
19802				}
19803				var numberOfExistingItems = itemsToBeInsertedToDom.length;
19804				for (var idx = 0; idx < possibleNumberOfItems - numberOfExistingItems; idx++) {
19805					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (index + idx + 1));
19806				}
19807			}
19808			else {
19809				for (var idx = index; idx <= this.galleryItems.length - 1 &&
19810					idx < index + possibleNumberOfItems / 2; idx++) {
19811					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + idx);
19812				}
19813				var numberOfExistingItems = itemsToBeInsertedToDom.length;
19814				for (var idx = 0; idx < possibleNumberOfItems - numberOfExistingItems; idx++) {
19815					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (index - idx - 1));
19816				}
19817			}
19818			if (this.settings.loop) {
19819				if (index === this.galleryItems.length - 1) {
19820					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + 0);
19821				}
19822				else if (index === 0) {
19823					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (this.galleryItems.length - 1));
19824				}
19825			}
19826			if (itemsToBeInsertedToDom.indexOf(prevIndexItem) === -1) {
19827				itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + prevIndex);
19828			}
19829			return itemsToBeInsertedToDom;
19830		};
19831		LightGallery.prototype.organizeSlideItems = function (index, prevIndex) {
19832			var _this = this;
19833			var itemsToBeInsertedToDom = this.getItemsToBeInsertedToDom(index, prevIndex, this.settings.numberOfSlideItemsInDom);
19834			itemsToBeInsertedToDom.forEach(function (item) {
19835				if (_this.currentItemsInDom.indexOf(item) === -1) {
19836					_this.$inner.append("<div id=\"" + item + "\" class=\"lg-item\"></div>");
19837				}
19838			});
19839			this.currentItemsInDom.forEach(function (item) {
19840				if (itemsToBeInsertedToDom.indexOf(item) === -1) {
19841					$LG("#" + item).remove();
19842				}
19843			});
19844			return itemsToBeInsertedToDom;
19845		};
19846		/**
19847		 * Get previous index of the slide
19848		 */
19849		LightGallery.prototype.getPreviousSlideIndex = function () {
19850			var prevIndex = 0;
19851			try {
19852				var currentItemId = this.outer
19853					.find('.lg-current')
19854					.first()
19855					.attr('id');
19856				prevIndex = parseInt(currentItemId.split('-')[3]) || 0;
19857			}
19858			catch (error) {
19859				prevIndex = 0;
19860			}
19861			return prevIndex;
19862		};
19863		LightGallery.prototype.setDownloadValue = function (index) {
19864			if (this.settings.download) {
19865				var currentGalleryItem = this.galleryItems[index];
19866				var hideDownloadBtn = currentGalleryItem.downloadUrl === false ||
19867					currentGalleryItem.downloadUrl === 'false';
19868				if (hideDownloadBtn) {
19869					this.outer.addClass('lg-hide-download');
19870				}
19871				else {
19872					var $download = this.getElementById('lg-download');
19873					this.outer.removeClass('lg-hide-download');
19874					$download.attr('href', currentGalleryItem.downloadUrl ||
19875						currentGalleryItem.src);
19876					if (currentGalleryItem.download) {
19877						//Uncode edit ##START##
19878						if ( typeof currentGalleryItem.video !== 'undefined' && currentGalleryItem.video ) {
19879							var currentVideo = JSON.parse( currentGalleryItem.video ),
19880								download_name = currentVideo.source[0].src;
19881							$download.attr('href', download_name).removeAttr('download');
19882						} else {
19883							var download_url = currentGalleryItem.downloadUrl || currentGalleryItem.src,
19884								download_name = download_url.substring(download_url.lastIndexOf('/')+1);
19885							$download.attr('download', download_name);
19886						}
19887						// $download.attr('download', currentGalleryItem.download);
19888						//Uncode edit ##END##
19889					}
19890				}
19891			}
19892		};
19893		LightGallery.prototype.makeSlideAnimation = function (direction, currentSlideItem, previousSlideItem) {
19894			var _this = this;
19895			if (this.lGalleryOn) {
19896				previousSlideItem.addClass('lg-slide-progress');
19897			}
19898			setTimeout(function () {
19899				// remove all transitions
19900				_this.outer.addClass('lg-no-trans');
19901				_this.outer
19902					.find('.lg-item')
19903					.removeClass('lg-prev-slide lg-next-slide');
19904				if (direction === 'prev') {
19905					//prevslide
19906					currentSlideItem.addClass('lg-prev-slide');
19907					previousSlideItem.addClass('lg-next-slide');
19908				}
19909				else {
19910					// next slide
19911					currentSlideItem.addClass('lg-next-slide');
19912					previousSlideItem.addClass('lg-prev-slide');
19913				}
19914				// give 50 ms for browser to add/remove class
19915				setTimeout(function () {
19916					_this.outer.find('.lg-item').removeClass('lg-current');
19917					currentSlideItem.addClass('lg-current');
19918					// reset all transitions
19919					_this.outer.removeClass('lg-no-trans');
19920				}, 50);
19921			}, this.lGalleryOn ? this.settings.slideDelay : 0);
19922		};
19923		/**
19924		 * Goto a specific slide.
19925		 * @param {Number} index - index of the slide
19926		 * @param {Boolean} fromTouch - true if slide function called via touch event or mouse drag
19927		 * @param {Boolean} fromThumb - true if slide function called via thumbnail click
19928		 * @param {String} direction - Direction of the slide(next/prev)
19929		 * @category lGPublicMethods
19930		 * @example
19931		 *  const plugin = lightGallery();
19932		 *  // to go to 3rd slide
19933		 *  plugin.slide(2);
19934		 *
19935		 */
19936		LightGallery.prototype.slide = function (index, fromTouch, fromThumb, direction) {
19937			var _this = this;
19938			var prevIndex = this.getPreviousSlideIndex();
19939			this.currentItemsInDom = this.organizeSlideItems(index, prevIndex);
19940			// Prevent multiple call, Required for hsh plugin
19941			if (this.lGalleryOn && prevIndex === index) {
19942				return;
19943			}
19944			var numberOfGalleryItems = this.galleryItems.length;
19945			if (!this.lgBusy) {
19946				if (this.settings.counter) {
19947					this.updateCurrentCounter(index);
19948				}
19949				var currentSlideItem = this.getSlideItem(index);
19950				var previousSlideItem_1 = this.getSlideItem(prevIndex);
19951				var currentGalleryItem = this.galleryItems[index];
19952				var videoInfo = currentGalleryItem.__slideVideoInfo;
19953				this.outer.attr('data-lg-slide-type', this.getSlideType(currentGalleryItem));
19954				this.setDownloadValue(index);
19955				if (videoInfo) {
19956					var _a = this.mediaContainerPosition, top_3 = _a.top, bottom = _a.bottom;
19957					//Uncode edit ##START##
19958					var videoSize = utils.getSize(this.items[index], this.outer, top_3 + bottom, videoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
19959					// var videoSize = utils.getSize(this.items[index], this.outer, top_3 + bottom, videoInfo && this.settings.videoMaxSize);
19960					//Uncode edit ##END##
19961					this.resizeVideoSlide(index, videoSize);
19962				}
19963				this.LGel.trigger(lGEvents.beforeSlide, {
19964					prevIndex: prevIndex,
19965					index: index,
19966					fromTouch: !!fromTouch,
19967					fromThumb: !!fromThumb,
19968					//Uncode edit ##START##
19969					currentSlide: currentSlideItem,
19970					previousSlide: previousSlideItem_1,
19971					info: currentGalleryItem,
19972					item: this.items[index]
19973					//Uncode edit ##END##
19974				});
19975				this.lgBusy = true;
19976				clearTimeout(this.hideBarTimeout);
19977				this.arrowDisable(index);
19978				if (!direction) {
19979					if (index < prevIndex) {
19980						direction = 'prev';
19981					}
19982					else if (index > prevIndex) {
19983						direction = 'next';
19984					}
19985				}
19986				if (!fromTouch) {
19987					this.makeSlideAnimation(direction, currentSlideItem, previousSlideItem_1);
19988				}
19989				else {
19990					this.outer
19991						.find('.lg-item')
19992						.removeClass('lg-prev-slide lg-current lg-next-slide');
19993					var touchPrev = void 0;
19994					var touchNext = void 0;
19995					if (numberOfGalleryItems > 2) {
19996						touchPrev = index - 1;
19997						touchNext = index + 1;
19998						if (index === 0 && prevIndex === numberOfGalleryItems - 1) {
19999							// next slide
20000							touchNext = 0;
20001							touchPrev = numberOfGalleryItems - 1;
20002						}
20003						else if (index === numberOfGalleryItems - 1 &&
20004							prevIndex === 0) {
20005							// prev slide
20006							touchNext = 0;
20007							touchPrev = numberOfGalleryItems - 1;
20008						}
20009					}
20010					else {
20011						touchPrev = 0;
20012						touchNext = 1;
20013					}
20014					if (direction === 'prev') {
20015						this.getSlideItem(touchNext).addClass('lg-next-slide');
20016					}
20017					else {
20018						this.getSlideItem(touchPrev).addClass('lg-prev-slide');
20019					}
20020					currentSlideItem.addClass('lg-current');
20021				}
20022				// Do not put load content in set timeout as it needs to load immediately when the gallery is opened
20023				if (!this.lGalleryOn) {
20024					this.loadContent(index, true);
20025				}
20026				else {
20027					setTimeout(function () {
20028						_this.loadContent(index, true);
20029						// Add title if this.settings.appendSubHtmlTo === lg-sub-html
20030						if (_this.settings.appendSubHtmlTo !== '.lg-item') {
20031							_this.addHtml(index);
20032						}
20033					}, this.settings.speed + 50 + (fromTouch ? 0 : this.settings.slideDelay));
20034				}
20035				setTimeout(function () {
20036					_this.lgBusy = false;
20037					previousSlideItem_1.removeClass('lg-slide-progress');
20038					_this.LGel.trigger(lGEvents.afterSlide, {
20039						prevIndex: prevIndex,
20040						index: index,
20041						fromTouch: fromTouch,
20042						fromThumb: fromThumb,
20043					});
20044				}, (this.lGalleryOn ? this.settings.speed + 100 : 100) + (fromTouch ? 0 : this.settings.slideDelay));
20045			}
20046			this.index = index;
20047		};
20048		LightGallery.prototype.updateCurrentCounter = function (index) {
20049			this.getElementById('lg-counter-current').html(index + 1 + '');
20050		};
20051		LightGallery.prototype.updateCounterTotal = function () {
20052			this.getElementById('lg-counter-all').html(this.galleryItems.length + '');
20053		};
20054		LightGallery.prototype.getSlideType = function (item) {
20055			if (item.__slideVideoInfo) {
20056				return 'video';
20057			}
20058			else if (item.iframe) {
20059				return 'iframe';
20060			}
20061			//Uncode edit ##START##
20062			else if (typeof item.src !== '' && item.src.search(/.mp3|.m4a/i) > -1) {
20063				return 'audio';
20064			}
20065			//Uncode edit ##END##
20066			else {
20067				return 'image';
20068			}
20069		};
20070		LightGallery.prototype.touchMove = function (startCoords, endCoords, e) {
20071			var distanceX = endCoords.pageX - startCoords.pageX;
20072			var distanceY = endCoords.pageY - startCoords.pageY;
20073			var allowSwipe = false;
20074			if (this.swipeDirection) {
20075				allowSwipe = true;
20076			}
20077			else {
20078				if (Math.abs(distanceX) > 15) {
20079					this.swipeDirection = 'horizontal';
20080					allowSwipe = true;
20081				}
20082				else if (Math.abs(distanceY) > 15) {
20083					this.swipeDirection = 'vertical';
20084					allowSwipe = true;
20085				}
20086			}
20087			if (!allowSwipe) {
20088				return;
20089			}
20090			var $currentSlide = this.getSlideItem(this.index);
20091			if (this.swipeDirection === 'horizontal') {
20092				e === null || e === void 0 ? void 0 : e.preventDefault();
20093				// reset opacity and transition duration
20094				this.outer.addClass('lg-dragging');
20095				// move current slide
20096				this.setTranslate($currentSlide, distanceX, 0);
20097				// move next and prev slide with current slide
20098				var width = $currentSlide.get().offsetWidth;
20099				var slideWidthAmount = (width * 15) / 100;
20100				var gutter = slideWidthAmount - Math.abs((distanceX * 10) / 100);
20101				this.setTranslate(this.outer.find('.lg-prev-slide').first(), -width + distanceX - gutter, 0);
20102				this.setTranslate(this.outer.find('.lg-next-slide').first(), width + distanceX + gutter, 0);
20103			}
20104			else if (this.swipeDirection === 'vertical') {
20105				if (this.settings.swipeToClose) {
20106					e === null || e === void 0 ? void 0 : e.preventDefault();
20107					this.$container.addClass('lg-dragging-vertical');
20108					var opacity = 1 - Math.abs(distanceY) / window.innerHeight;
20109					this.$backdrop.css('opacity', opacity);
20110					var scale = 1 - Math.abs(distanceY) / (window.innerWidth * 2);
20111					this.setTranslate($currentSlide, 0, distanceY, scale, scale);
20112					if (Math.abs(distanceY) > 100) {
20113						this.outer
20114							.addClass('lg-hide-items')
20115							.removeClass('lg-components-open');
20116					}
20117				}
20118			}
20119		};
20120		LightGallery.prototype.touchEnd = function (endCoords, startCoords, event) {
20121			var _this = this;
20122			var distance;
20123			// keep slide animation for any mode while dragg/swipe
20124			if (this.settings.mode !== 'lg-slide') {
20125				this.outer.addClass('lg-slide');
20126			}
20127			// set transition duration
20128			setTimeout(function () {
20129				_this.$container.removeClass('lg-dragging-vertical');
20130				_this.outer
20131					.removeClass('lg-dragging lg-hide-items')
20132					.addClass('lg-components-open');
20133				var triggerClick = true;
20134				if (_this.swipeDirection === 'horizontal') {
20135					distance = endCoords.pageX - startCoords.pageX;
20136					var distanceAbs = Math.abs(endCoords.pageX - startCoords.pageX);
20137					if (distance < 0 &&
20138						distanceAbs > _this.settings.swipeThreshold) {
20139						_this.goToNextSlide(true);
20140						triggerClick = false;
20141					}
20142					else if (distance > 0 &&
20143						distanceAbs > _this.settings.swipeThreshold) {
20144						_this.goToPrevSlide(true);
20145						triggerClick = false;
20146					}
20147				}
20148				else if (_this.swipeDirection === 'vertical') {
20149					distance = Math.abs(endCoords.pageY - startCoords.pageY);
20150					if (_this.settings.closable &&
20151						_this.settings.swipeToClose &&
20152						distance > 100) {
20153						_this.closeGallery();
20154						return;
20155					}
20156					else {
20157						_this.$backdrop.css('opacity', 1);
20158					}
20159				}
20160				_this.outer.find('.lg-item').removeAttr('style');
20161				if (triggerClick &&
20162					Math.abs(endCoords.pageX - startCoords.pageX) < 5) {
20163					// Trigger click if distance is less than 5 pix
20164					var target = $LG(event.target);
20165					if (_this.isPosterElement(target)) {
20166						_this.LGel.trigger(lGEvents.posterClick);
20167					}
20168				}
20169				_this.swipeDirection = undefined;
20170			});
20171			// remove slide class once drag/swipe is completed if mode is not slide
20172			setTimeout(function () {
20173				if (!_this.outer.hasClass('lg-dragging') &&
20174					_this.settings.mode !== 'lg-slide') {
20175					_this.outer.removeClass('lg-slide');
20176				}
20177			}, this.settings.speed + 100);
20178		};
20179		LightGallery.prototype.enableSwipe = function () {
20180			var _this = this;
20181			var startCoords = {};
20182			var endCoords = {};
20183			var isMoved = false;
20184			var isSwiping = false;
20185			if (this.settings.enableSwipe) {
20186				this.$inner.on('touchstart.lg', function (e) {
20187					_this.dragOrSwipeEnabled = true;
20188					var $item = _this.getSlideItem(_this.index);
20189					if (($LG(e.target).hasClass('lg-item') ||
20190						$item.get().contains(e.target)) &&
20191						!_this.outer.hasClass('lg-zoomed') &&
20192						!_this.lgBusy &&
20193						e.targetTouches.length === 1) {
20194						isSwiping = true;
20195						_this.touchAction = 'swipe';
20196						_this.manageSwipeClass();
20197						startCoords = {
20198							pageX: e.targetTouches[0].pageX,
20199							pageY: e.targetTouches[0].pageY,
20200						};
20201					}
20202				});
20203				this.$inner.on('touchmove.lg', function (e) {
20204					if (isSwiping &&
20205						_this.touchAction === 'swipe' &&
20206						e.targetTouches.length === 1) {
20207						endCoords = {
20208							pageX: e.targetTouches[0].pageX,
20209							pageY: e.targetTouches[0].pageY,
20210						};
20211						_this.touchMove(startCoords, endCoords, e);
20212						isMoved = true;
20213					}
20214				});
20215				this.$inner.on('touchend.lg', function (event) {
20216					if (_this.touchAction === 'swipe') {
20217						if (isMoved) {
20218							isMoved = false;
20219							_this.touchEnd(endCoords, startCoords, event);
20220						}
20221						else if (isSwiping) {
20222							var target = $LG(event.target);
20223							if (_this.isPosterElement(target)) {
20224								_this.LGel.trigger(lGEvents.posterClick);
20225							}
20226						}
20227						_this.touchAction = undefined;
20228						isSwiping = false;
20229					}
20230				});
20231			}
20232		};
20233		LightGallery.prototype.enableDrag = function () {
20234			var _this = this;
20235			var startCoords = {};
20236			var endCoords = {};
20237			var isDraging = false;
20238			var isMoved = false;
20239			if (this.settings.enableDrag) {
20240				this.outer.on('mousedown.lg', function (e) {
20241					_this.dragOrSwipeEnabled = true;
20242					var $item = _this.getSlideItem(_this.index);
20243					if ($LG(e.target).hasClass('lg-item') ||
20244						$item.get().contains(e.target)) {
20245						if (!_this.outer.hasClass('lg-zoomed') && !_this.lgBusy) {
20246							e.preventDefault();
20247							if (!_this.lgBusy) {
20248								_this.manageSwipeClass();
20249								startCoords = {
20250									pageX: e.pageX,
20251									pageY: e.pageY,
20252								};
20253								isDraging = true;
20254								// ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723
20255								_this.outer.get().scrollLeft += 1;
20256								_this.outer.get().scrollLeft -= 1;
20257								// *
20258								_this.outer
20259									.removeClass('lg-grab')
20260									.addClass('lg-grabbing');
20261								_this.LGel.trigger(lGEvents.dragStart);
20262							}
20263						}
20264					}
20265				});
20266				$LG(window).on("mousemove.lg.global" + this.lgId, function (e) {
20267					if (isDraging && _this.lgOpened) {
20268						isMoved = true;
20269						endCoords = {
20270							pageX: e.pageX,
20271							pageY: e.pageY,
20272						};
20273						_this.touchMove(startCoords, endCoords);
20274						_this.LGel.trigger(lGEvents.dragMove);
20275					}
20276				});
20277				$LG(window).on("mouseup.lg.global" + this.lgId, function (event) {
20278					if (!_this.lgOpened) {
20279						return;
20280					}
20281					var target = $LG(event.target);
20282					if (isMoved) {
20283						isMoved = false;
20284						_this.touchEnd(endCoords, startCoords, event);
20285						_this.LGel.trigger(lGEvents.dragEnd);
20286					}
20287					else if (_this.isPosterElement(target)) {
20288						_this.LGel.trigger(lGEvents.posterClick);
20289					}
20290					// Prevent execution on click
20291					if (isDraging) {
20292						isDraging = false;
20293						_this.outer.removeClass('lg-grabbing').addClass('lg-grab');
20294					}
20295				});
20296			}
20297		};
20298		LightGallery.prototype.triggerPosterClick = function () {
20299			var _this = this;
20300			this.$inner.on('click.lg', function (event) {
20301				if (!_this.dragOrSwipeEnabled &&
20302					_this.isPosterElement($LG(event.target))) {
20303					_this.LGel.trigger(lGEvents.posterClick);
20304				}
20305			});
20306		};
20307		LightGallery.prototype.manageSwipeClass = function () {
20308			var _touchNext = this.index + 1;
20309			var _touchPrev = this.index - 1;
20310			if (this.settings.loop && this.galleryItems.length > 2) {
20311				if (this.index === 0) {
20312					_touchPrev = this.galleryItems.length - 1;
20313				}
20314				else if (this.index === this.galleryItems.length - 1) {
20315					_touchNext = 0;
20316				}
20317			}
20318			this.outer.find('.lg-item').removeClass('lg-next-slide lg-prev-slide');
20319			if (_touchPrev > -1) {
20320				this.getSlideItem(_touchPrev).addClass('lg-prev-slide');
20321			}
20322			this.getSlideItem(_touchNext).addClass('lg-next-slide');
20323		};
20324		/**
20325		 * Go to next slide
20326		 * @param {Boolean} fromTouch - true if slide function called via touch event
20327		 * @category lGPublicMethods
20328		 * @example
20329		 *  const plugin = lightGallery();
20330		 *  plugin.goToNextSlide();
20331		 * @see <a href="/demos/methods/">Demo</a>
20332		 */
20333		LightGallery.prototype.goToNextSlide = function (fromTouch) {
20334			var _this = this;
20335			var _loop = this.settings.loop;
20336			if (fromTouch && this.galleryItems.length < 3) {
20337				_loop = false;
20338			}
20339			if (!this.lgBusy) {
20340				if (this.index + 1 < this.galleryItems.length) {
20341					this.index++;
20342					this.LGel.trigger(lGEvents.beforeNextSlide, {
20343						index: this.index,
20344					});
20345					this.slide(this.index, !!fromTouch, false, 'next');
20346				}
20347				else {
20348					if (_loop) {
20349						this.index = 0;
20350						this.LGel.trigger(lGEvents.beforeNextSlide, {
20351							index: this.index,
20352						});
20353						this.slide(this.index, !!fromTouch, false, 'next');
20354					}
20355					else if (this.settings.slideEndAnimation && !fromTouch) {
20356						this.outer.addClass('lg-right-end');
20357						setTimeout(function () {
20358							_this.outer.removeClass('lg-right-end');
20359						}, 400);
20360					}
20361				}
20362			}
20363		};
20364		/**
20365		 * Go to previous slides
20366		 * @param {Boolean} fromTouch - true if slide function called via touch event
20367		 * @category lGPublicMethods
20368		 * @example
20369		 *  const plugin = lightGallery({});
20370		 *  plugin.goToPrevSlide();
20371		 * @see <a href="/demos/methods/">Demo</a>
20372		 *
20373		 */
20374		LightGallery.prototype.goToPrevSlide = function (fromTouch) {
20375			var _this = this;
20376			var _loop = this.settings.loop;
20377			if (fromTouch && this.galleryItems.length < 3) {
20378				_loop = false;
20379			}
20380			if (!this.lgBusy) {
20381				if (this.index > 0) {
20382					this.index--;
20383					this.LGel.trigger(lGEvents.beforePrevSlide, {
20384						index: this.index,
20385						fromTouch: fromTouch,
20386					});
20387					this.slide(this.index, !!fromTouch, false, 'prev');
20388				}
20389				else {
20390					if (_loop) {
20391						this.index = this.galleryItems.length - 1;
20392						this.LGel.trigger(lGEvents.beforePrevSlide, {
20393							index: this.index,
20394							fromTouch: fromTouch,
20395						});
20396						this.slide(this.index, !!fromTouch, false, 'prev');
20397					}
20398					else if (this.settings.slideEndAnimation && !fromTouch) {
20399						this.outer.addClass('lg-left-end');
20400						setTimeout(function () {
20401							_this.outer.removeClass('lg-left-end');
20402						}, 400);
20403					}
20404				}
20405			}
20406		};
20407		LightGallery.prototype.keyPress = function () {
20408			var _this = this;
20409			$LG(window).on("keydown.lg.global" + this.lgId, function (e) {
20410				if (_this.lgOpened &&
20411					_this.settings.escKey === true &&
20412					e.keyCode === 27) {
20413					e.preventDefault();
20414					if (_this.settings.allowMediaOverlap &&
20415						_this.outer.hasClass('lg-can-toggle') &&
20416						_this.outer.hasClass('lg-components-open')) {
20417						_this.outer.removeClass('lg-components-open');
20418					}
20419					else {
20420						_this.closeGallery();
20421					}
20422				}
20423				if (_this.lgOpened && _this.galleryItems.length > 1) {
20424					if (e.keyCode === 37) {
20425						e.preventDefault();
20426						_this.goToPrevSlide();
20427					}
20428					if (e.keyCode === 39) {
20429						e.preventDefault();
20430						_this.goToNextSlide();
20431					}
20432				}
20433			});
20434		};
20435		LightGallery.prototype.arrow = function () {
20436			var _this = this;
20437			this.getElementById('lg-prev').on('click.lg', function () {
20438				_this.goToPrevSlide();
20439			});
20440			this.getElementById('lg-next').on('click.lg', function () {
20441				_this.goToNextSlide();
20442			});
20443		};
20444		LightGallery.prototype.arrowDisable = function (index) {
20445			// Disable arrows if settings.hideControlOnEnd is true
20446			if (!this.settings.loop && this.settings.hideControlOnEnd) {
20447				var $prev = this.getElementById('lg-prev');
20448				var $next = this.getElementById('lg-next');
20449				if (index + 1 === this.galleryItems.length) {
20450					$next.attr('disabled', 'disabled').addClass('disabled');
20451				}
20452				else {
20453					$next.removeAttr('disabled').removeClass('disabled');
20454				}
20455				if (index === 0) {
20456					$prev.attr('disabled', 'disabled').addClass('disabled');
20457				}
20458				else {
20459					$prev.removeAttr('disabled').removeClass('disabled');
20460				}
20461			}
20462		};
20463		LightGallery.prototype.setTranslate = function ($el, xValue, yValue, scaleX, scaleY) {
20464			if (scaleX === void 0) { scaleX = 1; }
20465			if (scaleY === void 0) { scaleY = 1; }
20466			$el.css('transform', 'translate3d(' +
20467				xValue +
20468				'px, ' +
20469				yValue +
20470				'px, 0px) scale3d(' +
20471				scaleX +
20472				', ' +
20473				scaleY +
20474				', 1)');
20475		};
20476		LightGallery.prototype.mousewheel = function () {
20477			var _this = this;
20478			var lastCall = 0;
20479			this.outer.on('wheel.lg', function (e) {
20480				if (!e.deltaY || _this.galleryItems.length < 2) {
20481					return;
20482				}
20483				e.preventDefault();
20484				var now = new Date().getTime();
20485				if (now - lastCall < 1000) {
20486					return;
20487				}
20488				lastCall = now;
20489				if (e.deltaY > 0) {
20490					_this.goToNextSlide();
20491				}
20492				else if (e.deltaY < 0) {
20493					_this.goToPrevSlide();
20494				}
20495			});
20496		};
20497		LightGallery.prototype.isSlideElement = function (target) {
20498			return (target.hasClass('lg-outer') ||
20499				target.hasClass('lg-item') ||
20500				target.hasClass('lg-img-wrap'));
20501		};
20502		LightGallery.prototype.isPosterElement = function (target) {
20503			var playButton = this.getSlideItem(this.index)
20504				.find('.lg-video-play-button')
20505				.get();
20506			return (target.hasClass('lg-video-poster') ||
20507				target.hasClass('lg-video-play-button') ||
20508				(playButton && playButton.contains(target.get())));
20509		};
20510		/**
20511		 * Maximize minimize inline gallery.
20512		 * @category lGPublicMethods
20513		 */
20514		LightGallery.prototype.toggleMaximize = function () {
20515			var _this = this;
20516			this.getElementById('lg-maximize').on('click.lg', function () {
20517				_this.$container.toggleClass('lg-inline');
20518				_this.refreshOnResize();
20519			});
20520		};
20521		LightGallery.prototype.invalidateItems = function () {
20522			for (var index = 0; index < this.items.length; index++) {
20523				var element = this.items[index];
20524				var $element = $LG(element);
20525				$element.off("click.lgcustom-item-" + $element.attr('data-lg-id'));
20526			}
20527		};
20528		LightGallery.prototype.trapFocus = function () {
20529			var _this = this;
20530			this.$container.get().focus({
20531				preventScroll: true,
20532			});
20533			$LG(window).on("keydown.lg.global" + this.lgId, function (e) {
20534				if (!_this.lgOpened) {
20535					return;
20536				}
20537				var isTabPressed = e.key === 'Tab' || e.keyCode === 9;
20538				if (!isTabPressed) {
20539					return;
20540				}
20541				var focusableEls = utils.getFocusableElements(_this.$container.get());
20542				var firstFocusableEl = focusableEls[0];
20543				var lastFocusableEl = focusableEls[focusableEls.length - 1];
20544				if (e.shiftKey) {
20545					if (document.activeElement === firstFocusableEl) {
20546						lastFocusableEl.focus();
20547						e.preventDefault();
20548					}
20549				}
20550				else {
20551					if (document.activeElement === lastFocusableEl) {
20552						firstFocusableEl.focus();
20553						e.preventDefault();
20554					}
20555				}
20556			});
20557		};
20558		LightGallery.prototype.manageCloseGallery = function () {
20559			var _this = this;
20560			if (!this.settings.closable)
20561				return;
20562			var mousedown = false;
20563			this.getElementById('lg-close').on('click.lg', function () {
20564				_this.closeGallery();
20565			});
20566			if (this.settings.closeOnTap) {
20567				// If you drag the slide and release outside gallery gets close on chrome
20568				// for preventing this check mousedown and mouseup happened on .lg-item or lg-outer
20569				this.outer.on('mousedown.lg', function (e) {
20570					var target = $LG(e.target);
20571					if (_this.isSlideElement(target)) {
20572						mousedown = true;
20573					}
20574					else {
20575						mousedown = false;
20576					}
20577				});
20578				this.outer.on('mousemove.lg', function () {
20579					mousedown = false;
20580				});
20581				this.outer.on('mouseup.lg', function (e) {
20582					var target = $LG(e.target);
20583					if (_this.isSlideElement(target) && mousedown) {
20584						if (!_this.outer.hasClass('lg-dragging')) {
20585							_this.closeGallery();
20586						}
20587					}
20588				});
20589			}
20590		};
20591		/**
20592		 * Close lightGallery if it is opened.
20593		 *
20594		 * @description If closable is false in the settings, you need to pass true via closeGallery method to force close gallery
20595		 * @return returns the estimated time to close gallery completely including the close animation duration
20596		 * @category lGPublicMethods
20597		 * @example
20598		 *  const plugin = lightGallery();
20599		 *  plugin.closeGallery();
20600		 *
20601		 */
20602		LightGallery.prototype.closeGallery = function (force) {
20603			var _this = this;
20604			if (!this.lgOpened || (!this.settings.closable && !force)) {
20605				return 0;
20606			}
20607			this.LGel.trigger(lGEvents.beforeClose);
20608			if (this.settings.resetScrollPosition && !this.settings.hideScrollbar) {
20609				$LG(window).scrollTop(this.prevScrollTop);
20610			}
20611			var currentItem = this.items[this.index];
20612			var transform;
20613			if (this.zoomFromOrigin && currentItem) {
20614				var _a = this.mediaContainerPosition, top_4 = _a.top, bottom = _a.bottom;
20615				var _b = this.galleryItems[this.index], __slideVideoInfo = _b.__slideVideoInfo, poster = _b.poster;
20616				//Uncode edit ##START##
20617				var imageSize = utils.getSize(currentItem, this.outer, top_4 + bottom, __slideVideoInfo && poster && this.settings.videoMaxSize, this.galleryItems[this.index]);
20618				// var imageSize = utils.getSize(currentItem, this.outer, top_4 + bottom, __slideVideoInfo && poster && this.settings.videoMaxSize);
20619				//Uncode edit ##END##
20620				transform = utils.getTransform(currentItem, this.outer, top_4, bottom, imageSize);
20621			}
20622			if (this.zoomFromOrigin && transform) {
20623				this.outer.addClass('lg-closing lg-zoom-from-image');
20624				this.getSlideItem(this.index)
20625					.addClass('lg-start-end-progress')
20626					.css('transition-duration', this.settings.startAnimationDuration + 'ms')
20627					.css('transform', transform);
20628			}
20629			else {
20630				this.outer.addClass('lg-hide-items');
20631				// lg-zoom-from-image is used for setting the opacity to 1 if zoomFromOrigin is true
20632				// If the closing item doesn't have the lg-size attribute, remove this class to avoid the closing css conflicts
20633				this.outer.removeClass('lg-zoom-from-image');
20634			}
20635			// Unbind all events added by lightGallery
20636			// @todo
20637			//this.$el.off('.lg.tm');
20638			this.destroyModules();
20639			this.lGalleryOn = false;
20640			this.isDummyImageRemoved = false;
20641			this.zoomFromOrigin = this.settings.zoomFromOrigin;
20642			clearTimeout(this.hideBarTimeout);
20643			this.hideBarTimeout = false;
20644			$LG('html').removeClass('lg-on');
20645			this.outer.removeClass('lg-visible lg-components-open');
20646			// Resetting opacity to 0 isd required as  vertical swipe to close function adds inline opacity.
20647			this.$backdrop.removeClass('in').css('opacity', 0);
20648			var removeTimeout = this.zoomFromOrigin && transform
20649				? Math.max(this.settings.startAnimationDuration, this.settings.backdropDuration)
20650				: this.settings.backdropDuration;
20651			this.$container.removeClass('lg-show-in');
20652			// Once the closign animation is completed and gallery is invisible
20653			setTimeout(function () {
20654				if (_this.zoomFromOrigin && transform) {
20655					_this.outer.removeClass('lg-zoom-from-image');
20656				}
20657				_this.$container.removeClass('lg-show');
20658				// Reset scrollbar
20659				_this.resetScrollBar();
20660				// Need to remove inline opacity as it is used in the stylesheet as well
20661				_this.$backdrop
20662					.removeAttr('style')
20663					.css('transition-duration', _this.settings.backdropDuration + 'ms');
20664				_this.outer.removeClass("lg-closing " + _this.settings.startClass);
vendor: 6,259 bytes, lines 20665-20868
20665				_this.getSlideItem(_this.index).removeClass('lg-start-end-progress');
20666				_this.$inner.empty();
20667				if (_this.lgOpened) {
20668					_this.LGel.trigger(lGEvents.afterClose, {
20669						instance: _this,
20670					});
20671				}
20672				if (_this.$container.get()) {
20673					_this.$container.get().blur();
20674				}
20675				_this.lgOpened = false;
20676			}, removeTimeout + 100);
20677			return removeTimeout + 100;
20678		};
20679		LightGallery.prototype.initModules = function () {
20680			this.plugins.forEach(function (module) {
20681				try {
20682					module.init();
20683				}
20684				catch (err) {
20685					console.warn("lightGallery:- make sure lightGallery module is properly initiated");
20686				}
20687			});
20688		};
20689		LightGallery.prototype.destroyModules = function (destroy) {
20690			this.plugins.forEach(function (module) {
20691				try {
20692					if (destroy) {
20693						module.destroy();
20694					}
20695					else {
20696						module.closeGallery && module.closeGallery();
20697					}
20698				}
20699				catch (err) {
20700					console.warn("lightGallery:- make sure lightGallery module is properly destroyed");
20701				}
20702			});
20703		};
20704		/**
20705		 * Refresh lightGallery with new set of children.
20706		 *
20707		 * @description This is useful to update the gallery when the child elements are changed without calling destroy method.
20708		 *
20709		 * If you are using dynamic mode, you can pass the modified array of dynamicEl as the first parameter to refresh the dynamic gallery
20710		 * @see <a href="/demos/dynamic-mode/">Demo</a>
20711		 * @category lGPublicMethods
20712		 * @example
20713		 *  const plugin = lightGallery();
20714		 *  // Delete or add children, then call
20715		 *  plugin.refresh();
20716		 *
20717		 */
20718		LightGallery.prototype.refresh = function (galleryItems) {
20719			if (!this.settings.dynamic) {
20720				this.invalidateItems();
20721			}
20722			if (galleryItems) {
20723				this.galleryItems = galleryItems;
20724			}
20725			else {
20726				this.galleryItems = this.getItems();
20727			}
20728			this.updateControls();
20729			this.openGalleryOnItemClick();
20730			this.LGel.trigger(lGEvents.updateSlides);
20731		};
20732		LightGallery.prototype.updateControls = function () {
20733			this.addSlideVideoInfo(this.galleryItems);
20734			this.updateCounterTotal();
20735			this.manageSingleSlideClassName();
20736		};
20737		/**
20738		 * Destroy lightGallery.
20739		 * Destroy lightGallery and its plugin instances completely
20740		 *
20741		 * @description This method also calls CloseGallery function internally. Returns the time takes to completely close and destroy the instance.
20742		 * In case if you want to re-initialize lightGallery right after destroying it, initialize it only once the destroy process is completed.
20743		 * You can use refresh method most of the times.
20744		 * @category lGPublicMethods
20745		 * @example
20746		 *  const plugin = lightGallery();
20747		 *  plugin.destroy();
20748		 *
20749		 */
20750		LightGallery.prototype.destroy = function () {
20751			var _this = this;
20752			var closeTimeout = this.closeGallery(true);
20753			setTimeout(function () {
20754				_this.destroyModules(true);
20755				if (!_this.settings.dynamic) {
20756					_this.invalidateItems();
20757				}
20758				$LG(window).off(".lg.global" + _this.lgId);
20759				_this.LGel.off('.lg');
20760				_this.$container.remove();
20761			}, closeTimeout);
20762			return closeTimeout;
20763		};
20764		return LightGallery;
20765	}());
20766
20767	function lightGallery(el, options) {
20768		return new LightGallery(el, options);
20769	}
20770
20771	return lightGallery;
20772
20773})));
20774
20775/*!
20776 * lightgallery | 2.5.0 | June 13th 2022
20777 * http://www.lightgalleryjs.com/
20778 * Copyright (c) 2020 Sachin Neravath;
20779 * @license GPLv3
20780 */
20781
20782(function (global, factory) {
20783	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
20784	typeof define === 'function' && define.amd ? define(factory) :
20785	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgZoom = factory());
20786}(this, (function () { 'use strict';
20787
20788	/*! *****************************************************************************
20789	Copyright (c) Microsoft Corporation.
20790
20791	Permission to use, copy, modify, and/or distribute this software for any
20792	purpose with or without fee is hereby granted.
20793
20794	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
20795	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
20796	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
20797	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
20798	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
20799	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20800	PERFORMANCE OF THIS SOFTWARE.
20801	***************************************************************************** */
20802
20803	var __assign = function() {
20804		__assign = Object.assign || function __assign(t) {
20805			for (var s, i = 1, n = arguments.length; i < n; i++) {
20806				s = arguments[i];
20807				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
20808			}
20809			return t;
20810		};
20811		return __assign.apply(this, arguments);
20812	};
20813
20814	var zoomSettings = {
20815		scale: 1,
20816		zoom: true,
20817		actualSize: true,
20818		showZoomInOutIcons: false,
20819		actualSizeIcons: {
20820			zoomIn: 'lg-zoom-in',
20821			zoomOut: 'lg-zoom-out',
20822		},
20823		enableZoomAfter: 300,
20824		zoomPluginStrings: {
20825			zoomIn: 'Zoom in',
20826			zoomOut: 'Zoom out',
20827			viewActualSize: 'View actual size',
20828		},
20829	};
20830
20831	/**
20832	 * List of lightGallery events
20833	 * All events should be documented here
20834	 * Below interfaces are used to build the website documentations
20835	 * */
20836	var lGEvents = {
20837		afterAppendSlide: 'lgAfterAppendSlide',
20838		init: 'lgInit',
20839		hasVideo: 'lgHasVideo',
20840		containerResize: 'lgContainerResize',
20841		updateSlides: 'lgUpdateSlides',
20842		afterAppendSubHtml: 'lgAfterAppendSubHtml',
20843		beforeOpen: 'lgBeforeOpen',
20844		afterOpen: 'lgAfterOpen',
20845		slideItemLoad: 'lgSlideItemLoad',
20846		beforeSlide: 'lgBeforeSlide',
20847		afterSlide: 'lgAfterSlide',
20848		posterClick: 'lgPosterClick',
20849		dragStart: 'lgDragStart',
20850		dragMove: 'lgDragMove',
20851		dragEnd: 'lgDragEnd',
20852		beforeNextSlide: 'lgBeforeNextSlide',
20853		beforePrevSlide: 'lgBeforePrevSlide',
20854		beforeClose: 'lgBeforeClose',
20855		afterClose: 'lgAfterClose',
20856		rotateLeft: 'lgRotateLeft',
20857		rotateRight: 'lgRotateRight',
20858		flipHorizontal: 'lgFlipHorizontal',
20859		flipVertical: 'lgFlipVertical',
20860		autoplay: 'lgAutoplay',
20861		autoplayStart: 'lgAutoplayStart',
20862		autoplayStop: 'lgAutoplayStop',
20863	};
20864
20865	var Zoom = /** @class */ (function () {
20866		function Zoom(instance, $LG) {
20867			// get lightGallery core plugin instance
20868			this.core = instance;
20869			this.$LG = $LG;
20870			this.settings = __assign(__assign({}, zoomSettings), this.core.settings);
20871			return this;
20872		}
20873		// Append Zoom controls. Actual size, Zoom-in, Zoom-out
20874		Zoom.prototype.buildTemplates = function () {
20875			var zoomIcons = this.settings.showZoomInOutIcons
20876				? "<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>"
20877				: '';
20878			if (this.settings.actualSize) {
20879				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>";
20880			}
20881			this.core.outer.addClass('lg-use-transition-for-zoom');
20882			this.core.$toolbar.first().append(zoomIcons);
20883		};
20884		/**
20885		 * @desc Enable zoom option only once the image is completely loaded
20886		 * If zoomFromOrigin is true, Zoom is enabled once the dummy image has been inserted
20887		 *
20888		 * Zoom styles are defined under lg-zoomable CSS class.
20889		 */
20890		Zoom.prototype.enableZoom = function (event) {
20891			var _this = this;
20892			// delay will be 0 except first time
20893			var _speed = this.settings.enableZoomAfter + event.detail.delay;
20894			// set _speed value 0 if gallery opened from direct url and if it is first slide
20895			if (this.$LG('body').first().hasClass('lg-from-hash') &&
20896				event.detail.delay) {
20897				// will execute only once
20898				_speed = 0;
20899			}
20900			else {
20901				// Remove lg-from-hash to enable starting animation.
20902				this.$LG('body').first().removeClass('lg-from-hash');
20903			}
20904			this.zoomableTimeout = setTimeout(function () {
20905				if (!_this.isImageSlide()) {
20906					return;
20907				}
20908				_this.core.getSlideItem(event.detail.index).addClass('lg-zoomable');
20909				if (event.detail.index === _this.core.index) {
20910					_this.setZoomEssentials();
20911				}
20912			}, _speed + 30);
20913		};
20914		Zoom.prototype.enableZoomOnSlideItemLoad = function () {
20915			// Add zoomable class
20916			this.core.LGel.on(lGEvents.slideItemLoad + ".zoom", this.enableZoom.bind(this));
20917		};
20918		Zoom.prototype.getModifier = function (rotateValue, axis, el) {
20919			var originalRotate = rotateValue;
20920			rotateValue = Math.abs(rotateValue);
20921			var transformValues = this.getCurrentTransform(el);
20922			if (!transformValues) {
20923				return 1;
20924			}
20925			var modifier = 1;
20926			if (axis === 'X') {
20927				var flipHorizontalValue = Math.sign(parseFloat(transformValues[0]));
20928				if (rotateValue === 0 || rotateValue === 180) {
20929					modifier = 1;
20930				}
20931				else if (rotateValue === 90) {
20932					if ((originalRotate === -90 && flipHorizontalValue === 1) ||
20933						(originalRotate === 90 && flipHorizontalValue === -1)) {
20934						modifier = -1;
20935					}
20936					else {
20937						modifier = 1;
20938					}
20939				}
20940				modifier = modifier * flipHorizontalValue;
20941			}
20942			else {
20943				var flipVerticalValue = Math.sign(parseFloat(transformValues[3]));
20944				if (rotateValue === 0 || rotateValue === 180) {
20945					modifier = 1;
20946				}
20947				else if (rotateValue === 90) {
20948					var sinX = parseFloat(transformValues[1]);
20949					var sinMinusX = parseFloat(transformValues[2]);
20950					modifier = Math.sign(sinX * sinMinusX * originalRotate * flipVerticalValue);
20951				}
20952				modifier = modifier * flipVerticalValue;
20953			}
20954			return modifier;
20955		};
20956		Zoom.prototype.getImageSize = function ($image, rotateValue, axis) {
20957			var imageSizes = {
20958				y: 'offsetHeight',
20959				x: 'offsetWidth',
20960			};
20961			if (Math.abs(rotateValue) === 90) {
20962				// Swap axis
20963				if (axis === 'x') {
20964					axis = 'y';
20965				}
20966				else {
20967					axis = 'x';
20968				}
20969			}
20970			return $image[imageSizes[axis]];
20971		};
20972		Zoom.prototype.getDragCords = function (e, rotateValue) {
20973			if (rotateValue === 90) {
20974				return {
20975					x: e.pageY,
20976					y: e.pageX,
20977				};
20978			}
20979			else {
20980				return {
20981					x: e.pageX,
20982					y: e.pageY,
20983				};
20984			}
20985		};
20986		Zoom.prototype.getSwipeCords = function (e, rotateValue) {
20987			var x = e.targetTouches[0].pageX;
20988			var y = e.targetTouches[0].pageY;
20989			if (rotateValue === 90) {
20990				return {
20991					x: y,
20992					y: x,
20993				};
20994			}
20995			else {
20996				return {
20997					x: x,
20998					y: y,
20999				};
21000			}
21001		};
21002		Zoom.prototype.getDragAllowedAxises = function (rotateValue, scale) {
21003			scale = scale || this.scale || 1;
21004			var allowY = this.imageYSize * scale > this.containerRect.height;
21005			var allowX = this.imageXSize * scale > this.containerRect.width;
21006			if (rotateValue === 90) {
21007				return {
21008					allowX: allowY,
21009					allowY: allowX,
21010				};
21011			}
21012			else {
21013				return {
21014					allowX: allowX,
21015					allowY: allowY,
21016				};
21017			}
21018		};
21019		/**
21020		 *
21021		 * @param {Element} el
21022		 * @return matrix(cos(X), sin(X), -sin(X), cos(X), 0, 0);
21023		 * Get the current transform value
21024		 */
21025		Zoom.prototype.getCurrentTransform = function (el) {
21026			if (!el) {
21027				return;
21028			}
21029			var st = window.getComputedStyle(el, null);
21030			var tm = st.getPropertyValue('-webkit-transform') ||
21031				st.getPropertyValue('-moz-transform') ||
21032				st.getPropertyValue('-ms-transform') ||
21033				st.getPropertyValue('-o-transform') ||
21034				st.getPropertyValue('transform') ||
21035				'none';
21036			if (tm !== 'none') {
21037				return tm.split('(')[1].split(')')[0].split(',');
21038			}
21039			return;
21040		};
21041		Zoom.prototype.getCurrentRotation = function (el) {
21042			if (!el) {
21043				return 0;
21044			}
21045			var values = this.getCurrentTransform(el);
21046			if (values) {
21047				return Math.round(Math.atan2(parseFloat(values[1]), parseFloat(values[0])) *
21048					(180 / Math.PI));
21049				// If you want rotate in 360
21050				//return (angle < 0 ? angle + 360 : angle);
21051			}
21052			return 0;
21053		};
21054		Zoom.prototype.setZoomEssentials = function () {
21055			var $image = this.core
21056				.getSlideItem(this.core.index)
21057				.find('.lg-image')
21058				.first();
21059			var rotateEl = this.core
21060				.getSlideItem(this.core.index)
21061				.find('.lg-img-rotate')
21062				.first()
21063				.get();
21064			this.rotateValue = this.getCurrentRotation(rotateEl);
21065			this.imageYSize = this.getImageSize($image.get(), this.rotateValue, 'y');
21066			this.imageXSize = this.getImageSize($image.get(), this.rotateValue, 'x');
21067			this.containerRect = this.core.outer.get().getBoundingClientRect();
21068			this.modifierX = this.getModifier(this.rotateValue, 'X', rotateEl);
21069			this.modifierY = this.getModifier(this.rotateValue, 'Y', rotateEl);
21070		};
21071		/**
21072		 * @desc Image zoom
21073		 * Translate the wrap and scale the image to get better user experience
21074		 *
21075		 * @param {String} scale - Zoom decrement/increment value
21076		 */
21077		Zoom.prototype.zoomImage = function (scale) {
21078			// Find offset manually to avoid issue after zoom
21079			var offsetX = (this.containerRect.width - this.imageXSize) / 2 +
21080				this.containerRect.left;
21081			var _a = this.core.mediaContainerPosition, top = _a.top, bottom = _a.bottom;
21082			var topBottomSpacing = Math.abs(top - bottom) / 2;
21083			var offsetY = (this.containerRect.height -
21084				this.imageYSize -
21085				topBottomSpacing * this.modifierX) /
21086				2 +
21087				this.scrollTop +
21088				this.containerRect.top;
21089			var originalX;
21090			var originalY;
21091			if (scale === 1) {
21092				this.positionChanged = false;
21093			}
21094			var dragAllowedAxises = this.getDragAllowedAxises(Math.abs(this.rotateValue), scale);
21095			var allowY = dragAllowedAxises.allowY, allowX = dragAllowedAxises.allowX;
21096			if (this.positionChanged) {
21097				originalX = this.left / (this.scale - 1);
21098				originalY = this.top / (this.scale - 1);
21099				this.pageX = Math.abs(originalX) + offsetX;
21100				this.pageY = Math.abs(originalY) + offsetY;
21101				this.positionChanged = false;
21102			}
21103			var possibleSwipeCords = this.getPossibleSwipeDragCords(this.rotateValue, scale);
21104			var _x = offsetX - this.pageX;
21105			var _y = offsetY - this.pageY;
21106			var x = (scale - 1) * _x;
21107			var y = (scale - 1) * _y;
21108			if (allowX) {
21109				if (this.isBeyondPossibleLeft(x, possibleSwipeCords.minX)) {
21110					x = possibleSwipeCords.minX;
21111				}
21112				else if (this.isBeyondPossibleRight(x, possibleSwipeCords.maxX)) {
21113					x = possibleSwipeCords.maxX;
21114				}
21115			}
21116			else {
21117				if (scale > 1) {
21118					if (x < possibleSwipeCords.minX) {
21119						x = possibleSwipeCords.minX;
21120					}
21121					else if (x > possibleSwipeCords.maxX) {
21122						x = possibleSwipeCords.maxX;
21123					}
21124				}
21125			}
21126			if (allowY) {
21127				if (this.isBeyondPossibleTop(y, possibleSwipeCords.minY)) {
21128					y = possibleSwipeCords.minY;
21129				}
21130				else if (this.isBeyondPossibleBottom(y, possibleSwipeCords.maxY)) {
21131					y = possibleSwipeCords.maxY;
21132				}
21133			}
21134			else {
21135				// If the translate value based on index of beyond the viewport, utilize the available space to prevent image being cut out
21136				if (scale > 1) {
21137					//If image goes beyond viewport top, use the minim possible translate value
21138					if (y < possibleSwipeCords.minY) {
21139						y = possibleSwipeCords.minY;
21140					}
21141					else if (y > possibleSwipeCords.maxY) {
21142						y = possibleSwipeCords.maxY;
21143					}
21144				}
21145			}
21146			this.setZoomStyles({
21147				x: x,
21148				y: y,
21149				scale: scale,
21150			});
21151		};
21152		/**
21153		 * @desc apply scale3d to image and translate to image wrap
21154		 * @param {style} X,Y and scale
21155		 */
21156		Zoom.prototype.setZoomStyles = function (style) {
21157			var $image = this.core
21158				.getSlideItem(this.core.index)
21159				.find('.lg-image')
21160				.first();
21161			var $dummyImage = this.core.outer
21162				.find('.lg-current .lg-dummy-img')
21163				.first();
21164			var $imageWrap = $image.parent();
21165			this.scale = style.scale;
21166			$image.css('transform', 'scale3d(' + style.scale + ', ' + style.scale + ', 1)');
21167			$dummyImage.css('transform', 'scale3d(' + style.scale + ', ' + style.scale + ', 1)');
21168			var transform = 'translate3d(' + style.x + 'px, ' + style.y + 'px, 0)';
21169			$imageWrap.css('transform', transform);
21170			this.left = style.x;
21171			this.top = style.y;
21172		};
21173		/**
21174		 * @param index - Index of the current slide
21175		 * @param event - event will be available only if the function is called on clicking/taping the imags
21176		 */
21177		Zoom.prototype.setActualSize = function (index, event) {
21178			var _this = this;
21179			// Allow zoom only on image
21180			if (!this.isImageSlide() ||
21181				this.core.outer.hasClass('lg-first-slide-loading')) {
21182				return;
21183			}
21184			var scale = this.getCurrentImageActualSizeScale();
21185			if (this.core.outer.hasClass('lg-zoomed')) {
21186				this.scale = 1;
21187			}
21188			else {
21189				this.scale = this.getScale(scale);
21190			}
21191			this.setPageCords(event);
21192			this.beginZoom(this.scale);
21193			this.zoomImage(this.scale);
21194			setTimeout(function () {
21195				_this.core.outer.removeClass('lg-grabbing').addClass('lg-grab');
21196			}, 10);
21197		};
21198		Zoom.prototype.getNaturalWidth = function (index) {
21199			var $image = this.core.getSlideItem(index).find('.lg-image').first();
21200			var naturalWidth = this.core.galleryItems[index].width;
21201			return naturalWidth
21202				? parseFloat(naturalWidth)
21203				: $image.get().naturalWidth;
21204		};
21205		Zoom.prototype.getActualSizeScale = function (naturalWidth, width) {
21206			var _scale;
21207			var scale;
21208			if (naturalWidth > width) {
21209				_scale = naturalWidth / width;
21210				scale = _scale || 2;
21211			}
21212			else {
21213				scale = 1;
21214			}
21215			return scale;
21216		};
21217		Zoom.prototype.getCurrentImageActualSizeScale = function () {
21218			var $image = this.core
21219				.getSlideItem(this.core.index)
21220				.find('.lg-image')
21221				.first();
21222			var width = $image.get().offsetWidth;
21223			var naturalWidth = this.getNaturalWidth(this.core.index) || width;
21224			return this.getActualSizeScale(naturalWidth, width);
21225		};
21226		Zoom.prototype.getPageCords = function (event) {
21227			var cords = {};
21228			if (event) {
21229				cords.x = event.pageX || event.targetTouches[0].pageX;
21230				cords.y = event.pageY || event.targetTouches[0].pageY;
21231			}
21232			else {
21233				var containerRect = this.core.outer.get().getBoundingClientRect();
21234				cords.x = containerRect.width / 2 + containerRect.left;
21235				cords.y =
21236					containerRect.height / 2 + this.scrollTop + containerRect.top;
21237			}
21238			return cords;
21239		};
21240		Zoom.prototype.setPageCords = function (event) {
21241			var pageCords = this.getPageCords(event);
21242			this.pageX = pageCords.x;
21243			this.pageY = pageCords.y;
21244		};
21245		// If true, zoomed - in else zoomed out
21246		Zoom.prototype.beginZoom = function (scale) {
21247			this.core.outer.removeClass('lg-zoom-drag-transition lg-zoom-dragging');
21248			if (scale > 1) {
21249				this.core.outer.addClass('lg-zoomed');
21250				var $actualSize = this.core.getElementById('lg-actual-size');
21251				$actualSize
21252					.removeClass(this.settings.actualSizeIcons.zoomIn)
21253					.addClass(this.settings.actualSizeIcons.zoomOut);
21254			}
21255			else {
21256				this.resetZoom();
21257			}
21258			return scale > 1;
21259		};
21260		Zoom.prototype.getScale = function (scale) {
21261			var actualSizeScale = this.getCurrentImageActualSizeScale();
21262			if (scale < 1) {
21263				scale = 1;
21264			}
21265			else if (scale > actualSizeScale) {
21266				scale = actualSizeScale;
21267			}
21268			return scale;
21269		};
21270		Zoom.prototype.init = function () {
21271			var _this = this;
21272			if (!this.settings.zoom) {
21273				return;
21274			}
21275			this.buildTemplates();
21276			this.enableZoomOnSlideItemLoad();
21277			var tapped = null;
21278			this.core.outer.on('dblclick.lg', function (event) {
21279				if (!_this.$LG(event.target).hasClass('lg-image')) {
21280					return;
21281				}
21282				_this.setActualSize(_this.core.index, event);
21283			});
21284			this.core.outer.on('touchstart.lg', function (event) {
21285				var $target = _this.$LG(event.target);
21286				if (event.targetTouches.length === 1 &&
21287					$target.hasClass('lg-image')) {
21288					if (!tapped) {
21289						tapped = setTimeout(function () {
21290							tapped = null;
21291						}, 300);
21292					}
21293					else {
21294						clearTimeout(tapped);
21295						tapped = null;
21296						event.preventDefault();
21297						_this.setActualSize(_this.core.index, event);
21298					}
21299				}
21300			});
21301			// Update zoom on resize and orientationchange
21302			this.core.LGel.on(lGEvents.containerResize + ".zoom " + lGEvents.rotateRight + ".zoom " + lGEvents.rotateLeft + ".zoom " + lGEvents.flipHorizontal + ".zoom " + lGEvents.flipVertical + ".zoom", function () {
21303				if (!_this.core.lgOpened || !_this.isImageSlide())
21304					return;
21305				_this.setPageCords();
21306				_this.setZoomEssentials();
21307				_this.zoomImage(_this.scale);
21308			});
21309			// Update zoom on resize and orientationchange
21310			this.$LG(window).on("scroll.lg.zoom.global" + this.core.lgId, function () {
21311				if (!_this.core.lgOpened)
21312					return;
21313				_this.scrollTop = _this.$LG(window).scrollTop();
21314			});
21315			this.core.getElementById('lg-zoom-out').on('click.lg', function () {
21316				if (_this.core.outer.find('.lg-current .lg-image').get()) {
21317					_this.scale -= _this.settings.scale;
21318					_this.scale = _this.getScale(_this.scale);
21319					_this.beginZoom(_this.scale);
21320					_this.zoomImage(_this.scale);
21321				}
21322			});
21323			this.core.getElementById('lg-zoom-in').on('click.lg', function () {
21324				_this.zoomIn();
21325			});
21326			this.core.getElementById('lg-actual-size').on('click.lg', function () {
21327				_this.setActualSize(_this.core.index);
21328			});
21329			this.core.LGel.on(lGEvents.beforeOpen + ".zoom", function () {
21330				_this.core.outer.find('.lg-item').removeClass('lg-zoomable');
21331			});
21332			this.core.LGel.on(lGEvents.afterOpen + ".zoom", function () {
21333				_this.scrollTop = _this.$LG(window).scrollTop();
21334				// Set the initial value center
21335				_this.pageX = _this.core.outer.width() / 2;
21336				_this.pageY = _this.core.outer.height() / 2 + _this.scrollTop;
21337				_this.scale = 1;
21338			});
21339			// Reset zoom on slide change
21340			this.core.LGel.on(lGEvents.afterSlide + ".zoom", function (event) {
21341				var prevIndex = event.detail.prevIndex;
21342				_this.scale = 1;
21343				_this.positionChanged = false;
21344				_this.resetZoom(prevIndex);
21345				if (_this.isImageSlide()) {
21346					_this.setZoomEssentials();
21347				}
21348			});
21349			// Drag option after zoom
21350			this.zoomDrag();
21351			this.pinchZoom();
21352			this.zoomSwipe();
21353			// Store the zoomable timeout value just to clear it while closing
21354			this.zoomableTimeout = false;
21355			this.positionChanged = false;
21356		};
21357		Zoom.prototype.zoomIn = function (scale) {
21358			// Allow zoom only on image
21359			if (!this.isImageSlide()) {
21360				return;
21361			}
21362			if (scale) {
21363				this.scale = scale;
21364			}
21365			else {
21366				this.scale += this.settings.scale;
21367			}
21368			this.scale = this.getScale(this.scale);
21369			this.beginZoom(this.scale);
21370			this.zoomImage(this.scale);
21371		};
21372		// Reset zoom effect
21373		Zoom.prototype.resetZoom = function (index) {
21374			this.core.outer.removeClass('lg-zoomed lg-zoom-drag-transition');
21375			var $actualSize = this.core.getElementById('lg-actual-size');
21376			var $item = this.core.getSlideItem(index !== undefined ? index : this.core.index);
21377			$actualSize
21378				.removeClass(this.settings.actualSizeIcons.zoomOut)
21379				.addClass(this.settings.actualSizeIcons.zoomIn);
21380			$item.find('.lg-img-wrap').first().removeAttr('style');
21381			$item.find('.lg-image').first().removeAttr('style');
21382			this.scale = 1;
21383			this.left = 0;
21384			this.top = 0;
21385			// Reset pagx pagy values to center
21386			this.setPageCords();
21387		};
21388		Zoom.prototype.getTouchDistance = function (e) {
21389			return Math.sqrt((e.targetTouches[0].pageX - e.targetTouches[1].pageX) *
21390				(e.targetTouches[0].pageX - e.targetTouches[1].pageX) +
21391				(e.targetTouches[0].pageY - e.targetTouches[1].pageY) *
21392					(e.targetTouches[0].pageY - e.targetTouches[1].pageY));
21393		};
21394		Zoom.prototype.pinchZoom = function () {
21395			var _this = this;
21396			var startDist = 0;
21397			var pinchStarted = false;
21398			var initScale = 1;
21399			var $item = this.core.getSlideItem(this.core.index);
21400			this.core.$inner.on('touchstart.lg', function (e) {
21401				$item = _this.core.getSlideItem(_this.core.index);
21402				if (!_this.isImageSlide()) {
21403					return;
21404				}
21405				if (e.targetTouches.length === 2 &&
21406					!_this.core.outer.hasClass('lg-first-slide-loading') &&
21407					(_this.$LG(e.target).hasClass('lg-item') ||
21408						$item.get().contains(e.target))) {
21409					initScale = _this.scale || 1;
21410					_this.core.outer.removeClass('lg-zoom-drag-transition lg-zoom-dragging');
21411					_this.core.touchAction = 'pinch';
21412					startDist = _this.getTouchDistance(e);
21413				}
21414			});
21415			this.core.$inner.on('touchmove.lg', function (e) {
21416				if (e.targetTouches.length === 2 &&
21417					_this.core.touchAction === 'pinch' &&
21418					(_this.$LG(e.target).hasClass('lg-item') ||
21419						$item.get().contains(e.target))) {
21420					e.preventDefault();
21421					var endDist = _this.getTouchDistance(e);
21422					var distance = startDist - endDist;
21423					if (!pinchStarted && Math.abs(distance) > 5) {
21424						pinchStarted = true;
21425					}
21426					if (pinchStarted) {
21427						_this.scale = Math.max(1, initScale + -distance * 0.008);
21428						_this.zoomImage(_this.scale);
21429					}
21430				}
21431			});
21432			this.core.$inner.on('touchend.lg', function (e) {
21433				if (_this.core.touchAction === 'pinch' &&
21434					(_this.$LG(e.target).hasClass('lg-item') ||
21435						$item.get().contains(e.target))) {
21436					pinchStarted = false;
21437					startDist = 0;
21438					if (_this.scale <= 1) {
21439						_this.resetZoom();
21440					}
21441					else {
21442						_this.scale = _this.getScale(_this.scale);
21443						_this.zoomImage(_this.scale);
21444						_this.core.outer.addClass('lg-zoomed');
21445					}
21446					_this.core.touchAction = undefined;
21447				}
21448			});
21449		};
21450		Zoom.prototype.touchendZoom = function (startCoords, endCoords, allowX, allowY, touchDuration, rotateValue) {
21451			var distanceXnew = endCoords.x - startCoords.x;
21452			var distanceYnew = endCoords.y - startCoords.y;
21453			var speedX = Math.abs(distanceXnew) / touchDuration + 1;
21454			var speedY = Math.abs(distanceYnew) / touchDuration + 1;
21455			if (speedX > 2) {
21456				speedX += 1;
21457			}
21458			if (speedY > 2) {
21459				speedY += 1;
21460			}
21461			distanceXnew = distanceXnew * speedX;
21462			distanceYnew = distanceYnew * speedY;
21463			var _LGel = this.core
21464				.getSlideItem(this.core.index)
21465				.find('.lg-img-wrap')
21466				.first();
21467			var distance = {};
21468			distance.x = this.left + distanceXnew * this.modifierX;
21469			distance.y = this.top + distanceYnew * this.modifierY;
21470			var possibleSwipeCords = this.getPossibleSwipeDragCords(rotateValue);
21471			if (Math.abs(distanceXnew) > 15 || Math.abs(distanceYnew) > 15) {
21472				if (allowY) {
21473					if (this.isBeyondPossibleTop(distance.y, possibleSwipeCords.minY)) {
21474						distance.y = possibleSwipeCords.minY;
21475					}
21476					else if (this.isBeyondPossibleBottom(distance.y, possibleSwipeCords.maxY)) {
21477						distance.y = possibleSwipeCords.maxY;
21478					}
21479				}
21480				if (allowX) {
21481					if (this.isBeyondPossibleLeft(distance.x, possibleSwipeCords.minX)) {
21482						distance.x = possibleSwipeCords.minX;
21483					}
21484					else if (this.isBeyondPossibleRight(distance.x, possibleSwipeCords.maxX)) {
21485						distance.x = possibleSwipeCords.maxX;
21486					}
21487				}
21488				if (allowY) {
21489					this.top = distance.y;
21490				}
21491				else {
21492					distance.y = this.top;
21493				}
21494				if (allowX) {
21495					this.left = distance.x;
21496				}
21497				else {
21498					distance.x = this.left;
21499				}
21500				this.setZoomSwipeStyles(_LGel, distance);
21501				this.positionChanged = true;
21502			}
21503		};
21504		Zoom.prototype.getZoomSwipeCords = function (startCoords, endCoords, allowX, allowY, possibleSwipeCords) {
21505			var distance = {};
21506			if (allowY) {
21507				distance.y =
21508					this.top + (endCoords.y - startCoords.y) * this.modifierY;
21509				if (this.isBeyondPossibleTop(distance.y, possibleSwipeCords.minY)) {
21510					var diffMinY = possibleSwipeCords.minY - distance.y;
21511					distance.y = possibleSwipeCords.minY - diffMinY / 6;
21512				}
21513				else if (this.isBeyondPossibleBottom(distance.y, possibleSwipeCords.maxY)) {
21514					var diffMaxY = distance.y - possibleSwipeCords.maxY;
21515					distance.y = possibleSwipeCords.maxY + diffMaxY / 6;
21516				}
21517			}
21518			else {
21519				distance.y = this.top;
21520			}
21521			if (allowX) {
21522				distance.x =
21523					this.left + (endCoords.x - startCoords.x) * this.modifierX;
21524				if (this.isBeyondPossibleLeft(distance.x, possibleSwipeCords.minX)) {
21525					var diffMinX = possibleSwipeCords.minX - distance.x;
21526					distance.x = possibleSwipeCords.minX - diffMinX / 6;
21527				}
21528				else if (this.isBeyondPossibleRight(distance.x, possibleSwipeCords.maxX)) {
21529					var difMaxX = distance.x - possibleSwipeCords.maxX;
21530					distance.x = possibleSwipeCords.maxX + difMaxX / 6;
21531				}
21532			}
21533			else {
21534				distance.x = this.left;
21535			}
21536			return distance;
21537		};
21538		Zoom.prototype.isBeyondPossibleLeft = function (x, minX) {
21539			return x >= minX;
21540		};
21541		Zoom.prototype.isBeyondPossibleRight = function (x, maxX) {
21542			return x <= maxX;
21543		};
21544		Zoom.prototype.isBeyondPossibleTop = function (y, minY) {
21545			return y >= minY;
21546		};
21547		Zoom.prototype.isBeyondPossibleBottom = function (y, maxY) {
21548			return y <= maxY;
21549		};
21550		Zoom.prototype.isImageSlide = function () {
21551			var currentItem = this.core.galleryItems[this.core.index];
21552			return this.core.getSlideType(currentItem) === 'image';
21553		};
21554		Zoom.prototype.getPossibleSwipeDragCords = function (rotateValue, scale) {
21555			var dataScale = scale || this.scale || 1;
21556			var elDataScale = Math.abs(dataScale);
21557			var _a = this.core.mediaContainerPosition, top = _a.top, bottom = _a.bottom;
21558			var topBottomSpacing = Math.abs(top - bottom) / 2;
21559			var minY = (this.imageYSize - this.containerRect.height) / 2 +
21560				topBottomSpacing * this.modifierX;
21561			var maxY = this.containerRect.height - this.imageYSize * elDataScale + minY;
21562			var minX = (this.imageXSize - this.containerRect.width) / 2;
21563			var maxX = this.containerRect.width - this.imageXSize * elDataScale + minX;
21564			var possibleSwipeCords = {
21565				minY: minY,
21566				maxY: maxY,
21567				minX: minX,
21568				maxX: maxX,
21569			};
21570			if (Math.abs(rotateValue) === 90) {
21571				possibleSwipeCords = {
21572					minY: minX,
21573					maxY: maxX,
21574					minX: minY,
21575					maxX: maxY,
21576				};
21577			}
21578			return possibleSwipeCords;
21579		};
21580		Zoom.prototype.setZoomSwipeStyles = function (LGel, distance) {
21581			LGel.css('transform', 'translate3d(' + distance.x + 'px, ' + distance.y + 'px, 0)');
21582		};
21583		Zoom.prototype.zoomSwipe = function () {
21584			var _this = this;
21585			var startCoords = {};
21586			var endCoords = {};
21587			var isMoved = false;
21588			// Allow x direction drag
21589			var allowX = false;
21590			// Allow Y direction drag
21591			var allowY = false;
21592			var startTime = new Date();
21593			var endTime = new Date();
21594			var possibleSwipeCords;
21595			var _LGel;
21596			var $item = this.core.getSlideItem(this.core.index);
21597			this.core.$inner.on('touchstart.lg', function (e) {
21598				// Allow zoom only on image
21599				if (!_this.isImageSlide()) {
21600					return;
21601				}
21602				$item = _this.core.getSlideItem(_this.core.index);
21603				if ((_this.$LG(e.target).hasClass('lg-item') ||
21604					$item.get().contains(e.target)) &&
21605					e.targetTouches.length === 1 &&
21606					_this.core.outer.hasClass('lg-zoomed')) {
21607					e.preventDefault();
21608					startTime = new Date();
21609					_this.core.touchAction = 'zoomSwipe';
21610					_LGel = _this.core
21611						.getSlideItem(_this.core.index)
21612						.find('.lg-img-wrap')
21613						.first();
21614					var dragAllowedAxises = _this.getDragAllowedAxises(Math.abs(_this.rotateValue));
21615					allowY = dragAllowedAxises.allowY;
21616					allowX = dragAllowedAxises.allowX;
21617					if (allowX || allowY) {
21618						startCoords = _this.getSwipeCords(e, Math.abs(_this.rotateValue));
21619					}
21620					possibleSwipeCords = _this.getPossibleSwipeDragCords(_this.rotateValue);
21621					// reset opacity and transition duration
21622					_this.core.outer.addClass('lg-zoom-dragging lg-zoom-drag-transition');
21623				}
21624			});
21625			this.core.$inner.on('touchmove.lg', function (e) {
21626				if (e.targetTouches.length === 1 &&
21627					_this.core.touchAction === 'zoomSwipe' &&
21628					(_this.$LG(e.target).hasClass('lg-item') ||
21629						$item.get().contains(e.target))) {
21630					e.preventDefault();
21631					_this.core.touchAction = 'zoomSwipe';
21632					endCoords = _this.getSwipeCords(e, Math.abs(_this.rotateValue));
21633					var distance = _this.getZoomSwipeCords(startCoords, endCoords, allowX, allowY, possibleSwipeCords);
21634					if (Math.abs(endCoords.x - startCoords.x) > 15 ||
21635						Math.abs(endCoords.y - startCoords.y) > 15) {
21636						isMoved = true;
21637						_this.setZoomSwipeStyles(_LGel, distance);
21638					}
21639				}
21640			});
21641			this.core.$inner.on('touchend.lg', function (e) {
21642				if (_this.core.touchAction === 'zoomSwipe' &&
21643					(_this.$LG(e.target).hasClass('lg-item') ||
21644						$item.get().contains(e.target))) {
21645					_this.core.touchAction = undefined;
21646					_this.core.outer.removeClass('lg-zoom-dragging');
21647					if (!isMoved) {
21648						return;
21649					}
21650					isMoved = false;
21651					endTime = new Date();
21652					var touchDuration = endTime.valueOf() - startTime.valueOf();
21653					_this.touchendZoom(startCoords, endCoords, allowX, allowY, touchDuration, _this.rotateValue);
21654				}
21655			});
21656		};
21657		Zoom.prototype.zoomDrag = function () {
21658			var _this = this;
21659			var startCoords = {};
21660			var endCoords = {};
21661			var isDragging = false;
21662			var isMoved = false;
21663			// Allow x direction drag
21664			var allowX = false;
21665			// Allow Y direction drag
21666			var allowY = false;
21667			var startTime;
21668			var endTime;
21669			var possibleSwipeCords;
21670			var _LGel;
21671			this.core.outer.on('mousedown.lg.zoom', function (e) {
21672				// Allow zoom only on image
21673				if (!_this.isImageSlide()) {
21674					return;
21675				}
21676				var $item = _this.core.getSlideItem(_this.core.index);
21677				if (_this.$LG(e.target).hasClass('lg-item') ||
21678					$item.get().contains(e.target)) {
21679					startTime = new Date();
21680					_LGel = _this.core
21681						.getSlideItem(_this.core.index)
21682						.find('.lg-img-wrap')
21683						.first();
21684					var dragAllowedAxises = _this.getDragAllowedAxises(Math.abs(_this.rotateValue));
21685					allowY = dragAllowedAxises.allowY;
21686					allowX = dragAllowedAxises.allowX;
21687					if (_this.core.outer.hasClass('lg-zoomed')) {
21688						if (_this.$LG(e.target).hasClass('lg-object') &&
21689							(allowX || allowY)) {
21690							e.preventDefault();
21691							startCoords = _this.getDragCords(e, Math.abs(_this.rotateValue));
21692							possibleSwipeCords = _this.getPossibleSwipeDragCords(_this.rotateValue);
21693							isDragging = true;
21694							// ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723
21695							_this.core.outer.get().scrollLeft += 1;
21696							_this.core.outer.get().scrollLeft -= 1;
21697							_this.core.outer
21698								.removeClass('lg-grab')
21699								.addClass('lg-grabbing lg-zoom-drag-transition lg-zoom-dragging');
21700							// reset opacity and transition duration
21701						}
21702					}
21703				}
21704			});
21705			this.$LG(window).on("mousemove.lg.zoom.global" + this.core.lgId, function (e) {
21706				if (isDragging) {
21707					isMoved = true;
21708					endCoords = _this.getDragCords(e, Math.abs(_this.rotateValue));
21709					var distance = _this.getZoomSwipeCords(startCoords, endCoords, allowX, allowY, possibleSwipeCords);
21710					_this.setZoomSwipeStyles(_LGel, distance);
21711				}
21712			});
21713			this.$LG(window).on("mouseup.lg.zoom.global" + this.core.lgId, function (e) {
21714				if (isDragging) {
21715					endTime = new Date();
21716					isDragging = false;
21717					_this.core.outer.removeClass('lg-zoom-dragging');
21718					// Fix for chrome mouse move on click
21719					if (isMoved &&
21720						(startCoords.x !== endCoords.x ||
21721							startCoords.y !== endCoords.y)) {
21722						endCoords = _this.getDragCords(e, Math.abs(_this.rotateValue));
21723						var touchDuration = endTime.valueOf() - startTime.valueOf();
21724						_this.touchendZoom(startCoords, endCoords, allowX, allowY, touchDuration, _this.rotateValue);
21725					}
21726					isMoved = false;
21727				}
21728				_this.core.outer.removeClass('lg-grabbing').addClass('lg-grab');
21729			});
21730		};
21731		Zoom.prototype.closeGallery = function () {
21732			this.resetZoom();
21733		};
21734		Zoom.prototype.destroy = function () {
21735			// Unbind all events added by lightGallery zoom plugin
21736			this.$LG(window).off(".lg.zoom.global" + this.core.lgId);
21737			this.core.LGel.off('.lg.zoom');
21738			this.core.LGel.off('.zoom');
21739			clearTimeout(this.zoomableTimeout);
21740			this.zoomableTimeout = false;
21741		};
21742		return Zoom;
21743	}());
21744
21745	return Zoom;
21746
21747})));
21748/*!
21749 * lightgallery | 2.5.0 | June 13th 2022
21750 * http://www.lightgalleryjs.com/
21751 * Copyright (c) 2020 Sachin Neravath;
21752 * @license GPLv3
21753 */
21754
21755(function (global, factory) {
21756	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
21757	typeof define === 'function' && define.amd ? define(factory) :
21758	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgFullscreen = factory());
21759}(this, (function () { 'use strict';
21760
21761	/*! *****************************************************************************
21762	Copyright (c) Microsoft Corporation.
21763
21764	Permission to use, copy, modify, and/or distribute this software for any
21765	purpose with or without fee is hereby granted.
21766
21767	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
21768	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
21769	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
21770	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21771	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21772	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21773	PERFORMANCE OF THIS SOFTWARE.
21774	***************************************************************************** */
21775
21776	var __assign = function() {
21777		__assign = Object.assign || function __assign(t) {
21778			for (var s, i = 1, n = arguments.length; i < n; i++) {
21779				s = arguments[i];
21780				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
21781			}
21782			return t;
21783		};
21784		return __assign.apply(this, arguments);
21785	};
21786
21787	var fullscreenSettings = {
21788		fullScreen: true,
21789		fullscreenPluginStrings: {
21790			toggleFullscreen: 'Toggle Fullscreen',
21791		},
21792	};
21793
21794	var FullScreen = /** @class */ (function () {
21795		function FullScreen(instance, $LG) {
21796			// get lightGallery core plugin instance
21797			this.core = instance;
21798			this.$LG = $LG;
21799			// extend module default settings with lightGallery core settings
21800			this.settings = __assign(__assign({}, fullscreenSettings), this.core.settings);
21801			return this;
21802		}
21803		FullScreen.prototype.init = function () {
21804			var fullScreen = '';
21805			if (this.settings.fullScreen) {
21806				// check for fullscreen browser support
21807				if (!document.fullscreenEnabled &&
21808					!document.webkitFullscreenEnabled &&
21809					!document.mozFullScreenEnabled &&
21810					!document.msFullscreenEnabled) {
21811					return;
21812				}
21813				else {
21814					fullScreen = "<button type=\"button\" aria-label=\"" + this.settings.fullscreenPluginStrings['toggleFullscreen'] + "\" class=\"lg-fullscreen lg-icon\"></button>";
21815					this.core.$toolbar.append(fullScreen);
21816					this.fullScreen();
21817				}
21818			}
21819		};
21820		FullScreen.prototype.isFullScreen = function () {
21821			return (document.fullscreenElement ||
21822				document.mozFullScreenElement ||
21823				document.webkitFullscreenElement ||
21824				document.msFullscreenElement);
21825		};
21826		FullScreen.prototype.requestFullscreen = function () {
21827			var el = document.documentElement;
21828			if (el.requestFullscreen) {
21829				el.requestFullscreen();
21830			}
21831			else if (el.msRequestFullscreen) {
21832				el.msRequestFullscreen();
21833			}
21834			else if (el.mozRequestFullScreen) {
21835				el.mozRequestFullScreen();
21836			}
21837			else if (el.webkitRequestFullscreen) {
21838				el.webkitRequestFullscreen();
21839			}
21840		};
21841		FullScreen.prototype.exitFullscreen = function () {
21842			if (document.exitFullscreen) {
21843				document.exitFullscreen();
21844			}
21845			else if (document.msExitFullscreen) {
21846				document.msExitFullscreen();
21847			}
21848			else if (document.mozCancelFullScreen) {
21849				document.mozCancelFullScreen();
21850			}
21851			else if (document.webkitExitFullscreen) {
21852				document.webkitExitFullscreen();
21853			}
21854		};
21855		// https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Using_full_screen_mode
21856		FullScreen.prototype.fullScreen = function () {
21857			var _this = this;
21858			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 () {
21859				if (!_this.core.lgOpened)
21860					return;
21861				_this.core.outer.toggleClass('lg-fullscreen-on');
21862			});
21863			this.core.outer
21864				.find('.lg-fullscreen')
21865				.first()
21866				.on('click.lg', function () {
21867				if (_this.isFullScreen()) {
21868					_this.exitFullscreen();
21869				}
21870				else {
21871					_this.requestFullscreen();
21872				}
21873			});
21874		};
21875		FullScreen.prototype.closeGallery = function () {
21876			// exit from fullscreen if activated
21877			if (this.isFullScreen()) {
21878				this.exitFullscreen();
21879			}
21880		};
21881		FullScreen.prototype.destroy = function () {
21882			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);
21883		};
21884		return FullScreen;
21885	}());
21886
21887	return FullScreen;
21888
21889})));
21890
21891/*!
21892 * lightgallery | 2.5.0 | June 13th 2022
21893 * http://www.lightgalleryjs.com/
21894 * Copyright (c) 2020 Sachin Neravath;
21895 * @license GPLv3
21896 */
21897
21898(function (global, factory) {
21899	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
21900	typeof define === 'function' && define.amd ? define(factory) :
21901	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgHash = factory());
21902}(this, (function () { 'use strict';
21903
21904	/*! *****************************************************************************
21905	Copyright (c) Microsoft Corporation.
21906
21907	Permission to use, copy, modify, and/or distribute this software for any
21908	purpose with or without fee is hereby granted.
21909
21910	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
21911	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
21912	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
21913	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21914	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21915	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21916	PERFORMANCE OF THIS SOFTWARE.
21917	***************************************************************************** */
21918
21919	var __assign = function() {
21920		__assign = Object.assign || function __assign(t) {
21921			for (var s, i = 1, n = arguments.length; i < n; i++) {
21922				s = arguments[i];
21923				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
21924			}
21925			return t;
21926		};
21927		return __assign.apply(this, arguments);
21928	};
21929
21930	/**
21931	 * List of lightGallery events
21932	 * All events should be documented here
21933	 * Below interfaces are used to build the website documentations
21934	 * */
21935	var lGEvents = {
21936		afterAppendSlide: 'lgAfterAppendSlide',
21937		init: 'lgInit',
21938		hasVideo: 'lgHasVideo',
21939		containerResize: 'lgContainerResize',
21940		updateSlides: 'lgUpdateSlides',
21941		afterAppendSubHtml: 'lgAfterAppendSubHtml',
21942		beforeOpen: 'lgBeforeOpen',
21943		afterOpen: 'lgAfterOpen',
21944		slideItemLoad: 'lgSlideItemLoad',
21945		beforeSlide: 'lgBeforeSlide',
21946		afterSlide: 'lgAfterSlide',
21947		posterClick: 'lgPosterClick',
21948		dragStart: 'lgDragStart',
21949		dragMove: 'lgDragMove',
21950		dragEnd: 'lgDragEnd',
21951		beforeNextSlide: 'lgBeforeNextSlide',
21952		beforePrevSlide: 'lgBeforePrevSlide',
21953		beforeClose: 'lgBeforeClose',
21954		afterClose: 'lgAfterClose',
21955		rotateLeft: 'lgRotateLeft',
21956		rotateRight: 'lgRotateRight',
21957		flipHorizontal: 'lgFlipHorizontal',
21958		flipVertical: 'lgFlipVertical',
21959		autoplay: 'lgAutoplay',
21960		autoplayStart: 'lgAutoplayStart',
21961		autoplayStop: 'lgAutoplayStop',
21962	};
21963
21964	var hashSettings = {
21965		hash: true,
21966		galleryId: '1',
21967		customSlideName: false,
21968	};
21969
21970	var Hash = /** @class */ (function () {
21971		function Hash(instance, $LG) {
21972			// get lightGallery core plugin instance
21973			this.core = instance;
21974			this.$LG = $LG;
21975			// extend module default settings with lightGallery core settings
21976			this.settings = __assign(__assign({}, hashSettings), this.core.settings);
21977			return this;
21978		}
21979		Hash.prototype.init = function () {
21980			var _this = this;
21981			if (!this.settings.hash) {
21982				return;
21983			}
21984			this.oldHash = window.location.hash;
21985			setTimeout(function () {
21986				_this.buildFromHash();
21987			}, 100);
21988			// Change hash value on after each slide transition
21989			this.core.LGel.on(lGEvents.afterSlide + ".hash", this.onAfterSlide.bind(this));
21990			this.core.LGel.on(lGEvents.afterClose + ".hash", this.onCloseAfter.bind(this));
21991			// Listen hash change and change the slide according to slide value
21992			this.$LG(window).on("hashchange.lg.hash.global" + this.core.lgId, this.onHashchange.bind(this));
21993		};
21994		Hash.prototype.onAfterSlide = function (event) {
21995			var slideName = this.core.galleryItems[event.detail.index].slideName;
21996			slideName = this.settings.customSlideName
21997				? slideName || event.detail.index
21998				: event.detail.index;
21999			if (history.replaceState) {
22000				history.replaceState(null, '', window.location.pathname +
22001					window.location.search +
22002					'#lg=' +
22003					this.settings.galleryId +
22004					'&slide=' +
22005					slideName);
22006			}
22007			else {
22008				window.location.hash =
22009					'lg=' + this.settings.galleryId + '&slide=' + slideName;
22010			}
22011		};
22012		/**
22013		 * Get index of the slide from custom slideName. Has to be a public method. Used in hash plugin
22014		 * @param {String} hash
22015		 * @returns {Number} Index of the slide.
22016		 */
22017		Hash.prototype.getIndexFromUrl = function (hash) {
22018			if (hash === void 0) { hash = window.location.hash; }
22019			var slideName = hash.split('&slide=')[1];
22020			var _idx = 0;
22021			if (this.settings.customSlideName) {
22022				for (var index = 0; index < this.core.galleryItems.length; index++) {
22023					var dynamicEl = this.core.galleryItems[index];
22024					if (dynamicEl.slideName === slideName) {
22025						_idx = index;
22026						break;
22027					}
22028				}
22029			}
22030			else {
22031				_idx = parseInt(slideName, 10);
22032			}
22033			return isNaN(_idx) ? 0 : _idx;
22034		};
22035		// Build Gallery if gallery id exist in the URL
22036		Hash.prototype.buildFromHash = function () {
22037			// if dynamic option is enabled execute immediately
22038			var _hash = window.location.hash;
22039			//Uncode edit ##START##
22040			// if (_hash.indexOf('lg=' + this.settings.galleryId) > 0) {
22041			if (_hash.indexOf('lg=' + this.settings.galleryId + '&') > 0) {
22042			//Uncode edit ##END##
22043				// This class is used to remove the initial animation if galleryId present in the URL
22044				this.$LG(document.body).addClass('lg-from-hash');
22045				var index = this.getIndexFromUrl(_hash);
22046				this.core.openGallery(index);
22047				return true;
22048			}
22049		};
22050		Hash.prototype.onCloseAfter = function () {
22051			// Reset to old hash value
22052			if (this.oldHash &&
22053				this.oldHash.indexOf('lg=' + this.settings.galleryId) < 0) {
22054				if (history.replaceState) {
22055					history.replaceState(null, '', this.oldHash);
22056				}
22057				else {
22058					window.location.hash = this.oldHash;
22059				}
22060			}
22061			else {
22062				if (history.replaceState) {
22063					history.replaceState(null, document.title, window.location.pathname + window.location.search);
22064				}
22065				else {
22066					window.location.hash = '';
22067				}
22068			}
22069		};
22070		Hash.prototype.onHashchange = function () {
22071			if (!this.core.lgOpened)
22072				return;
22073			var _hash = window.location.hash;
22074			var index = this.getIndexFromUrl(_hash);
22075			// it galleryId doesn't exist in the url close the gallery
22076			if (_hash.indexOf('lg=' + this.settings.galleryId) > -1) {
22077				this.core.slide(index, false, false);
22078			}
22079			else if (this.core.lGalleryOn) {
22080				this.core.closeGallery();
22081			}
22082		};
22083		Hash.prototype.closeGallery = function () {
22084			if (this.settings.hash) {
22085				this.$LG(document.body).removeClass('lg-from-hash');
22086			}
22087		};
22088		Hash.prototype.destroy = function () {
22089			this.core.LGel.off('.lg.hash');
22090			this.core.LGel.off('.hash');
22091			this.$LG(window).off("hashchange.lg.hash.global" + this.core.lgId);
22092		};
22093		return Hash;
22094	}());
22095
22096	return Hash;
22097
22098})));
22099/*!
22100 * lightgallery | 2.5.0 | June 13th 2022
22101 * http://www.lightgalleryjs.com/
22102 * Copyright (c) 2020 Sachin Neravath;
22103 * @license GPLv3
22104 */
22105
22106(function (global, factory) {
22107	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
22108	typeof define === 'function' && define.amd ? define(factory) :
22109	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgShare = factory());
22110}(this, (function () { 'use strict';
22111
22112	/*! *****************************************************************************
22113	Copyright (c) Microsoft Corporation.
22114
22115	Permission to use, copy, modify, and/or distribute this software for any
22116	purpose with or without fee is hereby granted.
22117
22118	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
22119	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
22120	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
22121	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
22122	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
22123	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22124	PERFORMANCE OF THIS SOFTWARE.
22125	***************************************************************************** */
22126
22127	var __assign = function() {
22128		__assign = Object.assign || function __assign(t) {
22129			for (var s, i = 1, n = arguments.length; i < n; i++) {
22130				s = arguments[i];
22131				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
22132			}
22133			return t;
22134		};
22135		return __assign.apply(this, arguments);
22136	};
22137
22138	function __spreadArrays() {
22139		for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
22140		for (var r = Array(s), k = 0, i = 0; i < il; i++)
22141			for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
22142				r[k] = a[j];
22143		return r;
22144	}
22145
22146	var shareSettings = {
22147		share: true,
22148		facebook: true,
22149		facebookDropdownText: 'Facebook',
22150		twitter: true,
22151		twitterDropdownText: 'Twitter',
22152		pinterest: true,
22153		pinterestDropdownText: 'Pinterest',
22154		additionalShareOptions: [],
22155		sharePluginStrings: { share: 'Share' },
22156	};
22157
22158	function getFacebookShareLink(galleryItem) {
22159		var facebookBaseUrl = '//www.facebook.com/sharer/sharer.php?u=';
22160		return (facebookBaseUrl +
22161			encodeURIComponent(galleryItem.facebookShareUrl || window.location.href));
22162	}
22163
22164	function getTwitterShareLink(galleryItem) {
22165		var twitterBaseUrl = '//twitter.com/intent/tweet?text=';
22166		var url = encodeURIComponent(galleryItem.twitterShareUrl || window.location.href);
22167		var text = galleryItem.tweetText;
22168		return twitterBaseUrl + text + '&url=' + url;
22169	}
22170
22171	function getPinterestShareLink(galleryItem) {
22172		var pinterestBaseUrl = 'http://www.pinterest.com/pin/create/button/?url=';
22173		var description = galleryItem.pinterestText;
22174		var media = encodeURIComponent(galleryItem.src);
22175		var url = encodeURIComponent(galleryItem.pinterestShareUrl || window.location.href);
22176		return (pinterestBaseUrl +
22177			url +
22178			'&media=' +
22179			media +
22180			'&description=' +
22181			description);
22182	}
22183
22184	/**
22185	 * List of lightGallery events
22186	 * All events should be documented here
22187	 * Below interfaces are used to build the website documentations
22188	 * */
22189	var lGEvents = {
22190		afterAppendSlide: 'lgAfterAppendSlide',
22191		init: 'lgInit',
22192		hasVideo: 'lgHasVideo',
22193		containerResize: 'lgContainerResize',
22194		updateSlides: 'lgUpdateSlides',
22195		afterAppendSubHtml: 'lgAfterAppendSubHtml',
22196		beforeOpen: 'lgBeforeOpen',
22197		afterOpen: 'lgAfterOpen',
22198		slideItemLoad: 'lgSlideItemLoad',
22199		beforeSlide: 'lgBeforeSlide',
22200		afterSlide: 'lgAfterSlide',
22201		posterClick: 'lgPosterClick',
22202		dragStart: 'lgDragStart',
22203		dragMove: 'lgDragMove',
22204		dragEnd: 'lgDragEnd',
22205		beforeNextSlide: 'lgBeforeNextSlide',
22206		beforePrevSlide: 'lgBeforePrevSlide',
22207		beforeClose: 'lgBeforeClose',
22208		afterClose: 'lgAfterClose',
22209		rotateLeft: 'lgRotateLeft',
22210		rotateRight: 'lgRotateRight',
22211		flipHorizontal: 'lgFlipHorizontal',
22212		flipVertical: 'lgFlipVertical',
22213		autoplay: 'lgAutoplay',
22214		autoplayStart: 'lgAutoplayStart',
22215		autoplayStop: 'lgAutoplayStop',
22216	};
22217
22218	var Share = /** @class */ (function () {
22219		function Share(instance) {
22220			this.shareOptions = [];
22221			// get lightGallery core plugin instance
22222			this.core = instance;
22223			// extend module default settings with lightGallery core settings
22224			this.settings = __assign(__assign({}, shareSettings), this.core.settings);
22225			return this;
22226		}
22227		Share.prototype.init = function () {
22228			if (!this.settings.share) {
22229				return;
22230			}
22231			this.shareOptions = __spreadArrays(this.getDefaultShareOptions(), this.settings.additionalShareOptions);
22232			this.setLgShareMarkup();
22233			this.core.outer
22234				.find('.lg-share .lg-dropdown')
22235				.append(this.getShareListHtml());
22236			this.core.LGel.on(lGEvents.afterSlide + ".share", this.onAfterSlide.bind(this));
22237		};
22238		Share.prototype.getShareListHtml = function () {
22239			var shareHtml = '';
22240			this.shareOptions.forEach(function (shareOption) {
22241				shareHtml += shareOption.dropdownHTML;
22242			});
22243			return shareHtml;
22244		};
22245		Share.prototype.setLgShareMarkup = function () {
22246			var _this = this;
22247			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>");
22248			this.core.outer.append('<div class="lg-dropdown-overlay"></div>');
22249			var $shareButton = this.core.outer.find('.lg-share');
22250			$shareButton.first().on('click.lg', function () {
22251				_this.core.outer.toggleClass('lg-dropdown-active');
22252				if (_this.core.outer.hasClass('lg-dropdown-active')) {
22253					_this.core.outer.attr('aria-expanded', true);
22254				}
22255				else {
22256					_this.core.outer.attr('aria-expanded', false);
22257				}
22258			});
22259			this.core.outer
22260				.find('.lg-dropdown-overlay')
22261				.first()
22262				.on('click.lg', function () {
22263				_this.core.outer.removeClass('lg-dropdown-active');
22264				_this.core.outer.attr('aria-expanded', false);
22265			});
22266		};
22267		Share.prototype.onAfterSlide = function (event) {
22268			var _this = this;
22269			var index = event.detail.index;
22270			var currentItem = this.core.galleryItems[index];
22271			setTimeout(function () {
22272				_this.shareOptions.forEach(function (shareOption) {
22273					var selector = shareOption.selector;
22274					_this.core.outer
22275						.find(selector)
22276						.attr('href', shareOption.generateLink(currentItem));
22277				});
22278			}, 100);
22279		};
22280		Share.prototype.getShareListItemHTML = function (type, text) {
22281			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>";
22282		};
22283		Share.prototype.getDefaultShareOptions = function () {
22284			return __spreadArrays((this.settings.facebook
22285				? [
22286					{
22287						type: 'facebook',
22288						generateLink: getFacebookShareLink,
22289						dropdownHTML: this.getShareListItemHTML('facebook', this.settings.facebookDropdownText),
22290						selector: '.lg-share-facebook',
22291					},
22292				]
22293				: []), (this.settings.twitter
22294				? [
22295					{
22296						type: 'twitter',
22297						generateLink: getTwitterShareLink,
22298						dropdownHTML: this.getShareListItemHTML('twitter', this.settings.twitterDropdownText),
22299						selector: '.lg-share-twitter',
22300					},
22301				]
22302				: []), (this.settings.pinterest
22303				? [
22304					{
22305						type: 'pinterest',
22306						generateLink: getPinterestShareLink,
22307						dropdownHTML: this.getShareListItemHTML('pinterest', this.settings.pinterestDropdownText),
22308						selector: '.lg-share-pinterest',
22309					},
22310				]
22311				: []));
22312		};
22313		Share.prototype.destroy = function () {
22314			this.core.outer.find('.lg-dropdown-overlay').remove();
22315			this.core.outer.find('.lg-share').remove();
22316			this.core.LGel.off('.lg.share');
22317			this.core.LGel.off('.share');
22318		};
22319		return Share;
22320	}());
22321
22322	return Share;
22323
22324})));
22325/*!
22326 * lightgallery | 2.5.0 | June 13th 2022
22327 * http://www.lightgalleryjs.com/
22328 * Copyright (c) 2020 Sachin Neravath;
22329 * @license GPLv3
22330 */
22331
22332(function (global, factory) {
22333	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
22334	typeof define === 'function' && define.amd ? define(factory) :
22335	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgThumbnail = factory());
22336}(this, (function () { 'use strict';
22337
22338	/*! *****************************************************************************
22339	Copyright (c) Microsoft Corporation.
22340
22341	Permission to use, copy, modify, and/or distribute this software for any
22342	purpose with or without fee is hereby granted.
22343
22344	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
22345	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
22346	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
22347	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
22348	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
22349	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22350	PERFORMANCE OF THIS SOFTWARE.
22351	***************************************************************************** */
22352
22353	var __assign = function() {
22354		__assign = Object.assign || function __assign(t) {
22355			for (var s, i = 1, n = arguments.length; i < n; i++) {
22356				s = arguments[i];
22357				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
22358			}
22359			return t;
22360		};
22361		return __assign.apply(this, arguments);
22362	};
22363
22364	var thumbnailsSettings = {
22365		thumbnail: true,
22366		animateThumb: true,
22367		currentPagerPosition: 'middle',
22368		alignThumbnails: 'middle',
22369		thumbWidth: 100,
22370		thumbHeight: '80px',
22371		thumbMargin: 5,
22372		appendThumbnailsTo: '.lg-components',
22373		toggleThumb: false,
22374		enableThumbDrag: true,
22375		enableThumbSwipe: true,
22376		thumbnailSwipeThreshold: 10,
22377		loadYouTubeThumbnail: true,
22378		youTubeThumbSize: 1,
22379		thumbnailPluginStrings: {
22380			toggleThumbnails: 'Toggle thumbnails',
22381		},
22382	};
22383
22384	/**
22385	 * List of lightGallery events
22386	 * All events should be documented here
22387	 * Below interfaces are used to build the website documentations
22388	 * */
22389	var lGEvents = {
22390		afterAppendSlide: 'lgAfterAppendSlide',
22391		init: 'lgInit',
22392		hasVideo: 'lgHasVideo',
22393		containerResize: 'lgContainerResize',
22394		updateSlides: 'lgUpdateSlides',
22395		afterAppendSubHtml: 'lgAfterAppendSubHtml',
22396		beforeOpen: 'lgBeforeOpen',
22397		afterOpen: 'lgAfterOpen',
22398		slideItemLoad: 'lgSlideItemLoad',
22399		beforeSlide: 'lgBeforeSlide',
22400		afterSlide: 'lgAfterSlide',
22401		posterClick: 'lgPosterClick',
22402		dragStart: 'lgDragStart',
22403		dragMove: 'lgDragMove',
22404		dragEnd: 'lgDragEnd',
22405		beforeNextSlide: 'lgBeforeNextSlide',
22406		beforePrevSlide: 'lgBeforePrevSlide',
22407		beforeClose: 'lgBeforeClose',
22408		afterClose: 'lgAfterClose',
22409		rotateLeft: 'lgRotateLeft',
22410		rotateRight: 'lgRotateRight',
22411		flipHorizontal: 'lgFlipHorizontal',
22412		flipVertical: 'lgFlipVertical',
22413		autoplay: 'lgAutoplay',
22414		autoplayStart: 'lgAutoplayStart',
22415		autoplayStop: 'lgAutoplayStop',
22416	};
22417
22418	var Thumbnail = /** @class */ (function () {
22419		function Thumbnail(instance, $LG) {
22420			this.thumbOuterWidth = 0;
22421			this.thumbTotalWidth = 0;
22422			this.translateX = 0;
22423			this.thumbClickable = false;
22424			// get lightGallery core plugin instance
22425			this.core = instance;
22426			this.$LG = $LG;
22427			return this;
22428		}
22429		Thumbnail.prototype.init = function () {
22430			// extend module default settings with lightGallery core settings
22431			this.settings = __assign(__assign({}, thumbnailsSettings), this.core.settings);
22432			this.thumbOuterWidth = 0;
22433			this.thumbTotalWidth =
22434				this.core.galleryItems.length *
22435					(this.settings.thumbWidth + this.settings.thumbMargin);
22436			// Thumbnail animation value
22437			this.translateX = 0;
22438			this.setAnimateThumbStyles();
22439			if (!this.core.settings.allowMediaOverlap) {
22440				this.settings.toggleThumb = false;
22441			}
22442			if (this.settings.thumbnail) {
22443				this.build();
22444				if (this.settings.animateThumb) {
22445					if (this.settings.enableThumbDrag) {
22446						this.enableThumbDrag();
22447					}
22448					if (this.settings.enableThumbSwipe) {
22449						this.enableThumbSwipe();
22450					}
22451					this.thumbClickable = false;
22452				}
22453				else {
22454					this.thumbClickable = true;
22455				}
22456				this.toggleThumbBar();
22457				this.thumbKeyPress();
22458			}
22459		};
22460		Thumbnail.prototype.build = function () {
22461			var _this = this;
22462			this.setThumbMarkup();
22463			this.manageActiveClassOnSlideChange();
22464			this.$lgThumb.first().on('click.lg touchend.lg', function (e) {
22465				var $target = _this.$LG(e.target);
22466				if (!$target.hasAttribute('data-lg-item-id')) {
22467					return;
22468				}
22469				setTimeout(function () {
22470					// In IE9 and bellow touch does not support
22471					// Go to slide if browser does not support css transitions
22472					if (_this.thumbClickable && !_this.core.lgBusy) {
22473						var index = parseInt($target.attr('data-lg-item-id'));
22474						_this.core.slide(index, false, true, false);
22475					}
22476				}, 50);
22477			});
22478			//Uncode edit ##START##
22479			// this.core.LGel.on(lGEvents.beforeSlide + ".thumb", function (event) {
22480			this.core.LGel.on(lGEvents.beforeSlide, function (event) {
22481			//Uncode edit ##END##
22482				var index = event.detail.index;
22483				_this.animateThumb(index);
22484			});
22485			//Uncode edit ##START##
22486			// this.core.LGel.on(lGEvents.beforeOpen + ".thumb", function () {
22487			this.core.LGel.on(lGEvents.beforeOpen, function () {
22488			//Uncode edit ##END##
22489				_this.thumbOuterWidth = _this.core.outer.get().offsetWidth;
22490			});
22491			//Uncode edit ##START##
22492			// this.core.LGel.on(lGEvents.updateSlides + ".thumb", function () {
22493			this.core.LGel.on(lGEvents.updateSlides, function () {
22494			//Uncode edit ##END##
22495				_this.rebuildThumbnails();
22496			});
22497			//Uncode edit ##START##
22498			// this.core.LGel.on(lGEvents.containerResize + ".thumb", function () {
22499			this.core.LGel.on(lGEvents.containerResize, function () {
22500			//Uncode edit ##END##
22501				if (!_this.core.lgOpened)
22502					return;
22503				setTimeout(function () {
22504					_this.thumbOuterWidth = _this.core.outer.get().offsetWidth;
22505					_this.animateThumb(_this.core.index);
22506					_this.thumbOuterWidth = _this.core.outer.get().offsetWidth;
22507				}, 50);
22508			});
22509		};
22510		Thumbnail.prototype.setThumbMarkup = function () {
22511			var thumbOuterClassNames = 'lg-thumb-outer ';
22512			if (this.settings.alignThumbnails) {
22513				thumbOuterClassNames += "lg-thumb-align-" + this.settings.alignThumbnails;
22514			}
22515			var html = "<div class=\"" + thumbOuterClassNames + "\">\n        <div class=\"lg-thumb lg-group\">\n        </div>\n        </div>";
22516			this.core.outer.addClass('lg-has-thumb');
22517			if (this.settings.appendThumbnailsTo === '.lg-components') {
22518				this.core.$lgComponents.append(html);
22519			}
22520			else {
22521				this.core.outer.append(html);
22522			}
22523			this.$thumbOuter = this.core.outer.find('.lg-thumb-outer').first();
22524			this.$lgThumb = this.core.outer.find('.lg-thumb').first();
22525			if (this.settings.animateThumb) {
22526				this.core.outer
22527					.find('.lg-thumb')
22528					.css('transition-duration', this.core.settings.speed + 'ms')
22529					.css('width', this.thumbTotalWidth + 'px')
22530					.css('position', 'relative');
22531			}
22532			this.setThumbItemHtml(this.core.galleryItems);
22533		};
22534		Thumbnail.prototype.enableThumbDrag = function () {
22535			var _this = this;
22536			var thumbDragUtils = {
22537				cords: {
22538					startX: 0,
22539					endX: 0,
22540				},
22541				isMoved: false,
22542				newTranslateX: 0,
22543				startTime: new Date(),
22544				endTime: new Date(),
22545				touchMoveTime: 0,
22546			};
22547			var isDragging = false;
22548			this.$thumbOuter.addClass('lg-grab');
22549			this.core.outer
22550				.find('.lg-thumb')
22551				.first()
22552				.on('mousedown.lg.thumb', function (e) {
22553				if (_this.thumbTotalWidth > _this.thumbOuterWidth) {
22554					// execute only on .lg-object
22555					e.preventDefault();
22556					thumbDragUtils.cords.startX = e.pageX;
22557					thumbDragUtils.startTime = new Date();
22558					_this.thumbClickable = false;
22559					isDragging = true;
22560					// ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723
22561					_this.core.outer.get().scrollLeft += 1;
22562					_this.core.outer.get().scrollLeft -= 1;
22563					// *
22564					_this.$thumbOuter
22565						.removeClass('lg-grab')
22566						.addClass('lg-grabbing');
22567				}
22568			});
22569			this.$LG(window).on("mousemove.lg.thumb.global" + this.core.lgId, function (e) {
22570				if (!_this.core.lgOpened)
22571					return;
22572				if (isDragging) {
22573					thumbDragUtils.cords.endX = e.pageX;
22574					thumbDragUtils = _this.onThumbTouchMove(thumbDragUtils);
22575				}
22576			});
22577			this.$LG(window).on("mouseup.lg.thumb.global" + this.core.lgId, function () {
22578				if (!_this.core.lgOpened)
22579					return;
22580				if (thumbDragUtils.isMoved) {
22581					thumbDragUtils = _this.onThumbTouchEnd(thumbDragUtils);
22582				}
22583				else {
22584					_this.thumbClickable = true;
22585				}
22586				if (isDragging) {
22587					isDragging = false;
22588					_this.$thumbOuter.removeClass('lg-grabbing').addClass('lg-grab');
22589				}
22590			});
22591		};
22592		Thumbnail.prototype.enableThumbSwipe = function () {
22593			var _this = this;
22594			var thumbDragUtils = {
22595				cords: {
22596					startX: 0,
22597					endX: 0,
22598				},
22599				isMoved: false,
22600				newTranslateX: 0,
22601				startTime: new Date(),
22602				endTime: new Date(),
22603				touchMoveTime: 0,
22604			};
22605			this.$lgThumb.on('touchstart.lg', function (e) {
22606				if (_this.thumbTotalWidth > _this.thumbOuterWidth) {
22607					e.preventDefault();
22608					thumbDragUtils.cords.startX = e.targetTouches[0].pageX;
22609					_this.thumbClickable = false;
22610					thumbDragUtils.startTime = new Date();
22611				}
22612			});
22613			this.$lgThumb.on('touchmove.lg', function (e) {
22614				if (_this.thumbTotalWidth > _this.thumbOuterWidth) {
22615					e.preventDefault();
22616					thumbDragUtils.cords.endX = e.targetTouches[0].pageX;
22617					thumbDragUtils = _this.onThumbTouchMove(thumbDragUtils);
22618				}
22619			});
22620			this.$lgThumb.on('touchend.lg', function () {
22621				if (thumbDragUtils.isMoved) {
22622					thumbDragUtils = _this.onThumbTouchEnd(thumbDragUtils);
22623				}
22624				else {
22625					_this.thumbClickable = true;
22626				}
22627			});
22628		};
22629		// Rebuild thumbnails
22630		Thumbnail.prototype.rebuildThumbnails = function () {
22631			var _this = this;
22632			// Remove transitions
22633			this.$thumbOuter.addClass('lg-rebuilding-thumbnails');
22634			setTimeout(function () {
22635				_this.thumbTotalWidth =
22636					_this.core.galleryItems.length *
22637						(_this.settings.thumbWidth + _this.settings.thumbMargin);
22638				_this.$lgThumb.css('width', _this.thumbTotalWidth + 'px');
22639				_this.$lgThumb.empty();
22640				_this.setThumbItemHtml(_this.core.galleryItems);
22641				_this.animateThumb(_this.core.index);
22642			}, 50);
22643			setTimeout(function () {
22644				_this.$thumbOuter.removeClass('lg-rebuilding-thumbnails');
22645			}, 200);
22646		};
22647		// @ts-check
22648		Thumbnail.prototype.setTranslate = function (value) {
22649			this.$lgThumb.css('transform', 'translate3d(-' + value + 'px, 0px, 0px)');
22650		};
22651		Thumbnail.prototype.getPossibleTransformX = function (left) {
22652			if (left > this.thumbTotalWidth - this.thumbOuterWidth) {
22653				left = this.thumbTotalWidth - this.thumbOuterWidth;
22654			}
22655			if (left < 0) {
22656				left = 0;
22657			}
22658			return left;
22659		};
22660		Thumbnail.prototype.animateThumb = function (index) {
22661			this.$lgThumb.css('transition-duration', this.core.settings.speed + 'ms');
22662			if (this.settings.animateThumb) {
22663				var position = 0;
22664				switch (this.settings.currentPagerPosition) {
22665					case 'left':
22666						position = 0;
22667						break;
22668					case 'middle':
22669						position =
22670							this.thumbOuterWidth / 2 - this.settings.thumbWidth / 2;
22671						break;
22672					case 'right':
22673						position = this.thumbOuterWidth - this.settings.thumbWidth;
22674				}
22675				this.translateX =
22676					(this.settings.thumbWidth + this.settings.thumbMargin) * index -
22677						1 -
22678						position;
22679				if (this.translateX > this.thumbTotalWidth - this.thumbOuterWidth) {
22680					this.translateX = this.thumbTotalWidth - this.thumbOuterWidth;
22681				}
22682				if (this.translateX < 0) {
22683					this.translateX = 0;
22684				}
22685				this.setTranslate(this.translateX);
22686			}
22687		};
22688		Thumbnail.prototype.onThumbTouchMove = function (thumbDragUtils) {
22689			thumbDragUtils.newTranslateX = this.translateX;
22690			thumbDragUtils.isMoved = true;
22691			thumbDragUtils.touchMoveTime = new Date().valueOf();
22692			thumbDragUtils.newTranslateX -=
22693				thumbDragUtils.cords.endX - thumbDragUtils.cords.startX;
22694			thumbDragUtils.newTranslateX = this.getPossibleTransformX(thumbDragUtils.newTranslateX);
22695			// move current slide
22696			this.setTranslate(thumbDragUtils.newTranslateX);
22697			this.$thumbOuter.addClass('lg-dragging');
22698			return thumbDragUtils;
22699		};
22700		Thumbnail.prototype.onThumbTouchEnd = function (thumbDragUtils) {
22701			thumbDragUtils.isMoved = false;
22702			thumbDragUtils.endTime = new Date();
22703			this.$thumbOuter.removeClass('lg-dragging');
22704			var touchDuration = thumbDragUtils.endTime.valueOf() -
22705				thumbDragUtils.startTime.valueOf();
22706			var distanceXnew = thumbDragUtils.cords.endX - thumbDragUtils.cords.startX;
22707			var speedX = Math.abs(distanceXnew) / touchDuration;
22708			// Some magical numbers
22709			// Can be improved
22710			if (speedX > 0.15 &&
22711				thumbDragUtils.endTime.valueOf() - thumbDragUtils.touchMoveTime < 30) {
22712				speedX += 1;
22713				if (speedX > 2) {
22714					speedX += 1;
22715				}
22716				speedX =
22717					speedX +
22718						speedX * (Math.abs(distanceXnew) / this.thumbOuterWidth);
22719				this.$lgThumb.css('transition-duration', Math.min(speedX - 1, 2) + 'settings');
22720				distanceXnew = distanceXnew * speedX;
22721				this.translateX = this.getPossibleTransformX(this.translateX - distanceXnew);
22722				this.setTranslate(this.translateX);
22723			}
22724			else {
22725				this.translateX = thumbDragUtils.newTranslateX;
22726			}
22727			if (Math.abs(thumbDragUtils.cords.endX - thumbDragUtils.cords.startX) <
22728				this.settings.thumbnailSwipeThreshold) {
22729				this.thumbClickable = true;
22730			}
22731			return thumbDragUtils;
22732		};
22733		Thumbnail.prototype.getThumbHtml = function (thumb, index) {
22734			var slideVideoInfo = this.core.galleryItems[index].__slideVideoInfo || {};
22735			var thumbImg;
22736			if (slideVideoInfo.youtube) {
22737				if (this.settings.loadYouTubeThumbnail) {
22738					thumbImg =
22739						'//img.youtube.com/vi/' +
22740							slideVideoInfo.youtube[1] +
22741							'/' +
22742							this.settings.youTubeThumbSize +
22743							'.jpg';
22744				}
22745				else {
22746					thumbImg = thumb;
22747				}
22748			}
22749			else {
22750				thumbImg = thumb;
22751			}
22752			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 + "\" src=\"" + thumbImg + "\" />\n        </div>";
22753		};
22754		Thumbnail.prototype.getThumbItemHtml = function (items) {
22755			var thumbList = '';
22756			for (var i = 0; i < items.length; i++) {
22757				thumbList += this.getThumbHtml(items[i].thumb, i);
22758			}
22759			return thumbList;
22760		};
22761		Thumbnail.prototype.setThumbItemHtml = function (items) {
22762			var thumbList = this.getThumbItemHtml(items);
22763			this.$lgThumb.html(thumbList);
22764		};
22765		Thumbnail.prototype.setAnimateThumbStyles = function () {
22766			if (this.settings.animateThumb) {
22767				this.core.outer.addClass('lg-animate-thumb');
22768			}
22769		};
22770		// Manage thumbnail active calss
22771		Thumbnail.prototype.manageActiveClassOnSlideChange = function () {
22772			var _this = this;
22773			// manage active class for thumbnail
22774			//Uncode edit ##START##
22775			// this.core.LGel.on(lGEvents.beforeSlide + ".thumb", function (event) {
22776			this.core.LGel.on(lGEvents.beforeSlide, function (event) {
22777			//Uncode edit ##END##
22778				var $thumb = _this.core.outer.find('.lg-thumb-item');
22779				var index = event.detail.index;
22780				$thumb.removeClass('active');
22781				$thumb.eq(index).addClass('active');
22782			});
22783		};
22784		// Toggle thumbnail bar
22785		Thumbnail.prototype.toggleThumbBar = function () {
22786			var _this = this;
22787			if (this.settings.toggleThumb) {
22788				this.core.outer.addClass('lg-can-toggle');
22789				this.core.$toolbar.append('<button type="button" aria-label="' +
22790					this.settings.thumbnailPluginStrings['toggleThumbnails'] +
22791					'" class="lg-toggle-thumb lg-icon"></button>');
22792				this.core.outer
22793					.find('.lg-toggle-thumb')
22794					.first()
22795					.on('click.lg', function () {
22796					_this.core.outer.toggleClass('lg-components-open');
22797				});
22798			}
22799		};
22800		Thumbnail.prototype.thumbKeyPress = function () {
22801			var _this = this;
22802			this.$LG(window).on("keydown.lg.thumb.global" + this.core.lgId, function (e) {
22803				if (!_this.core.lgOpened || !_this.settings.toggleThumb)
22804					return;
22805				if (e.keyCode === 38) {
22806					e.preventDefault();
22807					_this.core.outer.addClass('lg-components-open');
22808				}
22809				else if (e.keyCode === 40) {
22810					e.preventDefault();
22811					_this.core.outer.removeClass('lg-components-open');
22812				}
22813			});
22814		};
22815		Thumbnail.prototype.destroy = function () {
22816			if (this.settings.thumbnail) {
22817				this.$LG(window).off(".lg.thumb.global" + this.core.lgId);
22818				this.core.LGel.off('.lg.thumb');
22819				this.core.LGel.off('.thumb');
22820				this.$thumbOuter.remove();
22821				this.core.outer.removeClass('lg-has-thumb');
22822			}
22823		};
22824		return Thumbnail;
22825	}());
22826
22827	return Thumbnail;
22828
22829})));
22830/*!
22831 * lightgallery | 2.5.0 | June 13th 2022
22832 * http://www.lightgalleryjs.com/
22833 * Copyright (c) 2020 Sachin Neravath;
22834 * @license GPLv3
22835 */
22836
22837(function (global, factory) {
22838	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
22839	typeof define === 'function' && define.amd ? define(factory) :
22840	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgVideo = factory());
22841}(this, (function () { 'use strict';
22842
22843	/*! *****************************************************************************
22844	Copyright (c) Microsoft Corporation.
22845
22846	Permission to use, copy, modify, and/or distribute this software for any
22847	purpose with or without fee is hereby granted.
22848
22849	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
22850	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
22851	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
22852	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
22853	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
22854	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22855	PERFORMANCE OF THIS SOFTWARE.
22856	***************************************************************************** */
22857
22858	var __assign = function() {
22859		__assign = Object.assign || function __assign(t) {
22860			for (var s, i = 1, n = arguments.length; i < n; i++) {
22861				s = arguments[i];
22862				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
22863			}
22864			return t;
22865		};
22866		return __assign.apply(this, arguments);
22867	};
22868
22869	var videoSettings = {
22870		autoplayFirstVideo: true,
22871		youTubePlayerParams: false,
22872		vimeoPlayerParams: false,
22873		wistiaPlayerParams: false,
22874		gotoNextSlideOnVideoEnd: true,
22875		autoplayVideoOnSlide: false,
22876		videojs: false,
22877		videojsTheme: '',
22878		videojsOptions: {},
22879	};
22880
22881	/**
22882	 * List of lightGallery events
22883	 * All events should be documented here
22884	 * Below interfaces are used to build the website documentations
22885	 * */
22886	var lGEvents = {
22887		afterAppendSlide: 'lgAfterAppendSlide',
22888		init: 'lgInit',
22889		hasVideo: 'lgHasVideo',
22890		containerResize: 'lgContainerResize',
22891		updateSlides: 'lgUpdateSlides',
22892		afterAppendSubHtml: 'lgAfterAppendSubHtml',
22893		beforeOpen: 'lgBeforeOpen',
22894		afterOpen: 'lgAfterOpen',
22895		slideItemLoad: 'lgSlideItemLoad',
22896		beforeSlide: 'lgBeforeSlide',
22897		afterSlide: 'lgAfterSlide',
22898		posterClick: 'lgPosterClick',
22899		dragStart: 'lgDragStart',
22900		dragMove: 'lgDragMove',
22901		dragEnd: 'lgDragEnd',
22902		beforeNextSlide: 'lgBeforeNextSlide',
22903		beforePrevSlide: 'lgBeforePrevSlide',
22904		beforeClose: 'lgBeforeClose',
22905		afterClose: 'lgAfterClose',
22906		rotateLeft: 'lgRotateLeft',
22907		rotateRight: 'lgRotateRight',
22908		flipHorizontal: 'lgFlipHorizontal',
22909		flipVertical: 'lgFlipVertical',
22910		autoplay: 'lgAutoplay',
22911		autoplayStart: 'lgAutoplayStart',
22912		autoplayStop: 'lgAutoplayStop',
22913	};
22914
22915	var param = function (obj) {
22916		return Object.keys(obj)
22917			.map(function (k) {
22918			return encodeURIComponent(k) + '=' + encodeURIComponent(obj[k]);
22919		})
22920			.join('&');
22921	};
22922	var getVimeoURLParams = function (defaultParams, videoInfo) {
22923		if (!videoInfo || !videoInfo.vimeo)
22924			return '';
22925		var urlParams = videoInfo.vimeo[2] || '';
22926		var defaultPlayerParams = defaultParams && Object.keys(defaultParams).length !== 0
22927			? '&' + param(defaultParams)
22928			: '';
22929		// Support private video
22930		var urlWithHash = videoInfo.vimeo[0].split('/').pop() || '';
22931		var urlWithHashWithParams = urlWithHash.split('?')[0] || '';
22932		var hash = urlWithHashWithParams.split('#')[0];
22933		var isPrivate = videoInfo.vimeo[1] !== hash;
22934		if (isPrivate) {
22935			urlParams = urlParams.replace("/" + hash, '');
22936		}
22937		urlParams =
22938			urlParams[0] == '?' ? '&' + urlParams.slice(1) : urlParams || '';
22939		// For vimeo last params gets priority if duplicates found
22940		// Uncode edit ##START##
22941		var vimeoPlayerParams = '?autoplay=0';
22942		if ( videoInfo.autoplay !== '' ) {
22943			vimeoPlayerParams = vimeoPlayerParams.replace(new RegExp('([?&])autoplay=(.*?)(&|$)'), '$1$3' );
22944			vimeoPlayerParams = vimeoPlayerParams.replace(new RegExp('([?&])autoplay(&|$)'), '$1$2' );
22945		} else {
22946			if ( typeof SiteParameters !== 'undefined' && typeof SiteParameters.vimeoPlayerParams !== 'undefined' && SiteParameters.vimeoPlayerParams !== '' ) {
22947				vimeoPlayerParams = SiteParameters.vimeoPlayerParams;
22948			}
22949		}
22950		if ( videoInfo.muted !== '' ) {
22951			vimeoPlayerParams += '&muted=' + (videoInfo.muted === 'yes');
22952		} else {
22953			if ( urlParams.indexOf('muted=') < 0 && vimeoPlayerParams.indexOf('muted=') < 0 ) {
22954				vimeoPlayerParams += '&muted=1';
22955			}
22956		}
22957		// var vimeoPlayerParams = "?autoplay=0&muted=1" + (isPrivate ? "&h=" + hash : '') + defaultPlayerParams + urlParams;
22958		vimeoPlayerParams += (isPrivate ? "&h=" + hash : '') + defaultPlayerParams + urlParams;
22959		// Uncode edit ##END##
22960		return vimeoPlayerParams;
22961	};
22962
22963	/**
22964	 * Video module for lightGallery
22965	 * Supports HTML5, YouTube, Vimeo, wistia videos
22966	 *
22967	 *
22968	 * @ref Wistia
22969	 * https://wistia.com/support/integrations/wordpress(How to get url)
22970	 * https://wistia.com/support/developers/embed-options#using-embed-options
22971	 * https://wistia.com/support/developers/player-api
22972	 * https://wistia.com/support/developers/construct-an-embed-code
22973	 * http://jsfiddle.net/xvnm7xLm/
22974	 * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video
22975	 * https://wistia.com/support/embed-and-share/sharing-videos
22976	 * https://private-sharing.wistia.com/medias/mwhrulrucj
22977	 *
22978	 * @ref Youtube
22979	 * https://developers.google.com/youtube/player_parameters#enablejsapi
22980	 * https://developers.google.com/youtube/iframe_api_reference
22981	 * https://developer.chrome.com/blog/autoplay/#iframe-delegation
22982	 *
22983	 * @ref Vimeo
22984	 * https://stackoverflow.com/questions/10488943/easy-way-to-get-vimeo-id-from-a-vimeo-url
22985	 * https://vimeo.zendesk.com/hc/en-us/articles/360000121668-Starting-playback-at-a-specific-timecode
22986	 * https://vimeo.zendesk.com/hc/en-us/articles/360001494447-Using-Player-Parameters
22987	 */
22988	var Video = /** @class */ (function () {
22989		function Video(instance) {
22990			// get lightGallery core plugin instance
22991			this.core = instance;
22992			this.settings = __assign(__assign({}, videoSettings), this.core.settings);
22993			return this;
22994		}
22995		Video.prototype.init = function () {
22996			var _this = this;
22997			/**
22998			 * Event triggered when video url found without poster
22999			 * Append video HTML
23000			 * Play if autoplayFirstVideo is true
23001			 */
23002			this.core.LGel.on(lGEvents.hasVideo + ".video", this.onHasVideo.bind(this));
23003			this.core.LGel.on(lGEvents.posterClick + ".video", function () {
23004				var $el = _this.core.getSlideItem(_this.core.index);
23005				_this.loadVideoOnPosterClick($el);
23006			});
23007			this.core.LGel.on(lGEvents.slideItemLoad + ".video", this.onSlideItemLoad.bind(this));
23008			// @desc fired immediately before each slide transition.
23009			this.core.LGel.on(lGEvents.beforeSlide + ".video", this.onBeforeSlide.bind(this));
23010			// @desc fired immediately after each slide transition.
23011			this.core.LGel.on(lGEvents.afterSlide + ".video", this.onAfterSlide.bind(this));
23012		};
23013		/**
23014		 * @desc Event triggered when a slide is completely loaded
23015		 *
23016		 * @param {Event} event - lightGalley custom event
23017		 */
23018		Video.prototype.onSlideItemLoad = function (event) {
23019			var _this = this;
23020			var _a = event.detail, isFirstSlide = _a.isFirstSlide, index = _a.index;
23021			// Should check the active slide as well as user may have moved to different slide before the first slide is loaded
23022			if (this.settings.autoplayFirstVideo &&
23023				isFirstSlide &&
23024				index === this.core.index) {
23025				// Delay is just for the transition effect on video load
23026				setTimeout(function () {
23027					_this.loadAndPlayVideo(index);
23028				}, 200);
23029			}
23030			// Should not call on first slide. should check only if the slide is active
23031			if (!isFirstSlide &&
23032				this.settings.autoplayVideoOnSlide &&
23033				index === this.core.index) {
23034					setTimeout(function () {
23035						_this.loadAndPlayVideo(index);
23036					}, 500);
23037				}
23038		};
23039		/**
23040		 * @desc Event triggered when video url or poster found
23041		 * Append video HTML is poster is not given
23042		 * Play if autoplayFirstVideo is true
23043		 *
23044		 * @param {Event} event - Javascript Event object.
23045		 */
23046		Video.prototype.onHasVideo = function (event) {
23047			var _a = event.detail, index = _a.index, src = _a.src, html5Video = _a.html5Video, hasPoster = _a.hasPoster;
23048			if (!hasPoster) {
23049				// All functions are called separately if poster exist in loadVideoOnPosterClick function
23050				this.appendVideos(this.core.getSlideItem(index), {
23051					src: src,
23052					addClass: 'lg-object',
23053					index: index,
23054					html5Video: html5Video,
23055					// Uncode edit ##START##
23056					autoplay: event.target.getAttribute('data-lb-autoplay'),
23057					muted: event.target.getAttribute('data-lb-muted'),
23058					// Uncode edit ##END##
23059				});
23060				// Automatically navigate to next slide once video reaches the end.
23061				this.gotoNextSlideOnVideoEnd(src, index);
23062			}
23063		};
23064		/**
23065		 * @desc fired immediately before each slide transition.
23066		 * Pause the previous video
23067		 * Hide the download button if the slide contains YouTube, Vimeo, or Wistia videos.
23068		 *
23069		 * @param {Event} event - Javascript Event object.
23070		 * @param {number} prevIndex - Previous index of the slide.
23071		 * @param {number} index - Current index of the slide
23072		 */
23073		Video.prototype.onBeforeSlide = function (event) {
23074			if (this.core.lGalleryOn) {
23075				var prevIndex = event.detail.prevIndex;
23076				this.pauseVideo(prevIndex);
23077			}
23078			// Uncode edit ##START##
23079			var _a = event.detail, index = _a.index;
23080			var $slide = this.core.getSlideItem(index);
23081			
23082			var iframe = $slide.selector.querySelector('iframe');
23083			if ( iframe != null ) {
23084
23085				var data_play = iframe.getAttribute('data-autoplay');
23086				if ( typeof data_play !== 'undefined' && data_play === '1' ) {
23087					this.loadAndPlayVideo(index);
23088
23089					var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {},
23090						$videoElement = this.core.getSlideItem(index).find('.lg-video-object').first();
23091					if (videoInfo.vimeo) {
23092						var vimeoPlayer = new Vimeo.Player($videoElement.get());
23093						vimeoPlayer.on('play', function () {
23094							vimeoPlayer.setCurrentTime(0);
23095						});
23096					} else if ( videoInfo.youtube ) {
23097						try {
23098							$videoElement.get().contentWindow.postMessage("{\"event\":\"command\",\"func\":\"seekTo\",\"args\":[0, true]}", '*');
23099						}
23100						catch (e) {
23101							console.warn(e);
23102						}
23103					}
23104				}
23105			}
23106			// Uncode edit ##END##
23107		};
23108		/**
23109		 * @desc fired immediately after each slide transition.
23110		 * Play video if autoplayVideoOnSlide option is enabled.
23111		 *
23112		 * @param {Event} event - Javascript Event object.
23113		 * @param {number} prevIndex - Previous index of the slide.
23114		 * @param {number} index - Current index of the slide
23115		 * @todo should check on onSlideLoad as well if video is not loaded on after slide
23116		 */
23117		Video.prototype.onAfterSlide = function (event) {
23118			var _this = this;
23119			var _a = event.detail, index = _a.index, prevIndex = _a.prevIndex;
23120			// Do not call on first slide
23121			var $slide = this.core.getSlideItem(index);
23122			if (this.settings.autoplayVideoOnSlide && index !== prevIndex) {
23123				if ($slide.hasClass('lg-complete')) {
23124					setTimeout(function () {
23125						_this.loadAndPlayVideo(index);
23126					}, 100);
23127				}
23128			}
23129		};
23130		Video.prototype.loadAndPlayVideo = function (index) {
23131			var $slide = this.core.getSlideItem(index);
23132			var currentGalleryItem = this.core.galleryItems[index];
23133			if (currentGalleryItem.poster) {
23134				this.loadVideoOnPosterClick($slide, true);
23135			}
23136			else {
23137				//Uncode edit ##START##
23138				// this.playVideo(index);
23139				var iframe = $slide.selector.querySelector('iframe');
23140				if ( iframe != null ) {
23141					var data_play = iframe.getAttribute('data-autoplay');
23142					if ( typeof data_play !== 'undefined' ) {
23143						if ( data_play === '1' && this.core.index == index ) {
23144							this.playVideo(index);
23145						} else {
23146							this.pauseVideo(index);
23147						}
23148					}
23149				}
23150				//Uncode edit ##END##
23151			}
23152		};
23153		/**
23154		 * Play HTML5, Youtube, Vimeo or Wistia videos in a particular slide.
23155		 * @param {number} index - Index of the slide
23156		 */
23157		Video.prototype.playVideo = function (index) {
23158			this.controlVideo(index, 'play');
23159		};
23160		/**
23161		 * Pause HTML5, Youtube, Vimeo or Wistia videos in a particular slide.
23162		 * @param {number} index - Index of the slide
23163		 */
23164		Video.prototype.pauseVideo = function (index) {
23165			this.controlVideo(index, 'pause');
23166		};
23167		// Uncode edit ##START##
23168		//Video.prototype.getVideoHtml = function (src, addClass, index, html5Video) {
23169		Video.prototype.getVideoHtml = function (src, addClass, index, html5Video, autoplay, muted) {
23170		// Uncode edit ##END##
23171			var video = '';
23172			var videoInfo = this.core.galleryItems[index]
23173				.__slideVideoInfo || {};
23174			var currentGalleryItem = this.core.galleryItems[index];
23175			var videoTitle = currentGalleryItem.title || currentGalleryItem.alt;
23176			videoTitle = videoTitle ? 'title="' + videoTitle + '"' : '';
23177			var commonIframeProps = "allowtransparency=\"true\"\n            frameborder=\"0\"\n            scrolling=\"no\"\n            allowfullscreen\n            mozallowfullscreen\n            webkitallowfullscreen\n            oallowfullscreen\n            msallowfullscreen";
23178			if (videoInfo.youtube) {
23179				var videoId = 'lg-youtube' + index;
23180				var slideUrlParams = videoInfo.youtube[2]
23181					? videoInfo.youtube[2] + '&'
23182					: '';
23183				// For youtube first parms gets priority if duplicates found
23184				// Uncode edit ##START##
23185				// var youTubePlayerParams = "?" + slideUrlParams + "wmode=opaque&autoplay=0&mute=1&enablejsapi=1";
23186				var youTubePlayerParams = "?" + slideUrlParams + "wmode=opaque&enablejsapi=1";
23187				if ( ( slideUrlParams.indexOf('autoplay=') < 0 && youTubePlayerParams.indexOf('autoplay=') < 0 ) ) {
23188					youTubePlayerParams += '&autoplay=0';
23189				}
23190				if ( slideUrlParams.indexOf('mute=') < 0 && youTubePlayerParams.indexOf('mute=') < 0 ) {
23191					youTubePlayerParams += '&mute=1';
23192				}
23193				var data_video = '';
23194				if ( autoplay !== '' ) {
23195					//youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])autoplay=(.*?)(&|$)'), '$1autoplay=' + (autoplay === 'yes' ? 1 : 0) + '$3' );
23196					youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])autoplay=(.*?)(&|$)'), '$1$3' );
23197					youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])autoplay'), '$1' );
23198					data_video = ' data-autoplay="' + (autoplay === 'yes' ? 1 : 0) + '"';
23199				}
23200				// if ( muted !== '' ) {
23201				// 	youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])mute=(.*?)(&|$)'), '$1mute=' + (muted === 'yes' ? 1 : 0) + '$3' );
23202				// }
23203				youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])mute=(.*?)(&|$)'), '$1$3' );
23204
23205				youTubePlayerParams = youTubePlayerParams.replace('??', '?');
23206				// Uncode edit ##END##
23207				var playerParams = youTubePlayerParams +
23208					(this.settings.youTubePlayerParams
23209						? '&' + param(this.settings.youTubePlayerParams)
23210						: '');
23211				// Uncode edit ##START##
23212				// 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>";
23213				var nocookie = typeof SiteParameters.uncode_nocookie !== 'undefined' ? SiteParameters.uncode_nocookie : '';
23214				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>";
23215				var tag = document.createElement('script');
23216				tag.src = "//www.youtube.com/player_api";
23217				var firstScriptTag = document.getElementsByTagName('script')[0];
23218				firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
23219
23220				// Replace the 'ytplayer' element with an <iframe> and
23221				// YouTube player after the API code downloads.
23222				var ytIframeplayer,
23223					setMute = muted === 'yes' ? 0 : 100;
23224				window.onYouTubePlayerAPIReady = function() {
23225					ytIframeplayer = new YT.Player(videoId, {
23226						videoId: videoInfo.youtube[1],
23227						events: {
23228							'onReady': function (event) {
23229								event.target.setVolume(setMute);
23230							}
23231						}
23232					});
23233				}
23234				// Uncode edit ##END##
23235			}
23236			else if (videoInfo.vimeo) {
23237				var videoId = 'lg-vimeo' + index;
23238				// Uncode edit ##START##
23239				videoInfo.autoplay = autoplay;
23240				videoInfo.muted = muted;
23241				// Uncode edit ##END##
23242				var playerParams = getVimeoURLParams(this.settings.vimeoPlayerParams, videoInfo);
23243				// Uncode edit ##START##
23244				// 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>";
23245				var data_video = '';
23246				if ( autoplay !== '' ) {
23247					data_video = ' data-autoplay="' + (autoplay === 'yes' ? 1 : 0) + '"';
23248				}
23249				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>";
23250				// Uncode edit ##END##
23251			}
23252			else if (videoInfo.wistia) {
23253				var wistiaId = 'lg-wistia' + index;
23254				var playerParams = param(this.settings.wistiaPlayerParams);
23255				playerParams = playerParams ? '?' + playerParams : '';
23256				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>";
23257			}
23258			else if (videoInfo.html5) {
23259				var html5VideoMarkup = '';
23260				for (var i = 0; i < html5Video.source.length; i++) {
23261					html5VideoMarkup += "<source src=\"" + html5Video.source[i].src + "\" type=\"" + html5Video.source[i].type + "\">";
23262				}
23263				if (html5Video.tracks) {
23264					var _loop_1 = function (i) {
23265						var trackAttributes = '';
23266						var track = html5Video.tracks[i];
23267						Object.keys(track || {}
23267).forEach(function (key) {
23268							trackAttributes += key + "=\"" + track[key] + "\" ";
23269						});
23270						html5VideoMarkup += "<track " + trackAttributes + ">";
23271					};
23272					for (var i = 0; i < html5Video.tracks.length; i++) {
23273						_loop_1(i);
23274					}
23275				}
23276				var html5VideoAttrs_1 = '';
23277				var videoAttributes_1 = html5Video.attributes || {};
23278				Object.keys(videoAttributes_1 || {}).forEach(function (key) {
23279					html5VideoAttrs_1 += key + "=\"" + videoAttributes_1[key] + "\" ";
23280				});
23281				video = "<video class=\"lg-video-object lg-html5 " + (this.settings.videojs && this.settings.videojsTheme
23282					? this.settings.videojsTheme + ' '
23283					: '') + " " + (this.settings.videojs ? ' video-js' : '') + "\" " + html5VideoAttrs_1 + ">\n                " + html5VideoMarkup + "\n                Your browser does not support HTML5 video.\n            </video>";
23284			}
23285			return video;
23286		};
23287		/**
23288		 * @desc - Append videos to the slide
23289		 *
23290		 * @param {HTMLElement} el - slide element
23291		 * @param {Object} videoParams - Video parameters, Contains src, class, index, htmlVideo
23292		 */
23293		Video.prototype.appendVideos = function (el, videoParams) {
23294			var _a;
23295			// Uncode edit ##START##
23296			// var videoHtml = this.getVideoHtml(videoParams.src, videoParams.addClass, videoParams.index, videoParams.html5Video);
23297			var videoHtml = this.getVideoHtml(videoParams.src, videoParams.addClass, videoParams.index, videoParams.html5Video, videoParams.autoplay, videoParams.muted);
23298			// Uncode edit ##END##
23299			el.find('.lg-video-cont').append(videoHtml);
23300			var $videoElement = el.find('.lg-video-object').first();
23301			if (videoParams.html5Video) {
23302				$videoElement.on('mousedown.lg.video', function (e) {
23303					e.stopPropagation();
23304				});
23305			}
23306			if (this.settings.videojs && ((_a = this.core.galleryItems[videoParams.index].__slideVideoInfo) === null || _a === void 0 ? void 0 : _a.html5)) {
23307				try {
23308					return videojs($videoElement.get(), this.settings.videojsOptions);
23309				}
23310				catch (e) {
23311					console.warn('lightGallery:- Make sure you have included videojs');
23312				}
23313			}
23314		};
23315		Video.prototype.gotoNextSlideOnVideoEnd = function (src, index) {
23316			var _this = this;
23317			var $videoElement = this.core
23318				.getSlideItem(index)
23319				.find('.lg-video-object')
23320				.first();
23321			var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {};
23322			if (this.settings.gotoNextSlideOnVideoEnd) {
23323				if (videoInfo.html5) {
23324					$videoElement.on('ended', function () {
23325						_this.core.goToNextSlide();
23326					});
23327				}
23328				else if (videoInfo.vimeo) {
23329					try {
23330						// https://github.com/vimeo/player.js/#ended
23331						new Vimeo.Player($videoElement.get()).on('ended', function () {
23332							_this.core.goToNextSlide();
23333						});
23334					}
23335					catch (e) {
23336						console.warn('lightGallery:- Make sure you have included //github.com/vimeo/player.js');
23337					}
23338				}
23339				else if (videoInfo.wistia) {
23340					try {
23341						window._wq = window._wq || [];
23342						// @todo Event is gettign triggered multiple times
23343						window._wq.push({
23344							id: $videoElement.attr('id'),
23345							onReady: function (video) {
23346								video.bind('end', function () {
23347									_this.core.goToNextSlide();
23348								});
23349							},
23350						});
23351					}
23352					catch (e) {
23353						console.warn('lightGallery:- Make sure you have included //fast.wistia.com/assets/external/E-v1.js');
23354					}
23355				}
23356			}
23357		};
23358		Video.prototype.controlVideo = function (index, action) {
23359			var $videoElement = this.core
23360				.getSlideItem(index)
23361				.find('.lg-video-object')
23362				.first();
23363			var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {};
23364			if (!$videoElement.get())
23365				return;
23366			if (videoInfo.youtube) {
23367				try {
23368					$videoElement.get().contentWindow.postMessage("{\"event\":\"command\",\"func\":\"" + action + "Video\",\"args\":\"\"}", '*');
23369				}
23370				catch (e) {
23371					console.warn("lightGallery:- " + e);
23372				}
23373			}
23374			else if (videoInfo.vimeo) {
23375				try {
23376					new Vimeo.Player($videoElement.get())[action]();
23377				}
23378				catch (e) {
23379					console.warn('lightGallery:- Make sure you have included //github.com/vimeo/player.js');
23380				}
23381			}
23382			else if (videoInfo.html5) {
23383				if (this.settings.videojs) {
23384					try {
23385						videojs($videoElement.get())[action]();
23386					}
23387					catch (e) {
23388						console.warn('lightGallery:- Make sure you have included videojs');
23389					}
23390				}
23391				else {
23392					$videoElement.get()[action]();
23393				}
23394			}
23395			else if (videoInfo.wistia) {
23396				try {
23397					window._wq = window._wq || [];
23398					// @todo Find a way to destroy wistia player instance
23399					window._wq.push({
23400						id: $videoElement.attr('id'),
23401						onReady: function (video) {
23402							video[action]();
23403						},
23404					});
23405				}
23406				catch (e) {
23407					console.warn('lightGallery:- Make sure you have included //fast.wistia.com/assets/external/E-v1.js');
23408				}
23409			}
23410		};
23411		Video.prototype.loadVideoOnPosterClick = function ($el, forcePlay) {
23412			var _this = this;
23413			// check slide has poster
23414			if (!$el.hasClass('lg-video-loaded')) {
23415				// check already video element present
23416				if (!$el.hasClass('lg-has-video')) {
23417					$el.addClass('lg-has-video');
23418					var _html = void 0;
23419					var _src = this.core.galleryItems[this.core.index].src;
23420					var video = this.core.galleryItems[this.core.index].video;
23421					if (video) {
23422						_html =
23423							typeof video === 'string' ? JSON.parse(video) : video;
23424					}
23425					var videoJsPlayer_1 = this.appendVideos($el, {
23426						src: _src,
23427						addClass: '',
23428						index: this.core.index,
23429						html5Video: _html,
23430					});
23431					this.gotoNextSlideOnVideoEnd(_src, this.core.index);
23432					var $tempImg = $el.find('.lg-object').first().get();
23433					// @todo make sure it is working
23434					$el.find('.lg-video-cont').first().append($tempImg);
23435					$el.addClass('lg-video-loading');
23436					videoJsPlayer_1 &&
23437						videoJsPlayer_1.ready(function () {
23438							videoJsPlayer_1.on('loadedmetadata', function () {
23439								_this.onVideoLoadAfterPosterClick($el, _this.core.index);
23440							});
23441						});
23442					$el.find('.lg-video-object')
23443						.first()
23444						.on('load.lg error.lg loadedmetadata.lg', function () {
23445						setTimeout(function () {
23446							_this.onVideoLoadAfterPosterClick($el, _this.core.index);
23447						}, 50);
23448					});
23449				}
23450				else {
23451					this.playVideo(this.core.index);
23452				}
23453			}
23454			else if (forcePlay) {
23455				this.playVideo(this.core.index);
23456			}
23457		};
23458		Video.prototype.onVideoLoadAfterPosterClick = function ($el, index) {
23459			$el.addClass('lg-video-loaded');
23460			this.playVideo(index);
23461		};
23462		Video.prototype.destroy = function () {
23463			this.core.LGel.off('.lg.video');
23464			this.core.LGel.off('.video');
23465		};
23466		return Video;
23467	}());
23468
23469	return Video;
23470
23471})));
23472
23473
23474/*! @vimeo/player v2.17.1 | (c) 2022 Vimeo | MIT License | https://github.com/vimeo/player.js */
23475!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:{}}
23475),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 23475
23475var 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)}
23475},{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: 31,994 bytes, lines 23475-24682
23475))}(),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});
23476
23477/**
23478 * Owl carousel
23479 * @version 2.0.0-beta.3
23480 * @author Bartosz Wojciechowski
23481 * @license The MIT License (MIT)
23482 * @todo Lazy Load Icon
23483 * @todo prevent animationend bubling
23484 * @todo itemsScaleUp
23485 * @todo Test Zepto
23486 * @todo stagePadding calculate wrong active classes
23487 */
23488;(function($, window, document, undefined) {
23489
23490	/**
23491	 * Creates a carousel.
23492	 * @class The Owl Carousel.
23493	 * @public
23494	 * @param {HTMLElement|jQuery} element - The element to create the carousel for.
23495	 * @param {Object} [options] - The options
23496	 */
23497	function Owl(element, options) {
23498
23499		/**
23500		 * Current settings for the carousel.
23501		 * @public
23502		 */
23503		this.settings = null;
23504
23505		/**
23506		 * Current options set by the caller including defaults.
23507		 * @public
23508		 */
23509		this.options = $.extend({}, Owl.Defaults, options);
23510
23511		/**
23512		 * Plugin element.
23513		 * @public
23514		 */
23515		this.$element = $(element);
23516
23517		/**
23518		 * Proxied event handlers.
23519		 * @protected
23520		 */
23521		this._handlers = {};
23522
23523		/**
23524		 * References to the running plugins of this carousel.
23525		 * @protected
23526		 */
23527		this._plugins = {};
23528
23529		/**
23530		 * Currently suppressed events to prevent them from beeing retriggered.
23531		 * @protected
23532		 */
23533		this._supress = {};
23534
23535		/**
23536		 * Absolute current position.
23537		 * @protected
23538		 */
23539		this._current = null;
23540
23541		/**
23542		 * Animation speed in milliseconds.
23543		 * @protected
23544		 */
23545		this._speed = null;
23546
23547		/**
23548		 * Coordinates of all items in pixel.
23549		 * @todo The name of this member is missleading.
23550		 * @protected
23551		 */
23552		this._coordinates = [];
23553
23554		/**
23555		 * Current breakpoint.
23556		 * @todo Real media queries would be nice.
23557		 * @protected
23558		 */
23559		this._breakpoint = null;
23560
23561		/**
23562		 * Current width of the plugin element.
23563		 */
23564		this._width = null;
23565
23566		/**
23567		 * All real items.
23568		 * @protected
23569		 */
23570		this._items = [];
23571
23572		/**
23573		 * All cloned items.
23574		 * @protected
23575		 */
23576		this._clones = [];
23577
23578		/**
23579		 * Merge values of all items.
23580		 * @todo Maybe this could be part of a plugin.
23581		 * @protected
23582		 */
23583		this._mergers = [];
23584
23585		/**
23586		 * Widths of all items.
23587		 */
23588		this._widths = [];
23589
23590		/**
23591		 * Invalidated parts within the update process.
23592		 * @protected
23593		 */
23594		this._invalidated = {};
23595
23596		/**
23597		 * Ordered list of workers for the update process.
23598		 * @protected
23599		 */
23600		this._pipe = [];
23601
23602		/**
23603		 * Current state information for the drag operation.
23604		 * @todo #261
23605		 * @protected
23606		 */
23607		this._drag = {
23608			time: null,
23609			target: null,
23610			pointer: null,
23611			stage: {
23612				start: null,
23613				current: null
23614			},
23615			direction: null
23616		};
23617
23618		/**
23619		 * Current state information and their tags.
23620		 * @type {Object}
23621		 * @protected
23622		 */
23623		this._states = {
23624			current: {},
23625			tags: {
23626				'initializing': [ 'busy' ],
23627				'animating': [ 'busy' ],
23628				'dragging': [ 'interacting' ]
23629			}
23630		};
23631
23632		$.each([ 'onResize', 'onThrottledResize' ], $.proxy(function(i, handler) {
23633			this._handlers[handler] = $.proxy(this[handler], this);
23634		}, this));
23635
23636		$.each(Owl.Plugins, $.proxy(function(key, plugin) {
23637			this._plugins[key.charAt(0).toLowerCase() + key.slice(1)]
23638				= new plugin(this);
23639		}, this));
23640
23641		$.each(Owl.Workers, $.proxy(function(priority, worker) {
23642			this._pipe.push({
23643				'filter': worker.filter,
23644				'run': $.proxy(worker.run, this)
23645			});
23646		}, this));
23647
23648		this.setup();
23649		this.initialize();
23650	}
23651
23652	/**
23653	 * Default options for the carousel.
23654	 * @public
23655	 */
23656	Owl.Defaults = {
23657		items: 3,
23658		loop: false,
23659		center: false,
23660		rewind: false,
23661
23662		mouseDrag: true,
23663		touchDrag: true,
23664		pullDrag: true,
23665		freeDrag: false,
23666
23667		margin: 0,
23668		stagePadding: 0,
23669
23670		merge: false,
23671		mergeFit: true,
23672		autoWidth: false,
23673
23674		startPosition: 0,
23675		rtl: false,
23676
23677		smartSpeed: 250,
23678		fluidSpeed: false,
23679		dragEndSpeed: false,
23680
23681		responsive: {},
23682		responsiveRefreshRate: 200,
23683		responsiveBaseElement: window,
23684
23685		fallbackEasing: 'swing',
23686
23687		info: false,
23688
23689		nestedItemSelector: false,
23690		itemElement: 'div',
23691		stageElement: 'div',
23692
23693		refreshClass: 'owl-refresh',
23694		loadedClass: 'owl-loaded',
23695		loadingClass: 'owl-loading',
23696		rtlClass: 'owl-rtl',
23697		responsiveClass: 'owl-responsive',
23698		dragClass: 'owl-drag',
23699		itemClass: 'owl-item',
23700		stageClass: 'owl-stage',
23701		stageOuterClass: 'owl-stage-outer',
23702		grabClass: 'owl-grab'
23703	};
23704
23705	/**
23706	 * Enumeration for width.
23707	 * @public
23708	 * @readonly
23709	 * @enum {String}
23710	 */
23711	Owl.Width = {
23712		Default: 'default',
23713		Inner: 'inner',
23714		Outer: 'outer'
23715	};
23716
23717	/**
23718	 * Enumeration for types.
23719	 * @public
23720	 * @readonly
23721	 * @enum {String}
23722	 */
23723	Owl.Type = {
23724		Event: 'event',
23725		State: 'state'
23726	};
23727
23728	/**
23729	 * Contains all registered plugins.
23730	 * @public
23731	 */
23732	Owl.Plugins = {};
23733
23734	/**
23735	 * List of workers involved in the update process.
23736	 */
23737	Owl.Workers = [ {
23738		filter: [ 'width', 'settings' ],
23739		run: function() {
23740			this._width = (this.$element.closest('.px-gutter').length) ? 12 * Math.ceil(this.$element.width() / 12) : this.$element.width();
23741			//this._width = (UNCODE.isMobile) ? this.$element.width() : 12 * Math.ceil(this.$element.width() / 12);
23742		}
23743	}, {
23744		filter: [ 'width', 'items', 'settings' ],
23745		run: function(cache) {
23746			cache.current = this._items && this._items[this.relative(this._current)];
23747		}
23748	}, {
23749		filter: [ 'items', 'settings' ],
23750		run: function() {
23751			this.$stage.children('.cloned').remove();
23752		}
23753	}, {
23754		filter: [ 'width', 'items', 'settings' ],
23755		run: function(cache) {
23756			var margin = this.settings.margin || '',
23757				grid = !this.settings.autoWidth,
23758				rtl = this.settings.rtl,
23759				css = {
23760					'width': 'auto',
23761					'margin-left': rtl ? margin : '',
23762					'margin-right': rtl ? '' : margin
23763				};
23764
23765			!grid && this.$stage.children().css(css);
23766
23767			cache.css = css;
23768		}
23769	}, {
23770		filter: [ 'width', 'items', 'settings' ],
23771		run: function(cache) {
23772			//UNCODE edit to fix Chrome stage padding issue
23773			var width = Math.round((this.width() / this.settings.items).toFixed(3) - this.settings.margin),
23774				merge = null,
23775				iterator = this._items.length,
23776				grid = !this.settings.autoWidth,
23777				widths = [];
23778
23779			cache.items = {
23780				merge: false,
23781				width: width
23782			};
23783
23784			while (iterator--) {
23785				merge = this._mergers[iterator];
23786				merge = this.settings.mergeFit && Math.min(merge, this.settings.items) || merge;
23787
23788				cache.items.merge = merge > 1 || cache.items.merge;
23789
23790				widths[iterator] = !grid ? this._items[iterator].width() : width * merge;
23791			}
23792
23793			this._widths = widths;
23794		}
23795	}, {
23796		filter: [ 'items', 'settings' ],
23797		run: function() {
23798			var clones = [],
23799				items = this._items,
23800				settings = this.settings,
23801				view = Math.max(settings.items * 2, 4),
23802				size = Math.ceil(items.length / 2) * 2,
23803				repeat = settings.loop && items.length ? settings.rewind ? view : Math.max(view, size) : 0,
23804				append = '',
23805				prepend = '';
23806
23807			repeat /= 2;
23808
23809			while (repeat--) {
23810				clones.push(this.normalize(clones.length / 2, true));
23811				append = append + items[clones[clones.length - 1]][0].outerHTML;
23812				clones.push(this.normalize(items.length - 1 - (clones.length - 1) / 2, true));
23813				prepend = items[clones[clones.length - 1]][0].outerHTML + prepend;
23814			}
23815
23816			this._clones = clones;
23817
23818			// var appendVideo = $(append).find('.uncode-video-container');
23819			// if (appendVideo.length) {
23820			// 	appendVideo.attr('data-id', Math.round(Math.random() * 100000));
23821			// }
23822			// var prependVideo = $(prepend).find('.uncode-video-container');
23823			// if (prependVideo.length) {
23824			// 	prependVideo.attr('data-id', Math.round(Math.random() * 100000));
23825			// }
23826			$(append).addClass('cloned').appendTo(this.$stage);
23827			$(prepend).addClass('cloned').prependTo(this.$stage);
23828		}
23829	}, {
23830		filter: [ 'width', 'items', 'settings' ],
23831		run: function() {
23832			var rtl = this.settings.rtl ? 1 : -1,
23833				size = this._clones.length + this._items.length,
23834				iterator = -1,
23835				previous = 0,
23836				current = 0,
23837				coordinates = [];
23838
23839			while (++iterator < size) {
23840				previous = coordinates[iterator - 1] || 0;
23841				current = this._widths[this.relative(iterator)] + this.settings.margin;
23842				coordinates.push(previous + current * rtl);
23843			}
23844
23845			this._coordinates = coordinates;
23846		}
23847	}, {
23848		filter: [ 'width', 'items', 'settings' ],
23849		run: function() {
23850			var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200,
23851				padding = stagePadding,
23852				coordinates = this._coordinates,
23853				css = {
23854					'width': Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2,
23855					'padding-left': padding || '',
23856					'padding-right': padding || ''
23857				};
23858
23859			this.$stage.css(css);
23860		}
23861	}, {
23862		filter: [ 'width', 'items', 'settings' ],
23863		run: function(cache) {
23864			var iterator = this._coordinates.length,
23865				grid = !this.settings.autoWidth,
23866				items = this.$stage.children();
23867
23868			if (grid && cache.items.merge) {
23869				while (iterator--) {
23870					cache.css.width = this._widths[this.relative(iterator)];
23871					items.eq(iterator).css(cache.css);
23872				}
23873			} else if (grid) {
23874				cache.css.width = cache.items.width;
23875				items.css(cache.css);
23876			}
23877		}
23878	}, {
23879		filter: [ 'items' ],
23880		run: function() {
23881			this._coordinates.length < 1 && this.$stage.removeAttr('style');
23882		}
23883	}, {
23884		filter: [ 'width', 'items', 'settings' ],
23885		run: function(cache) {
23886			cache.current = cache.current ? this.$stage.children().index(cache.current) : 0;
23887			cache.current = Math.max(this.minimum(), Math.min(this.maximum(), cache.current));
23888			this.reset(cache.current);
23889		}
23890	}, {
23891		filter: [ 'position' ],
23892		run: function() {
23893			this.animate(this.coordinates(this._current));
23894		}
23895	}, {
23896		filter: [ 'width', 'position', 'items', 'settings' ],
23897		run: function() {
23898			var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200,
23899				rtl = this.settings.rtl ? 1 : -1,
23900				padding = this.settings.stagePadding * 2,
23901				begin = this.coordinates(this.current()) + padding,
23902				end = begin + this.width() * rtl,
23903				inner, outer, matches = [], i, n;
23904
23905			for (i = 0, n = this._coordinates.length; i < n; i++) {
23906				inner = this._coordinates[i - 1] || 0;
23907				outer = Math.abs(this._coordinates[i]) + padding * rtl;
23908
23909				if ((this.op(inner, '<=', begin) && (this.op(inner, '>', end)))
23910					|| (this.op(outer, '<', begin) && this.op(outer, '>', end))) {
23911					matches.push(i);
23912				}
23913			}
23914
23915			this.$stage.children('.active').removeClass('active');
23916			this.$stage.children(':eq(' + matches.join('), :eq(') + ')').addClass('active');
23917
23918			if (this.settings.center) {
23919				this.$stage.children('.center').removeClass('center');
23920				this.$stage.children().eq(this.current()).addClass('center');
23921			}
23922		}
23923	} ];
23924
23925	/**
23926	 * Initializes the carousel.
23927	 * @protected
23928	 */
23929	Owl.prototype.initialize = function() {
23930		this.enter('initializing');
23931		this.trigger('initialize');
23932
23933		this.$element.toggleClass(this.settings.rtlClass, this.settings.rtl);
23934
23935		if (this.settings.autoWidth && !this.is('pre-loading')) {
23936			var imgs, nestedSelector, width;
23937			imgs = this.$element.find('img');
23938			nestedSelector = this.settings.nestedItemSelector ? '.' + this.settings.nestedItemSelector : undefined;
23939			width = this.$element.children(nestedSelector).width();
23940
23941			if (imgs.length && width <= 0) {
23942				this.preloadAutoWidthImages(imgs);
23943			}
23944		}
23945
23946		this.$element.addClass(this.options.loadingClass);
23947
23948		// create stage
23949		this.$stage = $('<' + this.settings.stageElement + ' class="' + this.settings.stageClass + '"/>')
23950			.wrap('<div class="' + this.settings.stageOuterClass + '"/>');
23951
23952		// append stage
23953		this.$element.append(this.$stage.parent());
23954
23955		// append content
23956		this.replace(this.$element.children().not(this.$stage.parent()));
23957
23958		// check visibility
23959		if (this.$element.is(':visible')) {
23960			// update view
23961			this.refresh();
23962		} else {
23963			// invalidate width
23964			this.invalidate('width');
23965		}
23966
23967		this.$element
23968			.removeClass(this.options.loadingClass)
23969			.addClass(this.options.loadedClass);
23970
23971		// register event handlers
23972		this.registerEventHandlers();
23973
23974		this.leave('initializing');
23975		this.trigger('initialized');
23976	};
23977
23978	/**
23979	 * Setups the current settings.
23980	 * @todo Remove responsive classes. Why should adaptive designs be brought into IE8?
23981	 * @todo Support for media queries by using `matchMedia` would be nice.
23982	 * @public
23983	 */
23984	Owl.prototype.setup = function() {
23985		var viewport = this.viewport(),
23986			overwrites = this.options.responsive,
23987			match = -1,
23988			settings = null;
23989
23990		if (!overwrites) {
23991			settings = $.extend({}, this.options);
23992		} else {
23993			$.each(overwrites, function(breakpoint) {
23994				if (breakpoint <= viewport && breakpoint > match) {
23995					match = Number(breakpoint);
23996				}
23997			});
23998
23999			settings = $.extend({}, this.options, overwrites[match]);
24000			delete settings.responsive;
24001
24002			// responsive class
24003			if (settings.responsiveClass) {
24004				this.$element.attr('class',
24005					this.$element.attr('class').replace(new RegExp('(' + this.options.responsiveClass + '-)\\S+\\s', 'g'), '$1' + match)
24006				);
24007			}
24008		}
24009
24010		if (this.settings === null || this._breakpoint !== match) {
24011			this.trigger('change', { property: { name: 'settings', value: settings } });
24012			this._breakpoint = match;
24013			this.settings = settings;
24014			this.invalidate('settings');
24015			this.trigger('changed', { property: { name: 'settings', value: this.settings } });
24016		}
24017	};
24018
24019	/**
24020	 * Updates option logic if necessery.
24021	 * @protected
24022	 */
24023	Owl.prototype.optionsLogic = function() {
24024		if (this.settings.autoWidth) {
24025			this.settings.stagePadding = false;
24026			this.settings.merge = false;
24027		}
24028	};
24029
24030	/**
24031	 * Prepares an item before add.
24032	 * @todo Rename event parameter `content` to `item`.
24033	 * @protected
24034	 * @returns {jQuery|HTMLElement} - The item container.
24035	 */
24036	Owl.prototype.prepare = function(item, index) {
24037		var event = this.trigger('prepare', { content: item });
24038		if (!event.data) {
24039			event.data = $('<' + this.settings.itemElement + '/>')
24040				.addClass(this.options.itemClass).attr('data-index', index + 1).append(item)
24041		}
24042
24043		this.trigger('prepared', { content: event.data });
24044
24045		return event.data;
24046	};
24047
24048	/**
24049	 * Updates the view.
24050	 * @public
24051	 */
24052	Owl.prototype.update = function() {
24053		var i = 0,
24054			n = this._pipe.length,
24055			filter = $.proxy(function(p) { return this[p] }, this._invalidated),
24056			cache = {};
24057
24058		while (i < n) {
24059			if (this._invalidated.all || $.grep(this._pipe[i].filter, filter).length > 0) {
24060				this._pipe[i].run(cache);
24061			}
24062			i++;
24063		}
24064
24065		this._invalidated = {};
24066
24067		!this.is('valid') && this.enter('valid');
24068	};
24069
24070	/**
24071	 * Gets the width of the view.
24072	 * @public
24073	 * @param {Owl.Width} [dimension=Owl.Width.Default] - The dimension to return.
24074	 * @returns {Number} - The width of the view in pixel.
24075	 */
24076	Owl.prototype.width = function(dimension) {
24077		dimension = dimension || Owl.Width.Default;
24078		var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200;
24079		switch (dimension) {
24080			case Owl.Width.Inner:
24081			case Owl.Width.Outer:
24082				return this._width;
24083			default:
24084				return this._width - stagePadding * 2 + this.settings.margin;
24085		}
24086	};
24087
24088	/**
24089	 * Refreshes the carousel primarily for adaptive purposes.
24090	 * @public
24091	 */
24092	Owl.prototype.refresh = function() {
24093		this.enter('refreshing');
24094		this.trigger('refresh');
24095
24096		this.setup();
24097
24098		this.optionsLogic();
24099
24100		this.$element.addClass(this.options.refreshClass);
24101
24102		this.update();
24103
24104		this.$element.removeClass(this.options.refreshClass);
24105
24106		this.leave('refreshing');
24107		this.trigger('refreshed');
24108	};
24109
24110	/**
24111	 * Checks window `resize` event.
24112	 * @protected
24113	 */
24114	Owl.prototype.onThrottledResize = function() {
24115		window.clearTimeout(this.resizeTimer);
24116		this.resizeTimer = window.setTimeout(this._handlers.onResize, this.settings.responsiveRefreshRate);
24117	};
24118
24119	/**
24120	 * Checks window `resize` event.
24121	 * @protected
24122	 */
24123	Owl.prototype.onResize = function() {
24124		if (!this._items.length) {
24125			return false;
24126		}
24127
24128		if (this._width === this.$element.width()) {
24129			return false;
24130		}
24131
24132		if (!this.$element.is(':visible')) {
24133			return false;
24134		}
24135
24136		this.enter('resizing');
24137
24138		if (this.trigger('resize').isDefaultPrevented()) {
24139			this.leave('resizing');
24140			return false;
24141		}
24142
24143		this.invalidate('width');
24144
24145		this.refresh();
24146
24147		this.leave('resizing');
24148		this.trigger('resized');
24149	};
24150
24151	/**
24152	 * Registers event handlers.
24153	 * @todo Check `msPointerEnabled`
24154	 * @todo #261
24155	 * @protected
24156	 */
24157	Owl.prototype.registerEventHandlers = function() {
24158		if ($.support.transition) {
24159			this.$stage.on($.support.transition.end + '.owl.core', $.proxy(this.onTransitionEnd, this));
24160		}
24161
24162		if (this.settings.responsive !== false) {
24163			this.on(window, 'resize', this._handlers.onThrottledResize);
24164		}
24165
24166		if (this.settings.mouseDrag) {
24167			this.$element.addClass(this.options.dragClass);
24168			this.$stage.on('mousedown.owl.core', $.proxy(this.onDragStart, this));
24169			this.$stage.on('dragstart.owl.core selectstart.owl.core', function() { return false });
24170		}
24171
24172		if (this.settings.touchDrag){
24173			this.$stage.on('touchstart.owl.core', $.proxy(this.onDragStart, this));
24174			this.$stage.on('touchcancel.owl.core', $.proxy(this.onDragEnd, this));
24175		}
24176	};
24177
24178	/**
24179	 * Handles `touchstart` and `mousedown` events.
24180	 * @todo Horizontal swipe threshold as option
24181	 * @todo #261
24182	 * @protected
24183	 * @param {Event} event - The event arguments.
24184	 */
24185	Owl.prototype.onDragStart = function(event) {
24186		var stage = null;
24187
24188		if (event.which === 3) {
24189			return;
24190		}
24191
24192		if ($.support.transform) {
24193			stage = this.$stage.css('transform').replace(/.*\(|\)| /g, '').split(',');
24194			stage = {
24195				x: stage[stage.length === 16 ? 12 : 4],
24196				y: stage[stage.length === 16 ? 13 : 5]
24197			};
24198		} else {
24199			stage = this.$stage.position();
24200			stage = {
24201				x: this.settings.rtl ?
24202					stage.left + this.$stage.width() - this.width() + this.settings.margin :
24203					stage.left,
24204				y: stage.top
24205			};
24206		}
24207
24208		if (this.is('animating')) {
24209			$.support.transform ? this.animate(stage.x) : this.$stage.stop()
24210			this.invalidate('position');
24211		}
24212
24213		this.$element.toggleClass(this.options.grabClass, event.type === 'mousedown');
24214
24215		this.speed(0);
24216
24217		this._drag.time = new Date().getTime();
24218		this._drag.target = $(event.target);
24219		this._drag.stage.start = stage;
24220		this._drag.stage.current = stage;
24221		this._drag.pointer = this.pointer(event);
24222
24223		$(document).on('mouseup.owl.core touchend.owl.core', $.proxy(this.onDragEnd, this));
24224
24225		$(document).one('mousemove.owl.core touchmove.owl.core', $.proxy(function(event) {
24226			var delta = this.difference(this._drag.pointer, this.pointer(event));
24227
24228			$(document).on('mousemove.owl.core touchmove.owl.core', $.proxy(this.onDragMove, this));
24229
24230			if (Math.abs(delta.x) < Math.abs(delta.y) && this.is('valid')) {
24231				return;
24232			}
24233
24234			event.preventDefault();
24235
24236			this.enter('dragging');
24237			this.trigger('drag');
24238		}, this));
24239	};
24240
24241	/**
24242	 * Handles the `touchmove` and `mousemove` events.
24243	 * @todo #261
24244	 * @protected
24245	 * @param {Event} event - The event arguments.
24246	 */
24247	Owl.prototype.onDragMove = function(event) {
24248		var minimum = null,
24249			maximum = null,
24250			pull = null,
24251			delta = this.difference(this._drag.pointer, this.pointer(event)),
24252			stage = this.difference(this._drag.stage.start, delta);
24253
24254		if (!this.is('dragging')) {
24255			return;
24256		}
24257
24258		event.preventDefault();
24259
24260		if (this.settings.loop) {
24261			minimum = this.coordinates(this.minimum());
24262			maximum = this.coordinates(this.maximum() + 1) - minimum;
24263			stage.x = (((stage.x - minimum) % maximum + maximum) % maximum) + minimum;
24264		} else {
24265			minimum = this.settings.rtl ? this.coordinates(this.maximum()) : this.coordinates(this.minimum());
24266			maximum = this.settings.rtl ? this.coordinates(this.minimum()) : this.coordinates(this.maximum());
24267			pull = this.settings.pullDrag ? -1 * delta.x / 5 : 0;
24268			stage.x = Math.max(Math.min(stage.x, minimum + pull), maximum + pull);
24269		}
24270
24271		this._drag.stage.current = stage;
24272
24273		this.animate(stage.x);
24274	};
24275
24276	/**
24277	 * Handles the `touchend` and `mouseup` events.
24278	 * @todo #261
24279	 * @todo Threshold for click event
24280	 * @protected
24281	 * @param {Event} event - The event arguments.
24282	 */
24283	Owl.prototype.onDragEnd = function(event) {
24284		var delta = this.difference(this._drag.pointer, this.pointer(event)),
24285			stage = this._drag.stage.current,
24286			direction = delta.x > 0 ^ this.settings.rtl ? 'left' : 'right';
24287
24288		$(document).off('.owl.core');
24289
24290		this.$element.removeClass(this.options.grabClass);
24291
24292		if (delta.x !== 0 && this.is('dragging') || !this.is('valid')) {
24293			this.speed(this.settings.dragEndSpeed || this.settings.smartSpeed);
24294			this.current(this.closest(stage.x, delta.x !== 0 ? direction : this._drag.direction));
24295			this.invalidate('position');
24296			this.update();
24297
24298			this._drag.direction = direction;
24299
24300			if (Math.abs(delta.x) > 3 || new Date().getTime() - this._drag.time > 300) {
24301				this._drag.target.one('click.owl.core', function() { return false; });
24302			}
24303		}
24304
24305		if (!this.is('dragging')) {
24306			return;
24307		}
24308
24309		this.leave('dragging');
24310		this.trigger('dragged');
24311	};
24312
24313	/**
24314	 * Gets absolute position of the closest item for a coordinate.
24315	 * @todo Setting `freeDrag` makes `closest` not reusable. See #165.
24316	 * @protected
24317	 * @param {Number} coordinate - The coordinate in pixel.
24318	 * @param {String} direction - The direction to check for the closest item. Ether `left` or `right`.
24319	 * @return {Number} - The absolute position of the closest item.
24320	 */
24321	Owl.prototype.closest = function(coordinate, direction) {
24322		var position = -1,
24323			pull = 30,
24324			width = this.width(),
24325			coordinates = this.coordinates();
24326
24327		if (!this.settings.freeDrag) {
24328			// check closest item
24329			$.each(coordinates, $.proxy(function(index, value) {
24330				if (coordinate > value - pull && coordinate < value + pull) {
24331					position = index;
24332				} else if (this.op(coordinate, '<', value)
24333					&& this.op(coordinate, '>', coordinates[index + 1] || value - width)) {
24334					position = direction === 'left' ? index + 1 : index;
24335				}
24336				return position === -1;
24337			}, this));
24338		}
24339
24340		if (!this.settings.loop) {
24341			// non loop boundries
24342			if (this.op(coordinate, '>', coordinates[this.minimum()])) {
24343				position = coordinate = this.minimum();
24344			} else if (this.op(coordinate, '<', coordinates[this.maximum()])) {
24345				position = coordinate = this.maximum();
24346			}
24347		}
24348
24349		return position;
24350	};
24351
24352	/**
24353	 * Animates the stage.
24354	 * @todo #270
24355	 * @public
24356	 * @param {Number} coordinate - The coordinate in pixels.
24357	 */
24358	Owl.prototype.animate = function(coordinate) {
24359		var animate = this.speed() > 0;
24360
24361		this.is('animating') && this.onTransitionEnd();
24362
24363		if (animate) {
24364			this.enter('animating');
24365			this.trigger('translate');
24366		}
24367
24368		if ($.support.transform3d && $.support.transition) {
24369			this.$stage.css({
24370				transform: 'translate3d(' + coordinate + 'px,0px,0px)',
24371				transition: (this.speed() / 1000) + 's'
24372			});
24373		} else if (animate) {
24374			this.$stage.animate({
24375				left: coordinate + 'px'
24376			}, this.speed(), this.settings.fallbackEasing, $.proxy(this.onTransitionEnd, this));
24377		} else {
24378			this.$stage.css({
24379				left: coordinate + 'px'
24380			});
24381		}
24382	};
24383
24384	/**
24385	 * Checks whether the carousel is in a specific state or not.
24386	 * @param {String} state - The state to check.
24387	 * @returns {Boolean} - The flag which indicates if the carousel is busy.
24388	 */
24389	Owl.prototype.is = function(state) {
24390		return this._states.current[state] && this._states.current[state] > 0;
24391	};
24392
24393	/**
24394	 * Sets the absolute position of the current item.
24395	 * @public
24396	 * @param {Number} [position] - The new absolute position or nothing to leave it unchanged.
24397	 * @returns {Number} - The absolute position of the current item.
24398	 */
24399	Owl.prototype.current = function(position) {
24400		if (position === undefined) {
24401			return this._current;
24402		}
24403
24404		if (this._items.length === 0) {
24405			return undefined;
24406		}
24407
24408		position = this.normalize(position);
24409
24410		if (this._current !== position) {
24411			var event = this.trigger('change', { property: { name: 'position', value: position } });
24412
24413			if (event.data !== undefined) {
24414				position = this.normalize(event.data);
24415			}
24416
24417			this._current = position;
24418
24419			this.invalidate('position');
24420
24421			this.trigger('changed', { property: { name: 'position', value: this._current } });
24422		}
24423
24424		return this._current;
24425	};
24426
24427	/**
24428	 * Invalidates the given part of the update routine.
24429	 * @param {String} [part] - The part to invalidate.
24430	 * @returns {Array.<String>} - The invalidated parts.
24431	 */
24432	Owl.prototype.invalidate = function(part) {
24433		if ($.type(part) === 'string') {
24434			this._invalidated[part] = true;
24435			this.is('valid') && this.leave('valid');
24436		}
24437		return $.map(this._invalidated, function(v, i) { return i });
24438	};
24439
24440	/**
24441	 * Resets the absolute position of the current item.
24442	 * @public
24443	 * @param {Number} position - The absolute position of the new item.
24444	 */
24445	Owl.prototype.reset = function(position) {
24446		position = this.normalize(position);
24447
24448		if (position === undefined) {
24449			return;
24450		}
24451
24452		this._speed = 0;
24453		this._current = position;
24454
24455		this.suppress([ 'translate', 'translated' ]);
24456
24457		this.animate(this.coordinates(position));
24458
24459		this.release([ 'translate', 'translated' ]);
24460	};
24461
24462	/**
24463	 * Normalizes an absolute or a relative position of an item.
24464	 * @public
24465	 * @param {Number} position - The absolute or relative position to normalize.
24466	 * @param {Boolean} [relative=false] - Whether the given position is relative or not.
24467	 * @returns {Number} - The normalized position.
24468	 */
24469	Owl.prototype.normalize = function(position, relative) {
24470		var n = this._items.length,
24471			m = relative ? 0 : this._clones.length;
24472
24473		if (!$.isNumeric(position) || n < 1) {
24474			position = undefined;
24475		} else if (position < 0 || position >= n + m) {
24476			position = ((position - m / 2) % n + n) % n + m / 2;
24477		}
24478
24479		return position;
24480	};
24481
24482	/**
24483	 * Converts an absolute position of an item into a relative one.
24484	 * @public
24485	 * @param {Number} position - The absolute position to convert.
24486	 * @returns {Number} - The converted position.
24487	 */
24488	Owl.prototype.relative = function(position) {
24489		position -= this._clones.length / 2;
24490		return this.normalize(position, true);
24491	};
24492
24493	/**
24494	 * Gets the maximum position for the current item.
24495	 * @public
24496	 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
24497	 * @returns {Number}
24498	 */
24499	Owl.prototype.maximum = function(relative) {
24500		var settings = this.settings,
24501			maximum = this._coordinates.length,
24502			boundary = Math.abs(this._coordinates[maximum - 1]) - this._width,
24503			i = -1, j;
24504
24505		if (settings.loop) {
24506			maximum = this._clones.length / 2 + this._items.length - 1;
24507		} else if (settings.autoWidth || settings.merge) {
24508			// binary search
24509			while (maximum - i > 1) {
24510				Math.abs(this._coordinates[j = maximum + i >> 1]) < boundary
24511					? i = j : maximum = j;
24512			}
24513		} else if (settings.center) {
24514			maximum = this._items.length - 1;
24515		} else {
24516			maximum = this._items.length - settings.items;
24517		}
24518
24519		if (relative) {
24520			maximum -= this._clones.length / 2;
24521		}
24522
24523		return Math.max(maximum, 0);
24524	};
24525
24526	/**
24527	 * Gets the minimum position for the current item.
24528	 * @public
24529	 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
24530	 * @returns {Number}
24531	 */
24532	Owl.prototype.minimum = function(relative) {
24533		return relative ? 0 : this._clones.length / 2;
24534	};
24535
24536	/**
24537	 * Gets an item at the specified relative position.
24538	 * @public
24539	 * @param {Number} [position] - The relative position of the item.
24540	 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
24541	 */
24542	Owl.prototype.items = function(position) {
24543		if (position === undefined) {
24544			return this._items.slice();
24545		}
24546
24547		position = this.normalize(position, true);
24548		return this._items[position];
24549	};
24550
24551	/**
24552	 * Gets an item at the specified relative position.
24553	 * @public
24554	 * @param {Number} [position] - The relative position of the item.
24555	 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
24556	 */
24557	Owl.prototype.mergers = function(position) {
24558		if (position === undefined) {
24559			return this._mergers.slice();
24560		}
24561
24562		position = this.normalize(position, true);
24563		return this._mergers[position];
24564	};
24565
24566	/**
24567	 * Gets the absolute positions of clones for an item.
24568	 * @public
24569	 * @param {Number} [position] - The relative position of the item.
24570	 * @returns {Array.<Number>} - The absolute positions of clones for the item or all if no position was given.
24571	 */
24572	Owl.prototype.clones = function(position) {
24573		var odd = this._clones.length / 2,
24574			even = odd + this._items.length,
24575			map = function(index) { return index % 2 === 0 ? even + index / 2 : odd - (index + 1) / 2 };
24576
24577		if (position === undefined) {
24578			return $.map(this._clones, function(v, i) { return map(i) });
24579		}
24580
24581		return $.map(this._clones, function(v, i) { return v === position ? map(i) : null });
24582	};
24583
24584	/**
24585	 * Sets the current animation speed.
24586	 * @public
24587	 * @param {Number} [speed] - The animation speed in milliseconds or nothing to leave it unchanged.
24588	 * @returns {Number} - The current animation speed in milliseconds.
24589	 */
24590	Owl.prototype.speed = function(speed) {
24591		if (speed !== undefined) {
24592			this._speed = speed;
24593		}
24594
24595		return this._speed;
24596	};
24597
24598	/**
24599	 * Gets the coordinate of an item.
24600	 * @todo The name of this method is missleanding.
24601	 * @public
24602	 * @param {Number} position - The absolute position of the item within `minimum()` and `maximum()`.
24603	 * @returns {Number|Array.<Number>} - The coordinate of the item in pixel or all coordinates.
24604	 */
24605	Owl.prototype.coordinates = function(position) {
24606		var coordinate = null;
24607
24608		if (position === undefined) {
24609			return $.map(this._coordinates, $.proxy(function(coordinate, index) {
24610				return this.coordinates(index);
24611			}, this));
24612		}
24613
24614		if (this.settings.center) {
24615			coordinate = this._coordinates[position];
24616			coordinate += (this.width() - coordinate + (this._coordinates[position - 1] || 0)) / 2 * (this.settings.rtl ? -1 : 1);
24617		} else {
24618			coordinate = this._coordinates[position - 1] || 0;
24619		}
24620
24621		return coordinate;
24622	};
24623
24624	/**
24625	 * Calculates the speed for a translation.
24626	 * @protected
24627	 * @param {Number} from - The absolute position of the start item.
24628	 * @param {Number} to - The absolute position of the target item.
24629	 * @param {Number} [factor=undefined] - The time factor in milliseconds.
24630	 * @returns {Number} - The time in milliseconds for the translation.
24631	 */
24632	Owl.prototype.duration = function(from, to, factor) {
24633		return Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((factor || this.settings.smartSpeed));
24634	};
24635
24636	/**
24637	 * Slides to the specified item.
24638	 * @public
24639	 * @param {Number} position - The position of the item.
24640	 * @param {Number} [speed] - The time in milliseconds for the transition.
24641	 */
24642	Owl.prototype.to = function(position, speed) {
24643		var current = this.current(),
24644			revert = null,
24645			distance = position - this.relative(current),
24646			direction = (distance > 0) - (distance < 0),
24647			items = this._items.length,
24648			minimum = this.minimum(),
24649			maximum = this.maximum();
24650
24651		if (this.settings.loop) {
24652			if (!this.settings.rewind && Math.abs(distance) > items / 2) {
24653				distance += direction * -1 * items;
24654			}
24655
24656			position = current + distance;
24657			revert = ((position - minimum) % items + items) % items + minimum;
24658
24659			if (revert !== position && revert - distance <= maximum && revert - distance > 0) {
24660				current = revert - distance;
24661				position = revert;
24662				this.reset(current);
24663			}
24664		} else if (this.settings.rewind) {
24665			maximum += 1;
24666			position = (position % maximum + maximum) % maximum;
24667		} else {
24668			position = Math.max(minimum, Math.min(maximum, position));
24669		}
24670
24671		this.speed(this.duration(current, position, speed));
24672		this.current(position);
24673
24674		if (this.$element.is(':visible')) {
24675			this.update();
24676		}
24677	};
24678
24679	/**
24680	 * Slides to the next item.
24681	 * @public
24682	 * @param {Number}
vendor: 4,086 bytes, lines 24682-24818
24682 [speed] - The time in milliseconds for the transition.
24683	 */
24684	Owl.prototype.next = function(speed) {
24685		speed = speed || false;
24686		this.to(this.relative(this.current()) + 1, speed);
24687	};
24688
24689	/**
24690	 * Slides to the previous item.
24691	 * @public
24692	 * @param {Number} [speed] - The time in milliseconds for the transition.
24693	 */
24694	Owl.prototype.prev = function(speed) {
24695		speed = speed || false;
24696		this.to(this.relative(this.current()) - 1, speed);
24697	};
24698
24699	/**
24700	 * Handles the end of an animation.
24701	 * @protected
24702	 * @param {Event} event - The event arguments.
24703	 */
24704	Owl.prototype.onTransitionEnd = function(event) {
24705
24706		// if css2 animation then event object is undefined
24707		if (event !== undefined) {
24708			event.stopPropagation();
24709
24710			// Catch only owl-stage transitionEnd event
24711			if ((event.target || event.srcElement || event.originalTarget) !== this.$stage.get(0)) {
24712				return false;
24713			}
24714		}
24715
24716		this.leave('animating');
24717		this.trigger('translated');
24718	};
24719
24720	/**
24721	 * Gets viewport width.
24722	 * @protected
24723	 * @return {Number} - The width in pixel.
24724	 */
24725	Owl.prototype.viewport = function() {
24726		var width;
24727		if (this.options.responsiveBaseElement !== window) {
24728			width = $(this.options.responsiveBaseElement).width();
24729		} else if (window.innerWidth) {
24730			width = window.innerWidth;
24731		} else if (document.documentElement && document.documentElement.clientWidth) {
24732			width = document.documentElement.clientWidth;
24733		} else {
24734			throw 'Can not detect viewport width.';
24735		}
24736
24737		return width;
24738	};
24739
24740	/**
24741	 * Replaces the current content.
24742	 * @public
24743	 * @param {HTMLElement|jQuery|String} content - The new content.
24744	 */
24745	Owl.prototype.replace = function(content) {
24746		this.$stage.empty();
24747		this._items = [];
24748
24749		if (content) {
24750			content = (content instanceof jQuery) ? content : $(content);
24751		}
24752
24753		if (this.settings.nestedItemSelector) {
24754			content = content.find('.' + this.settings.nestedItemSelector);
24755		}
24756
24757		content.filter(function() {
24758			return this.nodeType === 1;
24759		}).each($.proxy(function(index, item) {
24760			item = this.prepare(item, index);
24761			this.$stage.append(item);
24762			this._items.push(item);
24763			this._mergers.push(item.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1);
24764		}, this));
24765
24766		this.reset($.isNumeric(this.settings.startPosition) ? this.settings.startPosition : 0);
24767
24768		this.invalidate('items');
24769	};
24770
24771	/**
24772	 * Adds an item.
24773	 * @todo Use `item` instead of `content` for the event arguments.
24774	 * @public
24775	 * @param {HTMLElement|jQuery|String} content - The item content to add.
24776	 * @param {Number} [position] - The relative position at which to insert the item otherwise the item will be added to the end.
24777	 */
24778	Owl.prototype.add = function(content, position) {
24779		var current = this.relative(this._current);
24780
24781		position = position === undefined ? this._items.length : this.normalize(position, true);
24782		content = content instanceof jQuery ? content : $(content);
24783
24784		this.trigger('add', { content: content, position: position });
24785
24786		content = this.prepare(content, this._items[current].index());
24787
24788		if (this._items.length === 0 || position === this._items.length) {
24789			this._items.length === 0 && this.$stage.append(content);
24790			this._items.length !== 0 && this._items[position - 1].after(content);
24791			this._items.push(content);
24792			this._mergers.push(content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1);
24793		} else {
24794			this._items[position].before(content);
24795			this._items.splice(position, 0, content);
24796			this._mergers.splice(position, 0, content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1);
24797		}
24798
24799		this._items[current] && this.reset(this._items[current].index());
24800
24801		this.invalidate('items');
24802
24803		this.trigger('added', { content: content, position: position });
24804	};
24805
24806	/**
24807	 * Removes an item by its position.
24808	 * @todo Use `item` instead of `content` for the event arguments.
24809	 * @public
24810	 * @param {Number} position - The relative position of the item to remove.
24811	 */
24812	Owl.prototype.remove = function(position) {
24813		position = this.normalize(position, true);
24814
24815		if (position === undefined) {
24816			return;
24817		}
24818
vendor: 40,414 bytes, lines 24819-26385
24819		this.trigger('remove', { content: this._items[position], position: position });
24820
24821		this._items[position].remove();
24822		this._items.splice(position, 1);
24823		this._mergers.splice(position, 1);
24824
24825		this.invalidate('items');
24826
24827		this.trigger('removed', { content: null, position: position });
24828	};
24829
24830	/**
24831	 * Preloads images with auto width.
24832	 * @todo Replace by a more generic approach
24833	 * @protected
24834	 */
24835	Owl.prototype.preloadAutoWidthImages = function(images) {
24836		images.each($.proxy(function(i, element) {
24837			this.enter('pre-loading');
24838			element = $(element);
24839			$(new Image()).one('load', $.proxy(function(e) {
24840				element.attr('src', e.target.src);
24841				element.css('opacity', 1);
24842				this.leave('pre-loading');
24843				!this.is('pre-loading') && !this.is('initializing') && this.refresh();
24844			}, this)).attr('src', element.attr('src') || element.attr('data-src') || element.attr('data-src-retina'));
24845		}, this));
24846	};
24847
24848	/**
24849	 * Destroys the carousel.
24850	 * @public
24851	 */
24852	Owl.prototype.destroy = function() {
24853
24854		this.$element.off('.owl.core');
24855		this.$stage.off('.owl.core');
24856		$(document).off('.owl.core');
24857
24858		if (this.settings.responsive !== false) {
24859			window.clearTimeout(this.resizeTimer);
24860			this.off(window, 'resize', this._handlers.onThrottledResize);
24861		}
24862
24863		for (var i in this._plugins) {
24864			this._plugins[i].destroy();
24865		}
24866
24867		this.$stage.children('.cloned').remove();
24868
24869		this.$stage.unwrap();
24870		this.$stage.children().contents().unwrap();
24871		this.$stage.children().unwrap();
24872
24873		this.$element
24874			.removeClass(this.options.refreshClass)
24875			.removeClass(this.options.loadingClass)
24876			.removeClass(this.options.loadedClass)
24877			.removeClass(this.options.rtlClass)
24878			.removeClass(this.options.dragClass)
24879			.removeClass(this.options.grabClass)
24880			.attr('class', this.$element.attr('class').replace(new RegExp(this.options.responsiveClass + '-\\S+\\s', 'g'), ''))
24881			.removeData('owl.carousel');
24882	};
24883
24884	/**
24885	 * Operators to calculate right-to-left and left-to-right.
24886	 * @protected
24887	 * @param {Number} [a] - The left side operand.
24888	 * @param {String} [o] - The operator.
24889	 * @param {Number} [b] - The right side operand.
24890	 */
24891	Owl.prototype.op = function(a, o, b) {
24892		var rtl = this.settings.rtl;
24893		switch (o) {
24894			case '<':
24895				return rtl ? a > b : a < b;
24896			case '>':
24897				return rtl ? a < b : a > b;
24898			case '>=':
24899				return rtl ? a <= b : a >= b;
24900			case '<=':
24901				return rtl ? a >= b : a <= b;
24902			default:
24903				break;
24904		}
24905	};
24906
24907	/**
24908	 * Attaches to an internal event.
24909	 * @protected
24910	 * @param {HTMLElement} element - The event source.
24911	 * @param {String} event - The event name.
24912	 * @param {Function} listener - The event handler to attach.
24913	 * @param {Boolean} capture - Wether the event should be handled at the capturing phase or not.
24914	 */
24915	Owl.prototype.on = function(element, event, listener, capture) {
24916		if (element.addEventListener) {
24917			element.addEventListener(event, listener, capture);
24918		} else if (element.attachEvent) {
24919			element.attachEvent('on' + event, listener);
24920		}
24921	};
24922
24923	/**
24924	 * Detaches from an internal event.
24925	 * @protected
24926	 * @param {HTMLElement} element - The event source.
24927	 * @param {String} event - The event name.
24928	 * @param {Function} listener - The attached event handler to detach.
24929	 * @param {Boolean} capture - Wether the attached event handler was registered as a capturing listener or not.
24930	 */
24931	Owl.prototype.off = function(element, event, listener, capture) {
24932		if (element.removeEventListener) {
24933			element.removeEventListener(event, listener, capture);
24934		} else if (element.detachEvent) {
24935			element.detachEvent('on' + event, listener);
24936		}
24937	};
24938
24939	/**
24940	 * Triggers a public event.
24941	 * @todo Remove `status`, `relatedTarget` should be used instead.
24942	 * @protected
24943	 * @param {String} name - The event name.
24944	 * @param {*} [data=null] - The event data.
24945	 * @param {String} [namespace=carousel] - The event namespace.
24946	 * @param {String} [state] - The state which is associated with the event.
24947	 * @param {Boolean} [enter=false] - Indicates if the call enters the specified state or not.
24948	 * @returns {Event} - The event arguments.
24949	 */
24950	Owl.prototype.trigger = function(name, data, namespace, state, enter) {
24951		var status = {
24952			item: { count: this._items.length, index: this.current() }
24953		}, handler = $.camelCase(
24954			$.grep([ 'on', name, namespace ], function(v) { return v })
24955				.join('-').toLowerCase()
24956		), event = $.Event(
24957			[ name, 'owl', namespace || 'carousel' ].join('.').toLowerCase(),
24958			$.extend({ relatedTarget: this }, status, data)
24959		);
24960
24961		if (!this._supress[name]) {
24962			$.each(this._plugins, function(name, plugin) {
24963				if (plugin.onTrigger) {
24964					plugin.onTrigger(event);
24965				}
24966			});
24967
24968			this.register({ type: Owl.Type.Event, name: name });
24969			this.$element.trigger(event);
24970
24971			if (this.settings && typeof this.settings[handler] === 'function') {
24972				this.settings[handler].call(this, event);
24973			}
24974		}
24975
24976		return event;
24977	};
24978
24979	/**
24980	 * Enters a state.
24981	 * @param name - The state name.
24982	 */
24983	Owl.prototype.enter = function(name) {
24984		$.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
24985			if (this._states.current[name] === undefined) {
24986				this._states.current[name] = 0;
24987			}
24988
24989			this._states.current[name]++;
24990		}, this));
24991	};
24992
24993	/**
24994	 * Leaves a state.
24995	 * @param name - The state name.
24996	 */
24997	Owl.prototype.leave = function(name) {
24998		$.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
24999			this._states.current[name]--;
25000		}, this));
25001	};
25002
25003	/**
25004	 * Registers an event or state.
25005	 * @public
25006	 * @param {Object} object - The event or state to register.
25007	 */
25008	Owl.prototype.register = function(object) {
25009		if (object.type === Owl.Type.Event) {
25010			if (!$.event.special[object.name]) {
25011				$.event.special[object.name] = {};
25012			}
25013
25014			if (!$.event.special[object.name].owl) {
25015				var _default = $.event.special[object.name]._default;
25016				$.event.special[object.name]._default = function(e) {
25017					if (_default && _default.apply && (!e.namespace || e.namespace.indexOf('owl') === -1)) {
25018						return _default.apply(this, arguments);
25019					}
25020					return e.namespace && e.namespace.indexOf('owl') > -1;
25021				};
25022				$.event.special[object.name].owl = true;
25023			}
25024		} else if (object.type === Owl.Type.State) {
25025			if (!this._states.tags[object.name]) {
25026				this._states.tags[object.name] = object.tags;
25027			} else {
25028				this._states.tags[object.name] = this._states.tags[object.name].concat(object.tags);
25029			}
25030
25031			this._states.tags[object.name] = $.grep(this._states.tags[object.name], $.proxy(function(tag, i) {
25032				return $.inArray(tag, this._states.tags[object.name]) === i;
25033			}, this));
25034		}
25035	};
25036
25037	/**
25038	 * Suppresses events.
25039	 * @protected
25040	 * @param {Array.<String>} events - The events to suppress.
25041	 */
25042	Owl.prototype.suppress = function(events) {
25043		$.each(events, $.proxy(function(index, event) {
25044			this._supress[event] = true;
25045		}, this));
25046	};
25047
25048	/**
25049	 * Releases suppressed events.
25050	 * @protected
25051	 * @param {Array.<String>} events - The events to release.
25052	 */
25053	Owl.prototype.release = function(events) {
25054		$.each(events, $.proxy(function(index, event) {
25055			delete this._supress[event];
25056		}, this));
25057	};
25058
25059	/**
25060	 * Gets unified pointer coordinates from event.
25061	 * @todo #261
25062	 * @protected
25063	 * @param {Event} - The `mousedown` or `touchstart` event.
25064	 * @returns {Object} - Contains `x` and `y` coordinates of current pointer position.
25065	 */
25066	Owl.prototype.pointer = function(event) {
25067		var result = { x: null, y: null };
25068
25069		event = event.originalEvent || event || window.event;
25070
25071		event = event.touches && event.touches.length ?
25072			event.touches[0] : event.changedTouches && event.changedTouches.length ?
25073				event.changedTouches[0] : event;
25074
25075		if (event.pageX) {
25076			result.x = event.pageX;
25077			result.y = event.pageY;
25078		} else {
25079			result.x = event.clientX;
25080			result.y = event.clientY;
25081		}
25082
25083		return result;
25084	};
25085
25086	/**
25087	 * Gets the difference of two vectors.
25088	 * @todo #261
25089	 * @protected
25090	 * @param {Object} - The first vector.
25091	 * @param {Object} - The second vector.
25092	 * @returns {Object} - The difference.
25093	 */
25094	Owl.prototype.difference = function(first, second) {
25095		return {
25096			x: first.x - second.x,
25097			y: first.y - second.y
25098		};
25099	};
25100
25101	/**
25102	 * The jQuery Plugin for the Owl Carousel
25103	 * @todo Navigation plugin `next` and `prev`
25104	 * @public
25105	 */
25106	$.fn.owlCarousel = function(option) {
25107		var args = Array.prototype.slice.call(arguments, 1);
25108
25109		return this.each(function() {
25110			var $this = $(this),
25111				data = $this.data('owl.carousel');
25112
25113			if (!data) {
25114				data = new Owl(this, typeof option == 'object' && option);
25115				$this.data('owl.carousel', data);
25116
25117				$.each([
25118					'next', 'prev', 'to', 'destroy', 'refresh', 'replace', 'add', 'remove'
25119				], function(i, event) {
25120					data.register({ type: Owl.Type.Event, name: event });
25121					data.$element.on(event + '.owl.carousel.core', $.proxy(function(e) {
25122						if (e.namespace && e.relatedTarget !== this) {
25123							this.suppress([ event ]);
25124							data[event].apply(this, [].slice.call(arguments, 1));
25125							this.release([ event ]);
25126						}
25127					}, data));
25128				});
25129			}
25130
25131			if (typeof option == 'string' && option.charAt(0) !== '_') {
25132				data[option].apply(data, args);
25133			}
25134		});
25135	};
25136
25137	/**
25138	 * The constructor for the jQuery Plugin
25139	 * @public
25140	 */
25141	$.fn.owlCarousel.Constructor = Owl;
25142
25143})(window.Zepto || window.jQuery, window, document);
25144
25145/**
25146 * AutoRefresh Plugin
25147 * @version 2.0.0-beta.3
25148 * @author Artus Kolanowski
25149 * @license The MIT License (MIT)
25150 */
25151;(function($, window, document, undefined) {
25152
25153	/**
25154	 * Creates the auto refresh plugin.
25155	 * @class The Auto Refresh Plugin
25156	 * @param {Owl} carousel - The Owl Carousel
25157	 */
25158	var AutoRefresh = function(carousel) {
25159		/**
25160		 * Reference to the core.
25161		 * @protected
25162		 * @type {Owl}
25163		 */
25164		this._core = carousel;
25165
25166		/**
25167		 * Refresh interval.
25168		 * @protected
25169		 * @type {number}
25170		 */
25171		this._interval = null;
25172
25173		/**
25174		 * Whether the element is currently visible or not.
25175		 * @protected
25176		 * @type {Boolean}
25177		 */
25178		this._visible = null;
25179
25180		/**
25181		 * All event handlers.
25182		 * @protected
25183		 * @type {Object}
25184		 */
25185		this._handlers = {
25186			'initialized.owl.carousel': $.proxy(function(e) {
25187				if (e.namespace && this._core.settings.autoRefresh) {
25188					this.watch();
25189				}
25190			}, this)
25191		};
25192
25193		// set default options
25194		this._core.options = $.extend({}, AutoRefresh.Defaults, this._core.options);
25195
25196		// register event handlers
25197		this._core.$element.on(this._handlers);
25198	};
25199
25200	/**
25201	 * Default options.
25202	 * @public
25203	 */
25204	AutoRefresh.Defaults = {
25205		autoRefresh: true,
25206		autoRefreshInterval: 500
25207	};
25208
25209	/**
25210	 * Watches the element.
25211	 */
25212	AutoRefresh.prototype.watch = function() {
25213		if (this._interval) {
25214			return;
25215		}
25216
25217		this._visible = this._core.$element.is(':visible');
25218		this._interval = window.setInterval($.proxy(this.refresh, this), this._core.settings.autoRefreshInterval);
25219	};
25220
25221	/**
25222	 * Refreshes the element.
25223	 */
25224	AutoRefresh.prototype.refresh = function() {
25225		if (this._core.$element.is(':visible') === this._visible) {
25226			return;
25227		}
25228
25229		this._visible = !this._visible;
25230
25231		this._core.$element.toggleClass('owl-hidden', !this._visible);
25232
25233		this._visible && (this._core.invalidate('width') && this._core.refresh());
25234	};
25235
25236	/**
25237	 * Destroys the plugin.
25238	 */
25239	AutoRefresh.prototype.destroy = function() {
25240		var handler, property;
25241
25242		window.clearInterval(this._interval);
25243
25244		for (handler in this._handlers) {
25245			this._core.$element.off(handler, this._handlers[handler]);
25246		}
25247		for (property in Object.getOwnPropertyNames(this)) {
25248			typeof this[property] != 'function' && (this[property] = null);
25249		}
25250	};
25251
25252	$.fn.owlCarousel.Constructor.Plugins.AutoRefresh = AutoRefresh;
25253
25254})(window.Zepto || window.jQuery, window, document);
25255
25256/**
25257 * Lazy Plugin
25258 * @version 2.0.0-beta.3
25259 * @author Bartosz Wojciechowski
25260 * @license The MIT License (MIT)
25261 */
25262;(function($, window, document, undefined) {
25263
25264	/**
25265	 * Creates the lazy plugin.
25266	 * @class The Lazy Plugin
25267	 * @param {Owl} carousel - The Owl Carousel
25268	 */
25269	var Lazy = function(carousel) {
25270
25271		/**
25272		 * Reference to the core.
25273		 * @protected
25274		 * @type {Owl}
25275		 */
25276		this._core = carousel;
25277
25278		/**
25279		 * Already loaded items.
25280		 * @protected
25281		 * @type {Array.<jQuery>}
25282		 */
25283		this._loaded = [];
25284
25285		/**
25286		 * Event handlers.
25287		 * @protected
25288		 * @type {Object}
25289		 */
25290		this._handlers = {
25291			'initialized.owl.carousel change.owl.carousel': $.proxy(function(e) {
25292				if (!e.namespace) {
25293					return;
25294				}
25295
25296				if (!this._core.settings || !this._core.settings.lazyLoad) {
25297					return;
25298				}
25299
25300				if ((e.property && e.property.name == 'position') || e.type == 'initialized') {
25301					var settings = this._core.settings,
25302						n = (settings.center && Math.ceil(settings.items / 2) || settings.items),
25303						i = ((settings.center && n * -1) || 0),
25304						position = ((e.property && e.property.value) || this._core.current()) + i,
25305						clones = this._core.clones().length,
25306						load = $.proxy(function(i, v) { this.load(v) }, this);
25307
25308					while (i++ < n) {
25309						this.load(clones / 2 + this._core.relative(position));
25310						clones && $.each(this._core.clones(this._core.relative(position)), load);
25311						position++;
25312					}
25313				}
25314			}, this)
25315		};
25316
25317		// set the default options
25318		this._core.options = $.extend({}, Lazy.Defaults, this._core.options);
25319
25320		// register event handler
25321		this._core.$element.on(this._handlers);
25322	}
25323
25324	/**
25325	 * Default options.
25326	 * @public
25327	 */
25328	Lazy.Defaults = {
25329		lazyLoad: false
25330	}
25331
25332	/**
25333	 * Loads all resources of an item at the specified position.
25334	 * @param {Number} position - The absolute position of the item.
25335	 * @protected
25336	 */
25337	Lazy.prototype.load = function(position) {
25338		var $item = this._core.$stage.children().eq(position),
25339			$elements = $item && $item.find('.owl-lazy');
25340
25341		if (!$elements || $.inArray($item.get(0), this._loaded) > -1) {
25342			return;
25343		}
25344
25345		$elements.each($.proxy(function(index, element) {
25346			var $element = $(element), image,
25347				url = (window.devicePixelRatio > 1 && $element.attr('data-src-retina')) || $element.attr('data-src');
25348
25349			this._core.trigger('load', { element: $element, url: url }, 'lazy');
25350
25351			if ($element.is('img')) {
25352				$element.one('load.owl.lazy', $.proxy(function() {
25353					$element.css('opacity', 1);
25354					this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
25355				}, this)).attr('src', url);
25356			} else {
25357				image = new Image();
25358				image.onload = $.proxy(function() {
25359					$element.css({
25360						'background-image': 'url(' + url + ')',
25361						'opacity': '1'
25362					});
25363					this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
25364				}, this);
25365				image.src = url;
25366			}
25367		}, this));
25368
25369		this._loaded.push($item.get(0));
25370	}
25371
25372	/**
25373	 * Destroys the plugin.
25374	 * @public
25375	 */
25376	Lazy.prototype.destroy = function() {
25377		var handler, property;
25378
25379		for (handler in this.handlers) {
25380			this._core.$element.off(handler, this.handlers[handler]);
25381		}
25382		for (property in Object.getOwnPropertyNames(this)) {
25383			typeof this[property] != 'function' && (this[property] = null);
25384		}
25385	};
25386
25387	$.fn.owlCarousel.Constructor.Plugins.Lazy = Lazy;
25388
25389})(window.Zepto || window.jQuery, window, document);
25390
25391/**
25392 * AutoHeight Plugin
25393 * @version 2.0.0-beta.3
25394 * @author Bartosz Wojciechowski
25395 * @license The MIT License (MIT)
25396 */
25397;(function($, window, document, undefined) {
25398
25399	/**
25400	 * Creates the auto height plugin.
25401	 * @class The Auto Height Plugin
25402	 * @param {Owl} carousel - The Owl Carousel
25403	 */
25404	var AutoHeight = function(carousel) {
25405		/**
25406		 * Reference to the core.
25407		 * @protected
25408		 * @type {Owl}
25409		 */
25410		this._core = carousel;
25411
25412		/**
25413		 * All event handlers.
25414		 * @protected
25415		 * @type {Object}
25416		 */
25417		this._handlers = {
25418			'initialized.owl.carousel refreshed.owl.carousel': $.proxy(function(e) {
25419				if (e.namespace && this._core.settings.autoHeight) {
25420					this.update();
25421				}
25422			}, this),
25423			'changed.owl.carousel': $.proxy(function(e) {
25424				if (e.namespace && this._core.settings.autoHeight && e.property.name == 'position'){
25425					this.update();
25426				}
25427			}, this),
25428			'loaded.owl.lazy': $.proxy(function(e) {
25429				if (e.namespace && this._core.settings.autoHeight
25430					&& e.element.closest('.' + this._core.settings.itemClass).index() === this._core.current()) {
25431					this.update();
25432				}
25433			}, this)
25434		};
25435
25436		// set default options
25437		this._core.options = $.extend({}, AutoHeight.Defaults, this._core.options);
25438
25439		// register event handlers
25440		this._core.$element.on(this._handlers);
25441	};
25442
25443	/**
25444	 * Default options.
25445	 * @public
25446	 */
25447	AutoHeight.Defaults = {
25448		autoHeight: false,
25449		autoHeightClass: 'owl-height'
25450	};
25451
25452	/**
25453	 * Updates the view.
25454	 */
25455	AutoHeight.prototype.update = function() {
25456		var start = this._core._current,
25457			end = start + this._core.settings.items,
25458			visible = this._core.$stage.children().toArray().slice(start, end);
25459			heights = [],
25460			maxheight = 0;
25461
25462		$.each(visible, function(index, item) {
25463			heights.push($(item).height());
25464		});
25465
25466		maxheight = Math.max.apply(null, heights);
25467
25468		this._core.$stage.parent()
25469			.height(maxheight)
25470			.addClass(this._core.settings.autoHeightClass);
25471	};
25472
25473	AutoHeight.prototype.destroy = function() {
25474		var handler, property;
25475
25476		for (handler in this._handlers) {
25477			this._core.$element.off(handler, this._handlers[handler]);
25478		}
25479		for (property in Object.getOwnPropertyNames(this)) {
25480			typeof this[property] != 'function' && (this[property] = null);
25481		}
25482	};
25483
25484	$.fn.owlCarousel.Constructor.Plugins.AutoHeight = AutoHeight;
25485
25486})(window.Zepto || window.jQuery, window, document);
25487
25488/**
25489 * Video Plugin
25490 * @version 2.0.0-beta.3
25491 * @author Bartosz Wojciechowski
25492 * @license The MIT License (MIT)
25493 */
25494;(function($, window, document, undefined) {
25495
25496	/**
25497	 * Creates the video plugin.
25498	 * @class The Video Plugin
25499	 * @param {Owl} carousel - The Owl Carousel
25500	 */
25501	var Video = function(carousel) {
25502		/**
25503		 * Reference to the core.
25504		 * @protected
25505		 * @type {Owl}
25506		 */
25507		this._core = carousel;
25508
25509		/**
25510		 * Cache all video URLs.
25511		 * @protected
25512		 * @type {Object}
25513		 */
25514		this._videos = {};
25515
25516		/**
25517		 * Current playing item.
25518		 * @protected
25519		 * @type {jQuery}
25520		 */
25521		this._playing = null;
25522
25523		/**
25524		 * All event handlers.
25525		 * @todo The cloned content removale is too late
25526		 * @protected
25527		 * @type {Object}
25528		 */
25529		this._handlers = {
25530			'initialized.owl.carousel': $.proxy(function(e) {
25531				if (e.namespace) {
25532					this._core.register({ type: 'state', name: 'playing', tags: [ 'interacting' ] });
25533				}
25534			}, this),
25535			'resize.owl.carousel': $.proxy(function(e) {
25536				if (e.namespace && this._core.settings.video && this.isInFullScreen()) {
25537					e.preventDefault();
25538				}
25539			}, this),
25540			'refreshed.owl.carousel': $.proxy(function(e) {
25541				if (e.namespace && this._core.is('resizing')) {
25542					this._core.$stage.find('.cloned .owl-video-frame').remove();
25543				}
25544			}, this),
25545			'changed.owl.carousel': $.proxy(function(e) {
25546				if (e.namespace && e.property.name === 'position' && this._playing) {
25547					this.stop();
25548				}
25549			}, this),
25550			'prepared.owl.carousel': $.proxy(function(e) {
25551				if (!e.namespace) {
25552					return;
25553				}
25554
25555				var $element = $(e.content).find('.owl-video');
25556
25557				if ($element.length) {
25558					$element.css('display', 'none');
25559					this.fetch($element, $(e.content));
25560				}
25561			}, this)
25562		};
25563
25564		// set default options
25565		this._core.options = $.extend({}, Video.Defaults, this._core.options);
25566
25567		// register event handlers
25568		this._core.$element.on(this._handlers);
25569
25570		this._core.$element.on('click.owl.video', '.owl-video-play-icon', $.proxy(function(e) {
25571			this.play(e);
25572		}, this));
25573	};
25574
25575	/**
25576	 * Default options.
25577	 * @public
25578	 */
25579	Video.Defaults = {
25580		video: false,
25581		videoHeight: false,
25582		videoWidth: false
25583	};
25584
25585	/**
25586	 * Gets the video ID and the type (YouTube/Vimeo only).
25587	 * @protected
25588	 * @param {jQuery} target - The target containing the video data.
25589	 * @param {jQuery} item - The item containing the video.
25590	 */
25591	Video.prototype.fetch = function(target, item) {
25592		var type = target.attr('data-vimeo-id') ? 'vimeo' : 'youtube',
25593			id = target.attr('data-vimeo-id') || target.attr('data-youtube-id'),
25594			width = target.attr('data-width') || this._core.settings.videoWidth,
25595			height = target.attr('data-height') || this._core.settings.videoHeight,
25596			url = target.attr('href');
25597
25598		if (url) {
25599			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+)?/);
25600
25601			if (id[3].indexOf('youtu') > -1) {
25602				type = 'youtube';
25603			} else if (id[3].indexOf('vimeo') > -1) {
25604				type = 'vimeo';
25605			} else {
25606				throw new Error('Video URL not supported.');
25607			}
25608			id = id[6];
25609		} else {
25610			throw new Error('Missing video URL.');
25611		}
25612
25613		this._videos[url] = {
25614			type: type,
25615			id: id,
25616			width: width,
25617			height: height
25618		};
25619
25620		item.attr('data-video', url);
25621
25622		this.thumbnail(target, this._videos[url]);
25623	};
25624
25625	/**
25626	 * Creates video thumbnail.
25627	 * @protected
25628	 * @param {jQuery} target - The target containing the video data.
25629	 * @param {Object} info - The video info object.
25630	 * @see `fetch`
25631	 */
25632	Video.prototype.thumbnail = function(target, video) {
25633		var tnLink,
25634			icon,
25635			path,
25636			dimensions = video.width && video.height ? 'style="width:' + video.width + 'px;height:' + video.height + 'px;"' : '',
25637			customTn = target.find('img'),
25638			srcType = 'src',
25639			lazyClass = '',
25640			settings = this._core.settings,
25641			create = function(path) {
25642				icon = '<div class="owl-video-play-icon"></div>';
25643
25644				if (settings.lazyLoad) {
25645					tnLink = '<div class="owl-video-tn ' + lazyClass + '" ' + srcType + '="' + path + '"></div>';
25646				} else {
25647					tnLink = '<div class="owl-video-tn" style="opacity:1;background-image:url(' + path + ')"></div>';
25648				}
25649				target.after(tnLink);
25650				target.after(icon);
25651			};
25652
25653		// wrap video content into owl-video-wrapper div
25654		target.wrap('<div class="owl-video-wrapper"' + dimensions + '></div>');
25655
25656		if (this._core.settings.lazyLoad) {
25657			srcType = 'data-src';
25658			lazyClass = 'owl-lazy';
25659		}
25660
25661		// custom thumbnail
25662		if (customTn.length) {
25663			create(customTn.attr(srcType));
25664			customTn.remove();
25665			return false;
25666		}
25667
25668		if (video.type === 'youtube') {
25669			path = "//img.youtube.com/vi/" + video.id + "/hqdefault.jpg";
25670			create(path);
25671		} else if (video.type === 'vimeo') {
25672			$.ajax({
25673				type: 'GET',
25674				url: '//vimeo.com/api/v2/video/' + video.id + '.json',
25675				jsonp: 'callback',
25676				dataType: 'jsonp',
25677				success: function(data) {
25678					path = data[0].thumbnail_large;
25679					create(path);
25680				}
25681			});
25682		}
25683	};
25684
25685	/**
25686	 * Stops the current video.
25687	 * @public
25688	 */
25689	Video.prototype.stop = function() {
25690		this._core.trigger('stop', null, 'video');
25691		this._playing.find('.owl-video-frame').remove();
25692		this._playing.removeClass('owl-video-playing');
25693		this._playing = null;
25694		this._core.leave('playing');
25695		this._core.trigger('stopped', null, 'video');
25696	};
25697
25698	/**
25699	 * Starts the current video.
25700	 * @public
25701	 * @param {Event} event - The event arguments.
25702	 */
25703	Video.prototype.play = function(event) {
25704		var target = $(event.target),
25705			item = target.closest('.' + this._core.settings.itemClass),
25706			video = this._videos[item.attr('data-video')],
25707			width = video.width || '100%',
25708			height = video.height || this._core.$stage.height(),
25709			html;
25710
25711		if (this._playing) {
25712			return;
25713		}
25714
25715		this._core.enter('playing');
25716		this._core.trigger('play', null, 'video');
25717
25718		item = this._core.items(this._core.relative(item.index()));
25719
25720		this._core.reset(item.index());
25721
25722		if (video.type === 'youtube') {
25723			html = '<iframe width="' + width + '" height="' + height + '" src="//www.youtube.com/embed/' +
25724				video.id + '?autoplay=1&v=' + video.id + '" frameborder="0" allowfullscreen></iframe>';
25725		} else if (video.type === 'vimeo') {
25726			html = '<iframe src="//player.vimeo.com/video/' + video.id +
25727				'?autoplay=1" width="' + width + '" height="' + height +
25728				'" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>';
25729		}
25730
25731		$('<div class="owl-video-frame">' + html + '</div>').insertAfter(item.find('.owl-video'));
25732
25733		this._playing = item.addClass('owl-video-playing');
25734	};
25735
25736	/**
25737	 * Checks whether an video is currently in full screen mode or not.
25738	 * @todo Bad style because looks like a readonly method but changes members.
25739	 * @protected
25740	 * @returns {Boolean}
25741	 */
25742	Video.prototype.isInFullScreen = function() {
25743		var element = document.fullscreenElement || document.mozFullScreenElement ||
25744				document.webkitFullscreenElement;
25745
25746		return element && $(element).parent().hasClass('owl-video-frame');
25747	};
25748
25749	/**
25750	 * Destroys the plugin.
25751	 */
25752	Video.prototype.destroy = function() {
25753		var handler, property;
25754
25755		this._core.$element.off('click.owl.video');
25756
25757		for (handler in this._handlers) {
25758			this._core.$element.off(handler, this._handlers[handler]);
25759		}
25760		for (property in Object.getOwnPropertyNames(this)) {
25761			typeof this[property] != 'function' && (this[property] = null);
25762		}
25763	};
25764
25765	$.fn.owlCarousel.Constructor.Plugins.Video = Video;
25766
25767})(window.Zepto || window.jQuery, window, document);
25768
25769/**
25770 * Animate Plugin
25771 * @version 2.0.0-beta.3
25772 * @author Bartosz Wojciechowski
25773 * @license The MIT License (MIT)
25774 */
25775;(function($, window, document, undefined) {
25776
25777	/**
25778	 * Creates the animate plugin.
25779	 * @class The Navigation Plugin
25780	 * @param {Owl} scope - The Owl Carousel
25781	 */
25782	var Animate = function(scope) {
25783		this.core = scope;
25784		this.core.options = $.extend({}, Animate.Defaults, this.core.options);
25785		this.swapping = true;
25786		this.previous = undefined;
25787		this.next = undefined;
25788
25789		this.handlers = {
25790			'change.owl.carousel': $.proxy(function(e) {
25791				if (e.namespace && e.property.name == 'position') {
25792					this.previous = this.core.current();
25793					this.next = e.property.value;
25794				}
25795			}, this),
25796			'drag.owl.carousel dragged.owl.carousel translated.owl.carousel': $.proxy(function(e) {
25797				if (e.namespace) {
25798					this.swapping = e.type == 'translated';
25799				}
25800			}, this),
25801			'translate.owl.carousel': $.proxy(function(e) {
25802				if (e.namespace && this.swapping && (this.core.options.animateOut || this.core.options.animateIn)) {
25803					this.swap();
25804				}
25805			}, this)
25806		};
25807
25808		this.core.$element.on(this.handlers);
25809	};
25810
25811	/**
25812	 * Default options.
25813	 * @public
25814	 */
25815	Animate.Defaults = {
25816		animateOut: false,
25817		animateIn: false
25818	};
25819
25820	/**
25821	 * Toggles the animation classes whenever an translations starts.
25822	 * @protected
25823	 * @returns {Boolean|undefined}
25824	 */
25825	Animate.prototype.swap = function() {
25826
25827		if (this.core.settings.items !== 1) {
25828			return;
25829		}
25830
25831		if (!$.support.animation || !$.support.transition) {
25832			return;
25833		}
25834
25835		this.core.speed(0);
25836
25837		var left,
25838			clear = $.proxy(this.clear, this),
25839			previous = this.core.$stage.children().eq(this.previous),
25840			next = this.core.$stage.children().eq(this.next),
25841			incoming = this.core.settings.animateIn,
25842			outgoing = this.core.settings.animateOut;
25843
25844		if (this.core.current() === this.previous) {
25845			return;
25846		}
25847
25848		if (outgoing) {
25849			left = this.core.coordinates(this.previous) - this.core.coordinates(this.next);
25850			previous.css( { 'left': left + 'px' } )
25851				.addClass('animated owl-animated-out')
25852				.addClass(outgoing)
25853				.on($.support.animation.end, clear);
25854		}
25855
25856		if (incoming) {
25857			next.addClass('animated owl-animated-in')
25858				.addClass(incoming)
25859				.on($.support.animation.end, clear);
25860		}
25861	};
25862
25863	Animate.prototype.clear = function(e) {
25864		if ($(e.target).hasClass('animated')) {
25865			$(e.target).css( { 'left': '' } )
25866				.removeClass('animated owl-animated-out owl-animated-in')
25867				.removeClass(this.core.settings.animateIn)
25868				.removeClass(this.core.settings.animateOut);
25869			this.core.onTransitionEnd();
25870		}
25871	};
25872
25873	/**
25874	 * Destroys the plugin.
25875	 * @public
25876	 */
25877	Animate.prototype.destroy = function() {
25878		var handler, property;
25879
25880		for (handler in this.handlers) {
25881			this.core.$element.off(handler, this.handlers[handler]);
25882		}
25883		for (property in Object.getOwnPropertyNames(this)) {
25884			typeof this[property] != 'function' && (this[property] = null);
25885		}
25886	};
25887
25888	$.fn.owlCarousel.Constructor.Plugins.Animate = Animate;
25889
25890})(window.Zepto || window.jQuery, window, document);
25891
25892/**
25893 * Autoplay Plugin
25894 * @version 2.0.0-beta.3
25895 * @author Bartosz Wojciechowski
25896 * @author Artus Kolanowski
25897 * @license The MIT License (MIT)
25898 */
25899;(function($, window, document, undefined) {
25900
25901	/**
25902	 * Creates the autoplay plugin.
25903	 * @class The Autoplay Plugin
25904	 * @param {Owl} scope - The Owl Carousel
25905	 */
25906	var Autoplay = function(carousel) {
25907		/**
25908		 * Reference to the core.
25909		 * @protected
25910		 * @type {Owl}
25911		 */
25912		this._core = carousel;
25913
25914		/**
25915		 * The autoplay interval.
25916		 * @type {Number}
25917		 */
25918		this._interval = null;
25919
25920		/**
25921		 * Indicates whenever the autoplay is paused.
25922		 * @type {Boolean}
25923		 */
25924		this._paused = false;
25925
25926		/**
25927		 * All event handlers.
25928		 * @protected
25929		 * @type {Object}
25930		 */
25931		this._handlers = {
25932			'changed.owl.carousel': $.proxy(function(e) {
25933				if (e.namespace && e.property.name === 'settings') {
25934					if (this._core.settings.autoplay) {
25935						this.play();
25936					} else {
25937						this.stop();
25938					}
25939				}
25940			}, this),
25941			'initialized.owl.carousel': $.proxy(function(e) {
25942				if (e.namespace && this._core.settings.autoplay) {
25943					this.play();
25944				}
25945			}, this),
25946			'play.owl.autoplay': $.proxy(function(e, t, s) {
25947				if (e.namespace) {
25948					this.play(t, s);
25949				}
25950			}, this),
25951			'stop.owl.autoplay': $.proxy(function(e) {
25952				if (e.namespace) {
25953					this.stop();
25954				}
25955			}, this),
25956			'mouseover.owl.autoplay': $.proxy(function() {
25957				if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
25958					this.pause();
25959				}
25960			}, this),
25961			'mouseleave.owl.autoplay': $.proxy(function() {
25962				if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
25963					this.play();
25964				}
25965			}, this)
25966		};
25967
25968		// register event handlers
25969		this._core.$element.on(this._handlers);
25970
25971		// set default options
25972		this._core.options = $.extend({}, Autoplay.Defaults, this._core.options);
25973	};
25974
25975	/**
25976	 * Default options.
25977	 * @public
25978	 */
25979	Autoplay.Defaults = {
25980		autoplay: false,
25981		autoplayTimeout: 5000,
25982		autoplayHoverPause: false,
25983		autoplaySpeed: false
25984	};
25985
25986	/**
25987	 * Starts the autoplay.
25988	 * @public
25989	 * @param {Number} [timeout] - The interval before the next animation starts.
25990	 * @param {Number} [speed] - The animation speed for the animations.
25991	 */
25992	Autoplay.prototype.play = function(timeout, speed) {
25993		this._paused = false;
25994
25995		if (this._core.is('rotating')) {
25996			return;
25997		}
25998
25999		this._core.enter('rotating');
26000
26001		this._interval = window.setInterval($.proxy(function() {
26002			if (this._paused || this._core.is('busy') || this._core.is('interacting') || document.hidden) {
26003				return;
26004			}
26005			this._core.next(speed || this._core.settings.autoplaySpeed);
26006		}, this), timeout || this._core.settings.autoplayTimeout);
26007	};
26008
26009	/**
26010	 * Stops the autoplay.
26011	 * @public
26012	 */
26013	Autoplay.prototype.stop = function() {
26014		if (!this._core.is('rotating')) {
26015			return;
26016		}
26017
26018		window.clearInterval(this._interval);
26019		this._core.leave('rotating');
26020	};
26021
26022	/**
26023	 * Stops the autoplay.
26024	 * @public
26025	 */
26026	Autoplay.prototype.pause = function() {
26027		if (!this._core.is('rotating')) {
26028			return;
26029		}
26030
26031		this._paused = true;
26032	};
26033
26034	/**
26035	 * Destroys the plugin.
26036	 */
26037	Autoplay.prototype.destroy = function() {
26038		var handler, property;
26039
26040		this.stop();
26041
26042		for (handler in this._handlers) {
26043			this._core.$element.off(handler, this._handlers[handler]);
26044		}
26045		for (property in Object.getOwnPropertyNames(this)) {
26046			typeof this[property] != 'function' && (this[property] = null);
26047		}
26048	};
26049
26050	$.fn.owlCarousel.Constructor.Plugins.autoplay = Autoplay;
26051
26052})(window.Zepto || window.jQuery, window, document);
26053
26054/**
26055 * Navigation Plugin
26056 * @version 2.0.0-beta.3
26057 * @author Artus Kolanowski
26058 * @license The MIT License (MIT)
26059 */
26060;(function($, window, document, undefined) {
26061	'use strict';
26062
26063	/**
26064	 * Creates the navigation plugin.
26065	 * @class The Navigation Plugin
26066	 * @param {Owl} carousel - The Owl Carousel.
26067	 */
26068	var Navigation = function(carousel) {
26069		/**
26070		 * Reference to the core.
26071		 * @protected
26072		 * @type {Owl}
26073		 */
26074		this._core = carousel;
26075
26076		/**
26077		 * Indicates whether the plugin is initialized or not.
26078		 * @protected
26079		 * @type {Boolean}
26080		 */
26081		this._initialized = false;
26082
26083		/**
26084		 * The current paging indexes.
26085		 * @protected
26086		 * @type {Array}
26087		 */
26088		this._pages = [];
26089
26090		/**
26091		 * All DOM elements of the user interface.
26092		 * @protected
26093		 * @type {Object}
26094		 */
26095		this._controls = {};
26096
26097		/**
26098		 * Markup for an indicator.
26099		 * @protected
26100		 * @type {Array.<String>}
26101		 */
26102		this._templates = [];
26103
26104		/**
26105		 * The carousel element.
26106		 * @type {jQuery}
26107		 */
26108		this.$element = this._core.$element;
26109
26110		/**
26111		 * Overridden methods of the carousel.
26112		 * @protected
26113		 * @type {Object}
26114		 */
26115		this._overrides = {
26116			next: this._core.next,
26117			prev: this._core.prev,
26118			to: this._core.to
26119		};
26120
26121		/**
26122		 * All event handlers.
26123		 * @protected
26124		 * @type {Object}
26125		 */
26126		this._handlers = {
26127			'prepared.owl.carousel': $.proxy(function(e) {
26128				if (e.namespace && this._core.settings.dotsData) {
26129					this._templates.push('<div class="' + this._core.settings.dotClass + '">' +
26130						$(e.content).find('[data-dot]').andSelf('[data-dot]').attr('data-dot') + '</div>');
26131				}
26132			}, this),
26133			'added.owl.carousel': $.proxy(function(e) {
26134				if (e.namespace && this._core.settings.dotsData) {
26135					this._templates.splice(e.position, 0, this._templates.pop());
26136				}
26137			}, this),
26138			'remove.owl.carousel': $.proxy(function(e) {
26139				if (e.namespace && this._core.settings.dotsData) {
26140					this._templates.splice(e.position, 1);
26141				}
26142			}, this),
26143			'changed.owl.carousel': $.proxy(function(e) {
26144				if (e.namespace && e.property.name == 'position') {
26145					this.draw();
26146				}
26147			}, this),
26148			'initialized.owl.carousel': $.proxy(function(e) {
26149				if (e.namespace && !this._initialized) {
26150					this._core.trigger('initialize', null, 'navigation');
26151					this.initialize();
26152					this.update();
26153					this.draw();
26154					this._initialized = true;
26155					this._core.trigger('initialized', null, 'navigation');
26156				}
26157			}, this),
26158			'refreshed.owl.carousel': $.proxy(function(e) {
26159				if (e.namespace && this._initialized) {
26160					this._core.trigger('refresh', null, 'navigation');
26161					this.update();
26162					this.draw();
26163					this._core.trigger('refreshed', null, 'navigation');
26164				}
26165			}, this)
26166		};
26167
26168		// set default options
26169		this._core.options = $.extend({}, Navigation.Defaults, this._core.options);
26170
26171		// register event handlers
26172		this.$element.on(this._handlers);
26173	};
26174
26175	/**
26176	 * Default options.
26177	 * @public
26178	 * @todo Rename `slideBy` to `navBy`
26179	 */
26180	Navigation.Defaults = {
26181		nav: false,
26182		navText: [ 'prev', 'next' ],
26183		navSpeed: false,
26184		navElement: 'div',
26185		navContainer: false,
26186		navContainerClass: 'owl-nav',
26187		navClass: [ 'owl-prev', 'owl-next' ],
26188		slideBy: 1,
26189		dotClass: 'owl-dot',
26190		dotsClass: 'owl-dots',
26191		dots: true,
26192		dotsEach: false,
26193		dotsData: false,
26194		dotsSpeed: false,
26195		dotsContainer: false
26196	};
26197
26198	/**
26199	 * Initializes the layout of the plugin and extends the carousel.
26200	 * @protected
26201	 */
26202	Navigation.prototype.initialize = function() {
26203		var override,
26204			settings = this._core.settings;
26205
26206		// create DOM structure for relative navigation
26207		this._controls.$relative = (settings.navContainer ? $(settings.navContainer)
26208			: $('<div>').addClass(settings.navContainerClass).appendTo(this.$element)).addClass('disabled');
26209
26210		this._controls.$previous = $('<' + settings.navElement + '>')
26211			.addClass(settings.navClass[0])
26212			.html(settings.navText[0])
26213			.prependTo(this._controls.$relative)
26214			.on('click', $.proxy(function(e) {
26215				this.prev(settings.navSpeed);
26216			}, this));
26217		this._controls.$next = $('<' + settings.navElement + '>')
26218			.addClass(settings.navClass[1])
26219			.html(settings.navText[1])
26220			.appendTo(this._controls.$relative)
26221			.on('click', $.proxy(function(e) {
26222				this.next(settings.navSpeed);
26223			}, this));
26224
26225		// create DOM structure for absolute navigation
26226		if (!settings.dotsData) {
26227			this._templates = [ $('<div>')
26228				.addClass(settings.dotClass)
26229				.append($('<span>'))
26230				.prop('outerHTML') ];
26231		}
26232
26233		this._controls.$absolute = (settings.dotsContainer ? $(settings.dotsContainer)
26234			: $('<div>').addClass(settings.dotsClass).appendTo(this.$element)).addClass('disabled');
26235
26236		this._controls.$absolute.on('click', 'div', $.proxy(function(e) {
26237			var index = $(e.target).parent().is(this._controls.$absolute)
26238				? $(e.target).index() : $(e.target).parent().index();
26239
26240			e.preventDefault();
26241
26242			this.to(index, settings.dotsSpeed);
26243		}, this));
26244
26245		// override public methods of the carousel
26246		for (override in this._overrides) {
26247			this._core[override] = $.proxy(this[override], this);
26248		}
26249	};
26250
26251	/**
26252	 * Destroys the plugin.
26253	 * @protected
26254	 */
26255	Navigation.prototype.destroy = function() {
26256		var handler, control, property, override;
26257
26258		for (handler in this._handlers) {
26259			this.$element.off(handler, this._handlers[handler]);
26260		}
26261		for (control in this._controls) {
26262			this._controls[control].remove();
26263		}
26264		for (override in this.overides) {
26265			this._core[override] = this._overrides[override];
26266		}
26267		for (property in Object.getOwnPropertyNames(this)) {
26268			typeof this[property] != 'function' && (this[property] = null);
26269		}
26270	};
26271
26272	/**
26273	 * Updates the internal state.
26274	 * @protected
26275	 */
26276	Navigation.prototype.update = function() {
26277		var i, j, k,
26278			lower = this._core.clones().length / 2,
26279			upper = lower + this._core.items().length,
26280			maximum = this._core.maximum(true),
26281			settings = this._core.settings,
26282			size = settings.center || settings.autoWidth || settings.dotsData
26283				? 1 : settings.dotsEach || settings.items;
26284
26285		if (settings.slideBy !== 'page') {
26286			settings.slideBy = Math.min(settings.slideBy, settings.items);
26287		}
26288
26289		if (settings.dots || settings.slideBy == 'page') {
26290			this._pages = [];
26291
26292			for (i = lower, j = 0, k = 0; i < upper; i++) {
26293				if (j >= size || j === 0) {
26294					this._pages.push({
26295						start: Math.min(maximum, i - lower),
26296						end: i - lower + size - 1
26297					});
26298					if (Math.min(maximum, i - lower) === maximum) {
26299						break;
26300					}
26301					j = 0, ++k;
26302				}
26303				j += this._core.mergers(this._core.relative(i));
26304			}
26305		}
26306	};
26307
26308	/**
26309	 * Draws the user interface.
26310	 * @todo The option `dotsData` wont work.
26311	 * @protected
26312	 */
26313	Navigation.prototype.draw = function() {
26314		var difference,
26315			settings = this._core.settings,
26316			disabled = this._core.items().length <= settings.items,
26317			index = this._core.relative(this._core.current()),
26318			loop = settings.loop || settings.rewind;
26319
26320		this._controls.$relative.toggleClass('disabled', !settings.nav || disabled);
26321
26322		if (settings.nav) {
26323			this._controls.$previous.toggleClass('disabled', !loop && index <= this._core.minimum(true));
26324			this._controls.$next.toggleClass('disabled', !loop && index >= this._core.maximum(true));
26325		}
26326
26327		this._controls.$absolute.toggleClass('disabled', !settings.dots || disabled);
26328
26329		if (settings.dots) {
26330			difference = this._pages.length - this._controls.$absolute.children().length;
26331
26332			if (settings.dotsData && difference !== 0) {
26333				this._controls.$absolute.html(this._templates.join(''));
26334			} else if (difference > 0) {
26335				this._controls.$absolute.append(new Array(difference + 1).join(this._templates[0]));
26336			} else if (difference < 0) {
26337				this._controls.$absolute.children().slice(difference).remove();
26338			}
26339
26340			this._controls.$absolute.find('.active').removeClass('active');
26341			this._controls.$absolute.children().eq($.inArray(this.current(), this._pages)).addClass('active');
26342		}
26343	};
26344
26345	/**
26346	 * Extends event data.
26347	 * @protected
26348	 * @param {Event} event - The event object which gets thrown.
26349	 */
26350	Navigation.prototype.onTrigger = function(event) {
26351		var settings = this._core.settings;
26352
26353		event.page = {
26354			index: $.inArray(this.current(), this._pages),
26355			count: this._pages.length,
26356			size: settings && (settings.center || settings.autoWidth || settings.dotsData
26357				? 1 : settings.dotsEach || settings.items)
26358		};
26359	};
26360
26361	/**
26362	 * Gets the current page position of the carousel.
26363	 * @protected
26364	 * @returns {Number}
26365	 */
26366	Navigation.prototype.current = function() {
26367		var current = this._core.relative(this._core.current());
26368		return $.grep(this._pages, $.proxy(function(page, index) {
26369			return page.start <= current && page.end >= current;
26370		}, this)).pop();
26371	};
26372
26373	/**
26374	 * Gets the current succesor/predecessor position.
26375	 * @protected
26376	 * @returns {Number}
26377	 */
26378	Navigation.prototype.getPosition = function(successor) {
26379		var position, length,
26380			settings = this._core.settings;
26381
26382		if (settings.slideBy == 'page') {
26383			position = $.inArray(this.current(), this._pages);
26384			length = this._pages.length;
26385			successor ? ++position : --position;
vendor: 5,674 bytes, lines 26386-26610
26386			position = this._pages[((position % length) + length) % length].start;
26387		} else {
26388			position = this._core.relative(this._core.current());
26389			length = this._core.items().length;
26390			successor ? position += settings.slideBy : position -= settings.slideBy;
26391		}
26392
26393		return position;
26394	};
26395
26396	/**
26397	 * Slides to the next item or page.
26398	 * @public
26399	 * @param {Number} [speed=false] - The time in milliseconds for the transition.
26400	 */
26401	Navigation.prototype.next = function(speed) {
26402		$.proxy(this._overrides.to, this._core)(this.getPosition(true), speed);
26403	};
26404
26405	/**
26406	 * Slides to the previous item or page.
26407	 * @public
26408	 * @param {Number} [speed=false] - The time in milliseconds for the transition.
26409	 */
26410	Navigation.prototype.prev = function(speed) {
26411		$.proxy(this._overrides.to, this._core)(this.getPosition(false), speed);
26412	};
26413
26414	/**
26415	 * Slides to the specified item or page.
26416	 * @public
26417	 * @param {Number} position - The position of the item or page.
26418	 * @param {Number} [speed] - The time in milliseconds for the transition.
26419	 * @param {Boolean} [standard=false] - Whether to use the standard behaviour or not.
26420	 */
26421	Navigation.prototype.to = function(position, speed, standard) {
26422		var length;
26423
26424		if (!standard) {
26425			length = this._pages.length;
26426			$.proxy(this._overrides.to, this._core)(this._pages[((position % length) + length) % length].start, speed);
26427		} else {
26428			$.proxy(this._overrides.to, this._core)(position, speed);
26429		}
26430	};
26431
26432	$.fn.owlCarousel.Constructor.Plugins.Navigation = Navigation;
26433
26434})(window.Zepto || window.jQuery, window, document);
26435
26436/**
26437 * Hash Plugin
26438 * @version 2.0.0-beta.3
26439 * @author Artus Kolanowski
26440 * @license The MIT License (MIT)
26441 */
26442;(function($, window, document, undefined) {
26443	'use strict';
26444
26445	/**
26446	 * Creates the hash plugin.
26447	 * @class The Hash Plugin
26448	 * @param {Owl} carousel - The Owl Carousel
26449	 */
26450	var Hash = function(carousel) {
26451		/**
26452		 * Reference to the core.
26453		 * @protected
26454		 * @type {Owl}
26455		 */
26456		this._core = carousel;
26457
26458		/**
26459		 * Hash index for the items.
26460		 * @protected
26461		 * @type {Object}
26462		 */
26463		this._hashes = {};
26464
26465		/**
26466		 * The carousel element.
26467		 * @type {jQuery}
26468		 */
26469		this.$element = this._core.$element;
26470
26471		/**
26472		 * All event handlers.
26473		 * @protected
26474		 * @type {Object}
26475		 */
26476		this._handlers = {
26477			'initialized.owl.carousel': $.proxy(function(e) {
26478				if (e.namespace && this._core.settings.startPosition === 'URLHash') {
26479					$(window).trigger('hashchange.owl.navigation');
26480				}
26481			}, this),
26482			'prepared.owl.carousel': $.proxy(function(e) {
26483				if (e.namespace) {
26484					var hash = $(e.content).find('[data-hash]').addBack('[data-hash]').attr('data-hash');
26485
26486					if (!hash) {
26487						return;
26488					}
26489
26490					this._hashes[hash] = e.content;
26491				}
26492			}, this),
26493			'changed.owl.carousel': $.proxy(function(e) {
26494				if (e.namespace && e.property.name === 'position') {
26495					var current = this._core.items(this._core.relative(this._core.current())),
26496						hash = $.map(this._hashes, function(item, hash) {
26497							return item === current ? hash : null;
26498						}).join();
26499
26500					if (!hash || window.location.hash.slice(1) === hash) {
26501						return;
26502					}
26503
26504					window.location.hash = hash;
26505				}
26506			}, this)
26507		};
26508
26509		// set default options
26510		this._core.options = $.extend({}, Hash.Defaults, this._core.options);
26511
26512		// register the event handlers
26513		this.$element.on(this._handlers);
26514
26515		// register event listener for hash navigation
26516		/*$(window).on('hashchange.owl.navigation', $.proxy(function(e) {
26517			var hash = window.location.hash.substring(1),
26518				items = this._core.$stage.children(),
26519				position = this._hashes[hash] && items.index(this._hashes[hash]);
26520
26521			if (position === undefined || position === this._core.current()) {
26522				return;
26523			}
26524
26525			this._core.to(this._core.relative(position), false, true);
26526		}, this));*/
26527	};
26528
26529	/**
26530	 * Default options.
26531	 * @public
26532	 */
26533	Hash.Defaults = {
26534		URLhashListener: false
26535	};
26536
26537	/**
26538	 * Destroys the plugin.
26539	 * @public
26540	 */
26541	Hash.prototype.destroy = function() {
26542		var handler, property;
26543
26544		$(window).off('hashchange.owl.navigation');
26545
26546		for (handler in this._handlers) {
26547			this._core.$element.off(handler, this._handlers[handler]);
26548		}
26549		for (property in Object.getOwnPropertyNames(this)) {
26550			typeof this[property] != 'function' && (this[property] = null);
26551		}
26552	};
26553
26554	$.fn.owlCarousel.Constructor.Plugins.Hash = Hash;
26555
26556})(window.Zepto || window.jQuery, window, document);
26557
26558/**
26559 * Support Plugin
26560 *
26561 * @version 2.0.0-beta.3
26562 * @author Vivid Planet Software GmbH
26563 * @author Artus Kolanowski
26564 * @license The MIT License (MIT)
26565 */
26566;(function($, window, document, undefined) {
26567
26568	var style = $('<support>').get(0).style,
26569		prefixes = 'Webkit Moz O ms'.split(' '),
26570		events = {
26571			transition: {
26572				end: {
26573					WebkitTransition: 'webkitTransitionEnd',
26574					MozTransition: 'transitionend',
26575					OTransition: 'oTransitionEnd',
26576					transition: 'transitionend'
26577				}
26578			},
26579			animation: {
26580				end: {
26581					WebkitAnimation: 'webkitAnimationEnd',
26582					MozAnimation: 'animationend',
26583					OAnimation: 'oAnimationEnd',
26584					animation: 'animationend'
26585				}
26586			}
26587		},
26588		tests = {
26589			csstransforms: function() {
26590				return !!test('transform');
26591			},
26592			csstransforms3d: function() {
26593				return !!test('perspective');
26594			},
26595			csstransitions: function() {
26596				return !!test('transition');
26597			},
26598			cssanimations: function() {
26599				return !!test('animation');
26600			}
26601		};
26602
26603	function test(property, prefixed) {
26604		var result = false,
26605			upper = property.charAt(0).toUpperCase() + property.slice(1);
26606
26607		$.each((property + ' ' + prefixes.join(upper + ' ') + upper).split(' '), function(i, property) {
26608			if (style[property] !== undefined) {
26609				result = prefixed ? property : true;
26610				return false;
26611			}
26612		});
26613
26614		return result;
26615	}
26616
26617	function prefixed(property) {
26618		return test(property, true);
26619	}
26620
26621	if (tests.csstransitions()) {
26622		/* jshint -W053 */
26623		$.support.transition = new String(prefixed('transition'))
26624		$.support.transition.end = events.transition.end[ $.support.transition ];
26625	}
26626
26627	if (tests.cssanimations()) {
26628		/* jshint -W053 */
26629		$.support.animation = new String(prefixed('animation'))
26630		$.support.animation.end = events.animation.end[ $.support.animation ];
26631	}
26632
26633	if (tests.csstransforms()) {
26634		/* jshint -W053 */
26635		$.support.transform = new String(prefixed('transform'));
26636		$.support.transform3d = tests.csstransforms3d();
26637	}
26638
26639})(window.Zepto || window.jQuery, window, document);
26640
26641(function(window, document, undefined) {
26642
26643	/**
26644	 * Find the absolute position of an element
26645	 */
26646	var absPos = function(element) {
26647		var offsetLeft, offsetTop;
26648		offsetLeft = offsetTop = 0;
26649		if (element.offsetParent) {
26650			do {
26651				offsetLeft += element.offsetLeft;
26652				offsetTop += element.offsetTop;
26653			} while (element = element.offsetParent);
26654		}
26655		return [offsetLeft, offsetTop];
26656	};
26657
26658	/**
26659	 * @constructor Progress Circle class
26660	 * @param params.canvas Canvas on which the circles will be drawn.
26661	 * @param params.minRadius Inner radius of the innermost circle, in px.
26662	 * @param params.arcWidth Width of each circle(to be more accurate, ring).
26663	 * @param params.gapWidth Space between each circle.
26664	 * @param params.centerX X coordinate of the center of circles.
26665	 * @param params.centerY Y coordinate of the center of circles.
26666	 * @param params.infoLineBaseAngle Base angle of the info line.
26667	 * @param params.infoLineAngleInterval Angles between the info lines.
26668	 */
26669	var ProgressCircle = function(params) {
26670		this.canvas = params.canvas;
26671		this.minRadius = params.minRadius || 15;
26672		this.arcWidth = params.arcWidth || 5;
26673		this.gapWidth = params.gapWidth || 3;
26674		this.centerX = params.centerX || this.canvas.width / 2;
26675		this.centerY = params.centerY || this.canvas.height / 2;
26676		this.infoLineLength = params.infoLineLength || 60;
26677		this.horizLineLength = params.horizLineLength || 10;
26678		this.infoLineAngleInterval = params.infoLineAngleInterval || Math.PI / 8;
26679		this.infoLineBaseAngle = params.infoLineBaseAngle || Math.PI / 6;
26680
26681		this.context = this.canvas.getContext('2d');
26682
26683		this.width = this.canvas.width;
26684		this.height = this.canvas.height;
26685
26686		this.circles = [];
26687		this.runningCount = 0;
26688	};
26689
26690	ProgressCircle.prototype = {
26691		constructor: ProgressCircle,
26692
26693		/**
26694		 * @method Adds an progress monitor entry.
26695		 * @param params.fillColor Color to fill in the circle.
26696		 * @param params.outlineColor Color to outline the circle.
26697		 * @param params.progressListener Callback function to fetch the progress.
26698		 * @param params.infoListener Callback function to fetch the info.
26699		 * @returns this
26700		 */
26701		addEntry: function(params) {
26702			this.circles.push(new Circle({
26703				canvas: this.canvas,
26704				context: this.context,
26705				centerX: this.centerX,
26706				centerY: this.centerY,
26707				innerRadius: this.minRadius + this.circles.length *
26708					(this.gapWidth + this.arcWidth),
26709				arcWidth: this.arcWidth,
26710				infoLineLength: this.infoLineLength,
26711				horizLineLength: this.horizLineLength,
26712
26713				id: this.circles.length,
26714				fillColor: params.fillColor,
26715				outlineColor: params.outlineColor,
26716				progressListener: params.progressListener,
26717				infoListener: params.infoListener,
26718				infoLineAngle: this.infoLineBaseAngle +
26719					this.circles.length * this.infoLineAngleInterval,
26720			}));
26721
26722			return this;
26723		},
26724
26725		/**
26726		 * @method Starts the monitor and updates with the given interval.
26727		 * @param interval Interval between updates, in millisecond.
26728		 * @returns this
26729		 */
26730		start: function(interval) {
26731			var self = this;
26732			this.timer = setInterval(function() {
26733				self._update();
26734			}, interval || 33);
26735
26736			return this;
26737		},
26738
26739		/**
26740		 * @method Stop the animation.
26741		 */
26742		stop: function() {
26743			clearTimeout(this.timer);
26744		},
26745
26746		/**
26747		 * @private
26748		 * @method Call update on each circle and redraw them.
26749		 * @returns this
26750		 */
26751		_update: function() {
26752			this._clear();
26753			this.circles.forEach(function(circle, idx, array) {
26754				circle.update();
26755			});
26756
26757			return this;
26758		},
26759
26760		/**
26761		 * @private
26762		 * @method Clear the canvas.
26763		 * @returns this
26764		 */
26765		_clear: function() {
26766			this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
26767
26768			return this;
26769		},
26770
26771	};
26772
26773	/**
26774	 * @private
26775	 * @class Individual progress circle.
26776	 * @param params.canvas Canvas on which the circle will be drawn.
26777	 * @param params.context Context of the canvas.
26778	 * @param params.innerRadius Inner radius of the circle, in px.
26779	 * @param params.arcWidth Width of each arc(circle).
26780	 * @param params.gapWidth Distance between each arc.
26781	 * @param params.centerX X coordinate of the center of circles.
26782	 * @param params.centerY Y coordinate of the center of circles.
26783	 * @param params.fillColor Color to fill in the circle.
26784	 * @param params.outlineColor Color to outline the circle.
26785	 * @param params.progressListener Callback function to fetch the progress.
26786	 * @param params.infoListener Callback function to fetch the info.
26787	 * @param params.infoLineAngle Angle of info line.
26788	 */
26789	var Circle = function(params) {
26790		this.id = params.id;
26791		this.canvas = params.canvas;
26792		this.context = params.context;
26793		this.centerX = params.centerX;
26794		this.centerY = params.centerY;
26795		this.arcWidth = params.arcWidth;
26796		this.innerRadius = params.innerRadius || 0;
26797		this.fillColor = params.fillColor || '#fff';
26798		this.outlineColor = params.outlineColor || this.fillColor;
26799		this.progressListener = params.progressListener;
26800		this.infoLineLength = params.infoLineLength || 250;
26801		this.horizLineLength = params.horizLineLength || 50;
26802		this.infoListener = params.infoListener;
26803		this.infoLineAngle = params.infoLineAngle;
26804
26805		this.outerRadius = this.innerRadius + this.arcWidth;
26806
26807		// If the info listener is not registered, then don't calculate
26808		// the related coordinates
26809		if (!this.infoListener) return;
26810
26811		// calculate the info-line turning points
26812		var angle = this.infoLineAngle,
26813			arcDistance = (this.innerRadius + this.outerRadius) / 2,
26814
26815			sinA = Math.sin(angle),
26816			cosA = Math.cos(angle);
26817
26818		this.infoLineStartX = this.centerX + sinA * arcDistance;
26819		this.infoLineStartY = this.centerY - cosA * arcDistance;
26820
26821		this.infoLineMidX = this.centerX + sinA * this.infoLineLength;
26822		this.infoLineMidY = this.centerY - cosA * this.infoLineLength;
26823
26824		this.infoLineEndX = this.infoLineMidX +
26825			 (sinA < 0 ? -this.horizLineLength : this.horizLineLength);
26826		this.infoLineEndY = this.infoLineMidY;
26827
26828		var infoText = document.createElement('div'),
26829			style = infoText.style;
26830
26831		style.color = this.fillColor;
26832		style.position = 'absolute';
26833		style.left = this.infoLineEndX + absPos(this.canvas)[0] + 'px';
26834		// style.top will be calculated in the `drawInfo` method. Since
26835		// user may want to change the size of the font, so the top offset
26836		// must be updated in each loop.
26837		infoText.className = 'ProgressCircleInfo'; // For css styling
26838		infoText.id = 'progress_circle_info_' + this.id;
26839		document.body.appendChild(infoText);
26840		this.infoText = infoText;
26841	};
26842
26843	Circle.prototype = {
26844		constructor: Circle,
26845
26846		update: function() {
26847			this.progress = this.progressListener();
26848			this._draw();
26849
26850			if (this.infoListener) {
26851				this.info = this.infoListener();
26852				this._drawInfo();
26853			}
26854		},
26855
26856		/**
26857		 * @private
26858		 * @method Draw the circle on the canvas.
26859		 * @returns this
26860		 */
26861		_draw: function() {
26862			var ctx = this.context,
26863
26864				ANGLE_OFFSET = -Math.PI / 2,
26865
26866				startAngle = 0 + ANGLE_OFFSET,
26867				endAngle= startAngle + this.progress * Math.PI * 2,
26868
26869				x = this.centerX,
26870				y = this.centerY,
26871
26872				innerRadius = this.innerRadius - this.arcWidth - 1,
26873				outerRadius = this.outerRadius - this.arcWidth - 1;
26874
26875			if ( innerRadius < 0 )
26876				return;
26877
26878			ctx.fillStyle = this.fillColor;
26879			ctx.strokeStyle = this.outlineColor;
26880
26881			ctx.beginPath();
26882			ctx.arc(x, y, innerRadius, startAngle, endAngle, false);
26883			ctx.arc(x, y, outerRadius, endAngle, startAngle, true);
26884			ctx.closePath();
26885			ctx.stroke();
26886			ctx.fill();
26887
26888			return this;
26889		},
26890
26891		/**
26892		 * @private
26893		 * @method Draw the info lines and info text.
26894		 * @returns this
26895		 */
26896		_drawInfo: function() {
26897
26898			var pointList, lineHeight;
26899
26900			pointList = [
26901				[this.infoLineStartX, this.infoLineStartY],
26902				[this.infoLineMidX, this.infoLineMidY],
26903				[this.infoLineEndX, this.infoLineEndY],
26904			];
26905			this._drawSegments(pointList, false);
26906
26907			this.infoText.innerHTML = this.info;
26908
26909			lineHeight = this.infoText.offsetHeight;
26910			this.infoText.style.top = this.infoLineEndY +
26911				absPos(this.canvas)[1] - lineHeight / 2 + 'px';
26912
26913			return this;
26914		},
26915
26916		/**
26917		 * @private
26918		 * @method Helper function to draw the segments
26919		 * @param pointList An array of points in the form of [x, y].
26920		 * @param close Whether to connect the first and last point.
26921		 */
26922		_drawSegments: function(pointList, close) {
26923			var ctx = this.context;
26924
26925			ctx.beginPath();
26926			ctx.moveTo(pointList[0][0], pointList[0][1]);
26927			for (var i = 1; i < pointList.length; ++i) {
26928				ctx.lineTo(pointList[i][0], pointList[i][1]);
26929			}
26930
26931			if (close) {
26932				ctx.closePath();
26933			}
26934			ctx.stroke();
26935		},
26936	};
26937
26938	window.ProgressCircle = ProgressCircle;
26939
26940})(window, document);
26941
26942
26943
26944
26945/* =========================================================
26946 * jquery.vc_chart.js v1.0
26947 * =========================================================
26948 * Copyright 2013 Wpbakery
26949 *
26950 * Jquery chart plugin for the Visual Composer.
26951 * ========================================================= */
26952(function($){
26953	/**
26954	 * Pie chart animated.
26955	 * @param element - DOM element
26956	 * @param options - settings object.
26957	 * @constructor
26958	 */
26959	var VcChart = function(element, options) {
26960		this.el = element;
26961		this.$el = $(this.el);
26962		var $this = this;
26963		$this.options = $.extend({
26964			color: 'wpb_button',
26965			units: '',
26966			width: '',
26967			label_selector: '.vc_pie_chart_value',
26968			back_selector: '.vc_pie_chart_back',
26969			responsive: true
26970		}, options);
26971		$this.init();
26972	};
26973	VcChart.prototype = {
26974		constructor: VcChart,
26975		_progress_v: 0,
26976		animated: false,
26977		colors: {
26978			'wpb_button': 'rgba(247, 247, 247, 1)',
26979			'btn-primary': 'rgba(0, 136, 204, 1)',
26980			'btn-info': 'rgba(88, 185, 218, 1)',
26981			'btn-success': 'rgba(106, 177, 101, 1)',
26982			'btn-warning': 'rgba(255, 153, 0, 1)',
26983			'btn-danger': 'rgba(255, 103, 91, 1)',
26984			'btn-inverse': 'rgba(85, 85, 85, 1)'
26985		},
26986		init: function() {
26987			this.setupColor();
26988			this.value = this.$el.data('pie-value')/100;
26989			this.label_value = this.$el.data('pie-label-value') || this.$el.data('pie-value');
26990			this.$wrapper = $('.vc_pie_wrapper', this.$el);
26991			this.$label = $(this.options.label_selector, this.$el);
26992			this.$back = $(this.options.back_selector, this.$el);
26993			this.$canvas = this.$el.find('canvas');
26994			this.arcWidth = this.$el.data('pie-width') * 2;
26995			this.draw();
26996			this.setWayPoint();
26997			if(this.options.responsive === true) this.setResponsive();
26998			if (UNCODE.isMobile) this._progress_v = this.value;
26999		},
27000		setupColor: function() {
27001			// if(typeof this.colors[this.options.color] !== 'undefined') {
27002			//     this.color = this.colors[this.options.color];
27003			// } else if(typeof this.options.color === 'string' && this.options.color.match(/^rgba?\([^\)]+\)/)) {
27004			//     this.color = this.options.color;
27005			// } else {
27006			//     this.color = 'rgba(247, 247, 247, 0.2)';
27007			// }
27008			if(typeof this.options.color !== 'undefined') {
27009				this.color = this.options.color;
27010			} else this.color = 'rgba(247, 247, 247, 0.2)';
27011
27012		},
27013		setResponsive: function() {
27014			var that = this;
27015			if (!UNCODE.isMobile) {
27016				$(window).resize(function(){
27017					if(that.animated === true) that.circle.stop();
27018					that.draw(true);
27019				});
27020			}
27021		},
27022		draw: function(redraw) {
27023			var w = this.$el.addClass('vc_ready').width() * 2,
27024				border_w = this.arcWidth,
27025				radius;
27026			if(!w) w = this.$el.parents(':visible').first().width()-2;
27027			//w = Math.round(w/100*80);
27028			//if (w < 250) w = 250;
27029			radius = w/2;
27030			this.$wrapper.css({"width" : (w / 2) + "px"});
27031			this.$label.css({"width" : (w / 2), "height" : (w / 2), "line-height" : (w / 2)+"px"});
27032			this.$back.css({"width" : (w / 2), "height" : (w / 2)});
27033			this.$canvas.attr({"width" : w + "px", "height" : w + "px"});
27034			this.$el.addClass('vc_ready');
27035			this.circle = new ProgressCircle({
27036				canvas: this.$canvas.get(0),
27037				minRadius: radius,
27038				arcWidth: border_w
27039			});
27040			if(redraw === true && this.animated === true) {
27041				this._progress_v = this.value;
27042				this.circle.addEntry({
27043					fillColor: this.color,
27044					progressListener: $.proxy(this.setProgress, this)
27045				}).start();
27046			}
27047		},
27048		setProgress: function() {
27049			if (this._progress_v >= this.value) {
27050				this.circle.stop();
27051				this.animated = true;
27052				this.$label.html(this.label_value + this.options.units);
27053				return this._progress_v;
27054			}
27055			this._progress_v += 0.01;
27056			if (!isNaN(this.label_value)) {
27057				var label_value = this._progress_v/this.value*this.label_value;
27058				var val = Math.round(label_value) + this.options.units;
27059				this.$label.html(val);
27060			} else this.$label.html(this.label_value + this.options.units);
27061			return this._progress_v;
27062		},
27063		animate: function() {
27064			if(this.animated !== true) {
27065				this.circle.addEntry({
27066					fillColor: this.color,
27067					progressListener: $.proxy(this.setProgress, this)
27068				}).start(10);
27069			}
27070		},
27071		setWayPoint: function() {
27072			if (typeof $.fn.waypoint !== 'undefined' && !UNCODE.isMobile) {
27073				this.$el.waypoint($.proxy(this.animate, this), { offset: '85%' });
27074			} else {
27075				this.animate();
27076			}
27077		}
27078	};
27079	/**
27080	 * jQuery plugin
27081	 * @param option - object with settings
27082	 * @return {*}
27083	 */
27084	$.fn.vcChat = function(option, value) {
27085		return this.each(function () {
27086			var $this = $(this),
27087				data = $this.data('vc_chart'),
27088				options = typeof option === 'object' ? option : {
27089					color: $this.data('pie-color'),
27090					units: $this.data('pie-units')
27091				};
27092			if (typeof option == 'undefined') $this.data('vc_chart', (data = new VcChart(this, options)));
27093			if (typeof option == 'string') data[option](value);
27094		});
27095	};
27096	/**
27097	 * Allows users to rewrite function inside theme.
27098	 */
27099	if ( typeof window['vc_pieChart'] !== 'function' ) {
27100		window.vc_pieChart = function() {
27101			$('.vc_pie_chart:visible:not(.vc_ready)').vcChat();
27102		}
27103	}
27104	$(document).ready(function(){
27105		!window.vc_iframe && vc_pieChart();
27106
27107		/**
27108		* Tab and collapse integration.
27109		*/
27110		$('.nav-tabs a').on('shown.bs.tab', function(e){
27111			var $cont = $(e.target).closest('.tab-container'),
27112				$active = $('.tab-pane.active', $cont);
27113			$('.vc_pie_chart:not(.vc_ready)', $active).vcChat();
27114		});
27115
27116		$('.panel-collapse').on('shown.bs.collapse', function (e) {
27117			$('.vc_pie_chart:not(.vc_ready)', e.target).vcChat();
27118		})
27119	});
27120
27121})(window.jQuery);
27122
27123/* Progress bar
27124 ---------------------------------------------------------- */
27125function uncode_progress_bar() {
27126	jQuery.each(jQuery('.vc_progress_bar'), function(index, val) {
27127		if (UNCODE.isUnmodalOpen && !val.closest('#unmodal-content')) {
27128			return;
27129		}
27130		if (!UNCODE.isMobile) {
27131			new Waypoint({
27132				context: UNCODE.isUnmodalOpen ? document.getElementById('unmodal-content') : window,
27133				element: val,
27134				handler: function() {
27135					var element = jQuery(this.element);
27136					element.find('.vc_single_bar').each(function(index) {
27137						var $this = jQuery(this),
27138							bar = $this.find('.vc_bar'),
27139							val = bar.data('percentage-value');
27140						setTimeout(function() {
27141							bar.css({
27142								"width": val + '%'
27143							});
27144						}, index * 200);
27145					});
27146				},
27147				offset: '80%'
27148			});
27149		} else {
27150			var element = jQuery(val);
27151			element.find('.vc_single_bar').each(function(index) {
27152				var $this = jQuery(this),
27153					bar = $this.find('.vc_bar'),
27154					val = bar.data('percentage-value');
27155				setTimeout(function() {
27156					bar.css({
27157						"width": val + '%'
27158					});
27159				}, index * 200);
27160			});
27161		}
27162	});
27163};
27164uncode_progress_bar();
27165
27166/*!
27167 * jquery.counterup.js 1.0
27168 *
27169 * Copyright 2013, Benjamin Intal http://gambit.ph @bfintal
27170 * Released under the GPL v2 License
27171 *
27172 * Date: Nov 26, 2013
27173 */
27174(function($) {
27175	"use strict";
27176	$.fn.counterUp = function(options) {
27177		// Defaults
27178		var settings = $.extend({
27179			'time': 400,
27180			'delay': 10
27181		}, options);
27182		return this.each(function() {
27183			// Store the object
27184			var $this = $(this);
27185			var $settings = settings;
27186			var counterUpper = function() {
27187				var nums = [];
27188				var divisions = $settings.time / $settings.delay;
27189				var numReal = $this.attr('data-val'),
27190				num = numReal;
27191				var isComma = /[0-9]+,[0-9]+/.test(num);
27192				num = num.replace(/,/g, '');
27193				var isInt = /^[0-9]+$/.test(num);
27194				var isFloat = /^[0-9]+\.[0-9]+$/.test(num);
27195				var decimalPlaces = isFloat ? (num.split('.')[1] || []).length : 0;
27196				// Generate list of incremental numbers to display
27197				for (var i = divisions; i >= 1; i--) {
27198					// Preserve as int if input was int
27199					var newNum = parseInt(num / divisions * i);
27200					// Preserve float if input was float
27201					if (isFloat) {
27202						newNum = parseFloat(num / divisions * i).toFixed(decimalPlaces);
27203					}
27204					// Preserve commas if input had commas
27205					if (isComma) {
27206						while (/(\d+)(\d{3})/.test(newNum.toString())) {
27207							newNum = newNum.toString().replace(/(\d+)(\d{3})/, '$1' + ',' + '$2');
27208						}
27209					}
27210					nums.unshift(newNum);
27211				}
27212				nums.push(numReal);
27213				$this.data('counterup-nums', nums);
27214				$this.text('0');
27215				// Updates the number until we're done
27216				var f = function() {
27217					if ($this.data('counterup-nums') != null) {
27218						$this.text($this.data('counterup-nums').shift());
27219						if ($this.data('counterup-nums').length) {
27220							setTimeout($this.data('counterup-func'), $settings.delay);
27221						} else {
27222							delete $this.data('counterup-nums');
27223							$this.data('counterup-nums', null);
27224							$this.data('counterup-func', null);
27225						}
27226					}
27227				};
27228				$this.data('counterup-func', f);
27229				// Start the count up
27230				setTimeout($this.data('counterup-func'), $settings.delay);
27231			};
27232			// Perform counts when the element gets into view
27233			new Waypoint({
27234				context: UNCODE.isUnmodalOpen ? document.getElementById('unmodal-content') : window,
27235				element: this,
27236				handler: function() {
27237					counterUpper();
27238					if (!UNCODE.isUnmodalOpen) {
27239						this.destroy();
27240					}
27241				},
27242				offset: '100%'
27243			});
27244		});
27245	};
27246})(jQuery);
27247
27248/*!
27249 * The Final Countdown for jQuery v2.2.0 (http://hilios.github.io/jQuery.countdown/)
27250 * Copyright (c) 2016 Edson Hilios
27251 *
27252 * Permission is hereby granted, free of charge, to any person obtaining a copy of
27253 * this software and associated documentation files (the "Software"), to deal in
27254 * the Software without restriction, including without limitation the rights to
27255 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
27256 * the Software, and to permit persons to whom the Software is furnished to do so,
27257 * subject to the following conditions:
27258 *
27259 * The above copyright notice and this permission notice shall be included in all
27260 * copies or substantial portions of the Software.
27261 *
27262 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27263 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
27264 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
27265 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
27266 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
27267 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27268 */
27269(function(factory) {
27270	"use strict";
27271	if (typeof define === "function" && define.amd) {
27272		define([ "jquery" ], factory);
27273	} else {
27274		factory(jQuery);
27275	}
27276})(function($) {
27277	"use strict";
27278	var instances = [], matchers = [], defaultOptions = {
27279		precision: 100,
27280		elapse: false,
27281		defer: false
27282	};
27283	matchers.push(/^[0-9]*$/.source);
27284	matchers.push(/([0-9]{1,2}\/){2}[0-9]{4}( [0-9]{1,2}(:[0-9]{2}){2})?/.source);
27285	matchers.push(/[0-9]{4}([\/\-][0-9]{1,2}){2}( [0-9]{1,2}(:[0-9]{2}){2})?/.source);
27286	matchers = new RegExp(matchers.join("|"));
27287	function parseDateString(dateString) {
27288		if (dateString instanceof Date) {
27289			return dateString;
27290		}
27291		if (String(dateString).match(matchers)) {
27292			if (String(dateString).match(/^[0-9]*$/)) {
27293				dateString = Number(dateString);
27294			}
27295			if (String(dateString).match(/\-/)) {
27296				dateString = String(dateString).replace(/\-/g, "/");
27297			}
27298			return new Date(dateString);
27299		} else {
27300			throw new Error("Couldn't cast `" + dateString + "` to a date object.");
27301		}
27302	}
27303	var DIRECTIVE_KEY_MAP = {
27304		Y: "years",
27305		m: "months",
27306		n: "daysToMonth",
27307		d: "daysToWeek",
27308		w: "weeks",
27309		W: "weeksToMonth",
27310		H: "hours",
27311		M: "minutes",
27312		S: "seconds",
27313		D: "totalDays",
27314		I: "totalHours",
27315		N: "totalMinutes",
27316		T: "totalSeconds"
27317	};
27318	function escapedRegExp(str) {
27319		var sanitize = str.toString().replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
27320		return new RegExp(sanitize);
27321	}
27322	function strftime(offsetObject) {
27323		return function(format) {
27324			var directives = format.match(/%(-|!)?[A-Z]{1}(:[^;]+;)?/gi);
27325			if (directives) {
27326				for (var i = 0, len = directives.length; i < len; ++i) {
27327					var directive = directives[i].match(/%(-|!)?([a-zA-Z]{1})(:[^;]+;)?/), regexp = escapedRegExp(directive[0]), modifier = directive[1] || "", plural = directive[3] || "", value = null;
27328					directive = directive[2];
27329					if (DIRECTIVE_KEY_MAP.hasOwnProperty(directive)) {
27330						value = DIRECTIVE_KEY_MAP[directive];
27331						value = Number(offsetObject[value]);
27332					}
27333					if (value !== null) {
27334						if (modifier === "!") {
27335							value = pluralize(plural, value);
27336						}
27337						if (modifier === "") {
27338							if (value < 10) {
27339								value = "0" + value.toString();
27340							}
27341						}
27342						format = format.replace(regexp, value.toString());
27343					}
27344				}
27345			}
27346			format = format.replace(/%%/, "%");
27347			return format;
27348		};
27349	}
27350	function pluralize(format, count) {
27351		var plural = "s", singular = "";
27352		if (format) {
27353			format = format.rep
vendor: 8,618 bytes, lines 27353-27497
27353lace(/(:|;|\s)/gi, "").split(/\,/);
27354			if (format.length === 1) {
27355				plural = format[0];
27356			} else {
27357				singular = format[0];
27358				plural = format[1];
27359			}
27360		}
27361		if (Math.abs(count) > 1) {
27362			return plural;
27363		} else {
27364			return singular;
27365		}
27366	}
27367	var Countdown = function(el, finalDate, options) {
27368		this.el = el;
27369		this.$el = $(el);
27370		this.interval = null;
27371		this.offset = {};
27372		this.options = $.extend({}, defaultOptions);
27373		this.instanceNumber = instances.length;
27374		instances.push(this);
27375		this.$el.data("countdown-instance", this.instanceNumber);
27376		if (options) {
27377			if (typeof options === "function") {
27378				this.$el.on("update.countdown", options);
27379				this.$el.on("stoped.countdown", options);
27380				this.$el.on("finish.countdown", options);
27381			} else {
27382				this.options = $.extend({}, defaultOptions, options);
27383			}
27384		}
27385		this.setFinalDate(finalDate);
27386		if (this.options.defer === false) {
27387			this.start();
27388		}
27389	};
27390	$.extend(Countdown.prototype, {
27391		start: function() {
27392			if (this.interval !== null) {
27393				clearInterval(this.interval);
27394			}
27395			var self = this;
27396			this.update();
27397			this.interval = setInterval(function() {
27398				self.update.call(self);
27399			}, this.options.precision);
27400		},
27401		stop: function() {
27402			clearInterval(this.interval);
27403			this.interval = null;
27404			this.dispatchEvent("stoped");
27405		},
27406		toggle: function() {
27407			if (this.interval) {
27408				this.stop();
27409			} else {
27410				this.start();
27411			}
27412		},
27413		pause: function() {
27414			this.stop();
27415		},
27416		resume: function() {
27417			this.start();
27418		},
27419		remove: function() {
27420			this.stop.call(this);
27421			instances[this.instanceNumber] = null;
27422			delete this.$el.data().countdownInstance;
27423		},
27424		setFinalDate: function(value) {
27425			this.finalDate = parseDateString(value);
27426		},
27427		update: function() {
27428			if (this.$el.closest("html").length === 0) {
27429				this.remove();
27430				return;
27431			}
27432			var hasEventsAttached = $._data(this.el, "events") !== undefined, now = new Date(), newTotalSecsLeft;
27433			newTotalSecsLeft = this.finalDate.getTime() - now.getTime();
27434			newTotalSecsLeft = Math.ceil(newTotalSecsLeft / 1e3);
27435			newTotalSecsLeft = !this.options.elapse && newTotalSecsLeft < 0 ? 0 : Math.abs(newTotalSecsLeft);
27436			if (this.totalSecsLeft === newTotalSecsLeft || !hasEventsAttached) {
27437				return;
27438			} else {
27439				this.totalSecsLeft = newTotalSecsLeft;
27440			}
27441			this.elapsed = now >= this.finalDate;
27442			this.offset = {
27443				seconds: this.totalSecsLeft % 60,
27444				minutes: Math.floor(this.totalSecsLeft / 60) % 60,
27445				hours: Math.floor(this.totalSecsLeft / 60 / 60) % 24,
27446				days: Math.floor(this.totalSecsLeft / 60 / 60 / 24) % 7,
27447				daysToWeek: Math.floor(this.totalSecsLeft / 60 / 60 / 24) % 7,
27448				daysToMonth: Math.floor(this.totalSecsLeft / 60 / 60 / 24 % 30.4368),
27449				weeks: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 7),
27450				weeksToMonth: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 7) % 4,
27451				months: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 30.4368),
27452				years: Math.abs(this.finalDate.getFullYear() - now.getFullYear()),
27453				totalDays: Math.floor(this.totalSecsLeft / 60 / 60 / 24),
27454				totalHours: Math.floor(this.totalSecsLeft / 60 / 60),
27455				totalMinutes: Math.floor(this.totalSecsLeft / 60),
27456				totalSeconds: this.totalSecsLeft
27457			};
27458			if (!this.options.elapse && this.totalSecsLeft === 0) {
27459				this.stop();
27460				this.dispatchEvent("finish");
27461			} else {
27462				this.dispatchEvent("update");
27463			}
27464		},
27465		dispatchEvent: function(eventName) {
27466			var event = $.Event(eventName + ".countdown");
27467			event.finalDate = this.finalDate;
27468			event.elapsed = this.elapsed;
27469			event.offset = $.extend({}, this.offset);
27470			event.strftime = strftime(this.offset);
27471			this.$el.trigger(event);
27472		}
27473	});
27474	$.fn.countdown = function() {
27475		var argumentsArray = Array.prototype.slice.call(arguments, 0);
27476		return this.each(function() {
27477			var instanceNumber = $(this).data("countdown-instance");
27478			if (instanceNumber !== undefined) {
27479				var instance = instances[instanceNumber], method = argumentsArray[0];
27480				if (Countdown.prototype.hasOwnProperty(method)) {
27481					instance[method].apply(instance, argumentsArray.slice(1));
27482				} else if (String(method).match(/^[$A-Z_][0-9A-Z_$]*$/i) === null) {
27483					instance.setFinalDate.call(instance, method);
27484					instance.start();
27485				} else {
27486					$.error("Method %s does not exist on jQuery.countdown".replace(/\%s/gi, method));
27487				}
27488			} else {
27489				new Countdown(this, argumentsArray[0], argumentsArray[1]);
27490			}
27491		});
27492	};
27493});
27494
27495!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;
27496function getStyles(config){
27497  // 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;
27497left: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+"}"
27498};
27499  var ShareUtils;
27500
27501if ((!("classList" in document.documentElement)) && Object.defineProperty && typeof HTMLElement !== "undefined") {
27502  Object.defineProperty(HTMLElement.prototype, "classList", {
27503    get: function() {
27504      var ret, self, update;
27505      update = function(fn) {
27506        return function(value) {
27507          var classes, index;
27508          classes = self.className.split(/\s+/);
27509          index = classes.indexOf(value);
27510          fn(classes, index, value);
27511          self.className = classes.join(" ");
27512        };
27513      };
27514      self = this;
27515      ret = {
27516        add: update(function(classes, index, value) {
27517          ~index || classes.push(value);
27518        }),
27519        remove: update(function(classes, index) {
27520          ~index && classes.splice(index, 1);
27521        }),
27522        toggle: update(function(classes, index, value) {
27523          if (~index) {
27524            classes.splice(index, 1);
27525          } else {
27526            classes.push(value);
27527          }
27528        }),
27529        contains: function(value) {
27530          return !!~self.className.split(/\s+/).indexOf(value);
27531        },
27532        item: function(i) {
27533          return self.className.split(/\s+/)[i] || null;
27534        }
27535      };
27536      Object.defineProperty(ret, "length", {
27537        get: function() {
27538          return self.className.split(/\s+/).length;
27539        }
27540      });
27541      return ret;
27542    }
27543  });
27544}
27545
27546String.prototype.to_rfc3986 = function() {
27547  var tmp;
27548  tmp = encodeURIComponent(this);
27549  return tmp.replace(/[!'()*]/g, function(c) {
27550    return "%" + c.charCodeAt(0).toString(16);
27551  });
27552};
27553
27554ShareUtils = (function() {
27555  function ShareUtils() {}
27556
27557  ShareUtils.prototype.extend = function(to, from, overwrite) {
27558    var hasProp, prop;
27559    for (prop in from) {
27560      hasProp = to[prop] !== undefined;
27561      if (hasProp && typeof from[prop] === "object") {
27562        this.extend(to[prop], from[prop], overwrite);
27563      } else {
27564        if (overwrite || !hasProp) {
27565          to[prop] = from[prop];
27566        }
27567      }
27568    }
27569  };
27570
27571  ShareUtils.prototype.hide = function(el) {
27572    return el.style.display = "none";
27573  };
27574
27575  ShareUtils.prototype.show = function(el) {
27576    return el.style.display = "block";
27577  };
27578
27579  ShareUtils.prototype.has_class = function(el, class_name) {
27580    return el.classList.contains(class_name);
27581  };
27582
27583  ShareUtils.prototype.add_class = function(el, class_name) {
27584    return el.classList.add(class_name);
27585  };
27586
27587  ShareUtils.prototype.remove_class = function(el, class_name) {
27588    return el.classList.remove(class_name);
27589  };
27590
27591  ShareUtils.prototype.is_encoded = function(str) {
27592    str = str.to_rfc3986();
27593    return decodeURIComponent(str) !== str;
27594  };
27595
27596  ShareUtils.prototype.encode = function(str) {
27597    if (typeof str === "undefined" || this.is_encoded(str)) {
27598      return str;
27599    } else {
27600      return str.to_rfc3986();
27601    }
27602  };
27603
27604  ShareUtils.prototype.popup = function(url, params) {
27605    var k, popup, qs, v;
27606    if (params == null) {
27607      params = {};
27608    }
27609    popup = {
27610      width: 500,
27611      height: 350
27612    };
27613    popup.top = (screen.height / 2) - (popup.height / 2);
27614    popup.left = (screen.width / 2) - (popup.width / 2);
27615    qs = ((function() {
27616      var _results;
27617      _results = [];
27618      for (k in params) {
27619        v = params[k];
27620        _results.push("" + k + "=" + (this.encode(v)));
27621      }
27622      return _results;
27623    }).call(this)).join('&');
27624    if (qs) {
27625      qs = "?" + qs;
27626    }
27627    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=" 
27627+ popup.width + ",height=" + popup.height);
27628  };
27629
27630  return ShareUtils;
27631
27632})();
27633var Share,
27634  __hasProp = {}.hasOwnProperty,
27635  __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; };
27636
27637Share = (function(_super) {
27638  __extends(Share, _super);
27639
27640  function Share(element, options) {
27641    this.element = element;
27642    this.el = {
27643      head: document.getElementsByTagName('head')[0],
27644      body: document.getElementsByTagName('body')[0]
27645    };
27646    this.config = {
27647      enabled_networks: 0,
27648      protocol: ['http', 'https'].indexOf(window.location.href.split(':')[0]) === -1 ? 'https://' : '//',
27649      url: window.location.href.replace("&", "%26"),
27650      caption: null,
27651      title: this.default_title(),
27652      image: this.default_image(),
27653      description: this.default_description(),
27654      ui: {
27655        flyout: 'top center',
27656        button_text: 'Share',
27657        button_font: true,
27658        icon_font: true
27659      },
27660      networks: {
27661        twitter: {
27662          enabled: true,
27663          url: null,
27664          title: null,
27665          description: null
27666        },
27667        facebook: {
27668          enabled: true,
27669          load_sdk: true,
27670          url: null,
27671          app_id: null,
27672          title: null,
27673          caption: null,
27674          description: null,
27675          image: null
27676        },
27677        threads: {
27678          enabled: true,
27679          url: null,
27680          title: null,
27681          description: null
27682        },
27683        bluesky: {
27684          enabled: true,
27685          url: null,
27686          title: null,
27687          description: null
27688        },
27689        pinterest: {
27690          enabled: true,
27691          url: null,
27692          image: null,
27693          description: null
27694        },
27695        reddit: {
27696          enabled: true,
27697          url: null,
27698          title: null
27699        },
27700        linkedin: {
27701          enabled: true,
27702          url: null,
27703          title: null,
27704          description: null
27705        },
27706        xing: {
27707          enabled: true,
27708          url: null,
27709          title: null,
27710          image: null,
27711          description: null
27712        },
27713        whatsapp: {
27714          enabled: true,
27715          title: null,
27716          url: null
27717        },
27718        email: {
27719          enabled: true,
27720          title: null,
27721          description: null,
27722          url: null
27723        }
27724      }
27725    };
27726    this.setup(element, options);
27727    return this;
27728  }
27729
27730  Share.prototype.setup = function(element, opts) {
27731    var index, instance, instances, _i, _len;
27732    instances = document.querySelectorAll(element);
27733    this.extend(this.config, opts, true);
27734    this.set_global_configuration();
27735    this.normalize_network_configuration();
27736    if (this.config.ui.icon_font) {
27737      this.inject_icons();
27738    }
27739    if (this.config.ui.button_font) {
27740      this.inject_fonts();
27741    }
27742    if (this.config.networks.facebook.enabled && this.config.networks.facebook.load_sdk) {
27743      this.inject_facebook_sdk();
27744    }
27745    for (index = _i = 0, _len = instances.length; _i < _len; index = ++_i) {
27746      instance = instances[index];
27747      this.setup_instance(element, index);
27748    }
27749  };
27750
27751  Share.prototype.setup_instance = function(element, index) {
27752    var button, instance, label, network, networks, _i, _len, _results,
27753      _this = this;
27754    instance = document.querySelectorAll(element)[index];
27755    this.hide(instance);
27756    this.add_class(instance, "sharer-" + index);
27757    instance = document.querySelectorAll(element)[index];
27758    this.inject_css(instance);
27759    this.inject_html(instance);
27760    this.show(instance);
27761    label = instance.getElementsByTagName("label")[0];
27762    button = instance.getElementsByClassName("social")[0];
27763    networks = instance.getElementsByTagName('li');
27764    this.add_class(button, "networks-" + this.config.enabled_networks);
27765    label.addEventListener("click", function() {
27766      return _this.event_toggle(button);
27767    });
27768    _this = this;
27769    _results = [];
27770    for (index = _i = 0, _len = networks.length; _i < _len; index = ++_i) {
27771      network = networks[index];
27772      _results.push(network.addEventListener("click", function() {
27773        _this.event_network(instance, this);
27774        return _this.event_close(button);
27775      }));
27776    }
27777    return _results;
27778  };
27779
27780  Share.prototype.event_toggle = function(button) {
27781    if (this.has_class(button, "active")) {
27782      return this.event_close(button);
27783    } else {
27784      return this.event_open(button);
27785    }
27786  };
27787
27788  Share.prototype.event_open = function(button) {
27789    if (this.has_class(button, "load")) {
27790      this.remove_class(button, "load");
27791    }
27792    return this.add_class(button, "active");
27793  };
27794
27795  Share.prototype.event_close = function(button) {
27796    return this.remove_class(button, "active");
27797  };
27798
27799  Share.prototype.event_network = function(instance, network) {
27800    var name;
27801    name = network.getAttribute("data-network");
27802    this.hook("before", name, instance);
27803    this["network_" + name]();
27804    return this.hook("after", name, instance);
27805  };
27806
27807  Share.prototype.open = function() {
27808    return this["public"]("open");
27809  };
27810
27811  Share.prototype.close = function() {
27812    return this["public"]("close");
27813  };
27814
27815  Share.prototype.toggle = function() {
27816    return this["public"]("toggle");
27817  };
27818
27819  Share.prototype["public"] = function(action) {
27820    var button, index, instance, _i, _len, _ref, _results;
27821    _ref = document.querySelectorAll(this.element);
27822    _results = [];
27823    for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) {
27824      instance = _ref[index];
27825      button = instance.getElementsByClassName("social")[0];
27826      _results.push(this["event_" + action](button));
27827    }
27828    return _results;
27829  };
27830
27831  Share.prototype.network_facebook = function() {
27832    if (this.config.networks.facebook.load_sdk) {
27833      if (!window.FB) {
27834        return console.error("The Facebook JS SDK hasn't loaded yet.");
27835      }
27836      return FB.ui({
27837        method: 'feed',
27838        name: this.config.networks.facebook.title,
27839        link: this.config.networks.facebook.url,
27840        picture: this.config.networks.facebook.image,
27841        caption: this.config.networks.facebook.caption,
27842        description: this.config.networks.facebook.description
27843      });
27844    } else {
27845      return this.popup('https://www.facebook.com/sharer/sharer.php', {
27846        u: this.config.networks.facebook.url
27847      });
27848    }
27849  };
27850
27851  Share.prototype.network_threads = function() {
27852    return this.popup('https://threads.net/intent/post', {
27853      text: this.config.networks.threads.title,
27854      url: this.config.networks.threads.url
27855    });
27856  };
27857
27858  Share.prototype.network_bluesky = function() {
27859    return this.popup('https://bsky.app/intent/compose', {
27860      text: this.config.networks.bluesky.title + ' ' + this.config.networks.bluesky.url
27861    });
27862  };
27863
27864  Share.prototype.network_twitter = function() {
27865    return this.popup('https://twitter.com/intent/tweet', {
27866      text: this.config.networks.twitter.title,
27867      url: this.config.networks.twitter.url
27868    });
27869  };
27870
27871  Share.prototype.network_pinterest = function() {
27872    return this.popup('https://www.pinterest.com/pin/create/button', {
27873      url: this.config.networks.pinterest.url,
27874      media: this.config.networks.pinterest.image,
27875      description: this.config.networks.pinterest.description
27876    });
27877  };
27878
27879  Share.prototype.network_linkedin = function() {
27880    return this.popup('https://www.linkedin.com/shareArticle', {
27881      url: this.config.networks.linkedin.url,
27882      title: this.config.networks.linkedin.title,
27883      summary: this.config.networks.linkedin.description
27884    });
27885  }
27886
27887  Share.prototype.network_xing = function() {
27888    return this.popup('https://www.xing.com/spi/shares/new', {
27889      url: this.config.networks.xing.url,
27890      image: this.config.networks.xing.image,
27891      title: this.config.networks.xing.title,
27892      summary: this.config.networks.xing.description
27893    });
27894  }
27895
27896  Share.prototype.network_whatsapp = function() {
27897    return this.popup('https://api.whatsapp.com/send', {
27898      text: this.config.networks.whatsapp.title + '%20' + this.config.networks.whatsapp.url,
27899    });
27900  }
27901
27902  Share.prototype.network_email = function() {
27903    return this.popup('mailto:', {
27904      subject: this.config.networks.email.title,
27905      body: this.config.networks.email.url + '%0A%0A' + this.config.networks.email.description,
27906    });
27907  };
27908
27909  Share.prototype.inject_icons = function() {
27910  //  return this.inject_stylesheet("https://www.sharebutton.co/fonts/v2/entypo.min.css");
27911  };
27912
27913  Share.prototype.inject_fonts = function() {
27914   // return this.inject_stylesheet("http://fonts.googleapis.com/css?family=Lato:900&text=" + this.config.ui.button_text);
27915  };
27916
27917  Share.prototype.inject_stylesheet = function(url) {
27918    var link;
27919    if (!this.el.head.querySelector("link[href=\"" + url + "\"]")) {
27920      link = document.createElement("link");
27921      link.setAttribute("rel", "stylesheet");
27922      link.setAttribute("href", url);
27923      return this.el.head.appendChild(link);
27924    }
27925  };
27926
27927  Share.prototype.inject_css = function(instance) {
27928    var css, meta, selector, style;
27929    selector = "." + (instance.getAttribute('class').split(" ").join("."));
27930    if (!this.el.head.querySelector("meta[name='sharer" + selector + "']")) {
27931      this.config.selector = selector;
27932      css = getStyles(this.config);
27933      style = document.createElement("style");
27934      style.type = "text/css";
27935      if (style.styleSheet) {
27936        style.styleSheet.cssText = css;
27937      } else {
27938        style.appendChild(document.createTextNode(css));
27939      }
27940      this.el.head.appendChild(style);
27941      delete this.config.selector;
27942      meta = document.createElement("meta");
27943      meta.setAttribute("name", "sharer" + selector);
27944      return this.el.head.appendChild(meta);
27945    }
27946  };
27947
27948  Share.prototype.inject_html = function(instance) {
27949    //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>";
27950    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>";
27951  };
27952
27953  Share.prototype.inject_facebook_sdk = function() {
27954    var fb_root, script;
27955    if (!window.FB && this.config.networks.facebook.app_id && !this.el.body.querySelector('#fb-root')) {
27956      script = document.createElement("script");
27957      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')";
27958      fb_root = document.createElement("div");
27959      fb_root.id = "fb-root";
27960      this.el.body.appendChild(fb_root);
27961      return this.el.body.appendChild(script);
27962    }
27963  };
27964
27965  Share.prototype.hook = function(type, network, instance) {
27966    var fn, opts;
27967    fn = this.config.networks[network][type];
27968    if (typeof fn === "function") {
27969      opts = fn.call(this.config.networks[network], instance);
27970      if (opts !== void 0) {
27971        opts = this.normalize_filter_config_updates(opts);
27972        this.extend(this.config.networks[network], opts, true);
27973        this.normalize_network_configuration();
27974      }
27975    }
27976  };
27977
27978  Share.prototype.default_title = function() {
27979    var content;
27980    if (content = document.querySelector('meta[property="og:title"]') || document.querySelector('meta[name="twitter:title"]')) {
27981      return encodeURIComponent(content.getAttribute('content'));
27982    } else if (content = document.querySelector('title')) {
27983      return encodeURIComponent(content.innerText);
27984    }
27985  };
27986
27987  Share.prototype.default_image = function() {
27988    var content;
27989    if (content = document.querySelector('meta[property="og:image"]') || document.querySelector('meta[name="twitter:image"]')) {
27990      return content.getAttribute('content');
27991    }
27992  };
27993
27994  Share.prototype.default_description = function() {
27995    var content;
27996    if (content = document.querySelector('meta[property="og:description"]') || document.querySelector('meta[name="twitter:description"]') || document.querySelector('meta[name="description"]')) {
27997      return encodeURIComponent(content.getAttribute('content'));
27998    } else {
27999      return '';
28000    }
28001  };
28002
28003  Share.prototype.set_global_configuration = function() {
28004    var display, network, option, options, _ref, _results;
28005    _ref = this.config.networks;
28006    _results = [];
28007    for (network in _ref) {
28008      options = _ref[network];
28009      for (option in options) {
28010        if (this.config.networks[network][option] == null) {
28011          this.config.networks[network][option] = this.config[option];
28012        }
28013      }
28014      if (this.config.networks[network].enabled) {
28015        display = 'block';
28016        this.config.enabled_networks += 1;
28017      } else {
28018        display = 'none';
28019      }
28020      _results.push(this.config.networks[network].display = display);
28021    }
28022    return _results;
28023  };
28024
28025  Share.prototype.normalize_network_configuration = function() {
28026    if (!this.config.networks.facebook.app_id) {
28027      this.config.networks.facebook.load_sdk = false;
28028    }
28029    if (!this.is_encoded(this.config.networks.twitter.description)) {
28030      this.config.networks.twitter.description = encodeURIComponent(this.config.networks.twitter.description);
28031    }
28032    if (typeof this.config.networks.facebook.app_id === 'number') {
28033      return this.config.networks.facebook.app_id = this.config.networks.facebook.app_id.toString();
28034    }
28035  };
28036
28037  Share.prototype.normalize_filter_config_updates = function(opts) {
28038    if (this.config.networks.facebook.app_id !== opts.app_id) {
28039      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.");
28040      delete opts.app_id;
28041    }
28042    if (this.config.networks.facebook.load_sdk !== opts.load_sdk) {
28043      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.");
28044      delete opts.app_id;
28045    }
28046    return opts;
28047  };
28048
28049  return Share;
28050
28051})(ShareUtils);
28052 return Share;
28053});
28054
28055// Generated by CoffeeScript 1.9.2
28056
28057// @license Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net
28058
28059(function() {
28060  var $, win;
28061
28062  $ = this.jQuery || window.jQuery;
28063
28064  win = $(window);
28065
28066  $.fn.stick_in_parent = function(opts) {
28067    var doc, elm, enable_bottoming, fn, i, inner_scrolling, len, manual_spacer, offset_top, outer_width, parent_selector, recalc_every, sticky_class;
28068    if (opts == null) {
28069      opts = {};
28070    }
28071    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;
28072    if (offset_top == null) {
28073      offset_top = 0;
28074    }
28075    if (parent_selector == null) {
28076      parent_selector = void 0;
28077    }
28078    if (inner_scrolling == null) {
28079      inner_scrolling = true;
28080    }
28081    if (sticky_class == null) {
28082      sticky_class = "is_stuck";
28083    }
28084    doc = $(document);
28085    if (enable_bottoming == null) {
28086      enable_bottoming = true;
28087    }
28088    outer_width = function(el) {
28089      var _el, computed, w;
28090      if (window.getComputedStyle) {
28091        _el = el[0];
28092        computed = window.getComputedStyle(el[0]);
28093        w = parseFloat(computed.getPropertyValue("width")) + parseFloat(computed.getPropertyValue("margin-left")) + parseFloat(computed.getPropertyValue("margin-right"));
28094        if (computed.getPropertyValue("box-sizing") !== "border-box") {
28095          w += parseFloat(computed.getPropertyValue("border-left-width")) + parseFloat(computed.getPropertyValue("border-right-width")) + parseFloat(computed.getPropertyValue("padding-left")) + parseFloat(computed.getPropertyValue("padding-right"));
28096        }
28097        return w;
28098      } else {
28099        return el.outerWidth(true);
28100      }
28101    };
28102    fn = function(elm, padding_bottom, parent_top, parent_height, top, height, el_float, detached) {
28103      var bottomed, detach, fixed, last_pos, last_scroll_height, offset, parent, recalc, recalc_and_tick, recalc_counter, spacer, tick;
28104      if (elm.data("sticky_kit")) {
28105        return;
28106      }
28107      elm.data("sticky_kit", true);
28108      last_scroll_height = doc.height();
28109      parent = elm.parent();
28110      if (parent_selector != null) {
28111        parent = parent.closest(parent_selector);
28112      }
28113      if (!parent.length) {
28114        throw "failed to find stick parent";
28115      }
28116      fixed = false;
28117      bottomed = false;
28118      spacer = manual_spacer != null ? manual_spacer && elm.closest(manual_spacer) : $("<div />");
28119      if (spacer) {
28120        spacer.css('position', elm.css('position'));
28121      }
28122      recalc = function() {
28123        var border_top, padding_top, restore;
28124        if (detached) {
28125          return;
28126        }
28127        last_scroll_height = doc.height();
28128        border_top = parseInt(parent.css("border-top-width"), 10);
28129        padding_top = parseInt(parent.css("padding-top"), 10);
28130        padding_bottom = parseInt(parent.css("padding-bottom"), 10);
28131        parent_top = parent.offset().top + border_top + padding_top;
28132        parent_height = parent.height();
28133        if (fixed) {
28134          fixed = false;
vendor: 6,068 bytes, lines 28135-28329
28135          bottomed = false;
28136          if (manual_spacer == null) {
28137            elm.insertAfter(spacer);
28138            spacer.detach();
28139          }
28140          elm.css({
28141            position: "",
28142            top: "",
28143            width: "",
28144            bottom: ""
28145          }).removeClass(sticky_class);
28146          restore = true;
28147        }
28148        top = elm.offset().top - (parseInt(elm.css("margin-top"), 10) || 0) - offset_top;
28149        height = elm.outerHeight(true);
28150        el_float = elm.css("float");
28151        if (spacer) {
28152          spacer.css({
28153            width: outer_width(elm),
28154            height: height,
28155            display: elm.css("display"),
28156            "vertical-align": elm.css("vertical-align"),
28157            "float": el_float
28158          });
28159        }
28160        if (restore) {
28161          return tick();
28162        }
28163      };
28164      recalc();
28165      if (height === parent_height) {
28166        return;
28167      }
28168      last_pos = void 0;
28169      offset = offset_top;
28170      recalc_counter = recalc_every;
28171      tick = function() {
28172        var css, delta, recalced, scroll, will_bottom, win_height;
28173        if (detached) {
28174          return;
28175        }
28176        recalced = false;
28177        if (recalc_counter != null) {
28178          recalc_counter -= 1;
28179          if (recalc_counter <= 0) {
28180            recalc_counter = recalc_every;
28181            recalc();
28182            recalced = true;
28183          }
28184        }
28185        if (!recalced && doc.height() !== last_scroll_height) {
28186          recalc();
28187          recalced = true;
28188        }
28189        scroll = win.scrollTop();
28190        if (last_pos != null) {
28191          delta = scroll - last_pos;
28192        }
28193        last_pos = scroll;
28194        if (fixed) {
28195          if (enable_bottoming) {
28196            will_bottom = scroll + height + offset > parent_height + parent_top;
28197            if (bottomed && !will_bottom) {
28198              bottomed = false;
28199              elm.css({
28200                position: "fixed",
28201                bottom: "",
28202                top: offset
28203              }).trigger("sticky_kit:unbottom");
28204            }
28205          }
28206          if (scroll < top) {
28207            fixed = false;
28208            offset = offset_top;
28209            if (manual_spacer == null) {
28210              if (el_float === "left" || el_float === "right") {
28211                elm.insertAfter(spacer);
28212              }
28213              spacer.detach();
28214            }
28215            css = {
28216              position: "",
28217              width: "",
28218              top: ""
28219            };
28220            elm.css(css).removeClass(sticky_class).trigger("sticky_kit:unstick");
28221          }
28222          if (inner_scrolling) {
28223            win_height = win.height();
28224            if (height + offset_top > win_height) {
28225              if (!bottomed) {
28226                offset -= delta;
28227                offset = Math.max(win_height - height, offset);
28228                offset = Math.min(offset_top, offset);
28229                if (fixed) {
28230                  elm.css({
28231                    top: offset + "px"
28232                  });
28233                }
28234              }
28235            }
28236          }
28237        } else {
28238          if (scroll > top) {
28239            fixed = true;
28240            css = {
28241              position: "fixed",
28242              top: offset
28243            };
28244            css.width = elm.css("box-sizing") === "border-box" ? elm.outerWidth() + "px" : elm.width() + "px";
28245            elm.css(css).addClass(sticky_class);
28246            if (manual_spacer == null) {
28247              elm.after(spacer);
28248              if (el_float === "left" || el_float === "right") {
28249                spacer.append(elm);
28250              }
28251            }
28252            elm.trigger("sticky_kit:stick");
28253          }
28254        }
28255        if (fixed && enable_bottoming) {
28256          if (will_bottom == null) {
28257            will_bottom = scroll + height + offset > parent_height + parent_top;
28258          }
28259          if (!bottomed && will_bottom) {
28260            bottomed = true;
28261            if (parent.css("position") === "static") {
28262              parent.css({
28263                position: "relative"
28264              });
28265            }
28266            return elm.css({
28267              position: "absolute",
28268              bottom: padding_bottom,
28269              top: "auto"
28270            }).trigger("sticky_kit:bottom");
28271          }
28272        }
28273      };
28274      recalc_and_tick = function() {
28275        recalc();
28276        return tick();
28277      };
28278      detach = function() {
28279        detached = true;
28280        win.off("touchmove", tick);
28281        win.off("scroll", tick);
28282        win.off("resize", recalc_and_tick);
28283        $(document.body).off("sticky_kit:recalc", recalc_and_tick);
28284        elm.off("sticky_kit:detach", detach);
28285        elm.removeData("sticky_kit");
28286        elm.css({
28287          position: "",
28288          bottom: "",
28289          top: "",
28290          width: ""
28291        });
28292        parent.position("position", "");
28293        if (fixed) {
28294          if (manual_spacer == null) {
28295            if (el_float === "left" || el_float === "right") {
28296              elm.insertAfter(spacer);
28297            }
28298            spacer.remove();
28299          }
28300          return elm.removeClass(sticky_class);
28301        }
28302      };
28303      win.on("touchmove", tick);
28304      win.on("scroll", tick);
28305      win.on("resize", recalc_and_tick);
28306      $(document.body).on("sticky_kit:recalc", recalc_and_tick);
28307      elm.on("sticky_kit:detach", detach);
28308      return setTimeout(tick, 0);
28309    };
28310    for (i = 0, len = this.length; i < len; i++) {
28311      elm = this[i];
28312      fn($(elm));
28313    }
28314    return this;
28315  };
28316
28317}).call(this);
28318/* ==========================================================================
28319 * bootstrap-tab-history.js
28320 * Author: Michael Narayan <[email protected]>
28321 * Repository: https://github.com/mnarayan01/bootstrap-tab-history/
28322 * ==========================================================================
28323 * Licensed under the Apache License, Version 2.0 (the "License"); you may
28324 * not use this file except in compliance with the License. You may obtain a
28325 * copy of the License at
28326 *
28327 * http://www.apache.org/licenses/LICENSE-2.0
28328 *
28329 * Unless required by applicable law or agreed to in writing, softw
28329are
28330 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
28331 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
28332 * License for the specific language governing permissions and limitations
28333 * under the License.
28334 * ========================================================================== */
28335
28336/* ========================================================================== */
28337/* JSHint directives                                                          */
28338/*                                                                            */
28339/* global BootstrapTabHistory: true                                           */
28340/*                                                                            */
28341/* global document                                                            */
28342/* global jQuery                                                              */
28343/* global history                                                             */
28344/* global window                                                              */
28345/* ========================================================================== */
28346
28347/**
28348 * Integrate [HTML5 history state tracking](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history)
28349 * with [`bootstrap/tab.js`](http://getbootstrap.com/javascript/#tabs). To enable tracking on a tab element, simply set
28350 * the `data-tab-history` attribute to true (or a string denoting a tab grouping).
28351 *
28352 * See the README for additional information.
28353 *
28354 * Functionality based upon bootstrap/tab.js v3.1.0; reference it when making any changes.
28355 */
28356
28357BootstrapTabHistory = {
28358  options: {
28359    /**
28360     * When the anchor portion of the URI is used to activate a tab, scroll down to the given offset, rather than the
28361     * element with the given `id` attribute. Set to null to disable. Only relevant if showTabsBasedOnAnchor is true.
28362     *
28363     * May be overriden on a per-element basis by the attribute `data-tab-history-anchor-y-offset`.
28364     *
28365     * @public
28366     * @type {?number}
28367     */
28368    defaultAnchorYOffset: 0,
28369    /**
28370     * Either 'push' or 'replace', for whether to use `history.pushState` or `history.replaceState`, resp.
28371     *
28372     * May be overriden on a per-element basis by the attribute `data-tab-history-changer`.
28373     *
28374     * @public
28375     * @type {string}
28376     */
28377    defaultChanger: 'replace',
28378    /**
28379     * If true, update the URL in onShownTab in the calls to `history.pushState` and `history.replaceState`. Otherwise,
28380     * `null` is passed as the third parameter to these calls.
28381     *
28382     * May be overriden on a per-element basis by the attribute `data-tab-history-update-url`.
28383     *
28384     * @public
28385     * @type {boolean}
28386     */
28387    defaultUpdateURL: false,
28388    /**
28389     * Should the anchor portion of the loaded URI be used to activate a single tab if no history was present on page
28390     * load.
28391     *
28392     * @public
28393     * @type {boolean}
28394     */
28395    showTabsBasedOnAnchor: true
28396  }
28397};
28398
28399(function () {
28400  'use strict';
28401
28402  jQuery(function () {
28403    if(history && history.pushState && history.replaceState) {
28404      var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory;
28405
28406      if(bootstrapTabHistory) {
28407        showTabsBasedOnState(bootstrapTabHistory);
28408      } else {
28409        showTabsBasedOnAnchor();
28410      }
28411
28412      backfillHistoryState();
28413
28414      jQuery(document).on('shown.bs.tab show.bs.collapse', onShownTab);
28415      jQuery(window).on('popstate', onPopState);
28416    } else {
28417      showTabsBasedOnAnchor();
28418    }
28419  });
28420
28421  /**
28422   * Used to prevent onShownTab from registering shown events that we triggered via showTabsBasedOnState.
28423   *
28424   * @type {boolean}
28425   */
28426  var showingTabsBasedOnState = false;
28427
28428  /**
28429   * Used to update `history.state` to reflect the default active tabs on initial page load. This supports proper
28430   * `history.back` handling when `data-tab-history-update-url` is true.
28431   */
28432  function backfillHistoryState() {
28433    var newState = null;
28434
28435    jQuery('li.active > [data-tab-history], .panel-title.active [data-tab-history]').each(function () {//edited by Uncode
28436      var $activeTabElement = jQuery(this);
28437      var selector = getTabSelector($activeTabElement);
28438
28439      if(selector) {
28440        var tabGroup = getTabGroup($activeTabElement);
28441
28442        if(tabGroup) {
28443          newState = createNewHistoryState(newState || history.state, tabGroup, selector);
28444        }
28445      }
28446    });
28447
28448    if(newState) {
28449      history.replaceState(newState, '', null);
28450    }
28451  }
28452
28453  /**
28454   * Clone the existing state, ensure its bootstrapTabHistory attribute is an Object, and add the provided tabGroup to
28455   * said bootstrapTabHistory attribute.
28456   *
28457   * @param {?object} existingState
28458   * @param {!string} tabGroup
28459   * @param {!string} selector
28460   * @returns {!object}
28461   */
28462  function createNewHistoryState(existingState, tabGroup, selector) {
28463    // Clone history.state and ensure it has a bootstrapTabHistory entry.
28464    var newState = jQuery.extend(true, {}, existingState, {
28465      bootstrapTabHistory: {}
28466    });
28467
28468    newState.bootstrapTabHistory[tabGroup] = selector;
28469
28470    return newState;
28471  }
28472
28473  /**
28474   * @param {jQuery} $tab
28475   * @returns {?string}
28476   */
28477  function getTabGroup($tab) {
28478    return parseTruthyAttributeValue($tab.data('tab-history'));
28479  }
28480
28481  /**
28482   * @param {jQuery} $tab
28483   * @returns {?string}
28484   */
28485  function getTabSelector($tab) {
28486    return $tab.data('target') || $tab.attr('href');
28487  }
28488
28489  /**
28490   * Receives the `shown.bs.tab` event. Updates `history.state` as appropriate.
28491   *
28492   * @param {jQuery.Event} shownEvt
28493   */
28494  function onShownTab(shownEvt) {
28495    if(!showingTabsBasedOnState) {
28496      var $activatedTab = jQuery(shownEvt.target);
28497      if ( $activatedTab.hasClass('panel-collapse') )
28498        $activatedTab = $activatedTab.closest('.panel').find('a');
28499      var selector = getTabSelector($activatedTab);
28500
28501      if(selector) {
28502        var tabGroup = getTabGroup($activatedTab);
28503
28504        if(tabGroup) {
28505          var historyChanger = $activatedTab.data('tab-history-changer') || BootstrapTabHistory.options.defaultChanger;
28506          var newState = createNewHistoryState(history.state, tabGroup, selector);
28507          var updateURL = (function ($activatedTab) {
28508            if(selector[0] === '#') {
28509              var elementUpdateURLOption = parseTruthyAttributeValue($activatedTab.data('tab-history-update-url'));
28510
28511              if(elementUpdateURLOption === undefined) {
28512                return BootstrapTabHistory.options.defaultUpdateURL;
28513              } else {
28514                return elementUpdateURLOption;
28515              }
28516            } else {
28517              return false;
28518            }
28519          })($activatedTab);
28520
28521          switch(historyChanger) {
28522            case 'push':
28523              history.pushState(newState, '', updateURL ? selector : null);
28524              break;
28525            case 'replace':
28526              history.replaceState(newState, '', updateURL ? selector : null);
28527              break;
28528            default:
28529              throw new Error('Unknown tab-history-changer: ' + historyChanger);
28530          }
28531        }
28532      }
28533    }
28534  }
28535
28536  /**
28537   * Receives the `popstate` event. Shows tabs based on the value of `history.state` as appropriate.
28538   */
28539  function onPopState() {
28540    var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory;
28541
28542    if(bootstrapTabHistory) {
28543      showTabsBasedOnState(bootstrapTabHistory);
28544    }
28545  }
28546
28547  /**
28548   * Returns the given value, _unless_ that value is an empty string, in which case `true` is returned.
28549   *
28550   * Rationale: HAML data attributes which are set to `true` are rendered as a blank string.
28551   *
28552   * @param {*} value
28553   * @returns {*}
28554   */
28555  function parseTruthyAttributeValue(value) {
28556    if(value) {
28557      return value;
28558    } else if(value === '') {
28559      return true;
28560    } else {
28561      return value;
28562    }
28563  }
28564
28565  /**
28566   * Show tabs based upon the anchor component of `window.location`.
28567   */
28568  function showTabsBasedOnAnchor() {
28569    if(BootstrapTabHistory.options.showTabsBasedOnAnchor) {
28570      var anchor = window.location && window.location.hash;
28571
28572      if(anchor) {
28573        var $tabElement = showTabForSelector(anchor);
28574
28575        if($tabElement && window.addEventListener && window.removeEventListener) {
28576          var anchorYOffset = (function ($tabElement) {
28577            var elementSetting = $tabElement.data('tab-history-anchor-y-offset');
28578
28579            if(elementSetting === undefined) {
28580              return BootstrapTabHistory.options.defaultAnchorYOffset;
28581            } else {
28582              return elementSetting;
28583            }
28584          })($tabElement);
28585
28586          // HACK: This prevents scrolling to the tab on page load. This relies on the fact that we should never get
28587          //   here on `history.forward`, `history.back`, or `location.reload`, since in all those situations the
28588          //   `history.state` object should have been used (unless the browser did not support the modern History API).
28589          if(anchorYOffset || anchorYOffset === 0) {
28590            var scrollListener = function resetAnchorScroll () {
28591              window.removeEventListener('scroll', scrollListener);
28592              window.scrollTo(0, anchorYOffset);
28593            };
28594
28595            window.addEventListener('scroll', scrollListener);
28596          }
28597        }
28598      }
28599    }
28600  }
28601
28602  /**
28603   * Show a tab which corresponds to the provided selector.
28604   *
28605   * @param {string} selector - A CSS selector.
28606   * @returns {?jQuery} - The tab which was found to show (even if said tab was already active).
28607   */
28608  function showTabForSelector(selector) {
28609    var $tabElement = (function (selector) {
28610      var $ret = null;
28611
28612      jQuery('[data-toggle="tab"], [data-toggle="pill"], [data-toggle="collapse"]').each(function () {
28613        var $potentialTab = jQuery(this);
28614
28615        if(($potentialTab.attr('href') === selector || $potentialTab.data('target') === selector ) && getTabGroup($potentialTab)) {
28616          $ret = $potentialTab;
28617          return false;
vendor: 43,483 bytes, lines 28618-29834
28618        } else {
28619         return null;
28620        }
28621      });
28622
28623      return $ret;
28624    })(selector);
28625
28626    if($tabElement) {
28627      if ( !$tabElement.parent().hasClass('active') ) {
28628        $tabElement.trigger('click');
28629      }
28630      //$tabElement.tab('show');
28631    }
28632
28633    return $tabElement;
28634  }
28635
28636  /**
28637   * Iterate through the provided set of tab tab groups, showing the tabs based on the stored selectors.
28638   *
28639   * @param {object} bootstrapTabHistory - Each of the values is passed to showTabForSelector; the keys are actually irrelevant.
28640   */
28641  function showTabsBasedOnState(bootstrapTabHistory) {
28642    showingTabsBasedOnState = true;
28643
28644    try {
28645      for(var k in bootstrapTabHistory) {
28646        if(bootstrapTabHistory.hasOwnProperty(k)) {
28647          showTabForSelector(bootstrapTabHistory[k]);
28648        }
28649      }
28650    } finally {
28651      showingTabsBasedOnState = false;
28652    }
28653  }
28654})();
28655
28656/*!
28657 * justifiedGallery - v3.8.1
28658 * http://miromannino.github.io/Justified-Gallery/
28659 * Copyright (c) 2020 Miro Mannino
28660 * Licensed under the MIT license.
28661 */
28662(function (factory) {
28663  if (typeof define === 'function' && define.amd) {
28664    // AMD. Register as an anonymous module.
28665    define(['jquery'], factory);
28666  } else if (typeof module === 'object' && module.exports) {
28667    // Node/CommonJS
28668    module.exports = function (root, jQuery) {
28669      if (jQuery === undefined) {
28670        // require('jQuery') returns a factory that requires window to
28671        // build a jQuery instance, we normalize how we use modules
28672        // that require this pattern but the window provided is a noop
28673        // if it's defined (how jquery works)
28674        if (typeof window !== 'undefined') {
28675          jQuery = require('jquery');
28676        }
28677        else {
28678          jQuery = require('jquery')(root);
28679        }
28680      }
28681      factory(jQuery);
28682      return jQuery;
28683    };
28684  } else {
28685    // Browser globals
28686    factory(jQuery);
28687  }
28688}(function ($) {
28689
28690  /**
28691   * Justified Gallery controller constructor
28692   *
28693   * @param $gallery the gallery to build
28694   * @param settings the settings (the defaults are in JustifiedGallery.defaults)
28695   * @constructor
28696   */
28697  var JustifiedGallery = function ($gallery, settings) {
28698
28699    this.settings = settings;
28700    this.checkSettings();
28701
28702    this.imgAnalyzerTimeout = null;
28703    this.entries = null;
28704    this.buildingRow = {
28705      entriesBuff: [],
28706      width: 0,
28707      height: 0,
28708      aspectRatio: 0
28709    };
28710    this.lastFetchedEntry = null;
28711    this.lastAnalyzedIndex = -1;
28712    this.yield = {
28713      every: 2, // do a flush every n flushes (must be greater than 1)
28714      flushed: 0 // flushed rows without a yield
28715    };
28716    this.border = settings.border >= 0 ? settings.border : settings.margins;
28717    this.maxRowHeight = this.retrieveMaxRowHeight();
28718    this.suffixRanges = this.retrieveSuffixRanges();
28719    this.offY = this.border;
28720    this.rows = 0;
28721    this.spinner = {
28722      phase: 0,
28723      timeSlot: 150,
28724      $el: $('<div class="jg-spinner"><span></span><span></span><span></span></div>'),
28725      intervalId: null
28726    };
28727    this.scrollBarOn = false;
28728    this.checkWidthIntervalId = null;
28729    this.galleryWidth = $gallery.width();
28730    this.$gallery = $gallery;
28731
28732  };
28733
28734  /** @returns {String} the best suffix given the width and the height */
28735  JustifiedGallery.prototype.getSuffix = function (width, height) {
28736    var longestSide, i;
28737    longestSide = (width > height) ? width : height;
28738    for (i = 0; i < this.suffixRanges.length; i++) {
28739      if (longestSide <= this.suffixRanges[i]) {
28740        return this.settings.sizeRangeSuffixes[this.suffixRanges[i]];
28741      }
28742    }
28743    return this.settings.sizeRangeSuffixes[this.suffixRanges[i - 1]];
28744  };
28745
28746  /**
28747   * Remove the suffix from the string
28748   *
28749   * @returns {string} a new string without the suffix
28750   */
28751  JustifiedGallery.prototype.removeSuffix = function (str, suffix) {
28752    return str.substring(0, str.length - suffix.length);
28753  };
28754
28755  /**
28756   * @returns {boolean} a boolean to say if the suffix is contained in the str or not
28757   */
28758  JustifiedGallery.prototype.endsWith = function (str, suffix) {
28759    return str.indexOf(suffix, str.length - suffix.length) !== -1;
28760  };
28761
28762  /**
28763   * Get the used suffix of a particular url
28764   *
28765   * @param str
28766   * @returns {String} return the used suffix
28767   */
28768  JustifiedGallery.prototype.getUsedSuffix = function (str) {
28769    for (var si in this.settings.sizeRangeSuffixes) {
28770      if (this.settings.sizeRangeSuffixes.hasOwnProperty(si)) {
28771        if (this.settings.sizeRangeSuffixes[si].length === 0) continue;
28772        if (this.endsWith(str, this.settings.sizeRangeSuffixes[si])) return this.settings.sizeRangeSuffixes[si];
28773      }
28774    }
28775    return '';
28776  };
28777
28778  /**
28779   * Given an image src, with the width and the height, returns the new image src with the
28780   * best suffix to show the best quality thumbnail.
28781   *
28782   * @returns {String} the suffix to use
28783   */
28784  JustifiedGallery.prototype.newSrc = function (imageSrc, imgWidth, imgHeight, image) {
28785    var newImageSrc;
28786
28787    if (this.settings.thumbnailPath) {
28788      newImageSrc = this.settings.thumbnailPath(imageSrc, imgWidth, imgHeight, image);
28789    } else {
28790      var matchRes = imageSrc.match(this.settings.extension);
28791      var ext = (matchRes !== null) ? matchRes[0] : '';
28792      newImageSrc = imageSrc.replace(this.settings.extension, '');
28793      newImageSrc = this.removeSuffix(newImageSrc, this.getUsedSuffix(newImageSrc));
28794      newImageSrc += this.getSuffix(imgWidth, imgHeight) + ext;
28795    }
28796
28797    return newImageSrc;
28798  };
28799
28800  /**
28801   * Shows the images that is in the given entry
28802   *
28803   * @param $entry the entry
28804   * @param callback the callback that is called when the show animation is finished
28805   */
28806  JustifiedGallery.prototype.showImg = function ($entry, callback) {
28807    if (this.settings.cssAnimation) {
28808      $entry.addClass('jg-entry-visible');
28809      if (callback) callback();
28810    } else {
28811      $entry.stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback);
28812      $entry.find(this.settings.imgSelector).stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback);
28813    }
28814  };
28815
28816  /**
28817   * Extract the image src form the image, looking from the 'safe-src', and if it can't be found, from the
28818   * 'src' attribute. It saves in the image data the 'jg.originalSrc' field, with the extracted src.
28819   *
28820   * @param $image the image to analyze
28821   * @returns {String} the extracted src
28822   */
28823  JustifiedGallery.prototype.extractImgSrcFromImage = function ($image) {
28824    var imageSrc = $image.data('safe-src');
28825    var imageSrcLoc = 'data-safe-src';
28826    // Begin Uncode edit
28827    if (typeof imageSrc === 'undefined') {
28828    	var imageCurrentSrc = $image[0].currentSrc;
28829    	if (imageCurrentSrc) {
28830    		imageSrc = imageCurrentSrc;
28831    	} else {
28832    		imageSrc = $image.attr('src');
28833    	}
28834		imageSrcLoc = 'src';
28835    }
28836    // End Uncode edit
28837    $image.data('jg.originalSrc', imageSrc); // this is saved for the destroy method
28838    $image.data('jg.src', imageSrc); // this will change overtime
28839    $image.data('jg.originalSrcLoc', imageSrcLoc); // this is saved for the destroy method
28840    return imageSrc;
28841  };
28842
28843  /** @returns {jQuery} the image in the given entry */
28844  JustifiedGallery.prototype.imgFromEntry = function ($entry) {
28845    var $img = $entry.find(this.settings.imgSelector);
28846    if ($img.length === 0) $img = $entry.find('.t-entry-visual-cont img');//hacked by Uncode
28847    return $img.length === 0 ? null : $img;
28848  };
28849
28850  /** @returns {jQuery} the caption in the given entry */
28851  JustifiedGallery.prototype.captionFromEntry = function ($entry) {
28852    var $caption = $entry.find('> .jg-caption');
28853    return $caption.length === 0 ? null : $caption;
28854  };
28855
28856  /**
28857   * Display the entry
28858   *
28859   * @param {jQuery} $entry the entry to display
28860   * @param {int} x the x position where the entry must be positioned
28861   * @param y the y position where the entry must be positioned
28862   * @param imgWidth the image width
28863   * @param imgHeight the image height
28864   * @param rowHeight the row height of the row that owns the entry
28865   */
28866  JustifiedGallery.prototype.displayEntry = function ($entry, x, y, imgWidth, imgHeight, rowHeight) {
28867    $entry.width(imgWidth);
28868    $entry.height(Math.floor(rowHeight));//hacked by Uncode
28869    $entry.css('top', Math.floor(y));//hacked by Uncode
28870    $entry.css('left', x);
28871
28872    var $image = this.imgFromEntry($entry);
28873    if ($image !== null) {
28874      $image.css('width', imgWidth);
28875      $image.css('height', imgHeight);
28876      $image.css('margin-left', - imgWidth / 2);
28877      $image.css('margin-top', - imgHeight / 2);
28878
28879      // Image reloading for an high quality of thumbnails
28880      var imageSrc = $image.data('jg.src');
28881      if (imageSrc) {
28882        imageSrc = this.newSrc(imageSrc, imgWidth, imgHeight, $image[0]);
28883
28884        $image.one('error', function () {
28885           this.resetImgSrc($image); //revert to the original thumbnail
28886        });
28887
28888        var loadNewImage = function () {
28889          // if (imageSrc !== newImageSrc) {
28890            $image.attr('src', imageSrc);
28891          // }
28892        };
28893
28894        if ($entry.data('jg.loaded') === 'skipped' && imageSrc) {
28895          this.onImageEvent(imageSrc, (function() {
28896            this.showImg($entry, loadNewImage); //load the new image after the fadeIn
28897            $entry.data('jg.loaded', true);
28898          }).bind(this));
28899        } else {
28900          this.showImg($entry, loadNewImage); //load the new image after the fadeIn
28901        }
28902
28903      }
28904
28905    } else {
28906      this.showImg($entry);
28907    }
28908
28909    this.displayEntryCaption($entry);
28910  };
28911
28912  /**
28913   * Display the entry caption. If the caption element doesn't exists, it creates the caption using the 'alt'
28914   * or the 'title' attributes.
28915   *
28916   * @param {jQuery} $entry the entry to process
28917   */
28918  JustifiedGallery.prototype.displayEntryCaption = function ($entry) {
28919    var $image = this.imgFromEntry($entry);
28920    if ($image !== null && this.settings.captions) {
28921      var $imgCaption = this.captionFromEntry($entry);
28922
28923      // Create it if it doesn't exists
28924      if ($imgCaption === null) {
28925        var caption = $image.attr('alt');
28926        if (!this.isValidCaption(caption)) caption = $entry.attr('title');
28927        if (this.isValidCaption(caption)) { // Create only we found something
28928          $imgCaption = $('<div class="jg-caption">' + caption + '</div>');
28929          $entry.append($imgCaption);
28930          $entry.data('jg.createdCaption', true);
28931        }
28932      }
28933
28934      // Create events (we check again the $imgCaption because it can be still inexistent)
28935      if ($imgCaption !== null) {
28936        if (!this.settings.cssAnimation) $imgCaption.stop().fadeTo(0, this.settings.captionSettings.nonVisibleOpacity);
28937        this.addCaptionEventsHandlers($entry);
28938      }
28939    } else {
28940      this.removeCaptionEventsHandlers($entry);
28941    }
28942  };
28943
28944  /**
28945   * Validates the caption
28946   *
28947   * @param caption The caption that should be validated
28948   * @return {boolean} Validation result
28949   */
28950  JustifiedGallery.prototype.isValidCaption = function (caption) {
28951    return (typeof caption !== 'undefined' && caption.length > 0);
28952  };
28953
28954  /**
28955   * The callback for the event 'mouseenter'. It assumes that the event currentTarget is an entry.
28956   * It shows the caption using jQuery (or using CSS if it is configured so)
28957   *
28958   * @param {Event} eventObject the event object
28959   */
28960  JustifiedGallery.prototype.onEntryMouseEnterForCaption = function (eventObject) {
28961    var $caption = this.captionFromEntry($(eventObject.currentTarget));
28962    if (this.settings.cssAnimation) {
28963      $caption.addClass('jg-caption-visible').removeClass('jg-caption-hidden');
28964    } else {
28965      $caption.stop().fadeTo(this.settings.captionSettings.animationDuration,
28966        this.settings.captionSettings.visibleOpacity);
28967    }
28968  };
28969
28970  /**
28971   * The callback for the event 'mouseleave'. It assumes that the event currentTarget is an entry.
28972   * It hides the caption using jQuery (or using CSS if it is configured so)
28973   *
28974   * @param {Event} eventObject the event object
28975   */
28976  JustifiedGallery.prototype.onEntryMouseLeaveForCaption = function (eventObject) {
28977    var $caption = this.captionFromEntry($(eventObject.currentTarget));
28978    if (this.settings.cssAnimation) {
28979      $caption.removeClass('jg-caption-visible').removeClass('jg-caption-hidden');
28980    } else {
28981      $caption.stop().fadeTo(this.settings.captionSettings.animationDuration,
28982        this.settings.captionSettings.nonVisibleOpacity);
28983    }
28984  };
28985
28986  /**
28987   * Add the handlers of the entry for the caption
28988   *
28989   * @param $entry the entry to modify
28990   */
28991  JustifiedGallery.prototype.addCaptionEventsHandlers = function ($entry) {
28992    var captionMouseEvents = $entry.data('jg.captionMouseEvents');
28993    if (typeof captionMouseEvents === 'undefined') {
28994      captionMouseEvents = {
28995        mouseenter: $.proxy(this.onEntryMouseEnterForCaption, this),
28996        mouseleave: $.proxy(this.onEntryMouseLeaveForCaption, this)
28997      };
28998      $entry.on('mouseenter', undefined, undefined, captionMouseEvents.mouseenter);
28999      $entry.on('mouseleave', undefined, undefined, captionMouseEvents.mouseleave);
29000      $entry.data('jg.captionMouseEvents', captionMouseEvents);
29001    }
29002  };
29003
29004  /**
29005   * Remove the handlers of the entry for the caption
29006   *
29007   * @param $entry the entry to modify
29008   */
29009  JustifiedGallery.prototype.removeCaptionEventsHandlers = function ($entry) {
29010    var captionMouseEvents = $entry.data('jg.captionMouseEvents');
29011    if (typeof captionMouseEvents !== 'undefined') {
29012      $entry.off('mouseenter', undefined, captionMouseEvents.mouseenter);
29013      $entry.off('mouseleave', undefined, captionMouseEvents.mouseleave);
29014      $entry.removeData('jg.captionMouseEvents');
29015    }
29016  };
29017
29018  /**
29019   * Clear the building row data to be used for a new row
29020   */
29021  JustifiedGallery.prototype.clearBuildingRow = function () {
29022    this.buildingRow.entriesBuff = [];
29023    this.buildingRow.aspectRatio = 0;
29024    this.buildingRow.width = 0;
29025  };
29026
29027  /**
29028   * Justify the building row, preparing it to
29029   *
29030   * @param isLastRow
29031   * @param hiddenRow undefined or false for normal behavior. hiddenRow = true to hide the row.
29032   * @returns a boolean to know if the row has been justified or not
29033   */
29034  JustifiedGallery.prototype.prepareBuildingRow = function (isLastRow, hiddenRow) {
29035    var i, $entry, imgAspectRatio, newImgW, newImgH, justify = true;
29036    var minHeight = 0;
29037    var availableWidth = this.galleryWidth - 2 * this.border - (
29038      (this.buildingRow.entriesBuff.length - 1) * this.settings.margins);
29039    var rowHeight = Math.floor( availableWidth / this.buildingRow.aspectRatio );//hacked by Uncode
29040    var defaultRowHeight = this.settings.rowHeight;
29041    var justifiable = this.buildingRow.width / availableWidth > this.settings.justifyThreshold;
29042
29043    //Skip the last row if we can't justify it and the lastRow == 'hide'
29044    if (hiddenRow || (isLastRow && this.settings.lastRow === 'hide' && !justifiable)) {
29045      for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
29046        $entry = this.buildingRow.entriesBuff[i];
29047        if (this.settings.cssAnimation)
29048          $entry.removeClass('jg-entry-visible');
29049        else {
29050          $entry.stop().fadeTo(0, 0.1);
29051          $entry.find('> img, > a > img').fadeTo(0, 0);
29052        }
29053      }
29054      return -1;
29055    }
29056
29057    // With lastRow = nojustify, justify if is justificable (the images will not become too big)
29058    if (isLastRow && !justifiable && this.settings.lastRow !== 'justify' && this.settings.lastRow !== 'hide') {
29059      justify = false;
29060
29061      if (this.rows > 0) {
29062        defaultRowHeight = (this.offY - this.border - this.settings.margins * this.rows) / this.rows;
29063        justify = defaultRowHeight * this.buildingRow.aspectRatio / availableWidth > this.settings.justifyThreshold;
29064      }
29065    }
29066
29067    for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
29068      $entry = this.buildingRow.entriesBuff[i];
29069      imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height');
29070
29071      if (justify) {
29072        newImgW = (i === this.buildingRow.entriesBuff.length - 1) ? availableWidth : rowHeight * imgAspectRatio;
29073        newImgH = rowHeight;
29074      } else {
29075        newImgW = defaultRowHeight * imgAspectRatio;
29076        newImgH = defaultRowHeight;
29077      }
29078
29079      availableWidth -= Math.round(newImgW);
29080      $entry.data('jg.jwidth', Math.round(newImgW));
29081      $entry.data('jg.jheight', Math.ceil(newImgH));
29082      if (i === 0 || minHeight > newImgH) minHeight = newImgH;
29083    }
29084
29085    this.buildingRow.height = minHeight;
29086    return justify;
29087  };
29088
29089  /**
29090   * Flush a row: justify it, modify the gallery height accordingly to the row height
29091   *
29092   * @param isLastRow
29093   * @param hiddenRow undefined or false for normal behavior. hiddenRow = true to hide the row.
29094   */
29095  JustifiedGallery.prototype.flushRow = function (isLastRow, hiddenRow) {
29096    var settings = this.settings;
29097    var $entry, buildingRowRes, offX = this.border, i;
29098
29099    buildingRowRes = this.prepareBuildingRow(isLastRow, hiddenRow);
29100    if (hiddenRow || (isLastRow && settings.lastRow === 'hide' && buildingRowRes === -1)) {
29101      this.clearBuildingRow();
29102      return;
29103    }
29104
29105    if (this.maxRowHeight) {
29106      if (this.maxRowHeight < this.buildingRow.height) this.buildingRow.height = this.maxRowHeight;
29107    }
29108
29109    //Align last (unjustified) row
29110    if (isLastRow && (settings.lastRow === 'center' || settings.lastRow === 'right')) {
29111      var availableWidth = this.galleryWidth - 2 * this.border - (this.buildingRow.entriesBuff.length - 1) * settings.margins;
29112
29113      for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
29114        $entry = this.buildingRow.entriesBuff[i];
29115        availableWidth -= $entry.data('jg.jwidth');
29116      }
29117
29118      if (settings.lastRow === 'center')
29119        offX += Math.round(availableWidth / 2);
29120      else if (settings.lastRow === 'right')
29121        offX += availableWidth;
29122    }
29123
29124    var lastEntryIdx = this.buildingRow.entriesBuff.length - 1;
29125    for (i = 0; i <= lastEntryIdx; i++) {
29126      $entry = this.buildingRow.entriesBuff[this.settings.rtl ? lastEntryIdx - i : i];
29127      this.displayEntry($entry, offX, this.offY, $entry.data('jg.jwidth'), $entry.data('jg.jheight'), this.buildingRow.height);
29128      offX += $entry.data('jg.jwidth') + settings.margins;
29129    }
29130
29131    //Gallery Height
29132    this.galleryHeightToSet = this.offY + this.buildingRow.height + this.border;
29133    this.setGalleryTempHeight(this.galleryHeightToSet + this.getSpinnerHeight());
29134
29135    if (!isLastRow || (this.buildingRow.height <= settings.rowHeight && buildingRowRes)) {
29136      //Ready for a new row
29137      this.offY += this.buildingRow.height + settings.margins;
29138      this.rows += 1;
29139      this.clearBuildingRow();
29140      this.settings.triggerEvent.call(this, 'jg.rowflush');
29141    }
29142  };
29143
29144
29145  // Scroll position not restoring: https://github.com/miromannino/Justified-Gallery/issues/221
29146  var galleryPrevStaticHeight = 0;
29147
29148  JustifiedGallery.prototype.rememberGalleryHeight = function () {
29149    galleryPrevStaticHeight = this.$gallery.height();
29150    this.$gallery.height(galleryPrevStaticHeight);
29151  };
29152
29153  // grow only
29154  JustifiedGallery.prototype.setGalleryTempHeight = function (height) {
29155    galleryPrevStaticHeight = Math.max(height, galleryPrevStaticHeight);
29156    this.$gallery.height(galleryPrevStaticHeight);
29157  };
29158
29159  JustifiedGallery.prototype.setGalleryFinalHeight = function (height) {
29160    galleryPrevStaticHeight = height;
29161    this.$gallery.height(height);
29162  };
29163
29164  /**
29165   * Checks the width of the gallery container, to know if a new justification is needed
29166   */
29167  JustifiedGallery.prototype.checkWidth = function () {
29168    this.checkWidthIntervalId = setInterval($.proxy(function () {
29169
29170      // if the gallery is not currently visible, abort.
29171      if (!this.$gallery.is(":visible")) return;
29172
29173      var galleryWidth = parseFloat(this.$gallery.width());
29174      if (Math.abs(galleryWidth - this.galleryWidth) > this.settings.refreshSensitivity) {
29175        this.galleryWidth = galleryWidth;
29176        this.rewind();
29177
29178        this.rememberGalleryHeight();
29179
29180        // Restart to analyze
29181        this.startImgAnalyzer(true);
29182      }
29183    }, this), this.settings.refreshTime);
29184  };
29185
29186  /**
29187   * @returns {boolean} a boolean saying if the spinner is active or not
29188   */
29189  JustifiedGallery.prototype.isSpinnerActive = function () {
29190    return this.spinner.intervalId !== null;
29191  };
29192
29193  /**
29194   * @returns {int} the spinner height
29195   */
29196  JustifiedGallery.prototype.getSpinnerHeight = function () {
29197    return this.spinner.$el.innerHeight();
29198  };
29199
29200  /**
29201   * Stops the spinner animation and modify the gallery height to exclude the spinner
29202   */
29203  JustifiedGallery.prototype.stopLoadingSpinnerAnimation = function () {
29204    clearInterval(this.spinner.intervalId);
29205    this.spinner.intervalId = null;
29206    this.setGalleryTempHeight(this.$gallery.height() - this.getSpinnerHeight());
29207    this.spinner.$el.detach();
29208  };
29209
29210  /**
29211   * Starts the spinner animation
29212   */
29213  JustifiedGallery.prototype.startLoadingSpinnerAnimation = function () {
29214    var spinnerContext = this.spinner;
29215    var $spinnerPoints = spinnerContext.$el.find('span');
29216    clearInterval(spinnerContext.intervalId);
29217    this.$gallery.append(spinnerContext.$el);
29218    this.setGalleryTempHeight(this.offY + this.buildingRow.height + this.getSpinnerHeight());
29219    spinnerContext.intervalId = setInterval(function () {
29220      if (spinnerContext.phase < $spinnerPoints.length) {
29221        $spinnerPoints.eq(spinnerContext.phase).fadeTo(spinnerContext.timeSlot, 1);
29222      } else {
29223        $spinnerPoints.eq(spinnerContext.phase - $spinnerPoints.length).fadeTo(spinnerContext.timeSlot, 0);
29224      }
29225      spinnerContext.phase = (spinnerContext.phase + 1) % ($spinnerPoints.length * 2);
29226    }, spinnerContext.timeSlot);
29227  };
29228
29229  /**
29230   * Rewind the image analysis to start from the first entry.
29231   */
29232  JustifiedGallery.prototype.rewind = function () {
29233    this.lastFetchedEntry = null;
29234    this.lastAnalyzedIndex = -1;
29235    this.offY = this.border;
29236    this.rows = 0;
29237    this.clearBuildingRow();
29238  };
29239
29240  /**
29241   * @returns {String} `settings.selector` rejecting spinner element
29242   */
29243  JustifiedGallery.prototype.getSelectorWithoutSpinner = function () {
29244    return this.settings.selector + ', div:not(.jg-spinner)';
29245  };
29246
29247  /**
29248   * @returns {Array} all entries matched by `settings.selector`
29249   */
29250  JustifiedGallery.prototype.getAllEntries = function () {
29251    var selector = this.getSelectorWithoutSpinner();
29252    return this.$gallery.children(selector).toArray();
29253  };
29254
29255  /**
29256   * Update the entries searching it from the justified gallery HTML element
29257   *
29258   * @param norewind if norewind only the new entries will be changed (i.e. randomized, sorted or filtered)
29259   * @returns {boolean} true if some entries has been founded
29260   */
29261  JustifiedGallery.prototype.updateEntries = function (norewind) {
29262    var newEntries;
29263
29264    if (norewind && this.lastFetchedEntry != null) {
29265      var selector = this.getSelectorWithoutSpinner();
29266      newEntries = $(this.lastFetchedEntry).nextAll(selector).toArray();
29267    } else {
29268      this.entries = [];
29269      newEntries = this.getAllEntries();
29270    }
29271
29272    if (newEntries.length > 0) {
29273
29274      // Sort or randomize
29275      if ($.isFunction(this.settings.sort)) {
29276        newEntries = this.sortArray(newEntries);
29277      } else if (this.settings.randomize) {
29278        newEntries = this.shuffleArray(newEntries);
29279      }
29280      this.lastFetchedEntry = newEntries[newEntries.length - 1];
29281
29282      // Filter
29283      if (this.settings.filter) {
29284        newEntries = this.filterArray(newEntries);
29285      } else {
29286        this.resetFilters(newEntries);
29287      }
29288
29289    }
29290
29291    this.entries = this.entries.concat(newEntries);
29292    return true;
29293  };
29294
29295  /**
29296   * Apply the entries order to the DOM, iterating the entries and appending the images
29297   *
29298   * @param entries the entries that has been modified and that must be re-ordered in the DOM
29299   */
29300  JustifiedGallery.prototype.insertToGallery = function (entries) {
29301    var that = this;
29302    $.each(entries, function () {
29303      $(this).appendTo(that.$gallery);
29304    });
29305  };
29306
29307  /**
29308   * Shuffle the array using the Fisher-Yates shuffle algorithm
29309   *
29310   * @param a the array to shuffle
29311   * @return the shuffled array
29312   */
29313  JustifiedGallery.prototype.shuffleArray = function (a) {
29314    var i, j, temp;
29315    for (i = a.length - 1; i > 0; i--) {
29316      j = Math.floor(Math.random() * (i + 1));
29317      temp = a[i];
29318      a[i] = a[j];
29319      a[j] = temp;
29320    }
29321    this.insertToGallery(a);
29322    return a;
29323  };
29324
29325  /**
29326   * Sort the array using settings.comparator as comparator
29327   *
29328   * @param a the array to sort (it is sorted)
29329   * @return the sorted array
29330   */
29331  JustifiedGallery.prototype.sortArray = function (a) {
29332    a.sort(this.settings.sort);
29333    this.insertToGallery(a);
29334    return a;
29335  };
29336
29337  /**
29338   * Reset the filters removing the 'jg-filtered' class from all the entries
29339   *
29340   * @param a the array to reset
29341   */
29342  JustifiedGallery.prototype.resetFilters = function (a) {
29343    for (var i = 0; i < a.length; i++) $(a[i]).removeClass('jg-filtered');
29344  };
29345
29346  /**
29347   * Filter the entries considering theirs classes (if a string has been passed) or using a function for filtering.
29348   *
29349   * @param a the array to filter
29350   * @return the filtered array
29351   */
29352  JustifiedGallery.prototype.filterArray = function (a) {
29353    var settings = this.settings;
29354    if ($.type(settings.filter) === 'string') {
29355      // Filter only keeping the entries passed in the string
29356      return a.filter(function (el) {
29357        var $el = $(el);
29358        if ($el.is(settings.filter)) {
29359          $el.removeClass('jg-filtered');
29360          return true;
29361        } else {
29362          $el.addClass('jg-filtered').removeClass('jg-visible');
29363          return false;
29364        }
29365      });
29366    } else if ($.isFunction(settings.filter)) {
29367      // Filter using the passed function
29368      var filteredArr = a.filter(settings.filter);
29369      for (var i = 0; i < a.length; i++) {
29370        if (filteredArr.indexOf(a[i]) === -1) {
29371          $(a[i]).addClass('jg-filtered').removeClass('jg-visible');
29372        } else {
29373          $(a[i]).removeClass('jg-filtered');
29374        }
29375      }
29376      return filteredArr;
29377    }
29378  };
29379
29380  /**
29381   * Revert the image src to the default value.
29382   */
29383  JustifiedGallery.prototype.resetImgSrc = function ($img) {
29384    if ($img.data('jg.originalSrcLoc') === 'src') {
29385      $img.attr('src', $img.data('jg.originalSrc'));
29386    } else {
29387      $img.attr('src', '');
29388    }
29389  };
29390
29391  /**
29392   * Destroy the Justified Gallery instance.
29393   *
29394   * It clears all the css properties added in the style attributes. We doesn't backup the original
29395   * values for those css attributes, because it costs (performance) and because in general one
29396   * shouldn't use the style attribute for an uniform set of images (where we suppose the use of
29397   * classes). Creating a backup is also difficult because JG could be called multiple times and
29398   * with different style attributes.
29399   */
29400  JustifiedGallery.prototype.destroy = function () {
29401    clearInterval(this.checkWidthIntervalId);
29402    this.stopImgAnalyzerStarter();
29403
29404    // Get fresh entries list since filtered entries are absent in `this.entries`
29405    $.each(this.getAllEntries(), $.proxy(function (_, entry) {
29406      var $entry = $(entry);
29407
29408      // Reset entry style
29409      $entry.css('width', '');
29410      $entry.css('height', '');
29411      $entry.css('top', '');
29412      $entry.css('left', '');
29413      $entry.data('jg.loaded', undefined);
29414      $entry.removeClass('jg-entry jg-filtered jg-entry-visible');
29415
29416      // Reset image style
29417      var $img = this.imgFromEntry($entry);
29418      if ($img) {
29419        $img.css('width', '');
29420        $img.css('height', '');
29421        $img.css('margin-left', '');
29422        $img.css('margin-top', '');
29423        this.resetImgSrc($img);
29424        $img.data('jg.originalSrc', undefined);
29425        $img.data('jg.originalSrcLoc', undefined);
29426        $img.data('jg.src', undefined);
29427      }
29428
29429      // Remove caption
29430      this.removeCaptionEventsHandlers($entry);
29431      var $caption = this.captionFromEntry($entry);
29432      if ($entry.data('jg.createdCaption')) {
29433        // remove also the caption element (if created by jg)
29434        $entry.data('jg.createdCaption', undefined);
29435        if ($caption !== null) $caption.remove();
29436      } else {
29437        if ($caption !== null) $caption.fadeTo(0, 1);
29438      }
29439
29440    }, this));
29441
29442    this.$gallery.css('height', '');
29443    this.$gallery.removeClass('justified-gallery');
29444    this.$gallery.data('jg.controller', undefined);
29445    this.settings.triggerEvent.call(this, 'jg.destroy');
29446  };
29447
29448  /**
29449   * Analyze the images and builds the rows. It returns if it found an image that is not loaded.
29450   *
29451   * @param isForResize if the image analyzer is called for resizing or not, to call a different callback at the end
29452   */
29453  JustifiedGallery.prototype.analyzeImages = function (isForResize) {
29454    for (var i = this.lastAnalyzedIndex + 1; i < this.entries.length; i++) {
29455      var $entry = $(this.entries[i]);
29456      if ($entry.data('jg.loaded') === true || $entry.data('jg.loaded') === 'skipped') {
29457        var availableWidth = this.galleryWidth - 2 * this.border - (
29458          (this.buildingRow.entriesBuff.length - 1) * this.settings.margins);
29459        var imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height');
29460
29461        this.buildingRow.entriesBuff.push($entry);
29462        this.buildingRow.aspectRatio += imgAspectRatio;
29463        this.buildingRow.width += imgAspectRatio * this.settings.rowHeight;
29464        this.lastAnalyzedIndex = i;
29465
29466        if (availableWidth / (this.buildingRow.aspectRatio + imgAspectRatio) < this.settings.rowHeight) {
29467          this.flushRow(false, this.settings.maxRowsCount > 0 && this.rows === this.settings.maxRowsCount);
29468
29469          if (++this.yield.flushed >= this.yield.every) {
29470            this.startImgAnalyzer(isForResize);
29471            return;
29472          }
29473        }
29474      } else if ($entry.data('jg.loaded') !== 'error') {
29475        return;
29476      }
29477    }
29478
29479    // Last row flush (the row is not full)
29480    if (this.buildingRow.entriesBuff.length > 0) {
29481      this.flushRow(true, this.settings.maxRowsCount > 0 && this.rows === this.settings.maxRowsCount);
29482    }
29483
29484    if (this.isSpinnerActive()) {
29485      this.stopLoadingSpinnerAnimation();
29486    }
29487
29488    /* Stop, if there is, the timeout to start the analyzeImages.
29489     This is because an image can be set loaded, and the timeout can be set,
29490     but this image can be analyzed yet.
29491     */
29492    this.stopImgAnalyzerStarter();
29493
29494    this.setGalleryFinalHeight(this.galleryHeightToSet);
29495
29496    //On complete callback
29497    this.settings.triggerEvent.call(this, isForResize ? 'jg.resize' : 'jg.complete');
29498  };
29499
29500  /**
29501   * Stops any ImgAnalyzer starter (that has an assigned timeout)
29502   */
29503  JustifiedGallery.prototype.stopImgAnalyzerStarter = function () {
29504    this.yield.flushed = 0;
29505    if (this.imgAnalyzerTimeout !== null) {
29506      clearTimeout(this.imgAnalyzerTimeout);
29507      this.imgAnalyzerTimeout = null;
29508    }
29509  };
29510
29511  /**
29512   * Starts the image analyzer. It is not immediately called to let the browser to update the view
29513   *
29514   * @param isForResize specifies if the image analyzer must be called for resizing or not
29515   */
29516  JustifiedGallery.prototype.startImgAnalyzer = function (isForResize) {
29517    var that = this;
29518    this.stopImgAnalyzerStarter();
29519    this.imgAnalyzerTimeout = setTimeout(function () {
29520      that.analyzeImages(isForResize);
29521    }, 0.001); // we can't start it immediately due to a IE different behaviour
29522  };
29523
29524  /**
29525   * Checks if the image is loaded or not using another image object. We cannot use the 'complete' image property,
29526   * because some browsers, with a 404 set complete = true.
29527   *
29528   * @param imageSrc the image src to load
29529   * @param onLoad callback that is called when the image has been loaded
29530   * @param onError callback that is called in case of an error
29531   */
29532  JustifiedGallery.prototype.onImageEvent = function (imageSrc, onLoad, onError) {
29533    if (!onLoad && !onError) return;
29534
29535    var memImage = new Image();
29536    var $memImage = $(memImage);
29537    if (onLoad) {
29538      $memImage.one('load', function () {
29539        $memImage.off('load error');
29540        onLoad(memImage);
29541      });
29542    }
29543    if (onError) {
29544      $memImage.one('error', function () {
29545        $memImage.off('load error');
29546        onError(memImage);
29547      });
29548    }
29549    memImage.src = imageSrc;
29550  };
29551
29552  /**
29553   * Init of Justified Gallery controlled
29554   * It analyzes all the entries starting theirs loading and calling the image analyzer (that works with loaded images)
29555   */
29556  JustifiedGallery.prototype.init = function () {
29557    var imagesToLoad = false, skippedImages = false, that = this;
29558    $.each(this.entries, function (index, entry) {
29559      var $entry = $(entry);
29560      var $image = that.imgFromEntry($entry);
29561
29562      $entry.addClass('jg-entry');
29563
29564      if ($entry.data('jg.loaded') !== true && $entry.data('jg.loaded') !== 'skipped') {
29565
29566        // Link Rel global overwrite
29567        if (that.settings.rel !== null) $entry.attr('rel', that.settings.rel);
29568
29569        // Link Target global overwrite
29570        if (that.settings.target !== null) $entry.attr('target', that.settings.target);
29571
29572        if ($image !== null) {
29573
29574          // Image src
29575          var imageSrc = that.extractImgSrcFromImage($image);
29576
29577          /* If we have the height and the width, we don't wait that the image is loaded,
29578             but we start directly with the justification */
29579          if (that.settings.waitThumbnailsLoad === false || !imageSrc) {
29580            var width = parseFloat($image.attr('width'));
29581            var height = parseFloat($image.attr('height'));
29582            if ($image.prop('tagName') === 'svg') {
29583              width = parseFloat($image[0].getBBox().width);
29584              height = parseFloat($image[0].getBBox().height);
29585            }
29586            if (!isNaN(width) && !isNaN(height)) {
29587              $entry.data('jg.width', width);
29588              $entry.data('jg.height', height);
29589              $entry.data('jg.loaded', 'skipped');
29590              skippedImages = true;
29591              that.startImgAnalyzer(false);
29592              return true; // continue
29593            }
29594          }
29595
29596          $entry.data('jg.loaded', false);
29597          imagesToLoad = true;
29598
29599          // Spinner start
29600          if (!that.isSpinnerActive()) that.startLoadingSpinnerAnimation();
29601
29602          that.onImageEvent(imageSrc, function (loadImg) { // image loaded
29603            $entry.data('jg.width', loadImg.width);
29604            $entry.data('jg.height', loadImg.height);
29605            $entry.data('jg.loaded', true);
29606            that.startImgAnalyzer(false);
29607          }, function () { // image load error
29608            $entry.data('jg.loaded', 'error');
29609            that.startImgAnalyzer(false);
29610          });
29611
29612        } else {
29613          $entry.data('jg.loaded', true);
29614          $entry.data('jg.width', $entry.width() | parseFloat($entry.css('width')) | 1);
29615          $entry.data('jg.height', $entry.height() | parseFloat($entry.css('height')) | 1);
29616        }
29617
29618      }
29619
29620    });
29621
29622    if (!imagesToLoad && !skippedImages) this.startImgAnalyzer(false);
29623    this.checkWidth();
29624  };
29625
29626  /**
29627   * Checks that it is a valid number. If a string is passed it is converted to a number
29628   *
29629   * @param settingContainer the object that contains the setting (to allow the conversion)
29630   * @param settingName the setting name
29631   */
29632  JustifiedGallery.prototype.checkOrConvertNumber = function (settingContainer, settingName) {
29633    if ($.type(settingContainer[settingName]) === 'string') {
29634      settingContainer[settingName] = parseFloat(settingContainer[settingName]);
29635    }
29636
29637    if ($.type(settingContainer[settingName]) === 'number') {
29638      if (isNaN(settingContainer[settingName])) throw 'invalid number for ' + settingName;
29639    } else {
29640      throw settingName + ' must be a number';
29641    }
29642  };
29643
29644  /**
29645   * Checks the sizeRangeSuffixes and, if necessary, converts
29646   * its keys from string (e.g. old settings with 'lt100') to int.
29647   */
29648  JustifiedGallery.prototype.checkSizeRangesSuffixes = function () {
29649    if ($.type(this.settings.sizeRangeSuffixes) !== 'object') {
29650      throw 'sizeRangeSuffixes must be defined and must be an object';
29651    }
29652
29653    var suffixRanges = [];
29654    for (var rangeIdx in this.settings.sizeRangeSuffixes) {
29655      if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(rangeIdx);
29656    }
29657
29658    var newSizeRngSuffixes = { 0: '' };
29659    for (var i = 0; i < suffixRanges.length; i++) {
29660      if ($.type(suffixRanges[i]) === 'string') {
29661        try {
29662          var numIdx = parseInt(suffixRanges[i].replace(/^[a-z]+/, ''), 10);
29663          newSizeRngSuffixes[numIdx] = this.settings.sizeRangeSuffixes[suffixRanges[i]];
29664        } catch (e) {
29665          throw 'sizeRangeSuffixes keys must contains correct numbers (' + e + ')';
29666        }
29667      } else {
29668        newSizeRngSuffixes[suffixRanges[i]] = this.settings.sizeRangeSuffixes[suffixRanges[i]];
29669      }
29670    }
29671
29672    this.settings.sizeRangeSuffixes = newSizeRngSuffixes;
29673  };
29674
29675  /**
29676   * check and convert the maxRowHeight setting
29677   * requires rowHeight to be already set
29678   * TODO: should be always called when only rowHeight is changed
29679   * @return number or null
29680   */
29681  JustifiedGallery.prototype.retrieveMaxRowHeight = function () {
29682    var newMaxRowHeight = null;
29683    var rowHeight = this.settings.rowHeight;
29684
29685    if ($.type(this.settings.maxRowHeight) === 'string') {
29686      if (this.settings.maxRowHeight.match(/^[0-9]+%$/)) {
29687        newMaxRowHeight = rowHeight * parseFloat(this.settings.maxRowHeight.match(/^([0-9]+)%$/)[1]) / 100;
29688      } else {
29689        newMaxRowHeight = parseFloat(this.settings.maxRowHeight);
29690      }
29691    } else if ($.type(this.settings.maxRowHeight) === 'number') {
29692      newMaxRowHeight = this.settings.maxRowHeight;
29693    } else if (this.settings.maxRowHeight === false || this.settings.maxRowHeight == null) {
29694      return null;
29695    } else {
29696      throw 'maxRowHeight must be a number or a percentage';
29697    }
29698
29699    // check if the converted value is not a number
29700    if (isNaN(newMaxRowHeight)) throw 'invalid number for maxRowHeight';
29701
29702    // check values, maxRowHeight must be >= rowHeight
29703    if (newMaxRowHeight < rowHeight) newMaxRowHeight = rowHeight;
29704
29705    return newMaxRowHeight;
29706  };
29707
29708  /**
29709   * Checks the settings
29710   */
29711  JustifiedGallery.prototype.checkSettings = function () {
29712    this.checkSizeRangesSuffixes();
29713
29714    this.checkOrConvertNumber(this.settings, 'rowHeight');
29715    this.checkOrConvertNumber(this.settings, 'margins');
29716    this.checkOrConvertNumber(this.settings, 'border');
29717    this.checkOrConvertNumber(this.settings, 'maxRowsCount');
29718
29719    var lastRowModes = [
29720      'justify',
29721      'nojustify',
29722      'left',
29723      'center',
29724      'right',
29725      'hide'
29726    ];
29727    if (lastRowModes.indexOf(this.settings.lastRow) === -1) {
29728      throw 'lastRow must be one of: ' + lastRowModes.join(', ');
29729    }
29730
29731    this.checkOrConvertNumber(this.settings, 'justifyThreshold');
29732    if (this.settings.justifyThreshold < 0 || this.settings.justifyThreshold > 1) {
29733      throw 'justifyThreshold must be in the interval [0,1]';
29734    }
29735    if ($.type(this.settings.cssAnimation) !== 'boolean') {
29736      throw 'cssAnimation must be a boolean';
29737    }
29738
29739    if ($.type(this.settings.captions) !== 'boolean') throw 'captions must be a boolean';
29740    this.checkOrConvertNumber(this.settings.captionSettings, 'animationDuration');
29741
29742    this.checkOrConvertNumber(this.settings.captionSettings, 'visibleOpacity');
29743    if (this.settings.captionSettings.visibleOpacity < 0 ||
29744      this.settings.captionSettings.visibleOpacity > 1) {
29745      throw 'captionSettings.visibleOpacity must be in the interval [0, 1]';
29746    }
29747
29748    this.checkOrConvertNumber(this.settings.captionSettings, 'nonVisibleOpacity');
29749    if (this.settings.captionSettings.nonVisibleOpacity < 0 ||
29750      this.settings.captionSettings.nonVisibleOpacity > 1) {
29751      throw 'captionSettings.nonVisibleOpacity must be in the interval [0, 1]';
29752    }
29753
29754    this.checkOrConvertNumber(this.settings, 'imagesAnimationDuration');
29755    this.checkOrConvertNumber(this.settings, 'refreshTime');
29756    this.checkOrConvertNumber(this.settings, 'refreshSensitivity');
29757    if ($.type(this.settings.randomize) !== 'boolean') throw 'randomize must be a boolean';
29758    if ($.type(this.settings.selector) !== 'string') throw 'selector must be a string';
29759
29760    if (this.settings.sort !== false && !$.isFunction(this.settings.sort)) {
29761      throw 'sort must be false or a comparison function';
29762    }
29763
29764    if (this.settings.filter !== false && !$.isFunction(this.settings.filter) &&
29765      $.type(this.settings.filter) !== 'string') {
29766      throw 'filter must be false, a string or a filter function';
29767    }
29768  };
29769
29770  /**
29771   * It brings all the indexes from the sizeRangeSuffixes and it orders them. They are then sorted and returned.
29772   * @returns {Array} sorted suffix ranges
29773   */
29774  JustifiedGallery.prototype.retrieveSuffixRanges = function () {
29775    var suffixRanges = [];
29776    for (var rangeIdx in this.settings.sizeRangeSuffixes) {
29777      if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(parseInt(rangeIdx, 10));
29778    }
29779    suffixRanges.sort(function (a, b) { return a > b ? 1 : a < b ? -1 : 0; });
29780    return suffixRanges;
29781  };
29782
29783  /**
29784   * Update the existing settings only changing some of them
29785   *
29786   * @param newSettings the new settings (or a subgroup of them)
29787   */
29788  JustifiedGallery.prototype.updateSettings = function (newSettings) {
29789    // In this case Justified Gallery has been called again changing only some options
29790    this.settings = $.extend({}, this.settings, newSettings);
29791    this.checkSettings();
29792
29793    // As reported in the settings: negative value = same as margins, 0 = disabled
29794    this.border = this.settings.border >= 0 ? this.settings.border : this.settings.margins;
29795
29796    this.maxRowHeight = this.retrieveMaxRowHeight();
29797    this.suffixRanges = this.retrieveSuffixRanges();
29798  };
29799
29800  JustifiedGallery.prototype.defaults = {
29801    sizeRangeSuffixes: {}, /* e.g. Flickr configuration
29802        {
29803          100: '_t',  // used when longest is less than 100px
29804          240: '_m',  // used when longest is between 101px and 240px
29805          320: '_n',  // ...
29806          500: '',
29807          640: '_z',
29808          1024: '_b'  // used as else case because it is the last
29809        }
29810    */
29811    thumbnailPath: undefined, /* If defined, sizeRangeSuffixes is not used, and this function is used to determine the
29812    path relative to a specific thumbnail size. The function should accept respectively three arguments:
29813    current path, width and height */
29814    rowHeight: 120, // required? required to be > 0?
29815    maxRowHeight: false, // false or negative value to deactivate. Positive number to express the value in pixels,
29816    // A string '[0-9]+%' to express in percentage (e.g. 300% means that the row height
29817    // can't exceed 3 * rowHeight)
29818    maxRowsCount: 0, // maximum number of rows to be displayed (0 = disabled)
29819    margins: 1,
29820    border: -1, // negative value = same as margins, 0 = disabled, any other value to set the border
29821
29822    lastRow: 'nojustify', // … which is the same as 'left', or can be 'justify', 'center', 'right' or 'hide'
29823
29824    justifyThreshold: 0.90, /* if row width / available space > 0.90 it will be always justified
29825                             * (i.e. lastRow setting is not considered) */
29826    waitThumbnailsLoad: true,
29827    captions: true,
29828    cssAnimation: true,
29829    imagesAnimationDuration: 500, // ignored with css animations
29830    captionSettings: { // ignored with css animations
29831      animationDuration: 500,
29832      visibleOpacity: 0.7,
29833      nonVisibleOpacity: 0.0
29834    },
29835    rel: null, // rewrite the rel of each analyzed links
29836    target: null, // rewrite the target of all links
29837    extension: /\.[^.\\/]+$/, // regexp to capture the extension of an image
29838    refreshTime: 200, // time interval (in ms) to check if the page changes its width
29839    refreshSensitivity: 0, // change in width allowed (in px) without re-building the gallery
29840    randomize: false,
29841    rtl: false, // right-to-left mode
29842    sort: false, /*
29843      - false: to do not sort
29844      - function: to sort them using the function as comparator (see Array.prototype.sort())
29845    */
29846    filter: false, /*
29847      - false, null or undefined: for a disabled filter
29848      - a string: an entry is kept if entry.is(filter string) returns true
29849                  see jQuery's .is() function for further information
29850      - a function: invoked with arguments (entry, index, array). Return true to keep the entry, false otherwise.
29851                    It follows the specifications of the Array.prototype.filter() function of JavaScript.
29852    */
29853    selector: 'a', // The selector that is used to know what are the entries of the gallery
29854    imgSelector: '> img, > a > img, > svg, > a > svg', // The selector that is used to know what are the images of each entry
29855    triggerEvent: function (event) { // This is called to trigger events, the default behavior is to call $.trigger
29856      this.$gallery.trigger(event);  // Consider that 'this' is this set to the JustifiedGallery object, so it can
29857    }                                // access to fields such as $gallery, useful to trigger events with jQuery.
29858  };
29859
29860
29861  /**
29862   * Justified Gallery plugin for jQuery
29863   *
29864   * Events
29865   *  - jg.complete : called when all the gallery has been created
29866   *  - jg.resize : called when the gallery has been resized
29867   *  - jg.rowflush : when a new row appears
29868   *
29869   * @param arg the action (or the settings) passed when the plugin is called
29870   * @returns {*} the object itself
29871   */
29872  $.fn.justifiedGallery = function (arg) {
29873    return this.each(function (index, gallery) {
29874
29875      var $gallery = $(gallery);
29876      $gallery.addClass('justified-gallery');
29877
29878      var controller = $gallery.data('jg.controller');
29879      if (typeof controller === 'undefined') {
29880        // Create controller and assign it to the object data
29881        if (typeof arg !== 'undefined' && arg !== null && $.type(arg) !== 'object') {
29882          if (arg === 'destroy') return; // Just a call to an unexisting object
29883          throw 'The argument must be an object';
29884        }
29885        controller = new JustifiedGallery($gallery, $.extend({}, JustifiedGallery.prototype.defaults, arg));
29886        $gallery.data('jg.controller', controller);
29887      } else if (arg === 'norewind') {
29888        // In this case we don't rewind: we analyze only the latest images (e.g. to complete the last unfinished row
29889        // ... left to be more readable
29890      } else if (arg === 'destroy') {
29891        controller.destroy();
29892        return;
29893      } else {
29894        // In this case Justified Gallery has been called again changing only some options
29895        controller.updateSettings(arg);
29896        controller.rewind();
29897      }
29898
29899      // Update the entries list
29900      if (!controller.updateEntries(arg === 'norewind')) return;
29901
29902      // Init justified gallery
29903      controller.init();
29904
29905    });
29906  };
29907
29908}));
29909
29910/*!
29911* Customized version of iScroll.js 0.0.1
29912* It fixes bugs affecting its integration with fullpage.js
29913*/
29914/*! iScroll v5.2.0 ~ (c) 2008-2016 Matteo Spinelli ~ http://cubiq.org/license */
29915(function (window, document, Math) {
29916var rAF = window.requestAnimationFrame  ||
29917    window.webkitRequestAnimationFrame  ||
29918    window.mozRequestAnimationFrame     ||
29919    window.oRequestAnimationFrame       ||
29920    window.msRequestAnimationFrame      ||
29921    function (callback) { window.setTimeout(callback, 1000 / 60); };
29922
29923var utils = (function () {
29924    var me = {};
29925
29926    var _elementStyle = document.createElement('div').style;
29927    var _vendor = (function () {
29928        var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'],
29929            transform,
29930            i = 0,
29931            l = vendors.length;
29932
29933        for ( ; i < l; i++ ) {
29934            transform = vendors[i] + 'ransform';
29935            if ( transform in _elementStyle ) return vendors[i].substr(0, vendors[i].length-1);
29936        }
29937
29938        return false;
29939    })();
29940
29941    function _prefixStyle (style) {
29942        if ( _vendor === false ) return false;
29943        if ( _vendor === '' ) return style;
29944        return _vendor + style.charAt(0).toUpperCase() + style.substr(1);
29945    }
29946
29947    me.getTime = Date.now || function getTime () { return new Date().getTime(); };
29948
29949    me.extend = function (target, obj) {
29950        for ( var i in obj ) {
29951            target[i] = obj[i];
29952        }
29953    };
29954
29955    me.addEvent = function (el, type, fn, capture) {
29956        el.addEventListener(type, fn, !!capture);
29957    };
29958
29959    me.removeEvent = function (el, type, fn, capture) {
29960        el.removeEventListener(type, fn, !!capture);
29961    };
29962
29963    me.prefixPointerEvent = function (pointerEvent) {
29964        return window.MSPointerEvent ?
29965            'MSPointer' + pointerEvent.charAt(7).toUpperCase() + pointerEvent.substr(8):
29966            pointerEvent;
29967    };
29968
29969    me.momentum = function (current, start, time, lowerMargin, wrapperSize, deceleration) {
29970        var distance = current - start,
29971            speed = Math.abs(distance) / time,
29972            destination,
29973            duration;
29974
29975        deceleration = deceleration === undefined ? 0.0006 : deceleration;
29976
29977        destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 );
29978        duration = speed / deceleration;
29979
29980        if ( destination < lowerMargin ) {
29981            destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin;
29982            distance = Math.abs(destination - current);
29983            duration = distance / speed;
29984        } else if ( destination > 0 ) {
29985            destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0;
29986            distance = Math.abs(current) + destination;
29987            duration = distance / speed;
29988        }
29989
29990        return {
29991            destination: Math.round(destination),
29992            duration: duration
29993        };
29994    };
29995
29996    var _transform = _prefixStyle('transform');
29997
29998    me.extend(me, {
29999        hasTransform: _transform !== false,
30000        hasPerspective: _prefixStyle('perspective') in _elementStyle,
30001        hasTouch: 'ontouchstart' in window,
30002        hasPointer: !!(window.PointerEvent || window.MSPointerEvent), // IE10 is prefixed
30003        hasTransition: _prefixStyle('transition') in _elementStyle
30004    });
30005
30006    /*
30007    This should find all Android browsers lower than build 535.19 (both stock browser and webview)
30008    - galaxy S2 is ok
30009    - 2.3.6 : `AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1`
30010    - 4.0.4 : `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
30011   - galaxy S3 is badAndroid (stock brower, webview)
30012     `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
30013   - galaxy S4 is badAndroid (stock brower, webview)
30014     `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
30015   - galaxy S5 is OK
30016     `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`
30017   - galaxy S6 is OK
30018     `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`
30019  */
30020    me.isBadAndroid = (function() {
30021        var appVersion = window.navigator.appVersion;
30022        // Android browser is not a chrome browser.
30023        if (/Android/.test(appVersion) && !(/Chrome\/\d/.test(appVersion))) {
30024            var safariVersion = appVersion.match(/Safari\/(\d+.\d)/);
30025            if(safariVersion && typeof safariVersion === "object" && safariVersion.length >= 2) {
30026                return parseFloat(safariVersion[1]) < 535.19;
30027            } else {
30028                return true;
30029            }
30030        } else {
30031            return false;
30032        }
30033    })();
30034
30035    me.extend(me.style = {}, {
30036        transform: _transform,
30037        transitionTimingFunction: _prefixStyle('transitionTimingFunction'),
30038        transitionDuration: _prefixStyle('transitionDuration'),
30039        transitionDelay: _prefixStyle('transitionDelay'),
30040        transformOrigin: _prefixStyle('transformOrigin')
30041    });
30042
30043    me.hasClass = function (e, c) {
30044        var re = new RegExp("(^|\\s)" + c + "(\\s|$)");
30045        return re.test(e.className);
30046    };
30047
30048    me.addClass = function (e, c) {
30049        if ( me.hasClass(e, c) ) {
30050            return;
30051        }
30052
30053        var newclass = e.className.split(' ');
30054        newclass.push(c);
30055        e.className = newclass.join(' ');
30056    };
30057
30058    me.removeClass = function (e, c) {
30059        if ( !me.hasClass(e, c) ) {
30060            return;
30061        }
30062
30063        var re = new RegExp("(^|\\s)" + c + "(\\s|$)", 'g');
30064        e.className = e.className.replace(re, ' ');
30065    };
30066
30067    me.offset = function (el) {
30068        var left = -el.offsetLeft,
30069            top = -el.offsetTop;
30070
30071        // jshint -W084
30072        while (el = el.offsetParent) {
30073            left -= el.offsetLeft;
30074            top -= el.offsetTop;
30075        }
30076        // jshint +W084
30077
30078        return {
30079            left: left,
30080            top: top
30081        };
30082    };
30083
30084    me.preventDefaultException = function (el, exceptions) {
30085        for ( var i in exceptions ) {
30086            if ( exceptions[i].test(el[i]) ) {
30087                return true;
30088            }
30089        }
30090
30091        return false;
30092    };
30093
30094    me.extend(me.eventType = {}, {
30095        touchstart: 1,
30096        touchmove: 1,
30097        touchend: 1,
30098
30099        mousedown: 2,
30100        mousemove: 2,
30101        mouseup: 2,
30102
30103        pointerdown: 3,
30104        pointermove: 3,
30105        pointerup: 3,
30106
30107        MSPointerDown: 3,
30108        MSPointerMove: 3,
30109        MSPointerUp: 3
30110    });
30111
30112    me.extend(me.ease = {}, {
30113        quadratic: {
30114            style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
30115            fn: function (k) {
30116                return k * ( 2 - k );
30117            }
30118        },
30119        circular: {
30120            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)
30121            fn: function (k) {
30122                return Math.sqrt( 1 - ( --k * k ) );
30123            }
30124        },
30125        back: {
30126            style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)',
30127            fn: function (k) {
30128                var b = 4;
30129                return ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1;
30130            }
30131        },
30132        bounce: {
30133            style: '',
30134            fn: function (k) {
30135                if ( ( k /= 1 ) < ( 1 / 2.75 ) ) {
30136                    return 7.5625 * k * k;
30137                } else if ( k < ( 2 / 2.75 ) ) {
30138                    return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75;
30139                } else if ( k < ( 2.5 / 2.75 ) ) {
30140                    return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375;
30141                } else {
30142                    return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375;
30143                }
30144            }
30145        },
30146        elastic: {
30147            style: '',
30148            fn: function (k) {
30149                var f = 0.22,
30150                    e = 0.4;
30151
30152                if ( k === 0 ) { return 0; }
30153                if ( k == 1 ) { return 1; }
30154
30155                return ( e * Math.pow( 2, - 10 * k ) * Math.sin( ( k - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 );
30156            }
30157        }
30158    });
30159
30160    me.tap = function (e, eventName) {
30161        var ev = document.createEvent('Event');
30162        ev.initEvent(eventName, true, true);
30163        ev.pageX = e.pageX;
30164        ev.pageY = e.pageY;
30165        e.target.dispatchEvent(ev);
30166    };
30167
30168    me.click = function (e) {
30169        var target = e.target,
30170            ev;
30171
30172        if ( !(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName) ) {
30173            // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent
30174            // initMouseEvent is deprecated.
30175            ev = document.createEvent(window.MouseEvent ? 'MouseEvents' : 'Event');
30176            ev.initEvent('click', true, true);
30177            ev.view = e.view || window;
30178            ev.detail = 1;
30179            ev.screenX = target.screenX || 0;
30180            ev.screenY = target.screenY || 0;
30181            ev.clientX = target.clientX || 0;
30182            ev.clientY = target.clientY || 0;
30183            ev.ctrlKey = !!e.ctrlKey;
30184            ev.altKey = !!e.altKey;
30185            ev.shiftKey = !!e.shiftKey;
30186            ev.metaKey = !!e.metaKey;
30187            ev.button = 0;
30188            ev.relatedTarget = null;
30189            ev._constructed = true;
30190            target.dispatchEvent(ev);
30191        }
30192    };
30193
30194    return me;
30195})();
30196function IScroll (el, options) {
30197    this.wrapper = typeof el == 'string' ? document.querySelector(el) : el;
30198    this.scroller = this.wrapper.children[0];
30199    this.scrollerStyle = this.scroller.style;       // cache style for better performance
30200
30201    this.options = {
30202
30203        resizeScrollbars: true,
30204
30205        mouseWheelSpeed: 20,
30206
30207        snapThreshold: 0.334,
30208
30209// INSERT POINT: OPTIONS
30210        disablePointer : !utils.hasPointer,
30211        disableTouch : utils.hasPointer || !utils.hasTouch,
30212        disableMouse : utils.hasPointer || utils.hasTouch,
30213        startX: 0,
30214        startY: 0,
30215        scrollY: true,
30216        directionLockThreshold: 5,
30217        momentum: true,
30218
30219        bounce: true,
30220        bounceTime: 600,
30221        bounceEasing: '',
30222
30223        preventDefault: true,
30224        preventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT|LABEL)$/ },
30225
30226        HWCompositing: true,
30227        useTransition: true,
30228        useTransform: true,
30229        bindToWrapper: typeof window.onmousedown === "undefined"
30230    };
30231
30232    for ( var i in options ) {
30233        this.options[i] = options[i];
30234    }
30235
30236    // Normalize options
30237    this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : '';
30238
30239    this.options.useTransition = utils.hasTransition && this.options.useTransition;
30240    this.options.useTransform = utils.hasTransform && this.options.useTransform;
30241
30242    this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough;
30243    this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault;
30244
30245    // If you want eventPassthrough I have to lock one of the axes
30246    this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY;
30247    this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX;
30248
30249    // With eventPassthrough we also need lockDirection mechanism
30250    this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough;
30251    this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold;
30252
30253    this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing;
30254
30255    this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling;
30256
30257    if ( this.options.tap === true ) {
30258        this.options.tap = 'tap';
30259    }
30260
30261    // https://github.com/cubiq/iscroll/issues/1029
30262    if (!this.options.useTransition && !this.options.useTransform) {
30263        if(!(/relative|absolute/i).test(this.scrollerStyle.position)) {
30264            this.scrollerStyle.position = "relative";
30265        }
30266    }
30267
30268    if ( this.options.shrinkScrollbars == 'scale' ) {
30269        this.options.useTransition = false;
30270    }
30271
30272    this.options.invertWheelDirection = this.options.invertWheelDirection ? -1 : 1;
30273
30274// INSERT POINT: NORMALIZATION
30275
30276    // Some defaults
30277    this.x = 0;
30278    this.y = 0;
30279    this.directionX = 0;
30280    this.directionY = 0;
30281    this._events = {};
30282
30283// INSERT POINT: DEFAULTS
30284
30285    this._init();
30286    this.refresh();
30287
30288    this.scrollTo(this.options.startX, this.options.startY);
30289    this.enable();
30290}
30291
30292IScroll.prototype = {
30293    version: '5.2.0',
30294
30295    _init: function () {
30296        this._initEvents();
30297
30298        if ( this.options.scrollbars || this.options.indicators ) {
30299            this._initIndicators();
30300        }
30301
30302        if ( this.options.mouseWheel ) {
30303            this._initWheel();
30304        }
30305
30306        if ( this.options.snap ) {
30307            this._initSnap();
30308        }
30309
30310        if ( this.options.keyBindings ) {
30311            this._initKeys();
30312        }
30313
30314// INSERT POINT: _init
30315
30316    },
30317
30318    destroy: function () {
30319        this._initEvents(true);
30320        clearTimeout(this.resizeTimeout);
30321        this.resizeTimeout = null;
30322        this._execEvent('destroy');
30323    },
30324
30325    _transitionEnd: function (e) {
30326        if ( e.target != this.scroller || !this.isInTransition ) {
30327            return;
30328        }
30329
30330        this._transitionTime();
30331        if ( !this.resetPosition(this.options.bounceTime) ) {
30332            this.isInTransition = false;
30333            this._execEvent('scrollEnd');
30334        }
30335    },
30336
30337    _start: function (e) {
30338        // React to left mouse button only
30339        if ( utils.eventType[e.type] != 1 ) {
30340          // for button property
30341          // http://unixpapa.com/js/mouse.html
30342          var button;
30343        if (!e.which) {
30344          /* IE case */
30345          button = (e.button < 2) ? 0 :
30346                   ((e.button == 4) ? 1 : 2);
30347        } else {
30348          /* All others */
30349          button = e.button;
30350        }
30351            if ( button !== 0 ) {
30352                return;
30353            }
30354        }
30355
30356        if ( !this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated) ) {
30357            return;
30358        }
30359
30360        if ( this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {
30361            e.preventDefault();
30362        }
30363
30364        var point = e.touches ? e.touches[0] : e,
30365            pos;
30366
30367        this.initiated  = utils.eventType[e.type];
30368        this.moved      = false;
30369        this.distX      = 0;
30370        this.distY      = 0;
30371        this.directionX = 0;
30372        this.directionY = 0;
30373        this.directionLocked = 0;
30374
30375        this.startTime = utils.getTime();
30376
30377        if ( this.options.useTransition && this.isInTransition ) {
30378            this._transitionTime();
30379            this.isInTransition = false;
30380            pos = this.getComputedPosition();
30381            this._translate(Math.round(pos.x), Math.round(pos.y));
30382            this._execEvent('scrollEnd');
30383        } else if ( !this.options.useTransition && this.isAnimating ) {
30384            this.isAnimating = false;
30385            this._execEvent('scrollEnd');
30386        }
30387
30388        this.startX    = this.x;
30389        this.startY    = this.y;
30390        this.absStartX = this.x;
30391        this.absStartY = this.y;
30392        this.pointX    = point.pageX;
30393        this.pointY    = point.pageY;
30394
30395        this._execEvent('beforeScrollStart');
30396    },
30397
30398    _move: function (e) {
30399        if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
30400            return;
30401        }
30402
30403        if ( this.options.preventDefault ) {    // increases performance on Android? TODO: check!
30404            e.preventDefault();
30405        }
30406
30407        var point       = e.touches ? e.touches[0] : e,
30408            deltaX      = point.pageX - this.pointX,
30409            deltaY      = point.pageY - this.pointY,
30410            timestamp   = utils.getTime(),
30411            newX, newY,
30412            absDistX, absDistY;
30413
30414        this.pointX     = point.pageX;
30415        this.pointY     = point.pageY;
30416
30417        this.distX      += deltaX;
30418        this.distY      += deltaY;
30419        absDistX        = Math.abs(this.distX);
30420        absDistY        = Math.abs(this.distY);
30421
30422        // We need to move at least 10 pixels for the scrolling to initiate
30423        if ( timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10) ) {
30424            return;
30425        }
30426
30427        // If you are scrolling in one direction lock the other
30428        if ( !this.directionLocked && !this.options.freeScroll ) {
30429            if ( absDistX > absDistY + this.options.directionLockThreshold ) {
30430                this.directionLocked = 'h';     // lock horizontally
30431            } else if ( absDistY >= absDistX + this.options.directionLockThreshold ) {
30432                this.directionLocked = 'v';     // lock vertically
30433            } else {
30434                this.directionLocked = 'n';     // no lock
30435            }
30436        }
30437
30438        if ( this.directionLocked == 'h' ) {
30439            if ( this.options.eventPassthrough == 'vertical' ) {
30440                e.preventDefault();
30441            } else if ( this.options.eventPassthrough == 'horizontal' ) {
30442                this.initiated = false;
30443                return;
30444            }
30445
30446            deltaY = 0;
30447        } else if ( this.directionLocked == 'v' ) {
30448            if ( this.options.eventPassthrough == 'horizontal' ) {
30449                e.preventDefault();
30450            } else if ( this.options.eventPassthrough == 'vertical' ) {
30451                this.initiated = false;
30452                return;
30453            }
30454
30455            deltaX = 0;
30456        }
30457
30458        deltaX = this.hasHorizontalScroll ? deltaX : 0;
30459        deltaY = this.hasVerticalScroll ? deltaY : 0;
30460
30461        newX = this.x + deltaX;
30462        newY = this.y + deltaY;
30463
30464        // Slow down if outside of the boundaries
30465        if ( newX > 0 || newX < this.maxScrollX ) {
30466            newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX;
30467        }
30468        if ( newY > 0 || newY < this.maxScrollY ) {
30469            newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY;
30470        }
30471
30472        this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0;
30473        this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0;
30474
30475        if ( !this.moved ) {
30476            this._execEvent('scrollStart');
30477        }
30478
30479        this.moved = true;
30480
30481        this._translate(newX, newY);
30482
30483/* REPLACE START: _move */
30484
30485        if ( timestamp - this.startTime > 300 ) {
30486            this.startTime = timestamp;
30487            this.startX = this.x;
30488            this.startY = this.y;
30489        }
30490
30491/* REPLACE END: _move */
30492
30493    },
30494
30495    _end: function (e) {
30496        if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
30497            return;
30498        }
30499
30500        if ( this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {
30501            e.preventDefault();
30502        }
30503
30504        var point = e.changedTouches ? e.changedTouches[0] : e,
30505            momentumX,
30506            momentumY,
30507            duration = utils.getTime() - this.startTime,
30508            newX = Math.round(this.x),
30509            newY = Math.round(this.y),
30510            distanceX = Math.abs(newX - this.startX),
30511            distanceY = Math.abs(newY - this.startY),
30512            time = 0,
30513            easing = '';
30514
30515        this.isInTransition = 0;
30516        this.initiated = 0;
30517        this.endTime = utils.getTime();
30518
30519        // reset if we are outside of the boundaries
30520        if ( this.resetPosition(this.options.bounceTime) ) {
30521            return;
30522        }
30523
30524        this.scrollTo(newX, newY);  // ensures that the last position is rounded
30525
30526        // we scrolled less than 10 pixels
30527        if ( !this.moved ) {
30528            if ( this.options.tap ) {
30529                utils.tap(e, this.options.tap);
30530            }
30531
30532            if ( this.options.click ) {
30533                utils.click(e);
30534            }
30535
30536            this._execEvent('scrollCancel');
30537            return;
30538        }
30539
30540        if ( this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100 ) {
30541            this._execEvent('flick');
30542            return;
30543        }
30544
30545        // start momentum animation if needed
30546        if ( this.options.momentum && duration < 300 ) {
30547            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 };
30548            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 };
30549            newX = momentumX.destination;
30550            newY = momentumY.destination;
30551            time = Math.max(momentumX.duration, momentumY.duration);
30552            this.isInTransition = 1;
30553        }
30554
30555
30556        if ( this.options.snap ) {
30557            var snap = this._nearestSnap(newX, newY);
30558            this.currentPage = snap;
30559            time = this.options.snapSpeed || Math.max(
30560                    Math.max(
30561                        Math.min(Math.abs(newX - snap.x), 1000),
30562                        Math.min(Math.abs(newY - snap.y), 1000)
30563                    ), 300);
30564            newX = snap.x;
30565            newY = snap.y;
30566
30567            this.directionX = 0;
30568            this.directionY = 0;
30569            easing = this.options.bounceEasing;
30570        }
30571
30572// INSERT POINT: _end
30573
30574        if ( newX != this.x || newY != this.y ) {
30575            // change easing function when scroller goes out of the boundaries
30576            if ( newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY ) {
30577                easing = utils.ease.quadratic;
30578            }
30579
30580            this.scrollTo(newX, newY, time, easing);
30581            return;
30582        }
30583
30584        this._execEvent('scrollEnd');
30585    },
30586
30587    _resize: function () {
30588        var that = this;
30589
30590        clearTimeout(this.resizeTimeout);
30591
30592        this.resizeTimeout = setTimeout(function () {
30593            that.refresh();
30594        }, this.options.resizePolling);
30595    },
30596
30597    resetPosition: function (time) {
30598        var x = this.x,
30599            y = this.y;
30600
30601        time = time || 0;
30602
30603        if ( !this.hasHorizontalScroll || this.x > 0 ) {
30604            x = 0;
30605        } else if ( this.x < this.maxScrollX ) {
30606            x = this.maxScrollX;
30607        }
30608
30609        if ( !this.hasVerticalScroll || this.y > 0 ) {
30610            y = 0;
30611        } else if ( this.y < this.maxScrollY ) {
30612            y = this.maxScrollY;
30613        }
30614
30615        if ( x == this.x && y == this.y ) {
30616            return false;
30617        }
30618
30619        this.scrollTo(x, y, time, this.options.bounceEasing);
30620
30621        return true;
30622    },
30623
30624    disable: function () {
30625        this.enabled = false;
30626    },
30627
30628    enable: function () {
30629        this.enabled = true;
30630    },
30631
30632    refresh: function () {
30633        var rf = this.wrapper.offsetHeight;     // Force reflow
30634
30635        this.wrapperWidth   = this.wrapper.clientWidth;
30636        this.wrapperHeight  = this.wrapper.clientHeight;
30637
30638/* REPLACE START: refresh */
30639
30640        this.scrollerWidth  = this.scroller.offsetWidth;
30641        this.scrollerHeight = this.scroller.offsetHeight;
30642
30643        this.maxScrollX     = this.wrapperWidth - this.scrollerWidth;
30644        this.maxScrollY     = this.wrapperHeight - this.scrollerHeight;
30645
30646/* REPLACE END: refresh */
30647
30648        this.hasHorizontalScroll    = this.options.scrollX && this.maxScrollX < 0;
30649        this.hasVerticalScroll      = this.options.scrollY && this.maxScrollY < 0;
30650
30651        if ( !this.hasHorizontalScroll ) {
30652            this.maxScrollX = 0;
30653            this.scrollerWidth = this.wrapperWidth;
30654        }
30655
30656        if ( !this.hasVerticalScroll ) {
30657            this.maxScrollY = 0;
30658            this.scrollerHeight = this.wrapperHeight;
30659        }
30660
30661        this.endTime = 0;
30662        this.directionX = 0;
30663        this.directionY = 0;
30664
30665        this.wrapperOffset = utils.offset(this.wrapper);
30666
30667        this._execEvent('refresh');
30668
30669        this.resetPosition();
30670
30671// INSERT POINT: _refresh
30672
30673    },
30674
30675
30676    on: function (type, fn) {
30677        if ( !this._events[type] ) {
30678            this._events[type] = [];
30679        }
30680
30681        this._events[type].push(fn);
30682    },
30683
30684    off: function (type, fn) {
30685        if ( !this._events[type] ) {
30686            return;
30687        }
30688
30689        var index = this._events[type].indexOf(fn);
30690
30691        if ( index > -1 ) {
30692            this._events[type].splice(index, 1);
30693        }
30694    },
30695
30696    _execEvent: function (type) {
30697        if ( !this._events[type] ) {
30698            return;
30699        }
30700
30701        var i = 0,
30702            l = this._events[type].length;
30703
30704        if ( !l ) {
30705            return;
30706        }
30707
30708        for ( ; i < l; i++ ) {
30709            this._events[type][i].apply(this, [].slice.call(arguments, 1));
30710        }
30711    },
30712
30713    scrollBy: function (x, y, time, easing) {
30714        x = this.x + x;
30715        y = this.y + y;
30716        time = time || 0;
30717
30718        this.scrollTo(x, y, time, easing);
30719    },
30720
30721    scrollTo: function (x, y, time, easing) {
30722        easing = easing || utils.ease.circular;
30723
30724        this.isInTransition = this.options.useTransition && time > 0;
30725        var transitionType = this.options.useTransition && easing.style;
30726        if ( !time || transitionType ) {
30727                if(transitionType) {
30728                    this._transitionTimingFunction(easing.style);
30729                    this._transitionTime(time);
30730                }
30731            this._translate(x, y);
30732        } else {
30733            this._animate(x, y, time, easing.fn);
30734        }
30735    },
30736
30737    scrollToElement: function (el, time, offsetX, offsetY, easing) {
30738        el = el.nodeType ? el : this.scroller.querySelector(el);
30739
30740        if ( !el ) {
30741            return;
30742        }
30743
30744        var pos = utils.offset(el);
30745
30746        pos.left -= this.wrapperOffset.left;
30747        pos.top  -= this.wrapperOffset.top;
30748
30749        // if offsetX/Y are true we center the element to the screen
30750        if ( offsetX === true ) {
30751            offsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2);
30752        }
30753        if ( offsetY === true ) {
30754            offsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2);
30755        }
30756
30757        pos.left -= offsetX || 0;
30758        pos.top  -= offsetY || 0;
30759
30760        pos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left;
30761        pos.top  = pos.top  > 0 ? 0 : pos.top  < this.maxScrollY ? this.maxScrollY : pos.top;
30762
30763        time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x-pos.left), Math.abs(this.y-pos.top)) : time;
30764
30765        this.scrollTo(pos.left, pos.top, time, easing);
30766    },
30767
30768    _transitionTime: function (time) {
30769        if (!this.options.useTransition) {
30770            return;
30771        }
30772        time = time || 0;
30773        var durationProp = utils.style.transitionDuration;
30774        if(!durationProp) {
30775            return;
30776        }
30777
30778        this.scrollerStyle[durationProp] = time + 'ms';
30779
30780        if ( !time && utils.isBadAndroid ) {
30781            this.scrollerStyle[durationProp] = '0.0001ms';
30782            // remove 0.0001ms
30783            var self = this;
30784            rAF(function() {
30785                if(self.scrollerStyle[durationProp] === '0.0001ms') {
30786                    self.scrollerStyle[durationProp] = '0s';
30787                }
30788            });
30789        }
30790
30791
30792        if ( this.indicators ) {
30793            for ( var i = this.indicators.length; i--; ) {
30794                this.indicators[i].transitionTime(time);
30795            }
30796        }
30797
30798
30799// INSERT POINT: _transitionTime
30800
30801    },
30802
30803    _transitionTimingFunction: function (easing) {
30804        this.scrollerStyle[utils.style.transitionTimingFunction] = easing;
30805
30806
30807        if ( this.indicators ) {
30808            for ( var i = this.indicators.length; i--; ) {
30809                this.indicators[i].transitionTimingFunction(easing);
30810            }
30811        }
30812
30813
30814// INSERT POINT: _transitionTimingFunction
30815
30816    },
30817
30818    _translate: function (x, y) {
30819        //Uncode addition
30820        if ( (" " + this.wrapper.className + " ").replace(/[\n\t]/g, " ").indexOf(" no-scrolloverflow ") > -1 )
30821            return false;
30822
30823        if ( this.options.useTransform ) {
30824
30825/* REPLACE START: _translate */
30826
30827            this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ;
30828
30829/* REPLACE END: _translate */
30830
30831        } else {
30832            x = Math.round(x);
30833            y = Math.round(y);
30834            this.scrollerStyle.left = x + 'px';
30835            this.scrollerStyle.top = y + 'px';
30836        }
30837
30838        this.x = x;
30839        this.y = y;
30840
30841
30842        if ( this.indicators ) {
30843            for ( var i = this.indicators.length; i--; ) {
30844                this.indicators[i].updatePosition();
30845            }
30846        }
30847
30848        //Uncode addition
30849        var uncodevent = new CustomEvent('fp-slide-scroll');
30850        window.dispatchEvent(uncodevent);
30851
30852// INSERT POINT: _translate
30853
30854    },
30855
30856    _initEvents: function (remove) {
30857        var eventType = remove ? utils.removeEvent : utils.addEvent,
30858            target = this.options.bindToWrapper ? this.wrapper : window;
30859
30860        eventType(window, 'orientationchange', this);
30861        eventType(window, 'resize', this);
30862
30863        if ( this.options.click ) {
30864            eventType(this.wrapper, 'click', this, true);
30865        }
30866
30867        if ( !this.options.disableMouse ) {
30868            eventType(this.wrapper, 'mousedown', this);
30869            eventType(target, 'mousemove', this);
30870            eventType(target, 'mousecancel', this);
30871            eventType(target, 'mouseup', this);
30872        }
30873
30874        if ( utils.hasPointer && !this.options.disablePointer ) {
30875            eventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this);
30876            eventType(target, utils.prefixPointerEvent('pointermove'), this);
30877            eventType(target, utils.prefixPointerEvent('pointercancel'), this);
30878            eventType(target, utils.prefixPointerEvent('pointerup'), this);
30879        }
30880
30881        if ( utils.hasTouch && !this.options.disableTouch ) {
30882            eventType(this.wrapper, 'touchstart', this);
30883            eventType(target, 'touchmove', this);
30884            eventType(target, 'touchcancel', this);
30885            eventType(target, 'touchend', this);
30886        }
30887
30888        eventType(this.scroller, 'transitionend', this);
30889        eventType(this.scroller, 'webkitTransitionEnd', this);
30890        eventType(this.scroller, 'oTransitionEnd', this);
30891        eventType(this.scroller, 'MSTransitionEnd', this);
30892    },
30893
30894    getComputedPosition: function () {
30895        var matrix = window.getComputedStyle(this.scroller, null),
30896            x, y;
30897
30898        if ( this.options.useTransform ) {
30899            matrix = matrix[utils.style.transform].split(')')[0].split(', ');
30900            x = +(matrix[12] || matrix[4]);
30901            y = +(matrix[13] || matrix[5]);
30902        } else {
30903            x = +matrix.left.replace(/[^-\d.]/g, '');
30904            y = +matrix.top.replace(/[^-\d.]/g, '');
30905        }
30906
30907        return { x: x, y: y };
30908    },
30909    _initIndicators: function () {
30910        var interactive = this.options.interactiveScrollbars,
30911            customStyle = typeof this.options.scrollbars != 'string',
30912            indicators = [],
30913            indicator;
30914
30915        var that = this;
30916
30917        this.indicators = [];
30918
30919        if ( this.options.scrollbars ) {
30920            // Vertical scrollbar
30921            if ( this.options.scrollY ) {
30922                indicator = {
30923                    el: createDefaultScrollbar('v', interactive, this.options.scrollbars),
30924                    interactive: interactive,
30925                    defaultScrollbars: true,
30926                    customStyle: customStyle,
30927                    resize: this.options.resizeScrollbars,
30928                    shrink: this.options.shrinkScrollbars,
30929                    fade: this.options.fadeScrollbars,
30930                    listenX: false
30931                };
30932
30933                this.wrapper.appendChild(indicator.el);
30934                indicators.push(indicator);
30935            }
30936
30937            // Horizontal scrollbar
30938            if ( this.options.scrollX ) {
30939                indicator = {
30940                    el: createDefaultScrollbar('h', interactive, this.options.scrollbars),
30941                    interactive: interactive,
30942                    defaultScrollbars: true,
30943                    customStyle: customStyle,
30944                    resize: this.options.resizeScrollbars,
30945                    shrink: this.options.shrinkScrollbars,
30946                    fade: this.options.fadeScrollbars,
30947                    listenY: false
30948                };
30949
30950                this.wrapper.appendChild(indicator.el);
30951                indicators.push(indicator);
30952            }
30953        }
30954
30955        if ( this.options.indicators ) {
30956            // TODO: check concat compatibility
30957            indicators = indicators.concat(this.options.indicators);
30958        }
30959
30960        for ( var i = indicators.length; i--; ) {
30961            this.indicators.push( new Indicator(this, indicators[i]) );
30962        }
30963
30964        // TODO: check if we can use array.map (wide compatibility and performance issues)
30965        function _indicatorsMap (fn) {
30966            if (that.indicators) {
30967                for ( var i = that.indicators.length; i--; ) {
30968                    fn.call(that.indicators[i]);
30969                }
30970            }
30971        }
30972
30973        if ( this.options.fadeScrollbars ) {
30974            this.on('scrollEnd', function () {
30975                _indicatorsMap(function () {
30976                    this.fade();
30977                });
30978            });
30979
30980            this.on('scrollCancel', function () {
30981                _indicatorsMap(function () {
30982                    this.fade();
30983                });
30984            });
30985
30986            this.on('scrollStart', function () {
30987                _indicatorsMap(function () {
30988                    this.fade(1);
30989                });
30990            });
30991
30992            this.on('beforeScrollStart', function () {
30993                _indicatorsMap(function () {
30994                    this.fade(1, true);
30995                });
30996            });
30997        }
30998
30999
31000        this.on('refresh', function () {
31001            _indicatorsMap(function () {
31002                this.refresh();
31003            });
31004        });
31005
31006        this.on('destroy', function () {
31007            _indicatorsMap(function () {
31008                this.destroy();
31009            });
31010
31011            delete this.indicators;
31012        });
31013    },
31014
31015    _initWheel: function () {
31016        utils.addEvent(this.wrapper, 'wheel', this);
31017        utils.addEvent(this.wrapper, 'mousewheel', this);
31018        utils.addEvent(this.wrapper, 'DOMMouseScroll', this);
31019
31020        this.on('destroy', function () {
31021            clearTimeout(this.wheelTimeout);
31022            this.wheelTimeout = null;
31023            utils.removeEvent(this.wrapper, 'wheel', this);
31024            utils.removeEvent(this.wrapper, 'mousewheel', this);
31025            utils.removeEvent(this.wrapper, 'DOMMouseScroll', this);
31026        });
31027    },
31028
31029    _wheel: function (e) {
31030        if ( !this.enabled ) {
31031            return;
31032        }
31033
31034        var wheelDeltaX, wheelDeltaY,
31035            newX, newY,
31036            that = this;
31037
31038        if ( this.wheelTimeout === undefined ) {
31039            that._execEvent('scrollStart');
31040        }
31041
31042        // Execute the scrollEnd event after 400ms the wheel stopped scrolling
31043        clearTimeout(this.wheelTimeout);
31044        this.wheelTimeout = setTimeout(function () {
31045            if(!that.options.snap) {
31046                that._execEvent('scrollEnd');
31047            }
31048            that.wheelTimeout = undefined;
31049        }, 400);
31050
31051        if ( 'deltaX' in e ) {
31052            if (e.deltaMode === 1) {
31053                wheelDeltaX = -e.deltaX * this.options.mouseWheelSpeed;
31054                wheelDeltaY = -e.deltaY * this.options.mouseWheelSpeed;
31055            } else {
31056                wheelDeltaX = -e.deltaX;
31057                wheelDeltaY = -e.deltaY;
31058            }
31059        } else if ( 'wheelDeltaX' in e ) {
31060            wheelDeltaX = e.wheelDeltaX / 120 * this.options.mouseWheelSpeed;
31061            wheelDeltaY = e.wheelDeltaY / 120 * this.options.mouseWheelSpeed;
31062        } else if ( 'wheelDelta' in e ) {
31063            wheelDeltaX = wheelDeltaY = e.wheelDelta / 120 * this.options.mouseWheelSpeed;
31064        } else if ( 'detail' in e ) {
31065            wheelDeltaX = wheelDeltaY = -e.detail / 3 * this.options.mouseWheelSpeed;
31066        } else {
31067            return;
31068        }
31069
31070        wheelDeltaX *= this.options.invertWheelDirection;
31071        wheelDeltaY *= this.options.invertWheelDirection;
31072
31073        if ( !this.hasVerticalScroll ) {
31074            wheelDeltaX = wheelDeltaY;
31075            wheelDeltaY = 0;
31076        }
31077
31078        if ( this.options.snap ) {
31079            newX = this.currentPage.pageX;
31080            newY = this.currentPage.pageY;
31081
31082            if ( wheelDeltaX > 0 ) {
31083                newX--;
31084            } else if ( wheelDeltaX < 0 ) {
31085                newX++;
31086            }
31087
31088            if ( wheelDeltaY > 0 ) {
31089                newY--;
31090            } else if ( wheelDeltaY < 0 ) {
31091                newY++;
31092            }
31093
31094            this.goToPage(newX, newY);
31095
31096            return;
31097        }
31098
31099        newX = this.x + Math.round(this.hasHorizontalScroll ? wheelDeltaX : 0);
31100        newY = this.y + Math.round(this.hasVerticalScroll ? wheelDeltaY : 0);
31101
31102        this.directionX = wheelDeltaX > 0 ? -1 : wheelDeltaX < 0 ? 1 : 0;
31103        this.directionY = wheelDeltaY > 0 ? -1 : wheelDeltaY < 0 ? 1 : 0;
31104
31105        if ( newX > 0 ) {
31106            newX = 0;
31107        } else if ( newX < this.maxScrollX ) {
31108            newX = this.maxScrollX;
31109        }
31110
31111        if ( newY > 0 ) {
31112            newY = 0;
31113        } else if ( newY < this.maxScrollY ) {
31114            newY = this.maxScrollY;
31115        }
31116
31117        this.scrollTo(newX, newY, 0);
31118
31119// INSERT POINT: _wheel
31120    },
31121
31122    _initSnap: function () {
31123        this.currentPage = {};
31124
31125        if ( typeof this.options.snap == 'string' ) {
31126            this.options.snap = this.scroller.querySelectorAll(this.options.snap);
31127        }
31128
31129        this.on('refresh', function () {
31130            var i = 0, l,
31131                m = 0, n,
31132                cx, cy,
31133                x = 0, y,
31134                stepX = this.options.snapStepX || this.wrapperWidth,
31135                stepY = this.options.snapStepY || this.wrapperHeight,
31136                el;
31137
31138            this.pages = [];
31139
31140            if ( !this.wrapperWidth || !this.wrapperHeight || !this.scrollerWidth || !this.scrollerHeight ) {
31141                return;
31142            }
31143
31144            if ( this.options.snap === true ) {
31145                cx = Math.round( stepX / 2 );
31146                cy = Math.round( stepY / 2 );
31147
31148                while ( x > -this.scrollerWidth ) {
31149                    this.pages[i] = [];
31150                    l = 0;
31151                    y = 0;
31152
31153                    while ( y > -this.scrollerHeight ) {
31154                        this.pages[i][l] = {
31155                            x: Math.max(x, this.maxScrollX),
31156                            y: Math.max(y, this.maxScrollY),
31157                            width: stepX,
31158                            height: stepY,
31159                            cx: x - cx,
31160                            cy: y - cy
31161                        };
31162
31163                        y -= stepY;
31164                        l++;
31165                    }
31166
31167                    x -= stepX;
31168                    i++;
31169                }
31170            } else {
31171                el = this.options.snap;
31172                l = el.length;
31173                n = -1;
31174
31175                for ( ; i < l; i++ ) {
31176                    if ( i === 0 || el[i].offsetLeft <= el[i-1].offsetLeft ) {
31177                        m = 0;
31178                        n++;
31179                    }
31180
31181                    if ( !this.pages[m] ) {
31182                        this.pages[m] = [];
31183                    }
31184
31185                    x = Math.max(-el[i].offsetLeft, this.maxScrollX);
31186                    y = Math.max(-el[i].offsetTop, this.maxScrollY);
31187                    cx = x - Math.round(el[i].offsetWidth / 2);
31188                    cy = y - Math.round(el[i].offsetHeight / 2);
31189
31190                    this.pages[m][n] = {
31191                        x: x,
31192                        y: y,
31193                        width: el[i].offsetWidth,
31194                        height: el[i].offsetHeight,
31195                        cx: cx,
31196                        cy: cy
31197                    };
31198
31199                    if ( x > this.maxScrollX ) {
31200                        m++;
31201                    }
31202                }
31203            }
31204
31205            this.goToPage(this.currentPage.pageX || 0, this.currentPage.pageY || 0, 0);
31206
31207            // Update snap threshold if needed
31208            if ( this.options.snapThreshold % 1 === 0 ) {
31209                this.snapThresholdX = this.options.snapThreshold;
31210                this.snapThresholdY = this.options.snapThreshold;
31211            } else {
31212                this.snapThresholdX = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].width * this.options.snapThreshold);
31213                this.snapThresholdY = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].height * this.options.snapThreshold);
31214            }
31215        });
31216
31217        this.on('flick', function () {
31218            var time = this.options.snapSpeed || Math.max(
31219                    Math.max(
31220                        Math.min(Math.abs(this.x - this.startX), 1000),
31221                        Math.min(Math.abs(this.y - this.startY), 1000)
31222                    ), 300);
31223
31224            this.goToPage(
31225                this.currentPage.pageX + this.directionX,
31226                this.currentPage.pageY + this.directionY,
31227                time
31228            );
31229        });
31230    },
31231
31232    _nearestSnap: function (x, y) {
31233        if ( !this.pages.length ) {
31234            return { x: 0, y: 0, pageX: 0, pageY: 0 };
31235        }
31236
31237        var i = 0,
31238            l = this.pages.length,
31239            m = 0;
31240
31241        // Check if we exceeded the snap threshold
31242        if ( Math.abs(x - this.absStartX) < this.snapThresholdX &&
31243            Math.abs(y - this.absStartY) < this.snapThresholdY ) {
31244            return this.currentPage;
31245        }
31246
31247        if ( x > 0 ) {
31248            x = 0;
31249        } else if ( x < this.maxScrollX ) {
31250            x = this.maxScrollX;
31251        }
31252
31253        if ( y > 0 ) {
31254            y = 0;
31255        } else if ( y < this.maxScrollY ) {
31256            y = this.maxScrollY;
31257        }
31258
31259        for ( ; i < l; i++ ) {
31260            if ( x >= this.pages[i][0].cx ) {
31261                x = this.pages[i][0].x;
31262                break;
31263            }
31264        }
31265
31266        l = this.pages[i].length;
31267
31268        for ( ; m < l; m++ ) {
31269            if ( y >= this.pages[0][m].cy ) {
31270                y = this.pages[0][m].y;
31271                break;
31272            }
31273        }
31274
31275        if ( i == this.currentPage.pageX ) {
31276            i += this.directionX;
31277
31278            if ( i < 0 ) {
31279                i = 0;
31280            } else if ( i >= this.pages.length ) {
31281                i = this.pages.length - 1;
31282            }
31283
31284            x = this.pages[i][0].x;
31285        }
31286
31287        if ( m == this.currentPage.pageY ) {
31288            m += this.directionY;
31289
31290            if ( m < 0 ) {
31291                m = 0;
31292            } else if ( m >= this.pages[0].length ) {
31293                m = this.pages[0].length - 1;
31294            }
31295
31296            y = this.pages[0][m].y;
31297        }
31298
31299        return {
31300            x: x,
31301            y: y,
31302            pageX: i,
31303            pageY: m
31304        };
31305    },
31306
31307    goToPage: function (x, y, time, easing) {
31308        easing = easing || this.options.bounceEasing;
31309
31310        if ( x >= this.pages.length ) {
31311            x = this.pages.length - 1;
31312        } else if ( x < 0 ) {
31313            x = 0;
31314        }
31315
31316        if ( y >= this.pages[x].length ) {
31317            y = this.pages[x].length - 1;
31318        } else if ( y < 0 ) {
31319            y = 0;
31320        }
31321
31322        var posX = this.pages[x][y].x,
31323            posY = this.pages[x][y].y;
31324
31325        time = time === undefined ? this.options.snapSpeed || Math.max(
31326            Math.max(
31327                Math.min(Math.abs(posX - this.x), 1000),
31328                Math.min(Math.abs(posY - this.y), 1000)
31329            ), 300) : time;
31330
31331        this.currentPage = {
31332            x: posX,
31333            y: posY,
31334            pageX: x,
31335            pageY: y
31336        };
31337
31338        this.scrollTo(posX, posY, time, easing);
31339    },
31340
31341    next: function (time, easing) {
31342        var x = this.currentPage.pageX,
31343            y = this.currentPage.pageY;
31344
31345        x++;
31346
31347        if ( x >= this.pages.length && this.hasVerticalScroll ) {
31348            x = 0;
31349            y++;
31350        }
31351
31352        this.goToPage(x, y, time, easing);
31353    },
31354
31355    prev: function (time, easing) {
31356        var x = this.currentPage.pageX,
31357            y = this.currentPage.pageY;
31358
31359        x--;
31360
31361        if ( x < 0 && this.hasVerticalScroll ) {
31362            x = 0;
31363            y--;
31364        }
31365
31366        this.goToPage(x, y, time, easing);
31367    },
31368
31369    _initKeys: function (e) {
31370        // default key bindings
31371        var keys = {
31372            pageUp: 33,
31373            pageDown: 34,
31374            end: 35,
31375            home: 36,
31376            left: 37,
31377            up: 38,
31378            right: 39,
31379            down: 40
31380        };
31381        var i;
31382
31383        // if you give me characters I give you keycode
31384        if ( typeof this.options.keyBindings == 'object' ) {
31385            for ( i in this.options.keyBindings ) {
31386                if ( typeof this.options.keyBindings[i] == 'string' ) {
31387                    this.options.keyBindings[i] = this.options.keyBindings[i].toUpperCase().charCo
31387deAt(0);
31388                }
31389            }
31390        } else {
31391            this.options.keyBindings = {};
31392        }
31393
31394        for ( i in keys ) {
31395            this.options.keyBindings[i] = this.options.keyBindings[i] || keys[i];
31396        }
31397
31398        utils.addEvent(window, 'keydown', this);
31399
31400        this.on('destroy', function () {
31401            utils.removeEvent(window, 'keydown', this);
31402        });
31403    },
31404
31405    _key: function (e) {
31406        if ( !this.enabled ) {
31407            return;
31408        }
31409
31410        var snap = this.options.snap,   // we are using this alot, better to cache it
31411            newX = snap ? this.currentPage.pageX : this.x,
31412            newY = snap ? this.currentPage.pageY : this.y,
31413            now = utils.getTime(),
31414            prevTime = this.keyTime || 0,
31415            acceleration = 0.250,
31416            pos;
31417
31418        if ( this.options.useTransition && this.isInTransition ) {
31419            pos = this.getComputedPosition();
31420
31421            this._translate(Math.round(pos.x), Math.round(pos.y));
31422            this.isInTransition = false;
31423        }
31424
31425        this.keyAcceleration = now - prevTime < 200 ? Math.min(this.keyAcceleration + acceleration, 50) : 0;
31426
31427        switch ( e.keyCode ) {
31428            case this.options.keyBindings.pageUp:
31429                if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {
31430                    newX += snap ? 1 : this.wrapperWidth;
31431                } else {
31432                    newY += snap ? 1 : this.wrapperHeight;
31433                }
31434                break;
31435            case this.options.keyBindings.pageDown:
31436                if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {
31437                    newX -= snap ? 1 : this.wrapperWidth;
31438                } else {
31439                    newY -= snap ? 1 : this.wrapperHeight;
31440                }
31441                break;
31442            case this.options.keyBindings.end:
31443                newX = snap ? this.pages.length-1 : this.maxScrollX;
31444                newY = snap ? this.pages[0].length-1 : this.maxScrollY;
31445                break;
31446            case this.options.keyBindings.home:
31447                newX = 0;
31448                newY = 0;
31449                break;
31450            case this.options.keyBindings.left:
31451                newX += snap ? -1 : 5 + this.keyAcceleration>>0;
31452                break;
31453            case this.options.keyBindings.up:
31454                newY += snap ? 1 : 5 + this.keyAcceleration>>0;
31455                break;
31456            case this.options.keyBindings.right:
31457                newX -= snap ? -1 : 5 + this.keyAcceleration>>0;
31458                break;
31459            case this.options.keyBindings.down:
31460                newY -= snap ? 1 : 5 + this.keyAcceleration>>0;
31461                break;
31462            default:
31463                return;
31464        }
31465
31466        if ( snap ) {
31467            this.goToPage(newX, newY);
31468            return;
31469        }
31470
31471        if ( newX > 0 ) {
31472            newX = 0;
31473            this.keyAcceleration = 0;
31474        } else if ( newX < this.maxScrollX ) {
31475            newX = this.maxScrollX;
31476            this.keyAcceleration = 0;
31477        }
31478
31479        if ( newY > 0 ) {
31480            newY = 0;
31481            this.keyAcceleration = 0;
31482        } else if ( newY < this.maxScrollY ) {
31483            newY = this.maxScrollY;
31484            this.keyAcceleration = 0;
31485        }
31486
31487        this.scrollTo(newX, newY, 0);
31488
31489        this.keyTime = now;
31490    },
31491
31492    _animate: function (destX, destY, duration, easingFn) {
31493        var that = this,
31494            startX = this.x,
31495            startY = this.y,
31496            startTime = utils.getTime(),
31497            destTime = startTime + duration;
31498
31499        function step () {
31500            var now = utils.getTime(),
31501                newX, newY,
31502                easing;
31503
31504            if ( now >= destTime ) {
31505                that.isAnimating = false;
31506                that._translate(destX, destY);
31507
31508                if ( !that.resetPosition(that.options.bounceTime) ) {
31509                    that._execEvent('scrollEnd');
31510                }
31511
31512                return;
31513            }
31514
31515            now = ( now - startTime ) / duration;
31516            easing = easingFn(now);
31517            newX = ( destX - startX ) * easing + startX;
31518            newY = ( destY - startY ) * easing + startY;
31519            that._translate(newX, newY);
31520
31521            if ( that.isAnimating ) {
31522                rAF(step);
31523            }
31524        }
31525
31526        this.isAnimating = true;
31527        step();
31528    },
31529    handleEvent: function (e) {
31530        switch ( e.type ) {
31531            case 'touchstart':
31532            case 'pointerdown':
31533            case 'MSPointerDown':
31534            case 'mousedown':
31535                this._start(e);
31536                break;
31537            case 'touchmove':
31538            case 'pointermove':
31539            case 'MSPointerMove':
31540            case 'mousemove':
31541                this._move(e);
31542                break;
31543            case 'touchend':
31544            case 'pointerup':
31545            case 'MSPointerUp':
31546            case 'mouseup':
31547            case 'touchcancel':
31548            case 'pointercancel':
31549            case 'MSPointerCancel':
31550            case 'mousecancel':
31551                this._end(e);
31552                break;
31553            case 'orientationchange':
31554            case 'resize':
31555                this._resize();
31556                break;
31557            case 'transitionend':
31558            case 'webkitTransitionEnd':
31559            case 'oTransitionEnd':
31560            case 'MSTransitionEnd':
31561                this._transitionEnd(e);
31562                break;
31563            case 'wheel':
31564            case 'DOMMouseScroll':
31565            case 'mousewheel':
31566                this._wheel(e);
31567                break;
31568            case 'keydown':
31569                this._key(e);
31570                break;
31571            case 'click':
31572                if ( this.enabled && !e._constructed ) {
31573                    e.preventDefault();
31574                    e.stopPropagation();
31575                }
31576                break;
31577        }
31578    }
31579};
31580function createDefaultScrollbar (direction, interactive, type) {
31581    var scrollbar = document.createElement('div'),
31582        indicator = document.createElement('div');
31583
31584    if ( type === true ) {
31585        scrollbar.style.cssText = 'position:absolute;z-index:9999';
31586        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';
31587    }
31588
31589    indicator.className = 'iScrollIndicator';
31590
31591    if ( direction == 'h' ) {
31592        if ( type === true ) {
31593            scrollbar.style.cssText += ';height:7px;left:2px;right:2px;bottom:0';
31594            indicator.style.height = '100%';
31595        }
31596        scrollbar.className = 'iScrollHorizontalScrollbar';
31597    } else {
31598        if ( type === true ) {
31599            scrollbar.style.cssText += ';width:7px;bottom:2px;top:2px;right:1px';
31600            indicator.style.width = '100%';
31601        }
31602        scrollbar.className = 'iScrollVerticalScrollbar';
31603    }
31604
31605    scrollbar.style.cssText += ';overflow:hidden';
31606
31607    if ( !interactive ) {
31608        scrollbar.style.pointerEvents = 'none';
31609    }
31610
31611    scrollbar.appendChild(indicator);
31612
31613    return scrollbar;
31614}
31615
31616function Indicator (scroller, options) {
31617    this.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el;
31618    this.wrapperStyle = this.wrapper.style;
31619    this.indicator = this.wrapper.children[0];
31620    this.indicatorStyle = this.indicator.style;
31621    this.scroller = scroller;
31622
31623    this.options = {
31624        listenX: true,
31625        listenY: true,
31626        interactive: false,
31627        resize: true,
31628        defaultScrollbars: false,
31629        shrink: false,
31630        fade: false,
31631        speedRatioX: 0,
31632        speedRatioY: 0
31633    };
31634
31635    for ( var i in options ) {
31636        this.options[i] = options[i];
31637    }
31638
31639    this.sizeRatioX = 1;
31640    this.sizeRatioY = 1;
31641    this.maxPosX = 0;
31642    this.maxPosY = 0;
31643
31644    if ( this.options.interactive ) {
31645        if ( !this.options.disableTouch ) {
31646            utils.addEvent(this.indicator, 'touchstart', this);
31647            utils.addEvent(window, 'touchend', this);
31648        }
31649        if ( !this.options.disablePointer ) {
31650            utils.addEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);
31651            utils.addEvent(window, utils.prefixPointerEvent('pointerup'), this);
31652        }
31653        if ( !this.options.disableMouse ) {
31654            utils.addEvent(this.indicator, 'mousedown', this);
31655            utils.addEvent(window, 'mouseup', this);
31656        }
31657    }
31658
31659    if ( this.options.fade ) {
31660        this.wrapperStyle[utils.style.transform] = this.scroller.translateZ;
31661        var durationProp = utils.style.transitionDuration;
31662        if(!durationProp) {
31663            return;
31664        }
31665        this.wrapperStyle[durationProp] = utils.isBadAndroid ? '0.0001ms' : '0ms';
31666        // remove 0.0001ms
31667        var self = this;
31668        if(utils.isBadAndroid) {
31669            rAF(function() {
31670                if(self.wrapperStyle[durationProp] === '0.0001ms') {
31671                    self.wrapperStyle[durationProp] = '0s';
31672                }
31673            });
31674        }
31675        this.wrapperStyle.opacity = '0';
31676    }
31677}
31678
31679Indicator.prototype = {
31680    handleEvent: function (e) {
31681        switch ( e.type ) {
31682            case 'touchstart':
31683            case 'pointerdown':
31684            case 'MSPointerDown':
31685            case 'mousedown':
31686                this._start(e);
31687                break;
31688            case 'touchmove':
31689            case 'pointermove':
31690            case 'MSPointerMove':
31691            case 'mousemove':
31692                this._move(e);
31693                break;
31694            case 'touchend':
31695            case 'pointerup':
31696            case 'MSPointerUp':
31697            case 'mouseup':
31698            case 'touchcancel':
31699            case 'pointercancel':
31700            case 'MSPointerCancel':
31701            case 'mousecancel':
31702                this._end(e);
31703                break;
31704        }
31705    },
31706
31707    destroy: function () {
31708        if ( this.options.fadeScrollbars ) {
31709            clearTimeout(this.fadeTimeout);
31710            this.fadeTimeout = null;
31711        }
31712        if ( this.options.interactive ) {
31713            utils.removeEvent(this.indicator, 'touchstart', this);
31714            utils.removeEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);
31715            utils.removeEvent(this.indicator, 'mousedown', this);
31716
31717            utils.removeEvent(window, 'touchmove', this);
31718            utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);
31719            utils.removeEvent(window, 'mousemove', this);
31720
31721            utils.removeEvent(window, 'touchend', this);
31722            utils.removeEvent(window, utils.prefixPointerEvent('pointerup'), this);
31723            utils.removeEvent(window, 'mouseup', this);
31724        }
31725
31726        if ( this.options.defaultScrollbars ) {
31727            this.wrapper.parentNode.removeChild(this.wrapper);
31728        }
31729    },
31730
31731    _start: function (e) {
31732        var point = e.touches ? e.touches[0] : e;
31733
31734        e.preventDefault();
31735        e.stopPropagation();
31736
31737        this.transitionTime();
31738
31739        this.initiated = true;
31740        this.moved = false;
31741        this.lastPointX = point.pageX;
31742        this.lastPointY = point.pageY;
31743
31744        this.startTime  = utils.getTime();
31745
31746        if ( !this.options.disableTouch ) {
31747            utils.addEvent(window, 'touchmove', this);
31748        }
31749        if ( !this.options.disablePointer ) {
31750            utils.addEvent(window, utils.prefixPointerEvent('pointermove'), this);
31751        }
31752        if ( !this.options.disableMouse ) {
31753            utils.addEvent(window, 'mousemove', this);
31754        }
31755
31756        this.scroller._execEvent('beforeScrollStart');
31757    },
31758
31759    _move: function (e) {
31760        var point = e.touches ? e.touches[0] : e,
31761            deltaX, deltaY,
31762            newX, newY,
31763            timestamp = utils.getTime();
31764
31765        if ( !this.moved ) {
31766            this.scroller._execEvent('scrollStart');
31767        }
31768
31769        this.moved = true;
31770
31771        deltaX = point.pageX - this.lastPointX;
31772        this.lastPointX = point.pageX;
31773
31774        deltaY = point.pageY - this.lastPointY;
31775        this.lastPointY = point.pageY;
31776
31777        newX = this.x + deltaX;
31778        newY = this.y + deltaY;
31779
31780        this._pos(newX, newY);
31781
31782// INSERT POINT: indicator._move
31783
31784        e.preventDefault();
31785        e.stopPropagation();
31786    },
31787
31788    _end: function (e) {
31789        if ( !this.initiated ) {
31790            return;
31791        }
31792
31793        this.initiated = false;
31794
31795        e.preventDefault();
31796        e.stopPropagation();
31797
31798        utils.removeEvent(window, 'touchmove', this);
31799        utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);
31800        utils.removeEvent(window, 'mousemove', this);
31801
31802        if ( this.scroller.options.snap ) {
31803            var snap = this.scroller._nearestSnap(this.scroller.x, this.scroller.y);
31804
31805            var time = this.options.snapSpeed || Math.max(
31806                    Math.max(
31807                        Math.min(Math.abs(this.scroller.x - snap.x), 1000),
31808                        Math.min(Math.abs(this.scroller.y - snap.y), 1000)
31809                    ), 300);
31810
31811            if ( this.scroller.x != snap.x || this.scroller.y != snap.y ) {
31812                this.scroller.directionX = 0;
31813                this.scroller.directionY = 0;
31814                this.scroller.currentPage = snap;
31815                this.scroller.scrollTo(snap.x, snap.y, time, this.scroller.options.bounceEasing);
31816            }
31817        }
31818
31819        if ( this.moved ) {
31820            this.scroller._execEvent('scrollEnd');
31821        }
31822    },
31823
31824    transitionTime: function (time) {
31825        time = time || 0;
31826        var durationProp = utils.style.transitionDuration;
31827        if(!durationProp) {
31828            return;
31829        }
31830
31831        this.indicatorStyle[durationProp] = time + 'ms';
31832
31833        if ( !time && utils.isBadAndroid ) {
31834            this.indicatorStyle[durationProp] = '0.0001ms';
31835            // remove 0.0001ms
31836            var self = this;
31837            rAF(function() {
31838                if(self.indicatorStyle[durationProp] === '0.0001ms') {
31839                    self.indicatorStyle[durationProp] = '0s';
31840                }
31841            });
31842        }
31843    },
31844
31845    transitionTimingFunction: function (easing) {
31846        this.indicatorStyle[utils.style.transitionTimingFunction] = easing;
31847    },
31848
31849    refresh: function () {
31850        this.transitionTime();
31851
31852        if ( this.options.listenX && !this.options.listenY ) {
31853            this.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none';
31854        } else if ( this.options.listenY && !this.options.listenX ) {
31855            this.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none';
31856        } else {
31857            this.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none';
31858        }
31859
31860        if ( this.scroller.hasHorizontalScroll && this.scroller.hasVerticalScroll ) {
31861            utils.addClass(this.wrapper, 'iScrollBothScrollbars');
31862            utils.removeClass(this.wrapper, 'iScrollLoneScrollbar');
31863
31864            if ( this.options.defaultScrollbars && this.options.customStyle ) {
31865                if ( this.options.listenX ) {
31866                    this.wrapper.style.right = '8px';
31867                } else {
31868                    this.wrapper.style.bottom = '8px';
31869                }
31870            }
31871        } else {
31872            utils.removeClass(this.wrapper, 'iScrollBothScrollbars');
31873            utils.addClass(this.wrapper, 'iScrollLoneScrollbar');
31874
31875            if ( this.options.defaultScrollbars && this.options.customStyle ) {
31876                if ( this.options.listenX ) {
31877                    this.wrapper.style.right = '2px';
31878                } else {
31879                    this.wrapper.style.bottom = '2px';
31880                }
31881            }
31882        }
31883
31884        var r = this.wrapper.offsetHeight;  // force refresh
31885
31886        if ( this.options.listenX ) {
31887            this.wrapperWidth = this.wrapper.clientWidth;
31888            if ( this.options.resize ) {
31889                this.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / (this.scroller.scrollerWidth || this.wrapperWidth || 1)), 8);
31890                this.indicatorStyle.width = this.indicatorWidth + 'px';
31891            } else {
31892                this.indicatorWidth = this.indicator.clientWidth;
31893            }
31894
31895            this.maxPosX = this.wrapperWidth - this.indicatorWidth;
31896
31897            if ( this.options.shrink == 'clip' ) {
31898                this.minBoundaryX = -this.indicatorWidth + 8;
31899                this.maxBoundaryX = this.wrapperWidth - 8;
31900            } else {
31901                this.minBoundaryX = 0;
31902                this.maxBoundaryX = this.maxPosX;
31903            }
31904
31905            this.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX));
31906        }
31907
31908        if ( this.options.listenY ) {
31909            this.wrapperHeight = this.wrapper.clientHeight;
31910            if ( this.options.resize ) {
31911                this.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / (this.scroller.scrollerHeight || this.wrapperHeight || 1)), 8);
31912                this.indicatorStyle.height = this.indicatorHeight + 'px';
31913            } else {
31914                this.indicatorHeight = this.indicator.clientHeight;
31915            }
31916
31917            this.maxPosY = this.wrapperHeight - this.indicatorHeight;
31918
31919            if ( this.options.shrink == 'clip' ) {
31920                this.minBoundaryY = -this.indicatorHeight + 8;
31921                this.maxBoundaryY = this.wrapperHeight - 8;
31922            } else {
31923                this.minBoundaryY = 0;
31924                this.maxBoundaryY = this.maxPosY;
31925            }
31926
31927            this.maxPosY = this.wrapperHeight - this.indicatorHeight;
31928            this.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY));
31929        }
31930
31931        this.updatePosition();
31932    },
31933
31934    updatePosition: function () {
31935        var x = this.options.listenX && Math.round(this.sizeRatioX * this.scroller.x) || 0,
31936            y = this.options.listenY && Math.round(this.sizeRatioY * this.scroller.y) || 0;
31937
31938        if ( !this.options.ignoreBoundaries ) {
31939            if ( x < this.minBoundaryX ) {
31940                if ( this.options.shrink == 'scale' ) {
31941                    this.width = Math.max(this.indicatorWidth + x, 8);
31942                    this.indicatorStyle.width = this.width + 'px';
31943                }
31944                x = this.minBoundaryX;
31945            } else if ( x > this.maxBoundaryX ) {
31946                if ( this.options.shrink == 'scale' ) {
31947                    this.width = Math.max(this.indicatorWidth - (x - this.maxPosX), 8);
31948                    this.indicatorStyle.width = this.width + 'px';
31949                    x = this.maxPosX + this.indicatorWidth - this.width;
31950                } else {
31951                    x = this.maxBoundaryX;
31952                }
31953            } else if ( this.options.shrink == 'scale' && this.width != this.indicatorWidth ) {
31954                this.width = this.indicatorWidth;
31955                this.indicatorStyle.width = this.width + 'px';
31956            }
31957
31958            if ( y < this.minBoundaryY ) {
31959                if ( this.options.shrink == 'scale' ) {
31960                    this.height = Math.max(this.indicatorHeight + y * 3, 8);
31961                    this.indicatorStyle.height = this.height + 'px';
31962                }
31963                y = this.minBoundaryY;
31964            } else if ( y > this.maxBoundaryY ) {
31965                if ( this.options.shrink == 'scale' ) {
31966                    this.height = Math.max(this.indicatorHeight - (y - this.maxPosY) * 3, 8);
31967                    this.indicatorStyle.height = this.height + 'px';
31968                    y = this.maxPosY + this.indicatorHeight - this.height;
31969                } else {
31970                    y = this.maxBoundaryY;
31971                }
31972            } else if ( this.options.shrink == 'scale' && this.height != this.indicatorHeight ) {
31973                this.height = this.indicatorHeight;
31974                this.indicatorStyle.height = this.height + 'px';
31975            }
31976        }
31977
31978        this.x = x;
31979        this.y = y;
31980
31981        if ( this.scroller.options.useTransform ) {
31982            this.indicatorStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.scroller.translateZ;
31983        } else {
31984            this.indicatorStyle.left = x + 'px';
31985            this.indicatorStyle.top = y + 'px';
31986        }
31987    },
31988
31989    _pos: function (x, y) {
31990        if ( x < 0 ) {
31991            x = 0;
31992        } else if ( x > this.maxPosX ) {
31993            x = this.maxPosX;
31994        }
31995
31996        if ( y < 0 ) {
31997            y = 0;
31998        } else if ( y > this.maxPosY ) {
31999            y = this.maxPosY;
32000        }
32001
32002        x = this.options.listenX ? Math.round(x / this.sizeRatioX) : this.scroller.x;
32003        y = this.options.listenY ? Math.round(y / this.sizeRatioY) : this.scroller.y;
32004
32005        this.scroller.scrollTo(x, y);
32006    },
32007
32008    fade: function (val, hold) {
32009        if ( hold && !this.visible ) {
32010            return;
32011        }
32012
32013        clearTimeout(this.fadeTimeout);
32014        this.fadeTimeout = null;
32015
32016        var time = val ? 250 : 500,
32017            delay = val ? 0 : 300;
32018
32019        val = val ? '1' : '0';
32020
32021        this.wrapperStyle[utils.style.transitionDuration] = time + 'ms';
32022
32023        this.fadeTimeout = setTimeout((function (val) {
32024            this.wrapperStyle.opacity = val;
32025            this.visible = +val;
32026        }).bind(this, val), delay);
32027    }
32028};
32029
32030IScroll.utils = utils;
32031
32032if ( typeof module != 'undefined' && module.exports ) {
32033    module.exports = IScroll;
32034} else if ( typeof define == 'function' && define.amd ) {
32035        define( function () { return IScroll; } );
32036} else {
32037    window.IScroll = IScroll;
32038}
32039
32040})(window, document, Math);
32041/*!
32042 * fullPage 2.9.4
32043 * https://github.com/alvarotrigo/fullPage.js
32044 * @license MIT licensed
32045 *
32046 * Copyright (C) 2015 alvarotrigo.com - A project by Alvaro Trigo
32047 */
32048(function(global, factory) {
32049    'use strict';
32050    if (typeof define === 'function' && define.amd) {
32051        define(['jquery'], function($) {
32052          return factory($, global, global.document, global.Math);
32053        });
32054    } else if (typeof exports === "object" && exports) {
32055        module.exports = factory(require('jquery'), global, global.document, global.Math);
32056    } else {
32057        factory(jQuery, global, global.document, global.Math);
32058    }
32059})(typeof window !== 'undefined' ? window : this, function($, window, document, Math, undefined) {
32060    'use strict';
32061
32062    // keeping central set of classnames and selectors
32063    var WRAPPER =               'fullpage-wrapper';
32064    var WRAPPER_SEL =           '.' + WRAPPER;
32065
32066    // slimscroll
32067    var SCROLLABLE =            'fp-scrollable';
32068    var SCROLLABLE_SEL =        '.' + SCROLLABLE;
32069
32070    // util
32071    var RESPONSIVE =            'fp-responsive';
32072    var NO_TRANSITION =         'fp-notransition';
32073    var DESTROYED =             'fp-destroyed';
32074    var ENABLED =               'fp-enabled';
32075    var VIEWING_PREFIX =        'fp-viewing';
32076    var ACTIVE =                'active';
32077    var ACTIVE_SEL =            '.' + ACTIVE;
32078    var COMPLETELY =            'fp-completely';
32079    var COMPLETELY_SEL =        '.' + COMPLETELY;
32080
32081    // section
32082    var SECTION_DEFAULT_SEL =   '.section';
32083    var SECTION =               'fp-section';
32084    var SECTION_SEL =           '.' + SECTION;
32085    var SECTION_ACTIVE_SEL =    SECTION_SEL + ACTIVE_SEL;
32086    var SECTION_FIRST_SEL =     SECTION_SEL + ':first';
32087    var SECTION_LAST_SEL =      SECTION_SEL + ':last';
32088    var TABLE_CELL =            'fp-tableCell';
32089    var TABLE_CELL_SEL =        '.' + TABLE_CELL;
32090    var AUTO_HEIGHT =           'fp-auto-height';
32091    var AUTO_HEIGHT_SEL =       '.fp-auto-height';
32092    var NORMAL_SCROLL =         'fp-normal-scroll';
32093    var NORMAL_SCROLL_SEL =     '.fp-normal-scroll';
32094
32095    // section nav
32096    var SECTION_NAV =           'fp-nav';
32097    var SECTION_NAV_SEL =       '#' + SECTION_NAV;
32098    var SECTION_NAV_TOOLTIP =   'fp-tooltip';
32099    var SECTION_NAV_TOOLTIP_SEL='.'+SECTION_NAV_TOOLTIP;
32100    var SHOW_ACTIVE_TOOLTIP =   'fp-show-active';
32101
32102    // slide
32103    var SLIDE_DEFAULT_SEL =     '.slide';
32104    var SLIDE =                 'fp-slide';
32105    var SLIDE_SEL =             '.' + SLIDE;
32106    var SLIDE_ACTIVE_SEL =      SLIDE_SEL + ACTIVE_SEL;
32107    var SLIDES_WRAPPER =        'fp-slides';
32108    var SLIDES_WRAPPER_SEL =    '.' + SLIDES_WRAPPER;
32109    var SLIDES_CONTAINER =      'fp-slidesContainer';
32110    var SLIDES_CONTAINER_SEL =  '.' + SLIDES_CONTAINER;
32111    var TABLE =                 'fp-table';
32112
32113    // slide nav
32114    var SLIDES_NAV =            'fp-slidesNav';
32115    var SLIDES_NAV_SEL =        '.' + SLIDES_NAV;
32116    var SLIDES_NAV_LINK_SEL =   SLIDES_NAV_SEL + ' a';
32117    var SLIDES_ARROW =          'fp-controlArrow';
32118    var SLIDES_ARROW_SEL =      '.' + SLIDES_ARROW;
32119    var SLIDES_PREV =           'fp-prev';
32120    var SLIDES_PREV_SEL =       '.' + SLIDES_PREV;
32121    var SLIDES_ARROW_PREV =     SLIDES_ARROW + ' ' + SLIDES_PREV;
32122    var SLIDES_ARROW_PREV_SEL = SLIDES_ARROW_SEL + SLIDES_PREV_SEL;
32123    var SLIDES_NEXT =           'fp-next';
32124    var SLIDES_NEXT_SEL =       '.' + SLIDES_NEXT;
32125    var SLIDES_ARROW_NEXT =     SLIDES_ARROW + ' ' + SLIDES_NEXT;
32126    var SLIDES_ARROW_NEXT_SEL = SLIDES_ARROW_SEL + SLIDES_NEXT_SEL;
32127
32128    var $window = $(window);
32129    var $document = $(document);
32130
32131    // Default options for iScroll.js used when using scrollOverflow
32132    var iscrollOptions = {
32133        scrollbars: true,
32134        mouseWheel: true,
32135        hideScrollbars: false,
32136        fadeScrollbars: false,
32137        disableMouse: true,
32138        interactiveScrollbars: true,
32139        bounce: false,
32140    };
32141
32142    $.fn.fullpage = function(options) {
32143        //only once my friend!
32144        if($('html').hasClass(ENABLED)){ displayWarnings(); return; }
32145
32146        // common jQuery objects
32147        var $htmlBody = $('html, body');
32148        var $body = $('body');
32149
32150        var FP = $.fn.fullpage;
32151
32152        // Creating some defaults, extending them with any options that were provided
32153        options = $.extend({
32154            //navigation
32155            menu: false,
32156            anchors:[],
32157            lockAnchors: false,
32158            navigation: false,
32159            navigationPosition: 'right',
32160            navigationTooltips: [],
32161            showActiveTooltip: false,
32162            slidesNavigation: false,
32163            slidesNavPosition: 'bottom',
32164            scrollBar: false,
32165            hybrid: false,
32166
32167            //scrolling
32168            css3: true,
32169            scrollingSpeed: 700,
32170            autoScrolling: true,
32171            fitToSection: true,
32172            fitToSectionDelay: 1000,
32173            easing: 'easeInOutCubic',
32174            easingcss3: 'ease',
32175            loopBottom: false,
32176            loopTop: false,
32177            loopHorizontal: true,
32178            continuousVertical: false,
32179            continuousHorizontal: false,
32180            scrollHorizontally: false,
32181            interlockedSlides: false,
32182            dragAndMove: false,
32183            offsetSections: false,
32184            resetSliders: false,
32185            fadingEffect: false,
32186            normalScrollElements: null,
32187            scrollOverflow: false,
32188            scrollOverflowReset: false,
32189            scrollOverflowHandler: iscrollHandler,
32190            scrollOverflowOptions: null,
32191            touchSensitivity: 5,
32192            normalScrollElementTouchThreshold: 5,
32193            bigSectionsDestination: null,
32194
32195            //Accessibility
32196            keyboardScrolling: true,
32197            animateAnchor: true,
32198            recordHistory: true,
32199
32200            //design
32201            controlArrows: true,
32202            controlArrowColor: '#fff',
32203            verticalCentered: true,
32204            sectionsColor : [],
32205            paddingTop: 0,
32206            paddingBottom: 0,
32207            fixedElements: null,
32208            responsive: 0, //backwards compabitility with responsiveWiddth
32209            responsiveWidth: 0,
32210            responsiveHeight: 0,
32211            responsiveSlides: false,
32212            parallax: false,
32213            parallaxOptions: {
32214                type: 'reveal',
32215                percentage: 62,
32216                property: 'translate'
32217            },
32218
32219            //Custom selectors
32220            sectionSelector: SECTION_DEFAULT_SEL,
32221            slideSelector: SLIDE_DEFAULT_SEL,
32222
32223            //events
32224            afterLoad: null,
32225            onLeave: null,
32226            afterRender: null,
32227            afterResize: null,
32228            afterReBuild: null,
32229            afterSlideLoad: null,
32230            onSlideLeave: null,
32231            afterResponsive: null,
32232
32233            lazyLoading: true
32234        }, options);
32235
32236        //flag to avoid very fast sliding for landscape sliders
32237        var slideMoving = false;
32238
32239        var isTouchDevice = navigator.userAgent.match(/(iPhone|iPod|iPad|Android|playbook|silk|BlackBerry|BB10|Windows Phone|Tizen|Bada|webOS|IEMobile|Opera Mini)/);
32240        var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0) || (navigator.maxTouchPoints));
32241        var container = $(this);
32242        var windowsHeight = $window.height();
32243        var isResizing = false;
32244        var isWindowFocused = true;
32245        var lastScrolledDestiny;
32246        var lastScrolledSlide;
32247        var canScroll = true;
32248        var scrollings = [];
32249        var controlPressed;
32250        var startingSection;
32251        var isScrollAllowed = {};
32252        isScrollAllowed.m = {  'up':true, 'down':true, 'left':true, 'right':true };
32253        isScrollAllowed.k = $.extend(true,{}, isScrollAllowed.m);
32254        var MSPointer = getMSPointer();
32255        var events = {
32256            touchmove: 'ontouchmove' in window ? 'touchmove' :  MSPointer.move,
32257            touchstart: 'ontouchstart' in window ? 'touchstart' :  MSPointer.down
32258        };
32259
32260        //cheks for passive event support
32261        //added by Uncode from new fullPage updates
32262        var g_supportsPassive = false;
32263        try {
32264          var opts = Object.defineProperty({}, 'passive', {
32265            get: function() {
32266              g_supportsPassive = true;
32267            }
32268          });
32269          window.addEventListener("testPassive", null, opts);
32270          window.removeEventListener("testPassive", null, opts);
32271        } catch (e) {}
32272
32273        //timeouts
32274        var resizeId;
32275        var afterSectionLoadsId;
32276        var afterSlideLoadsId;
32277        var scrollId;
32278        var scrollId2;
32279        var keydownId;
32280        var originals = $.extend(true, {}, options); //deep copy
32281
32282        //Uncode addition
32283        var $masthead = $('#masthead');
32284        var hideMenu = !$('body').hasClass('vmenu') && $('body').hasClass('uncode-fp-menu-hide') ? true : false;
32285        var menuHeight = $masthead.hasClass('menu-transparent') || hideMenu ? 0 : UNCODE.menuHeight;
32286        var bodyBorder = UNCODE.bodyBorder;
32287        var adminBarHeight = UNCODE.adminBarHeight;
32288
32289        displayWarnings();
32290
32291        //fixing bug in iScroll with links: https://github.com/cubiq/iscroll/issues/783
32292        iscrollOptions.click = isTouch; // see #2035
32293
32294        //extending iScroll options with the user custom ones
32295        iscrollOptions = $.extend(iscrollOptions, options.scrollOverflowOptions);
32296
32297        //easeInOutCubic animation included in the plugin
32298        $.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;}});
32299
32300        /**
32301        * Sets the autoScroll option.
32302        * It changes the scroll bar visibility and the history of the site as a result.
32303        */
32304        function setAutoScrolling(value, type){
32305            //removing the transformation
32306            if(!value){
32307                silentScroll(0);
32308            }
32309
32310            setVariableState('autoScrolling', value, type);
32311
32312            var element = $(SECTION_ACTIVE_SEL);
32313
32314            if(options.autoScrolling && !options.scrollBar){
32315                $htmlBody.css({
32316                    'overflow' : 'hidden !important',
32317                    'height' : '100%'
32318                });
32319
32320                //Uncode addition
32321                //setRecordHistory(originals.recordHistory, 'internal');
32322
32323                //for IE touch devices
32324                container.css({
32325                    '-ms-touch-action': 'none',
32326                    'touch-action': 'none'
32327                });
32328
32329                if(element.length){
32330                    //moving the container up
32331                    silentScroll(element.position().top);
32332                }
32333
32334            }else{
32335                $htmlBody.css({
32336                    'overflow' : 'visible !important',
32337                    'height' : 'initial'
32338                });
32339
32340                //Uncode addition
32341                //setRecordHistory(false, 'internal');
32342
32343                //for IE touch devices
32344                container.css({
32345                    '-ms-touch-action': '',
32346                    'touch-action': ''
32347                });
32348
32349                //scrolling the page to the section with no animation
32350                if (element.length) {
32351                    $htmlBody.scrollTop(element.position().top);
32352                }
32353            }
32354        }
32355
32356        /**
32357        * Defines wheter to record the history for each hash change in the URL.
32358        */
32359        function setRecordHistory(value, type){
32360            setVariableState('recordHistory', value, type);
32361        }
32362
32363        /**
32364        * Defines the scrolling speed
32365        */
32366        function setScrollingSpeed(value, type){
32367            setVariableState('scrollingSpeed', value, type);
32368        }
32369
32370        /**
32371        * Sets fitToSection
32372        */
32373        function setFitToSection(value, type){
32374            setVariableState('fitToSection', value, type);
32375        }
32376
32377        /**
32378        * Sets lockAnchors
32379        */
32380        function setLockAnchors(value){
32381            options.lockAnchors = value;
32382        }
32383
32384        /**
32385        * Adds or remove the possiblity of scrolling through sections by using the mouse wheel or the trackpad.
32386        */
32387        function setMouseWheelScrolling(value){
32388            if(value){
32389                addMouseWheelHandler();
32390                addMiddleWheelHandler();
32391            }else{
32392                removeMouseWheelHandler();
32393                removeMiddleWheelHandler();
32394            }
32395        }
32396
32397        /**
32398        * Adds or remove the possibility of scrolling through sections by using the mouse wheel/trackpad or touch gestures.
32399        * Optionally a second parameter can be used to specify the direction for which the action will be applied.
32400        *
32401        * @param directions string containing the direction or directions separated by comma.
32402        */
32403        function setAllowScrolling(value, directions){
32404            if(typeof directions !== 'undefined'){
32405                directions = directions.replace(/ /g,'').split(',');
32406
32407                $.each(directions, function (index, direction){
32408                    setIsScrollAllowed(value, direction, 'm');
32409                });
32410            }
32411            else if(value){
32412                setMouseWheelScrolling(true);
32413                addTouchHandler();
32414            }else{
32415                setMouseWheelScrolling(false);
32416                removeTouchHandler();
32417            }
32418        }
32419
32420        /**
32421        * Adds or remove the possibility of scrolling through sections by using the keyboard arrow keys
32422        */
32423        function setKeyboardScrolling(value, directions){
32424            if(typeof directions !== 'undefined'){
32425                directions = directions.replace(/ /g,'').split(',');
32426
32427                $.each(directions, function (index, direction){
32428                    setIsScrollAllowed(value, direction, 'k');
32429                });
32430            }else{
32431                options.keyboardScrolling = value;
32432            }
32433        }
32434
32435        /**
32436        * Moves the page up one section.
32437        */
32438        function moveSectionUp(){
32439            var prev = $(SECTION_ACTIVE_SEL).prev(SECTION_SEL);
32440
32441            //looping to the bottom if there's no more sections above
32442            if (!prev.length && (options.loopTop || options.continuousVertical)) {
32443                prev = $(SECTION_SEL).last();
32444            }
32445
32446            if (prev.length) {
32447                scrollPage(prev, null, true);
32448            }
32449        }
32450
32451        /**
32452        * Moves the page down one section.
32453        */
32454        function moveSectionDown(){
32455            var next = $(SECTION_ACTIVE_SEL).next(SECTION_SEL);
32456
32457            //looping to the top if there's no more sections below
32458            if(!next.length &&
32459                (options.loopBottom || options.continuousVertical)){
32460                next = $(SECTION_SEL).first();
32461            }
32462
32463            if(next.length){
32464                scrollPage(next, null, false);
32465            }
32466        }
32467
32468        /**
32469        * Moves the page to the given section and slide with no animation.
32470        * Anchors or index positions can be used as params.
32471        */
32472        function silentMoveTo(sectionAnchor, slideAnchor){
32473            setScrollingSpeed (0, 'internal');
32474            moveTo(sectionAnchor, slideAnchor);
32475            setScrollingSpeed (originals.scrollingSpeed, 'internal');
32476        }
32477
32478        /**
32479        * Moves the page to the given section and slide.
32480        * Anchors or index positions can be used as params.
32481        */
32482        function moveTo(sectionAnchor, slideAnchor){
32483            var destiny = getSectionByAnchor(sectionAnchor);
32484
32485            if (typeof slideAnchor !== 'undefined'){
32486                scrollPageAndSlide(sectionAnchor, slideAnchor);
32487            }else if(destiny.length > 0){
32488                scrollPage(destiny);
32489            }
32490        }
32491
32492        /**
32493        * Slides right the slider of the active section.
32494        * Optional `section` param.
32495        */
32496        function moveSlideRight(section){
32497            moveSlide('right', section);
32498        }
32499
32500        /**
32501        * Slides left the slider of the active section.
32502        * Optional `section` param.
32503        */
32504        function moveSlideLeft(section){
32505            moveSlide('left', section);
32506        }
32507
32508        /**
32509         * When resizing is finished, we adjust the slides sizes and positions
32510         */
32511        function reBuild(resizing){
32512            if(container.hasClass(DESTROYED)){ return; }  //nothing to do if the plugin was destroyed
32513
32514            isResizing = true;
32515
32516            windowsHeight = $window.height();  //updating global var
32517
32518            $(SECTION_SEL).each(function(){
32519                var slidesWrap = $(this).find(SLIDES_WRAPPER_SEL);
32520                var slides = $(this).find(SLIDE_SEL);
32521
32522                //adjusting the height of the table-cell for IE and Firefox
32523                if(options.verticalCentered){
32524                    $(this).find(TABLE_CELL_SEL).css('height', getTableHeight($(this)) + 'px');
32525                }
32526
32527                $(this).css('height', windowsHeight + 'px');
32528
32529                //resizing the scrolling divs
32530                if(options.scrollOverflow){
32531                    if(slides.length){
32532                        slides.each(function(){
32533                            createScrollBar($(this));
32534                        });
32535                    }else{
32536                        createScrollBar($(this));
32537                    }
32538                }
32539
32540                //adjusting the position fo the FULL WIDTH slides...
32541                if (slides.length > 1) {
32542                    landscapeScroll(slidesWrap, slidesWrap.find(SLIDE_ACTIVE_SEL));
32543                }
32544            });
32545
32546            var activeSection = $(SECTION_ACTIVE_SEL);
32547            var sectionIndex = activeSection.index(SECTION_SEL);
32548
32549            //isn't it the first section?
32550            if(sectionIndex){
32551                //adjusting the position for the current section
32552                silentMoveTo(sectionIndex + 1);
32553            }
32554
32555            isResizing = false;
32556            // Uncode change
32557            // $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container);
32558            $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container, getTableHeight());
32559            $.isFunction( options.afterReBuild ) && !resizing && options.afterReBuild.call(container);
32560        }
32561
32562        /**
32563        * Turns fullPage.js to normal scrolling mode when the viewport `width` or `height`
32564        * are smaller than the set limit values.
32565        */
32566        function setResponsive(active){
32567            var isResponsive = $body.hasClass(RESPONSIVE);
32568
32569            if(active){
32570                if(!isResponsive){
32571                    setAutoScrolling(false, 'internal');
32572                    setFitToSection(false, 'internal');
32573                    $(SECTION_NAV_SEL).hide();
32574                    $body.addClass(RESPONSIVE);
32575                    $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active);
32576                }
32577            }
32578            else if(isResponsive){
32579                setAutoScrolling(originals.autoScrolling, 'internal');
32580                setFitToSection(originals.autoScrolling, 'internal');
32581                $(SECTION_NAV_SEL).show();
32582                $body.removeClass(RESPONSIVE);
32583                $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active);
32584            }
32585        }
32586
32587        if($(this).length){
32588            //public functions
32589            FP.setAutoScrolling = setAutoScrolling;
32590            FP.setRecordHistory = setRecordHistory;
32591            FP.setScrollingSpeed = setScrollingSpeed;
32592            FP.setFitToSection = setFitToSection;
32593            FP.setLockAnchors = setLockAnchors;
32594            FP.setMouseWheelScrolling = setMouseWheelScrolling;
32595            FP.setAllowScrolling = setAllowScrolling;
32596            FP.setKeyboardScrolling = setKeyboardScrolling;
32597            FP.moveSectionUp = moveSectionUp;
32598            FP.moveSectionDown = moveSectionDown;
32599            FP.silentMoveTo = silentMoveTo;
32600            FP.moveTo = moveTo;
32601            FP.moveSlideRight = moveSlideRight;
32602            FP.moveSlideLeft = moveSlideLeft;
32603            FP.fitToSection = fitToSection;
32604            FP.reBuild = reBuild;
32605            FP.setResponsive = setResponsive;
32606            FP.destroy = destroy;
32607
32608            init();
32609
32610            bindEvents();
32611        }
32612
32613        function init(){
32614            //if css3 is not supported, it will use jQuery animations
32615            if(options.css3){
32616                options.css3 = support3d();
32617            }
32618
32619            options.scrollBar = options.scrollBar || options.hybrid;
32620
32621            setOptionsFromDOM();
32622            prepareDom();
32623            setAllowScrolling(true);
32624            setAutoScrolling(options.autoScrolling, 'internal');
32625            responsive();
32626
32627            //setting the class for the body element
32628            setBodyClass();
32629
32630            //Uncode addition
32631            // if(document.readyState === 'complete'){
32632            //     scrollToAnchor();
32633            // }
32634            // $window.on('load', scrollToAnchor);
32635        }
32636
32637        function bindEvents(){
32638            $window
32639                //when scrolling...
32640                //.on('scroll', scrollHandler)
32641
32642                //detecting any change on the URL to scroll to the given anchor link
32643                //(a way to detect back history button as we play with the hashes on the URL)
32644                .on('hashchange', hashChangeHandler)
32645
32646                //when opening a new tab (ctrl + t), `control` won't be pressed when coming back.
32647                .blur(blurHandler)
32648
32649                //when resizing the site, we adjust the heights of the sections, slimScroll...
32650                .resize(resizeHandler);
32651
32652            $document
32653                //Sliding with arrow keys, both, vertical and horizontal
32654                .keydown(keydownHandler)
32655
32656                //to prevent scrolling while zooming
32657                .keyup(keyUpHandler)
32658
32659                //Scrolls to the section when clicking the navigation bullet
32660                .on('click touchstart', SECTION_NAV_SEL + ' a', sectionBulletHandler)
32661
32662                //Scrolls the slider to the given slide destination for the given section
32663                .on('click touchstart', SLIDES_NAV_LINK_SEL, slideBulletHandler)
32664
32665                .on('click', SECTION_NAV_TOOLTIP_SEL, tooltipTextHandler);
32666
32667            //Scrolling horizontally when clicking on the slider controls.
32668            $(SECTION_SEL).on('click touchstart', SLIDES_ARROW_SEL, slideArrowHandler);
32669
32670            /**
32671            * Applying normalScroll elements.
32672            * Ignoring the scrolls over the specified selectors.
32673            */
32674            if(options.normalScrollElements){
32675                $document.on('mouseenter', options.normalScrollElements, function () {
32676                    setMouseWheelScrolling(false);
32677                });
32678
32679                $document.on('mouseleave', options.normalScrollElements, function(){
32680                    setMouseWheelScrolling(true);
32681                });
32682            }
32683        }
32684
32685        /**
32686        * Setting options from DOM elements if they are not provided.
32687        */
32688        function setOptionsFromDOM(){
32689            var sections = container.find(options.sectionSelector);
32690
32691            //no anchors option? Checking for them in the DOM attributes
32692            if(!options.anchors.length){
32693                options.anchors = sections.filter('[data-anchor]').map(function(){
32694                    return $(this).data('anchor').toString();
32695                }).get();
32696            }
32697
32698            //no tooltips option? Checking for them in the DOM attributes
32699            if(!options.navigationTooltips.length){
32700                options.navigationTooltips = sections.filter('[data-tooltip]').map(function(){
32701                    return $(this).data('tooltip').toString();
32702                }).get();
32703            }
32704        }
32705
32706        /**
32707        * Works over the DOM structure to set it up for the current fullpage options.
32708        */
32709        function prepareDom(){
32710            container.css({
32711                'height': '100%',
32712                'position': 'relative'
32713            });
32714
32715            //adding a class to recognize the container internally in the code
32716            container.addClass(WRAPPER);
32717            $('html').addClass(ENABLED);
32718
32719            windowsHeight = $window.height();
32720
32721            container.removeClass(DESTROYED); //in case it was destroyed before initializing it again
32722
32723            addInternalSelectors();
32724
32725             //styling the sections / slides / menu
32726            $(SECTION_SEL).each(function(index){
32727                var section = $(this);
32728                var slides = section.find(SLIDE_SEL);
32729                var numSlides = slides.length;
32730
32731                styleSection(section, index);
32732                styleMenu(section, index);
32733
32734                // if there's any slide
32735                if (numSlides > 0) {
32736                    styleSlides(section, slides, numSlides);
32737                }else{
32738                    if(options.verticalCentered){
32739                        addTableClass(section);
32740                    }
32741                }
32742            });
32743
32744            //fixed elements need to be moved out of the plugin container due to problems with CSS3.
32745            if(options.fixedElements && options.css3){
32746                $(options.fixedElements).appendTo($body);
32747            }
32748
32749            //vertical centered of the navigation + active bullet
32750            if(options.navigation){
32751                addVerticalNavigation();
32752            }
32753
32754            enableYoutubeAPI();
32755
32756            if(options.scrollOverflow){
32757                if(document.readyState === 'complete'){
32758                    createScrollBarHandler();
32759                }
32760                //after DOM and images are loaded
32761                $window.on('load', createScrollBarHandler);
32762            }else{
32763                afterRenderActions();
32764            }
32765        }
32766
32767        /**
32768        * Styles the horizontal slides for a section.
32769        */
32770        function styleSlides(section, slides, numSlides){
32771            var sliderWidth = numSlides * 100;
32772            var slideWidth = 100 / numSlides;
32773
32774            slides.wrapAll('<div class="' + SLIDES_CONTAINER + '" />');
32775            slides.parent().wrap('<div class="' + SLIDES_WRAPPER + '" />');
32776
32777            section.find(SLIDES_CONTAINER_SEL).css('width', sliderWidth + '%');
32778
32779            if(numSlides > 1){
32780                if(options.controlArrows){
32781                    createSlideArrows(section);
32782                }
32783
32784                if(options.slidesNavigation){
32785                    addSlidesNavigation(section, numSlides);
32786                }
32787            }
32788
32789            slides.each(function(index) {
32790                $(this).css('width', slideWidth + '%');
32791
32792                if(options.verticalCentered){
32793                    addTableClass($(this));
32794                }
32795            });
32796
32797            var startingSlide = section.find(SLIDE_ACTIVE_SEL);
32798
32799            //if the slide won't be an starting point, the default will be the first one
32800            //the active section isn't the first one? Is not the first slide of the first section? Then we load that section/sl
32800ide by default.
32801            if( startingSlide.length &&  ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) !== 0 || ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) === 0 && startingSlide.index() !== 0))){
32802                silentLandscapeScroll(startingSlide, 'internal');
32803            }else{
32804                slides.eq(0).addClass(ACTIVE);
32805            }
32806        }
32807
32808        /**
32809        * Styling vertical sections
32810        */
32811        function styleSection(section, index){
32812            //if no active section is defined, the 1st one will be the default one
32813            if(!index && $(SECTION_ACTIVE_SEL).length === 0) {
32814                section.addClass(ACTIVE);
32815            }
32816            startingSection = $(SECTION_ACTIVE_SEL);
32817
32818            section.css('height', windowsHeight + 'px');
32819
32820            if(options.paddingTop){
32821                section.css('padding-top', options.paddingTop);
32822            }
32823
32824            if(options.paddingBottom){
32825                section.css('padding-bottom', options.paddingBottom);
32826            }
32827
32828            if (typeof options.sectionsColor[index] !==  'undefined') {
32829                section.css('background-color', options.sectionsColor[index]);
32830            }
32831
32832            if (typeof options.anchors[index] !== 'undefined') {
32833                section.attr('data-anchor', options.anchors[index]);
32834            }
32835        }
32836
32837        /**
32838        * Sets the data-anchor attributes to the menu elements and activates the current one.
32839        */
32840        function styleMenu(section, index){
32841            if (typeof options.anchors[index] !== 'undefined') {
32842                //activating the menu / nav element on load
32843                if(section.hasClass(ACTIVE)){
32844                    activateMenuAndNav(options.anchors[index], index);
32845                }
32846            }
32847
32848            //moving the menu outside the main container if it is inside (avoid problems with fixed positions when using CSS3 tranforms)
32849            if(options.menu && options.css3 && $(options.menu).closest(WRAPPER_SEL).length){
32850                $(options.menu).appendTo($body);
32851            }
32852        }
32853
32854        /**
32855        * Adds internal classes to be able to provide customizable selectors
32856        * keeping the link with the style sheet.
32857        */
32858        function addInternalSelectors(){
32859            container.find(options.sectionSelector).addClass(SECTION);
32860            container.find(options.slideSelector).addClass(SLIDE);
32861        }
32862
32863        /**
32864        * Creates the control arrows for the given section
32865        */
32866        function createSlideArrows(section){
32867            section.find(SLIDES_WRAPPER_SEL).after('<div class="' + SLIDES_ARROW_PREV + '"></div><div class="' + SLIDES_ARROW_NEXT + '"></div>');
32868
32869            if(options.controlArrowColor!='#fff'){
32870                section.find(SLIDES_ARROW_NEXT_SEL).css('border-color', 'transparent transparent transparent '+options.controlArrowColor);
32871                section.find(SLIDES_ARROW_PREV_SEL).css('border-color', 'transparent '+ options.controlArrowColor + ' transparent transparent');
32872            }
32873
32874            if(!options.loopHorizontal){
32875                section.find(SLIDES_ARROW_PREV_SEL).hide();
32876            }
32877        }
32878
32879        /**
32880        * Creates a vertical navigation bar.
32881        */
32882        function addVerticalNavigation(){
32883            $body.append('<div id="' + SECTION_NAV + '"><ul></ul></div>');
32884            var nav = $(SECTION_NAV_SEL);
32885
32886            nav.addClass(function() {
32887                return options.showActiveTooltip ? SHOW_ACTIVE_TOOLTIP + ' ' + options.navigationPosition : options.navigationPosition;
32888            });
32889
32890            for (var i = 0; i < $(SECTION_SEL).length; i++) {
32891                var link = '';
32892                if (options.anchors.length) {
32893                    link = options.anchors[i];
32894                }
32895
32896                var li = '<li><a href="#' + link + '"><span></span></a>';
32897
32898                // Only add tooltip if needed (defined by user)
32899                var tooltip = options.navigationTooltips[i];
32900
32901                if (typeof tooltip !== 'undefined' && tooltip !== '') {
32902                    li += '<div class="' + SECTION_NAV_TOOLTIP + ' ' + options.navigationPosition + '">' + tooltip + '</div>';
32903                }
32904
32905                li += '</li>';
32906
32907                nav.find('ul').append(li);
32908            }
32909
32910            //centering it vertically
32911            $(SECTION_NAV_SEL).css('margin-top', '-' + ($(SECTION_NAV_SEL).height()/2) + 'px');
32912
32913            //activating the current active section
32914            $(SECTION_NAV_SEL).find('li').eq($(SECTION_ACTIVE_SEL).index(SECTION_SEL)).find('a').addClass(ACTIVE);
32915        }
32916
32917        /**
32918        * Creates the slim scroll scrollbar for the sections and slides inside them.
32919        */
32920        function createScrollBarHandler(){
32921            $(SECTION_SEL).each(function(){
32922                var slides = $(this).find(SLIDE_SEL);
32923
32924                if(slides.length){
32925                    slides.each(function(){
32926                        createScrollBar($(this));
32927                    });
32928                }else{
32929                    createScrollBar($(this));
32930                }
32931
32932            });
32933            afterRenderActions();
32934        }
32935
32936        /*
32937        * Enables the Youtube videos API so we can control their flow if necessary.
32938        */
32939        function enableYoutubeAPI(){
32940            container.find('iframe[src*="youtube.com/embed/"]').each(function(){
32941                addURLParam($(this), 'enablejsapi=1');
32942            });
32943        }
32944
32945        /**
32946        * Adds a new parameter and its value to the `src` of a given element
32947        */
32948        function addURLParam(element, newParam){
32949            var originalSrc = element.attr('src');
32950            element.attr('src', originalSrc + getUrlParamSign(originalSrc) + newParam);
32951        }
32952
32953        /*
32954        * Returns the prefix sign to use for a new parameter in an existen URL.
32955        *
32956        * @return {String}  ? | &
32957        */
32958        function getUrlParamSign(url){
32959            return ( !/\?/.test( url ) ) ? '?' : '&';
32960        }
32961
32962        /**
32963        * Actions and callbacks to fire afterRender
32964        */
32965        function afterRenderActions(){
32966            var section = $(SECTION_ACTIVE_SEL);
32967
32968            section.addClass(COMPLETELY);
32969
32970            if(options.scrollOverflowHandler.afterRender){
32971                options.scrollOverflowHandler.afterRender(section);
32972            }
32973            lazyLoad(section);
32974            playMedia(section);
32975            options.scrollOverflowHandler.afterLoad();
32976
32977            if(isDestinyTheStartingSection()){
32978                $.isFunction( options.afterLoad ) && options.afterLoad.call(section, section.data('anchor'), (section.index(SECTION_SEL) + 1));
32979            }
32980
32981            // Uncode change
32982            // $.isFunction( options.afterRender ) && options.afterRender.call(container);
32983            $.isFunction( options.afterRender ) && options.afterRender.call(container, getTableHeight());
32984        }
32985
32986        /**
32987        * Determines if the URL anchor destiny is the starting section (the one using 'active' class before initialization)
32988        */
32989        function isDestinyTheStartingSection(){
32990            var anchors =  window.location.hash.replace('#', '').split('/');
32991            var destinationSection = getSectionByAnchor(decodeURIComponent(anchors[0]));
32992
32993            return !destinationSection.length || destinationSection.length && destinationSection.index() === startingSection.index();
32994        }
32995
32996
32997        var isScrolling = false;
32998        var lastScroll = 0;
32999
33000        //when scrolling...
33001        function scrollHandler(){
33002            var currentSection;
33003
33004            if(!options.autoScrolling || options.scrollBar){
33005                var currentScroll = $window.scrollTop();
33006                var scrollDirection = getScrollDirection(currentScroll);
33007                var visibleSectionIndex = 0;
33008                var screen_mid = currentScroll + ($window.height() / 2.0);
33009                var isAtBottom = $body.height() - $window.height() === currentScroll;
33010                var sections =  document.querySelectorAll(SECTION_SEL);
33011
33012                //when using `auto-height` for a small last section it won't be centered in the viewport
33013                if(isAtBottom){
33014                    visibleSectionIndex = sections.length - 1;
33015                }
33016                //is at top? when using `auto-height` for a small first section it won't be centered in the viewport
33017                else if(!currentScroll){
33018                    visibleSectionIndex = 0;
33019                }
33020
33021                //taking the section which is showing more content in the viewport
33022                else{
33023                    for (var i = 0; i < sections.length; ++i) {
33024                        var section = sections[i];
33025
33026                        // Pick the the last section which passes the middle line of the screen.
33027                        if (section.offsetTop <= screen_mid)
33028                        {
33029                            visibleSectionIndex = i;
33030                        }
33031                    }
33032                }
33033
33034                if(isCompletelyInViewPort(scrollDirection)){
33035                    if(!$(SECTION_ACTIVE_SEL).hasClass(COMPLETELY)){
33036                        $(SECTION_ACTIVE_SEL).addClass(COMPLETELY).siblings().removeClass(COMPLETELY);
33037                    }
33038                }
33039
33040                //geting the last one, the current one on the screen
33041                currentSection = $(sections).eq(visibleSectionIndex);
33042
33043                //setting the visible section as active when manually scrolling
33044                //executing only once the first time we reach the section
33045                if(!currentSection.hasClass(ACTIVE)){
33046                    isScrolling = true;
33047                    var leavingSection = $(SECTION_ACTIVE_SEL);
33048                    var leavingSectionIndex = leavingSection.index(SECTION_SEL) + 1;
33049                    var yMovement = getYmovement(currentSection);
33050                    var anchorLink  = currentSection.data('anchor');
33051                    var sectionIndex = currentSection.index(SECTION_SEL) + 1;
33052                    var activeSlide = currentSection.find(SLIDE_ACTIVE_SEL);
33053                    var slideIndex;
33054                    var slideAnchorLink;
33055
33056                    if(activeSlide.length){
33057                        slideAnchorLink = activeSlide.data('anchor');
33058                        slideIndex = activeSlide.index();
33059                    }
33060
33061                    if(canScroll){
33062                        currentSection.addClass(ACTIVE).siblings().removeClass(ACTIVE);
33063
33064                        $.isFunction( options.onLeave ) && options.onLeave.call( leavingSection, leavingSectionIndex, sectionIndex, yMovement);
33065                        $.isFunction( options.afterLoad ) && options.afterLoad.call( currentSection, anchorLink, sectionIndex);
33066
33067                        stopMedia(leavingSection);
33068                        lazyLoad(currentSection);
33069                        playMedia(currentSection);
33070
33071                        activateMenuAndNav(anchorLink, sectionIndex - 1);
33072
33073                        if(options.anchors.length){
33074                            //needed to enter in hashChange event when using the menu with anchor links
33075                            lastScrolledDestiny = anchorLink;
33076                        }
33077                        setState(slideIndex, slideAnchorLink, anchorLink, sectionIndex);
33078                    }
33079
33080                    //small timeout in order to avoid entering in hashChange event when scrolling is not finished yet
33081                    clearTimeout(scrollId);
33082                    scrollId = setTimeout(function(){
33083                        isScrolling = false;
33084                    }, 100);
33085                }
33086
33087                if(options.fitToSection){
33088                    //for the auto adjust of the viewport to fit a whole section
33089                    clearTimeout(scrollId2);
33090
33091                    scrollId2 = setTimeout(function(){
33092                        //checking it again in case it changed during the delay
33093                        if(options.fitToSection){
33094                            fitToSection();
33095                        }
33096                    }, options.fitToSectionDelay);
33097                }
33098            }
33099        }
33100
33101        /**
33102        * Fits the site to the nearest active section
33103        */
33104        function fitToSection(){
33105            //checking fitToSection again in case it was set to false before the timeout delay
33106            if(canScroll){
33107                //allows to scroll to an active section and
33108                //if the section is already active, we prevent firing callbacks
33109                isResizing = true;
33110
33111                scrollPage($(SECTION_ACTIVE_SEL));
33112                isResizing = false;
33113            }
33114        }
33115
33116        /**
33117        * Determines whether the active section has seen in its whole or not.
33118        */
33119        function isCompletelyInViewPort(movement){
33120            var top = $(SECTION_ACTIVE_SEL).position().top;
33121            var bottom = top + $window.height();
33122
33123            if(movement == 'up'){
33124                return bottom >= ($window.scrollTop() + $window.height());
33125            }
33126            return top <= $window.scrollTop();
33127        }
33128
33129        /**
33130        * Gets the directon of the the scrolling fired by the scroll event.
33131        */
33132        function getScrollDirection(currentScroll){
33133            var direction = currentScroll > lastScroll ? 'down' : 'up';
33134
33135            lastScroll = currentScroll;
33136
33137            //needed for auto-height sections to determine if we want to scroll to the top or bottom of the destination
33138            previousDestTop = currentScroll;
33139
33140            return direction;
33141        }
33142
33143        /**
33144        * Determines the way of scrolling up or down:
33145        * by 'automatically' scrolling a section or by using the default and normal scrolling.
33146        */
33147        function scrolling(type, scrollable){
33148            if (!isScrollAllowed.m[type]){
33149                return;
33150            }
33151            var check = (type === 'down') ? 'bottom' : 'top';
33152            var scrollSection = (type === 'down') ? moveSectionDown : moveSectionUp;
33153
33154            if(scrollable.length > 0 ){
33155                //is the scrollbar at the start/end of the scroll?
33156                if(options.scrollOverflowHandler.isScrolled(check, scrollable)){
33157                    scrollSection();
33158                }else{
33159                    return true;
33160                }
33161            }else{
33162                // moved up/down
33163                scrollSection();
33164            }
33165        }
33166
33167        /*
33168        * Preventing bouncing in iOS #2285
33169        */
33170        function preventBouncing(event){
33171            var e = event.originalEvent;
33172            if(!checkParentForNormalScrollElement(event.target) && options.autoScrolling && isReallyTouch(e) && isScrollAllowed.m.up){
33173                //preventing the easing on iOS devices
33174                event.preventDefault();
33175            }
33176        }
33177
33178        var touchStartY = 0;
33179        var touchStartX = 0;
33180        var touchEndY = 0;
33181        var touchEndX = 0;
33182
33183        /* Detecting touch events
33184
33185        * As we are changing the top property of the page on scrolling, we can not use the traditional way to detect it.
33186        * This way, the touchstart and the touch moves shows an small difference between them which is the
33187        * used one to determine the direction.
33188        */
33189        function touchMoveHandler(event){
33190            var e = event.originalEvent;
33191            var activeSection = $(e.target).closest(SECTION_SEL);
33192
33193            // additional: if one of the normalScrollElements isn't within options.normalScrollElementTouchThreshold hops up the DOM chain
33194            if (!checkParentForNormalScrollElement(event.target) && isReallyTouch(e) ) {
33195
33196                if(options.autoScrolling){
33197                    //preventing the easing on iOS devices
33198                    event.preventDefault();
33199                }
33200
33201                var scrollable = options.scrollOverflowHandler.scrollable(activeSection);
33202                var touchEvents = getEventsPage(e);
33203
33204                touchEndY = touchEvents.y;
33205                touchEndX = touchEvents.x;
33206
33207                //if movement in the X axys is greater than in the Y and the currect section has slides...
33208                if (activeSection.find(SLIDES_WRAPPER_SEL).length && Math.abs(touchStartX - touchEndX) > (Math.abs(touchStartY - touchEndY))) {
33209
33210                    //is the movement greater than the minimum resistance to scroll?
33211                    if (!slideMoving && Math.abs(touchStartX - touchEndX) > ($window.outerWidth() / 100 * options.touchSensitivity)) {
33212                        if (touchStartX > touchEndX) {
33213                            if(isScrollAllowed.m.right){
33214                                moveSlideRight(activeSection); //next
33215                            }
33216                        } else {
33217                            if(isScrollAllowed.m.left){
33218                                moveSlideLeft(activeSection); //prev
33219                            }
33220                        }
33221                    }
33222                }
33223
33224                //vertical scrolling (only when autoScrolling is enabled)
33225                else if(options.autoScrolling && canScroll){
33226
33227                    //is the movement greater than the minimum resistance to scroll?
33228                    if (Math.abs(touchStartY - touchEndY) > ($window.height() / 100 * options.touchSensitivity)) {
33229                        if (touchStartY > touchEndY) {
33230                            scrolling('down', scrollable);
33231                        } else if (touchEndY > touchStartY) {
33232                            scrolling('up', scrollable);
33233                        }
33234                    }
33235                }
33236            }
33237        }
33238
33239        /**
33240         * recursive function to loop up the parent nodes to check if one of them exists in options.normalScrollElements
33241         * Currently works well for iOS - Android might need some testing
33242         * @param  {Element} el  target element / jquery selector (in subsequent nodes)
33243         * @param  {int}     hop current hop compared to options.normalScrollElementTouchThreshold
33244         * @return {boolean} true if there is a match to options.normalScrollElements
33245         */
33246        function checkParentForNormalScrollElement (el, hop) {
33247            hop = hop || 0;
33248            var parent = $(el).parent();
33249
33250            if (hop < options.normalScrollElementTouchThreshold &&
33251                parent.is(options.normalScrollElements) ) {
33252                return true;
33253            } else if (hop == options.normalScrollElementTouchThreshold) {
33254                return false;
33255            } else {
33256                return checkParentForNormalScrollElement(parent, ++hop);
33257            }
33258        }
33259
33260        /**
33261        * As IE >= 10 fires both touch and mouse events when using a mouse in a touchscreen
33262        * this way we make sure that is really a touch event what IE is detecting.
33263        */
33264        function isReallyTouch(e){
33265            //if is not IE   ||  IE is detecting `touch` or `pen`
33266            return typeof e.pointerType === 'undefined' || e.pointerType != 'mouse';
33267        }
33268
33269        /**
33270        * Handler for the touch start event.
33271        */
33272        function touchStartHandler(event){
33273            var e = event.originalEvent;
33274
33275            //stopping the auto scroll to adjust to a section
33276            if(options.fitToSection){
33277                $htmlBody.stop();
33278            }
33279
33280            if(isReallyTouch(e)){
33281                var touchEvents = getEventsPage(e);
33282                touchStartY = touchEvents.y;
33283                touchStartX = touchEvents.x;
33284            }
33285        }
33286
33287        /**
33288        * Gets the average of the last `number` elements of the given array.
33289        */
33290        function getAverage(elements, number){
33291            var sum = 0;
33292
33293            //taking `number` elements from the end to make the average, if there are not enought, 1
33294            var lastElements = elements.slice(Math.max(elements.length - number, 1));
33295
33296            for(var i = 0; i < lastElements.length; i++){
33297                sum = sum + lastElements[i];
33298            }
33299
33300            return Math.ceil(sum/number);
33301        }
33302
33303        /**
33304         * Detecting mousewheel scrolling
33305         *
33306         * http://blogs.sitepointstatic.com/examples/tech/mouse-wheel/index.html
33307         * http://www.sitepoint.com/html5-javascript-mouse-wheel/
33308         */
33309        var prevTime = new Date().getTime();
33310
33311        function MouseWheelHandler(e) {
33312            var curTime = new Date().getTime();
33313            var isNormalScroll = $(COMPLETELY_SEL).hasClass(NORMAL_SCROLL);
33314
33315            //autoscrolling and not zooming?
33316            if(options.autoScrolling && !controlPressed && !isNormalScroll){
33317                // cross-browser wheel delta
33318                e = e || window.event;
33319                var value = e.wheelDelta || -e.deltaY || -e.detail;
33320                var delta = Math.max(-1, Math.min(1, value));
33321
33322                var horizontalDetection = typeof e.wheelDeltaX !== 'undefined' || typeof e.deltaX !== 'undefined';
33323                var isScrollingVertically = (Math.abs(e.wheelDeltaX) < Math.abs(e.wheelDelta)) || (Math.abs(e.deltaX ) < Math.abs(e.deltaY) || !horizontalDetection);
33324
33325                //Limiting the array to 150 (lets not waste memory!)
33326                if(scrollings.length > 149){
33327                    scrollings.shift();
33328                }
33329
33330                //keeping record of the previous scrollings
33331                scrollings.push(Math.abs(value));
33332
33333                //preventing to scroll the site on mouse wheel when scrollbar is present
33334                if(options.scrollBar){
33335                    e.preventDefault ? e.preventDefault() : e.returnValue = false;
33336                }
33337
33338                var activeSection = $(SECTION_ACTIVE_SEL);
33339                var scrollable = options.scrollOverflowHandler.scrollable(activeSection);
33340
33341                //time difference between the last scroll and the current one
33342                var timeDiff = curTime-prevTime;
33343                prevTime = curTime;
33344
33345                //haven't they scrolled in a while?
33346                //(enough to be consider a different scrolling action to scroll another section)
33347                if(timeDiff > 200){
33348                    //emptying the array, we dont care about old scrollings for our averages
33349                    scrollings = [];
33350                }
33351
33352                if(canScroll){
33353                    var averageEnd = getAverage(scrollings, 10);
33354                    var averageMiddle = getAverage(scrollings, 70);
33355                    var isAccelerating = averageEnd >= averageMiddle;
33356
33357                    //to avoid double swipes...
33358                    if(isAccelerating && isScrollingVertically){
33359                        //scrolling down?
33360                        if (delta < 0) {
33361                            scrolling('down', scrollable);
33362
33363                        //scrolling up?
33364                        }else {
33365                            scrolling('up', scrollable);
33366                        }
33367                    }
33368                }
33369
33370                return false;
33371            }
33372
33373            if(options.fitToSection){
33374                //stopping the auto scroll to adjust to a section
33375                $htmlBody.stop();
33376            }
33377        }
33378
33379        /**
33380        * Slides a slider to the given direction.
33381        * Optional `section` param.
33382        */
33383        function moveSlide(direction, section){
33384            var activeSection = typeof section === 'undefined' ? $(SECTION_ACTIVE_SEL) : section;
33385            var slides = activeSection.find(SLIDES_WRAPPER_SEL);
33386            var numSlides = slides.find(SLIDE_SEL).length;
33387
33388            // more than one slide needed and nothing should be sliding
33389            if (!slides.length || slideMoving || numSlides < 2) {
33390                return;
33391            }
33392
33393            var currentSlide = slides.find(SLIDE_ACTIVE_SEL);
33394            var destiny = null;
33395
33396            if(direction === 'left'){
33397                destiny = currentSlide.prev(SLIDE_SEL);
33398            }else{
33399                destiny = currentSlide.next(SLIDE_SEL);
33400            }
33401
33402            //isn't there a next slide in the secuence?
33403            if(!destiny.length){
33404                //respect loopHorizontal settin
33405                if (!options.loopHorizontal) return;
33406
33407                if(direction === 'left'){
33408                    destiny = currentSlide.siblings(':last');
33409                }else{
33410                    destiny = currentSlide.siblings(':first');
33411                }
33412            }
33413
33414            slideMoving = true;
33415
33416            landscapeScroll(slides, destiny, direction);
33417        }
33418
33419        /**
33420        * Maintains the active slides in the viewport
33421        * (Because the `scroll` animation might get lost with some actions, such as when using continuousVertical)
33422        */
33423        function keepSlidesPosition(){
33424            $(SLIDE_ACTIVE_SEL).each(function(){
33425                silentLandscapeScroll($(this), 'internal');
33426            });
33427        }
33428
33429        var previousDestTop = 0;
33430        /**
33431        * Returns the destination Y position based on the scrolling direction and
33432        * the height of the section.
33433        */
33434        function getDestinationPosition(element){
33435            var elemPosition = element.position();
33436
33437            //top of the desination will be at the top of the viewport
33438            var position = elemPosition.top;
33439            var isScrollingDown =  elemPosition.top > previousDestTop;
33440            var sectionBottom = position - windowsHeight + element.outerHeight();
33441            var bigSectionsDestination = options.bigSectionsDestination;
33442
33443            //Uncode addition
33444            var containerH = container.outerHeight();
33445            var containerPosition = container.offset();
33446
33447            //########### Commented by Uncode - START ###########
33448            //is the destination element bigger than the viewport?
33449            // if(element.outerHeight() > windowsHeight){
33450            //     //scrolling up?
33451            //     if(!isScrollingDown && !bigSectionsDestination || bigSectionsDestination === 'bottom' ){
33452            //         position = sectionBottom;
33453            //     }
33454            // }
33455
33456            // //sections equal or smaller than the viewport height && scrolling down? ||  is resizing and its in the last section
33457            // else if(isScrollingDown || (isResizing && element.is(':last-child')) ){
33458            //     //The bottom of the destination will be at the bottom of the viewport
33459            //     position = sectionBottom;
33460            // }
33461            //########### Commented by Uncode - END ###########
33462
33463            //Uncode addition
33464            if ( !$masthead.hasClass('menu-transparent') && $('body').hasClass('uncode-fp-menu-shrink') && !element.is(':first-child') )
33465                position += 18;
33466            if ( ( containerH + menuHeight + bodyBorder + adminBarHeight - windowsHeight ) < position || ( isResizing && element.is(':last-child') ) ) {
33467                position = sectionBottom + menuHeight + bodyBorder*2 + adminBarHeight;
33468            }
33469
33470            /*
33471            Keeping record of the last scrolled position to determine the scrolling direction.
33472            No conventional methods can be used as the scroll bar might not be present
33473            AND the section might not be active if it is auto-height and didnt reach the middle
33474            of the viewport.
33475            */
33476            previousDestTop = position;
33477            return position;
33478        }
33479
33480        /**
33481        * Scrolls the site to the given element and scrolls to the slide if a callback is given.
33482        */
33483        function scrollPage(element, callback, isMovementUp){
33484            if(typeof element === 'undefined'){ return; } //there's no element to scroll, leaving the function
33485
33486            var dtop = getDestinationPosition(element);
33487            var slideAnchorLink;
33488            var slideIndex;
33489
33490            //local variables
33491            var v = {
33492                element: element,
33493                callback: callback,
33494                isMovementUp: isMovementUp,
33495                dtop: dtop,
33496                yMovement: getYmovement(element),
33497                anchorLink: element.data('anchor'),
33498                sectionIndex: element.index(SECTION_SEL),
33499                activeSlide: element.find(SLIDE_ACTIVE_SEL),
33500                activeSection: $(SECTION_ACTIVE_SEL),
33501                leavingSection: $(SECTION_ACTIVE_SEL).index(SECTION_SEL) + 1,
33502
33503                //caching the value of isResizing at the momment the function is called
33504                //because it will be checked later inside a setTimeout and the value might change
33505                localIsResizing: isResizing
33506            };
33507
33508            //quiting when destination scroll is the same as the current one
33509            if((v.activeSection.is(element) && !isResizing) || (options.scrollBar && $window.scrollTop() === v.dtop && !element.hasClass(AUTO_HEIGHT) )){ return; }
33510
33511            if(v.activeSlide.length){
33512                slideAnchorLink = v.activeSlide.data('anchor');
33513                slideIndex = v.activeSlide.index();
33514            }
33515
33516            // If continuousVertical && we need to wrap around
33517            if (options.autoScrolling && options.continuousVertical && typeof (v.isMovementUp) !== "undefined" &&
33518                ((!v.isMovementUp && v.yMovement == 'up') || // Intending to scroll down but about to go up or
33519                (v.isMovementUp && v.yMovement == 'down'))) { // intending to scroll up but about to go down
33520
33521                v = createInfiniteSections(v);
33522            }
33523
33524            //callback (onLeave) if the site is not just resizing and readjusting the slides
33525            if($.isFunction(options.onLeave) && !v.localIsResizing){
33526                if(options.onLeave.call(v.activeSection, v.leavingSection, (v.sectionIndex + 1), v.yMovement) === false){
33527                    return;
33528                }
33529            }
33530
33531            //pausing media of the leaving section (if we are not just resizing, as destinatino will be the same one)
33532            if(!v.localIsResizing){
33533                stopMedia(v.activeSection);
33534            }
33535
33536            options.scrollOverflowHandler.beforeLeave();
33537            element.addClass(ACTIVE).siblings().removeClass(ACTIVE);
33538            lazyLoad(element);
33539            options.scrollOverflowHandler.onLeave();
33540
33541
33542            //preventing from activating the MouseWheelHandler event
33543            //more than once if the page is scrolling
33544            canScroll = false;
33545
33546            setState(slideIndex, slideAnchorLink, v.anchorLink, v.sectionIndex);
33547
33548            performMovement(v);
33549
33550            //flag to avoid callingn `scrollPage()` twice in case of using anchor links
33551            lastScrolledDestiny = v.anchorLink;
33552
33553            //avoid firing it twice (as it does also on scroll)
33554            activateMenuAndNav(v.anchorLink, v.sectionIndex);
33555        }
33556
33557        /**
33558        * Performs the vertical movement (by CSS3 or by jQuery)
33559        */
33560        function performMovement(v){
33561            // using CSS3 translate functionality
33562            if (options.css3 && options.autoScrolling && !options.scrollBar) {
33563
33564                // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625
33565                // that's why we round it to 0.
33566                var translate3d = 'translate3d(0px, -' + Math.round(v.dtop) + 'px, 0px)';
33567                transformContainer(translate3d, true);
33568
33569                //even when the scrollingSpeed is 0 there's a little delay, which might cause the
33570                //scrollingSpeed to change in case of using silentMoveTo();
33571                if(options.scrollingSpeed){
33572                    clearTimeout(afterSectionLoadsId);
33573                    afterSectionLoadsId = setTimeout(function () {
33574                        afterSectionLoads(v);
33575                    }, options.scrollingSpeed);
33576                }else{
33577                    afterSectionLoads(v);
33578                }
33579            }
33580
33581            // using jQuery animate
33582            else{
33583                var scrollSettings = getScrollSettings(v);
33584
33585                $(scrollSettings.element).animate(
33586                    scrollSettings.options,
33587                options.scrollingSpeed, options.easing).promise().done(function () { //only one single callback in case of animating  `html, body`
33588                    if(options.scrollBar){
33589
33590                        /* Hack!
33591                        The timeout prevents setting the most dominant section in the viewport as "active" when the user
33592                        scrolled to a smaller section by using the mousewheel (auto scrolling) rather than draging the scroll bar.
33593
33594                        When using scrollBar:true It seems like the scroll events still getting propagated even after the scrolling animation has finished.
33595                        */
33596                        setTimeout(function(){
33597                            afterSectionLoads(v);
33598                        },30);
33599                    }else{
33600                        afterSectionLoads(v);
33601                    }
33602                });
33603            }
33604        }
33605
33606        /**
33607        * Gets the scrolling settings depending on the plugin autoScrolling option
33608        */
33609        function getScrollSettings(v){
33610            var scroll = {};
33611
33612            if(options.autoScrolling && !options.scrollBar){
33613                scroll.options = { 'top': -v.dtop};
33614                scroll.element = WRAPPER_SEL;
33615            }else{
33616                scroll.options = { 'scrollTop': v.dtop};
33617                scroll.element = 'html, body';
33618            }
33619
33620            return scroll;
33621        }
33622
33623        /**
33624        * Adds sections before or after the current one to create the infinite effect.
33625        */
33626        function createInfiniteSections(v){
33627            // Scrolling down
33628            if (!v.isMovementUp) {
33629                // Move all previous sections to after the active section
33630                $(SECTION_ACTIVE_SEL).after(v.activeSection.prevAll(SECTION_SEL).get().reverse());
33631            }
33632            else { // Scrolling up
33633                // Move all next sections to before the active section
33634                $(SECTION_ACTIVE_SEL).before(v.activeSection.nextAll(SECTION_SEL));
33635            }
33636
33637            // Maintain the displayed position (now that we changed the element order)
33638            silentScroll($(SECTION_ACTIVE_SEL).position().top);
33639
33640            // Maintain the active slides visible in the viewport
33641            keepSlidesPosition();
33642
33643            // save for later the elements that still need to be reordered
33644            v.wrapAroundElements = v.activeSection;
33645
33646            // Recalculate animation variables
33647            v.dtop = v.element.position().top;
33648            v.yMovement = getYmovement(v.element);
33649
33650            return v;
33651        }
33652
33653        /**
33654        * Fix section order after continuousVertical changes have been animated
33655        */
33656        function continuousVerticalFixSectionOrder (v) {
33657            // If continuousVertical is in effect (and autoScrolling would also be in effect then),
33658            // finish moving the elements around so the direct navigation will function more simply
33659            if (!v.wrapAroundElements || !v.wrapAroundElements.length) {
33660                return;
33661            }
33662
33663            if (v.isMovementUp) {
33664                $(SECTION_FIRST_SEL).before(v.wrapAroundElements);
33665            }
33666            else {
33667                $(SECTION_LAST_SEL).after(v.wrapAroundElements);
33668            }
33669
33670            silentScroll($(SECTION_ACTIVE_SEL).position().top);
33671
33672            // Maintain the active slides visible in the viewport
33673            keepSlidesPosition();
33674        }
33675
33676
33677        /**
33678        * Actions to do once the section is loaded.
33679        */
33680        function afterSectionLoads (v){
33681            continuousVerticalFixSectionOrder(v);
33682
33683            //callback (afterLoad) if the site is not just resizing and readjusting the slides
33684            $.isFunction(options.afterLoad) && !v.localIsResizing && options.afterLoad.call(v.element, v.anchorLink, (v.sectionIndex + 1));
33685            options.scrollOverflowHandler.afterLoad();
33686
33687            if(!v.localIsResizing){
33688                playMedia(v.element);
33689            }
33690
33691            v.element.addClass(COMPLETELY).siblings().removeClass(COMPLETELY);
33692
33693            canScroll = true;
33694
33695            $.isFunction(v.callback) && v.callback.call(this);
33696        }
33697
33698        /**
33699        * Sets the value for the given attribute from the `data-` attribute with the same suffix
33700        * ie: data-srcset ==> srcset  |  data-src ==> src
33701        */
33702        function setSrc(element, attribute){
33703            element
33704                .attr(attribute, element.data(attribute))
33705                .removeAttr('data-' + attribute);
33706        }
33707
33708        /**
33709        * Lazy loads image, video and audio elements.
33710        */
33711        function lazyLoad(destiny){
33712            if (!options.lazyLoading){
33713                return;
33714            }
33715
33716            var panel = getSlideOrSection(destiny);
33717            var element;
33718
33719            panel.find('img[data-src], img[data-srcset], source[data-src], audio[data-src], iframe[data-src]').each(function(){
33720                element = $(this);
33721
33722                $.each(['src', 'srcset'], function(index, type){
33723                    var attribute = element.attr('data-' + type);
33724                    if(typeof attribute !== 'undefined' && attribute){
33725                        setSrc(element, type);
33726                    }
33727                });
33728
33729                if(element.is('source')){
33730                    element.closest('video').get(0).load();
33731                }
33732            });
33733        }
33734
33735        /**
33736        * Plays video and audio elements.
33737        */
33738        function playMedia(destiny){
33739            var panel = getSlideOrSection(destiny);
33740
33741            //playing HTML5 media elements
33742            panel.find('video, audio').each(function(){
33743                var element = $(this).get(0);
33744
33745                if( element.hasAttribute('data-autoplay') && typeof element.play === 'function' ) {
33746                    element.play();
33747                }
33748            });
33749
33750            //youtube videos
33751            panel.find('iframe[src*="youtube.com/embed/"]').each(function(){
33752                var element = $(this).get(0);
33753
33754                if ( element.hasAttribute('data-autoplay') ){
33755                    playYoutube(element);
33756                }
33757
33758                //in case the URL was not loaded yet. On page load we need time for the new URL (with the API string) to load.
33759                element.onload = function() {
33760                    if ( element.hasAttribute('data-autoplay') ){
33761                        playYoutube(element);
33762                    }
33763                };
33764            });
33765        }
33766
33767        /**
33768        * Plays a youtube video
33769        */
33770        function playYoutube(element){
33771            element.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*');
33772        }
33773
33774        /**
33775        * Stops video and audio elements.
33776        */
33777        function stopMedia(destiny){
33778            var panel = getSlideOrSection(destiny);
33779
33780            //stopping HTML5 media elements
33781            panel.find('video, audio').each(function(){
33782                var element = $(this).get(0);
33783
33784                if( !element.hasAttribute('data-keepplaying') && typeof element.pause === 'function' ) {
33785                    element.pause();
33786                }
33787            });
33788
33789            //youtube videos
33790            panel.find('iframe[src*="youtube.com/embed/"]').each(function(){
33791                var element = $(this).get(0);
33792
33793                if( /youtube\.com\/embed\//.test($(this).attr('src')) && !element.hasAttribute('data-keepplaying')){
33794                    $(this).get(0).contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}','*');
33795                }
33796            });
33797        }
33798
33799        /**
33800        * Gets the active slide (or section) for the given section
33801        */
33802        function getSlideOrSection(destiny){
33803            var slide = destiny.find(SLIDE_ACTIVE_SEL);
33804            if( slide.length ) {
33805                destiny = $(slide);
33806            }
33807
33808            return destiny;
33809        }
33810
33811        /**
33812        * Scrolls to the anchor in the URL when loading the site
33813        */
33814        function scrollToAnchor(){
33815            //getting the anchor link in the URL and deleting the `#`
33816            var value =  window.location.hash.replace('#', '').split('/');
33817            var sectionAnchor = decodeURIComponent(value[0]);
33818            var slideAnchor = decodeURIComponent(value[1]);
33819
33820            if(sectionAnchor){  //if theres any #
33821                if(options.animateAnchor){
33822                    scrollPageAndSlide(sectionAnchor, slideAnchor);
33823                }else{
33824                    silentMoveTo(sectionAnchor, slideAnchor);
33825                }
33826            }
33827        }
33828
33829        /**
33830        * Detecting any change on the URL to scroll to the given anchor link
33831        * (a way to detect back history button as we play with the hashes on the URL)
33832        */
33833        function hashChangeHandler(){
33834            if(!isScrolling && !options.lockAnchors){
33835                var value =  window.location.hash.replace('#', '').split('/');
33836                var sectionAnchor = decodeURIComponent(value[0]);
33837                var slideAnchor = decodeURIComponent(value[1]);
33838
33839                    //when moving to a slide in the first section for the first time (first time to add an anchor to the URL)
33840                    var isFirstSlideMove =  (typeof lastScrolledDestiny === 'undefined');
33841                    var isFirstScrollMove = (typeof lastScrolledDestiny === 'undefined' && typeof slideAnchor === 'undefined' && !slideMoving);
33842
33843
33844                if(sectionAnchor.length){
33845                    /*in order to call scrollpage() only once for each destination at a time
33846                    It is called twice for each scroll otherwise, as in case of using anchorlinks `hashChange`
33847                    event is fired on every scroll too.*/
33848                    if ((sectionAnchor && sectionAnchor !== lastScrolledDestiny) && !isFirstSlideMove || isFirstScrollMove || (!slideMoving && lastScrolledSlide != slideAnchor ))  {
33849                        scrollPageAndSlide(sectionAnchor, slideAnchor);
33850                    }
33851                }
33852            }
33853        }
33854
33855        //Sliding with arrow keys, both, vertical and horizontal
33856        function keydownHandler(e) {
33857
33858            clearTimeout(keydownId);
33859
33860            var activeElement = $(':focus');
33861
33862            if(!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select') &&
33863                activeElement.attr('contentEditable') !== "true" && activeElement.attr('contentEditable') !== '' &&
33864                options.keyboardScrolling && options.autoScrolling){
33865                var keyCode = e.which;
33866
33867                //preventing the scroll with arrow keys & spacebar & Page Up & Down keys
33868                var keyControls = [40, 38, 32, 33, 34];
33869                if($.inArray(keyCode, keyControls) > -1){
33870                    e.preventDefault();
33871                }
33872
33873                controlPressed = e.ctrlKey;
33874
33875                keydownId = setTimeout(function(){
33876                    onkeydown(e);
33877                },150);
33878            }
33879        }
33880
33881        function tooltipTextHandler(){
33882            $(this).prev().trigger('click');
33883        }
33884
33885        //to prevent scrolling while zooming
33886        function keyUpHandler(e){
33887            if(isWindowFocused){ //the keyup gets fired on new tab ctrl + t in Firefox
33888                controlPressed = e.ctrlKey;
33889            }
33890        }
33891
33892        //binding the mousemove when the mouse's middle button is released
33893        function mouseDownHandler(e){
33894            //middle button
33895            if (e.which == 2){
33896                oldPageY = e.pageY;
33897                container.on('mousemove', mouseMoveHandler);
33898            }
33899        }
33900
33901        //unbinding the mousemove when the mouse's middle button is released
33902        function mouseUpHandler(e){
33903            //middle button
33904            if (e.which == 2){
33905                container.off('mousemove');
33906            }
33907        }
33908
33909        //Scrolling horizontally when clicking on the slider controls.
33910        function slideArrowHandler(){
33911            var section = $(this).closest(SECTION_SEL);
33912
33913            if ($(this).hasClass(SLIDES_PREV)) {
33914                if(isScrollAllowed.m.left){
33915                    moveSlideLeft(section);
33916                }
33917            } else {
33918                if(isScrollAllowed.m.right){
33919                    moveSlideRight(section);
33920                }
33921            }
33922        }
33923
33924        //when opening a new tab (ctrl + t), `control` won't be pressed when coming back.
33925        function blurHandler(){
33926            isWindowFocused = false;
33927            controlPressed = false;
33928        }
33929
33930        //Scrolls to the section when clicking the navigation bullet
33931        function sectionBulletHandler(e){
33932            e.preventDefault();
33933            var index = $(this).parent().index();
33934            scrollPage($(SECTION_SEL).eq(index));
33935        }
33936
33937        //Scrolls the slider to the given slide destination for the given section
33938        function slideBulletHandler(e){
33939            e.preventDefault();
33940            var slides = $(this).closest(SECTION_SEL).find(SLIDES_WRAPPER_SEL);
33941            var destiny = slides.find(SLIDE_SEL).eq($(this).closest('li').index());
33942
33943            landscapeScroll(slides, destiny);
33944        }
33945
33946        /**
33947        * Keydown event
33948        */
33949        function onkeydown(e){
33950            var shiftPressed = e.shiftKey;
33951
33952            //do nothing if we can not scroll or we are not using horizotnal key arrows.
33953            if(!canScroll && [37,39].indexOf(e.which) < 0){
33954                return;
33955            }
33956
33957            switch (e.which) {
33958                //up
33959                case 38:
33960                case 33:
33961                    if(isScrollAllowed.k.up){
33962                        moveSectionUp();
33963                    }
33964                    break;
33965
33966                //down
33967                case 32: //spacebar
33968                    if(shiftPressed && isScrollAllowed.k.up){
33969                        moveSectionUp();
33970                        break;
33971                    }
33972                /* falls through */
33973                case 40:
33974                case 34:
33975                    if(isScrollAllowed.k.down){
33976                        moveSectionDown();
33977                    }
33978                    break;
33979
33980                //Home
33981                case 36:
33982                    if(isScrollAllowed.k.up){
33983                        moveTo(1);
33984                    }
33985                    break;
33986
33987                //End
33988                case 35:
33989                     if(isScrollAllowed.k.down){
33990                        moveTo( $(SECTION_SEL).length );
33991                    }
33992                    break;
33993
33994                //left
33995                case 37:
33996                    if(isScrollAllowed.k.left){
33997                        moveSlideLeft();
33998                    }
33999                    break;
34000
34001                //right
34002                case 39:
34003                    if(isScrollAllowed.k.right){
34004                        moveSlideRight();
34005                    }
34006                    break;
34007
34008                default:
34009                    return; // exit this handler for other keys
34010            }
34011        }
34012
34013        /**
34014        * Detecting the direction of the mouse movement.
34015        * Used only for the middle button of the mouse.
34016        */
34017        var oldPageY = 0;
34018        function mouseMoveHandler(e){
34019            if(canScroll){
34020                // moving up
34021                if (e.pageY < oldPageY && isScrollAllowed.m.up){
34022                    moveSectionUp();
34023                }
34024
34025                // moving down
34026                else if(e.pageY > oldPageY && isScrollAllowed.m.down){
34027                    moveSectionDown();
34028                }
34029            }
34030            oldPageY = e.pageY;
34031        }
34032
34033        /**
34034        * Scrolls horizontal sliders.
34035        */
34036        function landscapeScroll(slides, destiny, direction){
34037            var section = slides.closest(SECTION_SEL);
34038            var v = {
34039                slides: slides,
34040                destiny: destiny,
34041                direction: direction,
34042                destinyPos: destiny.position(),
34043                slideIndex: destiny.index(),
34044                section: section,
34045                sectionIndex: section.index(SECTION_SEL),
34046                anchorLink: section.data('anchor'),
34047                slidesNav: section.find(SLIDES_NAV_SEL),
34048                slideAnchor:  getAnchor(destiny),
34049                prevSlide: section.find(SLIDE_ACTIVE_SEL),
34050                prevSlideIndex: section.find(SLIDE_ACTIVE_SEL).index(),
34051
34052                //caching the value of isResizing at the momment the function is called
34053                //because it will be checked later inside a setTimeout and the value might change
34054                localIsResizing: isResizing
34055            };
34056            v.xMovement = getXmovement(v.prevSlideIndex, v.slideIndex);
34057            v.direction = v.direction ? v.direction : v.xMovement;
34058
34059            //important!! Only do it when not resizing
34060            if(!v.localIsResizing){
34061                //preventing from scrolling to the next/prev section when using scrollHorizontally
34062                canScroll = false;
34063            }
34064
34065            if(options.onSlideLeave){
34066
34067                //if the site is not just resizing and readjusting the slides
34068                if(!v.localIsResizing && v.xMovement!=='none'){
34069                    if($.isFunction( options.onSlideLeave )){
34070                        if(options.onSlideLeave.call( v.prevSlide, v.anchorLink, (v.sectionIndex + 1), v.prevSlideIndex, v.xMovement, v.slideIndex ) === false){
34071                            slideMoving = false;
34072                            return;
34073                        }
34074                    }
34075                }
34076            }
34077
34078            destiny.addClass(ACTIVE).siblings().removeClass(ACTIVE);
34079
34080            if(!v.localIsResizing){
34081                stopMedia(v.prevSlide);
34082                lazyLoad(destiny);
34083            }
34084
34085            if(!options.loopHorizontal && options.controlArrows){
34086                //hidding it for the fist slide, showing for the rest
34087                section.find(SLIDES_ARROW_PREV_SEL).toggle(v.slideIndex!==0);
34088
34089                //hidding it for the last slide, showing for the rest
34090                section.find(SLIDES_ARROW_NEXT_SEL).toggle(!destiny.is(':last-child'));
34091            }
34092
34093            //only changing the URL if the slides are in the current section (not for resize re-adjusting)
34094            if(section.hasClass(ACTIVE) && !v.localIsResizing){
34095                setState(v.slideIndex, v.slideAnchor, v.anchorLink, v.sectionIndex);
34096            }
34097
34098            performHorizontalMove(slides, v, true);
34099        }
34100
34101
34102        function afterSlideLoads(v){
34103            activeSlidesNavigation(v.slidesNav, v.slideIndex);
34104
34105            //if the site is not just resizing and readjusting the slides
34106            if(!v.localIsResizing){
34107                $.isFunction( options.afterSlideLoad ) && options.afterSlideLoad.call( v.destiny, v.anchorLink, (v.sectionIndex + 1), v.slideAnchor, v.slideIndex);
34108
34109                //needs to be inside the condition to prevent problems with continuousVertical and scrollHorizontally
34110                //and to prevent double scroll right after a windows resize
34111                canScroll = true;
34112
34113                playMedia(v.destiny);
34114            }
34115
34116            //letting them slide again
34117            slideMoving = false;
34118        }
34119
34120        /**
34121        * Performs the horizontal movement. (CSS3 or jQuery)
34122        *
34123        * @param fireCallback {Bool} - determines whether or not to fire the callback
34124        */
34125        function performHorizontalMove(slides, v, fireCallback){
34126            var destinyPos = v.destinyPos;
34127
34128            if(options.css3){
34129                var translate3d = 'translate3d(-' + Math.round(destinyPos.left) + 'px, 0px, 0px)';
34130
34131                addAnimation(slides.find(SLIDES_CONTAINER_SEL)).css(getTransforms(translate3d), v);
34132
34133                afterSlideLoadsId = setTimeout(function(){
34134                    fireCallback && afterSlideLoads(v);
34135                }, options.scrollingSpeed, options.easing);
34136            }else{
34137                slides.animate({
34138                    scrollLeft : Math.round(destinyPos.left)
34139                }, options.scrollingSpeed, options.easing, function() {
34140
34141                    fireCallback && afterSlideLoads(v);
34142                });
34143            }
34144        }
34145
34146        /**
34147        * Sets the state for the horizontal bullet navigations.
34148        */
34149        function activeSlidesNavigation(slidesNav, slideIndex){
34150            slidesNav.find(ACTIVE_SEL).removeClass(ACTIVE);
34151            slidesNav.find('li').eq(slideIndex).find('a').addClass(ACTIVE);
34152        }
34153
34154        var previousHeight = windowsHeight;
34155
34156        //when resizing the site, we adjust the heights of the sections, slimScroll...
34157        function resizeHandler(){
34158            //checking if it needs to get responsive
34159            responsive();
34160
34161            // rebuild immediately on touch devices
34162            if (isTouchDevice) {
34163                var activeElement = $(document.activeElement);
34164
34165                //if the keyboard is NOT visible
34166                if (!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select')) {
34167                    var currentHeight = $window.height();
34168
34169                    //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)
34170                    if( Math.abs(currentHeight - previousHeight) > (20 * Math.max(previousHeight, currentHeight) / 100) ){
34171                        reBuild(true);
34172                        previousHeight = currentHeight;
34173                    }
34174                }
34175            }else{
34176                //in order to call the functions only when the resize is finished
34177                //http://stackoverflow.com/questions/4298612/jquery-how-to-call-resize-event-only-once-its-finished-resizing
34178                clearTimeout(resizeId);
34179
34180                resizeId = setTimeout(function(){
34181                    reBuild(true);
34182                }, 350);
34183            }
34184        }
34185
34186        /**
34187        * Checks if the site needs to get responsive and disables autoScrolling if so.
34188        * A class `fp-responsive` is added to the plugin's container in case the user wants to use it for his own responsive CSS.
34189        */
34190        function responsive(){
34191            var widthLimit = options.responsive || options.responsiveWidth; //backwards compatiblity
34192            var heightLimit = options.responsiveHeight;
34193
34194            //only calculating what we need. Remember its called on the resize event.
34195            var isBreakingPointWidth = widthLimit && $window.outerWidth() < widthLimit;
34196            var isBreakingPointHeight = heightLimit && $window.height() < heightLimit;
34197
34198            if(widthLimit && heightLimit){
34199                setResponsive(isBreakingPointWidth || isBreakingPointHeight);
34200            }
34201            else if(widthLimit){
34202                setResponsive(isBreakingPointWidth);
34203            }
34204            else if(heightLimit){
34205                setResponsive(isBreakingPointHeight);
34206            }
34207        }
34208
34209        /**
34210        * Adds transition animations for the given element
34211        */
34212        function addAnimation(container, element){
34213            var transition = 'all ' + options.scrollingSpeed + 'ms ' + options.easingcss3;
34214
34215            container.removeClass(NO_TRANSITION);
34216            return container.css({
34217                '-webkit-transition': transition,
34218                'transition': transition
34219            });
34220        }
34221
34222        /**
34223        * Remove transition animations for the given element
34224        */
34225        function removeAnimation(element){
34226            return element.addClass(NO_TRANSITION);
34227        }
34228
34229        /**
34230        * Activating the vertical navigation bullets according to the given slide name.
34231        */
34232        function activateNavDots(name, sectionIndex){
34233            if(options.navigation){
34234                $(SECTION_NAV_SEL).find(ACTIVE_SEL).removeClass(ACTIVE);
34235                if(name){
34236                    $(SECTION_NAV_SEL).find('a[href="#' + name + '"]').addClass(ACTIVE);
34237                }else{
34238                    $(SECTION_NAV_SEL).find('li').eq(sectionIndex).find('a').addClass(ACTIVE);
34239                }
34240            }
34241        }
34242
34243        /**
34244        * Activating the website main menu elements according to the given slide name.
34245        */
34246        function activateMenuElement(name){
34247            if(options.menu){
34248                $(options.menu).find(ACTIVE_SEL).removeClass(ACTIVE);
34249                $(options.menu).find('[data-menuanchor="'+name+'"]').addClass(ACTIVE);
34250            }
34251        }
34252
34253        /**
34254        * Sets to active the current menu and vertical nav items.
34255        */
34256        function activateMenuAndNav(anchor, index){
34257            activateMenuElement(anchor);
34258            activateNavDots(anchor, index);
34259        }
34260
34261        /**
34262        * Retuns `up` or `down` depending on the scrolling movement to reach its destination
34263        * from the current section.
34264        */
34265        function getYmovement(destiny){
34266            var fromIndex = $(SECTION_ACTIVE_SEL).index(SECTION_SEL);
34267            var toIndex = destiny.index(SECTION_SEL);
34268            if( fromIndex == toIndex){
34269                return 'none';
34270            }
34271            if(fromIndex > toIndex){
34272                return 'up';
34273            }
34274            return 'down';
34275        }
34276
34277        /**
34278        * Retuns `right` or `left` depending on the scrolling movement to reach its destination
34279        * from the current slide.
34280        */
34281        function getXmovement(fromIndex, toIndex){
34282            if( fromIndex == toIndex){
34283                return 'none';
34284            }
34285            if(fromIndex > toIndex){
34286                return 'left';
34287            }
34288            return 'right';
34289        }
34290
34291        /**
34292        * Checks if the element needs scrollbar and if the user wants to apply it.
34293        * If so it creates it.
34294        *
34295        * @param {Object} element   jQuery object of the section or slide
34296        */
34297        function createScrollBar(element){
34298            //User doesn't want scrollbar here? Sayonara baby!
34299            if(element.hasClass('fp-noscroll')) return;
34300
34301            //needed to make `scrollHeight` work under Opera 12
34302            element.css('overflow', 'hidden');
34303
34304            var scrollOverflowHandler = options.scrollOverflowHandler;
34305            var wrap = scrollOverflowHandler.wrapContent();
34306            //in case element is a slide
34307            var section = element.closest(SECTION_SEL);
34308            var scrollable = scrollOverflowHandler.scrollable(element);
34309            var contentHeight;
34310
34311            //if there was scroll, the contentHeight will be the one in the scrollable section
34312            if(scrollable.length){
34313                contentHeight = scrollOverflowHandler.scrollHeight(element);
34314            }else{
34315                contentHeight = element.get(0).scrollHeight;
34316                if(options.verticalCentered){
34317                    contentHeight = element.find(TABLE_CELL_SEL).get(0).scrollHeight;
34318                }
34319            }
34320
34321            var scrollHeight = windowsHeight - parseInt(section.css('padding-bottom')) - parseInt(section.css('padding-top'));
34322
34323            //needs scroll?
34324            if ( contentHeight > scrollHeight) {
34325                //did we already have an scrollbar ? Updating it
34326                if(scrollable.length){
34327                    scrollOverflowHandler.update(element, scrollHeight);
34328                }
34329                //creating the scrolling
34330                else{
34331                    if(options.verticalCentered){
34332                        element.find(TABLE_CELL_SEL).wrapInner(wrap);
34333                    }else{
34334                        element.wrapInner(wrap);
34335                    }
34336                    scrollOverflowHandler.create(element, scrollHeight);
34337                }
34338            }
34339            //removing the scrolling when it is not necessary anymore
34340            else{
34341                scrollOverflowHandler.remove(element);
34342            }
34343
34344            //undo
34345            element.css('overflow', '');
34346        }
34347
34348        function addTableClass(element){
34349            //In case we are styling for the 2nd time as in with reponsiveSlides
34350            if(!element.hasClass(TABLE)){
34351                element.addClass(TABLE).wrapInner('<div class="' + TABLE_CELL + '" style="height:' + getTableHeight(element) + 'px;" />');
34352            }
34353        }
34354
34355        function getTableHeight(element){
34356            var sectionHeight = windowsHeight;
34357
34358            if(options.paddingTop || options.paddingBottom){
34359                var section = element;
34360                if(!section.hasClass(SECTION)){
34361                    section = element.closest(SECTION_SEL);
34362                }
34363
34364                var paddings = parseInt(section.css('padding-top')) + parseInt(section.css('padding-bottom'));
34365                sectionHeight = (windowsHeight - paddings);
34366            }
34367
34368            return sectionHeight;
34369        }
34370
34371        /**
34372        * Adds a css3 transform property to the container class with or without animation depending on the animated param.
34373        */
34374        function transformContainer(translate3d, animated){
34375            if(animated){
34376                addAnimation(container);
34377            }else{
34378                removeAnimation(container);
34379            }
34380
34381            container.css(getTransforms(translate3d));
34382
34383            //syncronously removing the class after the animation has been applied.
34384            setTimeout(function(){
34385                container.removeClass(NO_TRANSITION);
34386            },10);
34387        }
34388
34389        /**
34390        * Gets a section by its anchor / index
34391        */
34392        function getSectionByAnchor(sectionAnchor){
34393            if(!sectionAnchor) return [];
34394
34395            var section = container.find(SECTION_SEL + '[data-anchor="'+sectionAnchor+'"]');
34396            if(!section.length){
34397                section = $(SECTION_SEL).eq( sectionAnchor -1);
34398            }
34399
34400            return section;
34401        }
34402
34403        /**
34404        * Gets a slide inside a given section by its anchor / index
34405        */
34406        function getSlideByAnchor(slideAnchor, section){
34407            var slides = section.find(SLIDES_WRAPPER_SEL);
34408            var slide =  slides.find(SLIDE_SEL + '[data-anchor="'+slideAnchor+'"]');
34409
34410            if(!slide.length){
34411                slide = slides.find(SLIDE_SEL).eq(slideAnchor);
34412            }
34413
34414            return slide;
34415        }
34416
34417        /**
34418        * Scrolls to the given section and slide anchors
34419        */
34420        function scrollPageAndSlide(destiny, slide){
34421            var section = getSectionByAnchor(destiny);
34422
34423            //do nothing if there's no section with the given anchor name
34424            if(!section.length) return;
34425
34426            //default slide
34427            if (typeof slide === 'undefined') {
34428                slide = 0;
34429            }
34430
34431            //we need to scroll to the section and then to the slide
34432            if (destiny !== lastScrolledDestiny && !section.hasClass(ACTIVE)){
34433                scrollPage(section, function(){
34434                    scrollSlider(section, slide);
34435                });
34436            }
34437            //if we were already in the section
34438            else{
34439                scrollSlider(section, slide);
34440            }
34441        }
34442
34443        /**
34444        * Scrolls the slider to the given slide destination for the given section
34445        */
34446        function scrollSlider(section, slideAnchor){
34447            if(typeof slideAnchor !== 'undefined'){
34448                var slides = section.find(SLIDES_WRAPPER_SEL);
34449                var destiny =  getSlideByAnchor(slideAnchor, section);
34450
34451                if(destiny.length){
34452                    landscapeScroll(slides, destiny);
34453                }
34454            }
34455        }
34456
34457        /**
34458        * Creates a landscape navigation bar with dots for horizontal sliders.
34459        */
34460        function addSlidesNavigation(section, numSlides){
34461            section.append('<div class="' + SLIDES_NAV + '"><ul></ul></div>');
34462            var nav = section.find(SLIDES_NAV_SEL);
34463
34464            //top or bottom
34465            nav.addClass(options.slidesNavPosition);
34466
34467            for(var i=0; i< numSlides; i++){
34468                nav.find('ul').append('<li><a href="#"><span></span></a></li>');
34469            }
34470
34471            //centering it
34472            nav.css('margin-left', '-' + (nav.width()/2) + 'px');
34473
34474            nav.find('li').first().find('a').addClass(ACTIVE);
34475        }
34476
34477
34478        /**
34479        * Sets the state of the website depending on the active section/slide.
34480        * It changes the URL hash when needed and updates the body class.
34481        */
34482        function setState(slideIndex, slideAnchor, anchorLink, sectionIndex){
34483            var sectionHash = '';
34484
34485            if(options.anchors.length && !options.lockAnchors){
34486
34487                //isn't it the first slide?
34488                if(slideIndex){
34489                    if(typeof anchorLink !== 'undefined'){
34490                        sectionHash = anchorLink;
34491                    }
34492
34493                    //slide without anchor link? We take the index instead.
34494                    if(typeof slideAnchor === 'undefined'){
34495                        slideAnchor = slideIndex;
34496                    }
34497
34498                    lastScrolledSlide = slideAnchor;
34499                    setUrlHash(sectionHash + '/' + slideAnchor);
34500
34501                //first slide won't have slide anchor, just the section one
34502                }else if(typeof slideIndex !== 'undefined'){
34503                    lastScrolledSlide = slideAnchor;
34504                    setUrlHash(anchorLink);
34505                }
34506
34507                //section without slides
34508                else{
34509                    setUrlHash(anchorLink);
34510                }
34511            }
34512
34513            setBodyClass();
34514        }
34515
34516        /**
34517        * Sets the URL hash.
34518        */
34519        function setUrlHash(url){
34520            //Uncode addition
34521            if ( typeof SiteParameters.slide_footer != 'undefined' && url == SiteParameters.slide_footer )
34522                return false;
34523
34524            if(options.recordHistory){
34525                location.hash = url;
34526            }else{
34527                //Uncode addition
34528                //Mobile Chrome doesn't work the normal way, so... lets use HTML5 for phones :)
34529                // if(isTouchDevice || isTouch){
34530                //     window.history.replaceState(undefined, undefined, '#' + url);
34531                // }else{
34532                //     var baseUrl = window.location.href.split('#')[0];
34533                //     window.location.replace( baseUrl + '#' + url );
34534                // }
34535                return false;
34536            }
34537        }
34538
34539        /**
34540        * Gets the anchor for the given slide / section. Its index will be used if there's none.
34541        */
34542        function getAnchor(element){
34543            var anchor = element.data('anchor');
34544            var index = element.index();
34545
34546            //Slide without anchor link? We take the index instead.
34547            if(typeof anchor === 'undefined'){
34548                anchor = index;
34549            }
34550
34551            return anchor;
34552        }
34553
34554        /**
34555        * Sets a class for the body of the page depending on the active section / slide
34556        */
34557        function setBodyClass(){
34558            var section = $(SECTION_ACTIVE_SEL);
34559            var slide = section.find(SLIDE_ACTIVE_SEL);
34560
34561            var sectionAnchor = getAnchor(section);
34562            var slideAnchor = getAnchor(slide);
34563
34564            var text = String(sectionAnchor);
34565
34566            if(slide.length){
34567                text = text + '-' + slideAnchor;
34568            }
34569
34570            //changing slash for dash to make it a valid CSS style
34571            text = text.replace('/', '-').replace('#','');
34572
34573            //removing previous anchor classes
34574            var classRe = new RegExp('\\b\\s?' + VIEWING_PREFIX + '-[^\\s]+\\b', "g");
34575            $body[0].className = $body[0].className.replace(classRe, '');
34576
34577            //adding the current anchor
34578            $body.addClass(VIEWING_PREFIX + '-' + text);
34579        }
34580
34581        /**
34582        * Checks for translate3d support
34583        * @return boolean
34584        * http://stackoverflow.com/questions/5661671/detecting-transform-translate3d-support
34585        */
34586        function support3d() {
34587            var el = document.createElement('p'),
34588                has3d,
34589                transforms = {
34590                    'webkitTransform':'-webkit-transform',
34591                    'OTransform':'-o-transform',
34592                    'msTransform':'-ms-transform',
34593                    'MozTransform':'-moz-transform',
34594                    'transform':'transform'
34595                };
34596
34597            // Add it to the body to get the computed style.
34598            document.body.insertBefore(el, null);
34599
34600            for (var t in transforms) {
34601                if (el.style[t] !== undefined) {
34602                    el.style[t] = 'translate3d(1px,1px,1px)';
34603                    has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]);
34604                }
34605            }
34606
34607            document.body.removeChild(el);
34608
34609            return (has3d !== undefined && has3d.length > 0 && has3d !== 'none');
34610        }
34611
34612        /**
34613        * Removes the auto scrolling action fired by the mouse wheel and trackpad.
34614        * After this function is called, the mousewheel and trackpad movements won't scroll through sections.
34615        */
34616        function removeMouseWheelHandler(){
34617            if (document.addEventListener) {
34618                document.removeEventListener('mousewheel', MouseWheelHandler, false); //IE9, Chrome, Safari, Oper
34619                document.removeEventListener('wheel', MouseWheelHandler, false); //Firefox
34620                document.removeEventListener('MozMousePixelScroll', MouseWheelHandler, false); //old Firefox
34621            } else {
34622                document.detachEvent('onmousewheel', MouseWheelHandler); //IE 6/7/8
34623            }
34624        }
34625
34626        /**
34627        * Adds the auto scrolling action for the mouse wheel and trackpad.
34628        * After this function is called, the mousewheel and trackpad movements will scroll through sections
34629        * https://developer.mozilla.org/en-US/docs/Web/Events/wheel
34630        */
34631        function addMouseWheelHandler(){
34632            var prefix = '';
34633            var _addEventListener;
34634
34635            if (window.addEventListener){
34636                _addEventListener = "addEventListener";
34637            }else{
34638                _addEventListener = "attachEvent";
34639                prefix = 'on';
34640            }
34641
34642             // detect available wheel event
34643            var support = 'onwheel' in document.createElement('div') ? 'wheel' : // Modern browsers support "wheel"
34644                      document.onmousewheel !== undefined ? 'mousewheel' : // Webkit and IE support at least "mousewheel"
34645                      'DOMMouseScroll'; // let's assume that remaining browsers are older Firefox
34646            var passiveEvent = g_supportsPassive ? {passive: false }
34646: false;
34647
34648
34649            if(support == 'DOMMouseScroll'){
34650                document[ _addEventListener ](prefix + 'MozMousePixelScroll', MouseWheelHandler, passiveEvent);
34651            }
34652
34653            //handle MozMousePixelScroll in older Firefox
34654            else{
34655                document[ _addEventListener ](prefix + support, MouseWheelHandler, passiveEvent);
34656            }
34657        }
34658
34659        /**
34660        * Binding the mousemove when the mouse's middle button is pressed
34661        */
34662        function addMiddleWheelHandler(){
34663            container
34664                .on('mousedown', mouseDownHandler)
34665                .on('mouseup', mouseUpHandler);
34666        }
34667
34668        /**
34669        * Unbinding the mousemove when the mouse's middle button is released
34670        */
34671        function removeMiddleWheelHandler(){
34672            container
34673                .off('mousedown', mouseDownHandler)
34674                .off('mouseup', mouseUpHandler);
34675        }
34676
34677        /**
34678        * Adds the possibility to auto scroll through sections on touch devices.
34679        */
34680        function addTouchHandler(){
34681            if(isTouchDevice || isTouch){
34682                if(options.autoScrolling){
34683                    $body.off(events.touchmove).on(events.touchmove, preventBouncing);
34684                }
34685
34686                $(WRAPPER_SEL)
34687                    .off(events.touchstart).on(events.touchstart, touchStartHandler)
34688                    .off(events.touchmove).on(events.touchmove, touchMoveHandler);
34689            }
34690        }
34691
34692        /**
34693        * Removes the auto scrolling for touch devices.
34694        */
34695        function removeTouchHandler(){
34696            if(isTouchDevice || isTouch){
34697                $(WRAPPER_SEL)
34698                    .off(events.touchstart)
34699                    .off(events.touchmove);
34700            }
34701        }
34702
34703        /*
34704        * Returns and object with Microsoft pointers (for IE<11 and for IE >= 11)
34705        * http://msdn.microsoft.com/en-us/library/ie/dn304886(v=vs.85).aspx
34706        */
34707        function getMSPointer(){
34708            var pointer;
34709
34710            //IE >= 11 & rest of browsers
34711            if(window.PointerEvent){
34712                pointer = { down: 'pointerdown', move: 'pointermove'};
34713            }
34714
34715            //IE < 11
34716            else{
34717                pointer = { down: 'MSPointerDown', move: 'MSPointerMove'};
34718            }
34719
34720            return pointer;
34721        }
34722
34723        /**
34724        * Gets the pageX and pageY properties depending on the browser.
34725        * https://github.com/alvarotrigo/fullPage.js/issues/194#issuecomment-34069854
34726        */
34727        function getEventsPage(e){
34728            var events = [];
34729
34730            events.y = (typeof e.pageY !== 'undefined' && (e.pageY || e.pageX) ? e.pageY : e.touches[0].pageY);
34731            events.x = (typeof e.pageX !== 'undefined' && (e.pageY || e.pageX) ? e.pageX : e.touches[0].pageX);
34732
34733            //in touch devices with scrollBar:true, e.pageY is detected, but we have to deal with touch events. #1008
34734            if(isTouch && isReallyTouch(e) && options.scrollBar){
34735                events.y = e.touches[0].pageY;
34736                events.x = e.touches[0].pageX;
34737            }
34738
34739            return events;
34740        }
34741
34742        /**
34743        * Slides silently (with no animation) the active slider to the given slide.
34744        * @param noCallback {bool} true or defined -> no callbacks
34745        */
34746        function silentLandscapeScroll(activeSlide, noCallbacks){
34747            setScrollingSpeed (0, 'internal');
34748
34749            if(typeof noCallbacks !== 'undefined'){
34750                //preventing firing callbacks afterSlideLoad etc.
34751                isResizing = true;
34752            }
34753
34754            landscapeScroll(activeSlide.closest(SLIDES_WRAPPER_SEL), activeSlide);
34755
34756            if(typeof noCallbacks !== 'undefined'){
34757                isResizing = false;
34758            }
34759
34760            setScrollingSpeed(originals.scrollingSpeed, 'internal');
34761        }
34762
34763        /**
34764        * Scrolls silently (with no animation) the page to the given Y position.
34765        */
34766        function silentScroll(top){
34767            // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625
34768            // that's why we round it to 0.
34769            var roundedTop = Math.round(top);
34770
34771            if (options.css3 && options.autoScrolling && !options.scrollBar){
34772                var translate3d = 'translate3d(0px, -' + roundedTop + 'px, 0px)';
34773                transformContainer(translate3d, false);
34774            }
34775            else if(options.autoScrolling && !options.scrollBar){
34776                container.css('top', -roundedTop);
34777            }
34778            else{
34779                $htmlBody.scrollTop(roundedTop);
34780            }
34781        }
34782
34783        /**
34784        * Returns the cross-browser transform string.
34785        */
34786        function getTransforms(translate3d){
34787            return {
34788                '-webkit-transform': translate3d,
34789                '-moz-transform': translate3d,
34790                '-ms-transform':translate3d,
34791                'transform': translate3d
34792            };
34793        }
34794
34795        /**
34796        * Allowing or disallowing the mouse/swipe scroll in a given direction. (not for keyboard)
34797        * @type  m (mouse) or k (keyboard)
34798        */
34799        function setIsScrollAllowed(value, direction, type){
34800            switch (direction){
34801                case 'up': isScrollAllowed[type].up = value; break;
34802                case 'down': isScrollAllowed[type].down = value; break;
34803                case 'left': isScrollAllowed[type].left = value; break;
34804                case 'right': isScrollAllowed[type].right = value; break;
34805                case 'all':
34806                    if(type == 'm'){
34807                        setAllowScrolling(value);
34808                    }else{
34809                        setKeyboardScrolling(value);
34810                    }
34811            }
34812        }
34813
34814        /*
34815        * Destroys fullpage.js plugin events and optinally its html markup and styles
34816        */
34817        function destroy(all){
34818            setAutoScrolling(false, 'internal');
34819            setAllowScrolling(false);
34820            setKeyboardScrolling(false);
34821            container.addClass(DESTROYED);
34822
34823            clearTimeout(afterSlideLoadsId);
34824            clearTimeout(afterSectionLoadsId);
34825            clearTimeout(resizeId);
34826            clearTimeout(scrollId);
34827            clearTimeout(scrollId2);
34828
34829            $window
34830                .off('scroll', scrollHandler)
34831                .off('hashchange', hashChangeHandler)
34832                .off('resize', resizeHandler);
34833
34834            $document
34835                .off('click touchstart', SECTION_NAV_SEL + ' a')
34836                .off('mouseenter', SECTION_NAV_SEL + ' li')
34837                .off('mouseleave', SECTION_NAV_SEL + ' li')
34838                .off('click touchstart', SLIDES_NAV_LINK_SEL)
34839                .off('mouseover', options.normalScrollElements)
34840                .off('mouseout', options.normalScrollElements);
34841
34842            $(SECTION_SEL)
34843                .off('click touchstart', SLIDES_ARROW_SEL);
34844
34845            clearTimeout(afterSlideLoadsId);
34846            clearTimeout(afterSectionLoadsId);
34847
34848            //lets make a mess!
34849            if(all){
34850                destroyStructure();
34851            }
34852        }
34853
34854        /*
34855        * Removes inline styles added by fullpage.js
34856        */
34857        function destroyStructure(){
34858            //reseting the `top` or `translate` properties to 0
34859            silentScroll(0);
34860
34861            //loading all the lazy load content
34862            container.find('img[data-src], source[data-src], audio[data-src], iframe[data-src]').each(function(){
34863                setSrc($(this), 'src');
34864            });
34865
34866            container.find('img[data-srcset]').each(function(){
34867                setSrc($(this), 'srcset');
34868            });
34869
34870            $(SECTION_NAV_SEL + ', ' + SLIDES_NAV_SEL +  ', ' + SLIDES_ARROW_SEL).remove();
34871
34872            //removing inline styles
34873            $(SECTION_SEL).css( {
34874                'height': '',
34875                'background-color' : '',
34876                'padding': ''
34877            });
34878
34879            $(SLIDE_SEL).css( {
34880                'width': ''
34881            });
34882
34883            container.css({
34884                'height': '',
34885                'position': '',
34886                '-ms-touch-action': '',
34887                'touch-action': ''
34888            });
34889
34890            $htmlBody.css({
34891                'overflow': '',
34892                'height': ''
34893            });
34894
34895            // remove .fp-enabled class
34896            $('html').removeClass(ENABLED);
34897
34898            // remove .fp-responsive class
34899            $body.removeClass(RESPONSIVE);
34900
34901            // remove all of the .fp-viewing- classes
34902            $.each($body.get(0).className.split(/\s+/), function (index, className) {
34903                if (className.indexOf(VIEWING_PREFIX) === 0) {
34904                    $body.removeClass(className);
34905                }
34906            });
34907
34908            //removing added classes
34909            $(SECTION_SEL + ', ' + SLIDE_SEL).each(function(){
34910                options.scrollOverflowHandler.remove($(this));
34911                $(this).removeClass(TABLE + ' ' + ACTIVE);
34912            });
34913
34914            removeAnimation(container);
34915
34916            //Unwrapping content
34917            container.find(TABLE_CELL_SEL + ', ' + SLIDES_CONTAINER_SEL + ', ' + SLIDES_WRAPPER_SEL).each(function(){
34918                //unwrap not being use in case there's no child element inside and its just text
34919                $(this).replaceWith(this.childNodes);
34920            });
34921
34922            //removing the applied transition from the fullpage wrapper
34923            container.css({
34924                '-webkit-transition': 'none',
34925                'transition': 'none'
34926            });
34927
34928            //scrolling the page to the top with no animation
34929            $htmlBody.scrollTop(0);
34930
34931            //removing selectors
34932            var usedSelectors = [SECTION, SLIDE, SLIDES_CONTAINER];
34933            $.each(usedSelectors, function(index, value){
34934                $('.' + value).removeClass(value);
34935            });
34936        }
34937
34938        /*
34939        * Sets the state for a variable with multiple states (original, and temporal)
34940        * Some variables such as `autoScrolling` or `recordHistory` might change automatically its state when using `responsive` or `autoScrolling:false`.
34941        * This function is used to keep track of both states, the original and the temporal one.
34942        * If type is not 'internal', then we assume the user is globally changing the variable.
34943        */
34944        function setVariableState(variable, value, type){
34945            options[variable] = value;
34946            if(type !== 'internal'){
34947                originals[variable] = value;
34948            }
34949        }
34950
34951        /**
34952        * Displays warnings
34953        */
34954        function displayWarnings(){
34955            var extensions = ['fadingEffect', 'continuousHorizontal', 'scrollHorizontally', 'interlockedSlides', 'resetSliders', 'responsiveSlides', 'offsetSections', 'dragAndMove', 'scrollOverflowReset', 'parallax'];
34956            //UNCODE.addition
34957            // if($('html').hasClass(ENABLED)){
34958            //     showError('error', 'Fullpage.js can only be initialized once and you are doing it multiple times!');
34959            //     return;
34960            // }
34961
34962            // Disable mutually exclusive settings
34963            //UNCODE.addition
34964            // if (options.continuousVertical &&
34965            //     (options.loopTop || options.loopBottom)) {
34966            //     options.continuousVertical = false;
34967            //     showError('warn', 'Option `loopTop/loopBottom` is mutually exclusive with `continuousVertical`; `continuousVertical` disabled');
34968            // }
34969
34970            // if(options.scrollBar && options.scrollOverflow){
34971            //     showError('warn', 'Option `scrollBar` is mutually exclusive with `scrollOverflow`. Sections with scrollOverflow might not work well in Firefox');
34972            // }
34973
34974            // if(options.continuousVertical && (options.scrollBar || !options.autoScrolling)){
34975            //     options.continuousVertical = false;
34976            //     showError('warn', 'Scroll bars (`scrollBar:true` or `autoScrolling:false`) are mutually exclusive with `continuousVertical`; `continuousVertical` disabled');
34977            // }
34978
34979            //using extensions? Wrong file!
34980            $.each(extensions, function(index, extension){
34981                //is the option set to true?
34982                if(options[extension]){
34983                    showError('warn', 'fullpage.js extensions require jquery.fullpage.extensions.min.js file instead of the usual jquery.fullpage.js. Requested: '+ extension);
34984                }
34985            });
34986
34987            //anchors can not have the same value as any element ID or NAME
34988            $.each(options.anchors, function(index, name){
34989
34990                //case insensitive selectors (http://stackoverflow.com/a/19465187/1081396)
34991                var nameAttr = $document.find('[name]').filter(function() {
34992                    return $(this).attr('name') && $(this).attr('name').toLowerCase() == name.toLowerCase();
34993                });
34994
34995                var idAttr = $document.find('[id]').filter(function() {
34996                    return $(this).attr('id') && $(this).attr('id').toLowerCase() == name.toLowerCase();
34997                });
34998
34999                if(idAttr.length || nameAttr.length ){
35000                    showError('error', 'data-anchor tags can not have the same value as any `id` element on the site (or `name` element for IE).');
35001                    idAttr.length && showError('error', '"' + name + '" is is being used by another element `id` property');
35002                    nameAttr.length && showError('error', '"' + name + '" is is being used by another element `name` property');
35003                }
35004            });
35005        }
35006
35007        /**
35008        * Shows a message in the console of the given type.
35009        */
35010        function showError(type, text){
35011            console && console[type] && console[type]('fullPage: ' + text);
35012        }
35013
35014    }; //end of $.fn.fullpage
35015
35016    if(typeof IScroll !== 'undefined'){
35017        /*
35018        * Turns iScroll `mousewheel` option off dynamically
35019        * https://github.com/cubiq/iscroll/issues/1036
35020        */
35021        IScroll.prototype.wheelOn = function () {
35022            this.wrapper.addEventListener('wheel', this);
35023            this.wrapper.addEventListener('mousewheel', this);
35024            this.wrapper.addEventListener('DOMMouseScroll', this);
35025        };
35026
35027        /*
35028        * Turns iScroll `mousewheel` option on dynamically
35029        * https://github.com/cubiq/iscroll/issues/1036
35030        */
35031        IScroll.prototype.wheelOff = function () {
35032            this.wrapper.removeEventListener('wheel', this);
35033            this.wrapper.removeEventListener('mousewheel', this);
35034            this.wrapper.removeEventListener('DOMMouseScroll', this);
35035        };
35036    }
35037
35038    /**
35039     * An object to handle overflow scrolling.
35040     * This uses jquery.slimScroll to accomplish overflow scrolling.
35041     * It is possible to pass in an alternate scrollOverflowHandler
35042     * to the fullpage.js option that implements the same functions
35043     * as this handler.
35044     *
35045     * @type {Object}
35046     */
35047    var iscrollHandler = {
35048        refreshId: null,
35049        iScrollInstances: [],
35050
35051        // Enables or disables the mouse wheel for the active section or all slides in it
35052        toggleWheel: function(value){
35053            var scrollable = $(SECTION_ACTIVE_SEL).find(SCROLLABLE_SEL);
35054            scrollable.each(function(){
35055                var iScrollInstance = $(this).data('iscrollInstance');
35056                if(typeof iScrollInstance !== 'undefined' && iScrollInstance){
35057                    if(value){
35058                        iScrollInstance.wheelOn();
35059                    }
35060                    else{
35061                        iScrollInstance.wheelOff();
35062                    }
35063                }
35064            });
35065        },
35066
35067        /**
35068        * Turns off iScroll for the destination section.
35069        * When scrolling very fast on some trackpads (and Apple laptops) the inertial scrolling would
35070        * scroll the destination section/slide before the sections animations ends.
35071        */
35072        onLeave: function(){
35073            iscrollHandler.toggleWheel(false);
35074        },
35075
35076        // Turns off iScroll for the leaving section
35077        beforeLeave: function(){
35078            iscrollHandler.onLeave()
35079        },
35080
35081        // Turns on iScroll on section load
35082        afterLoad: function(){
35083            iscrollHandler.toggleWheel(true);
35084        },
35085
35086        /**
35087         * Called when overflow scrolling is needed for a section.
35088         *
35089         * @param  {Object} element      jQuery object containing current section
35090         * @param  {Number} scrollHeight Current window height in pixels
35091         */
35092        create: function(element, scrollHeight) {
35093            var scrollable = element.find(SCROLLABLE_SEL);
35094
35095            scrollable.height(scrollHeight);
35096            scrollable.each(function() {
35097                var $this = $(this);
35098                var iScrollInstance = $this.data('iscrollInstance');
35099                if (iScrollInstance) {
35100                    $.each(iscrollHandler.iScrollInstances, function(){
35101                        $(this).destroy();
35102                    });
35103                }
35104
35105                iScrollInstance = new IScroll($this.get(0), iscrollOptions);
35106                iscrollHandler.iScrollInstances.push(iScrollInstance);
35107
35108                //off by default until the section gets active
35109                iScrollInstance.wheelOff();
35110
35111                $this.data('iscrollInstance', iScrollInstance);
35112            });
35113        },
35114
35115        /**
35116         * Return a boolean depending on whether the scrollable element is a
35117         * the end or at the start of the scrolling depending on the given type.
35118         *
35119         * @param  {String}  type       Either 'top' or 'bottom'
35120         * @param  {Object}  scrollable jQuery object for the scrollable element
35121         * @return {Boolean}
35122         */
35123        isScrolled: function(type, scrollable) {
35124            var scroller = scrollable.data('iscrollInstance');
35125
35126            //no scroller?
35127            if (!scroller) {
35128                return true;
35129            }
35130
35131            //Uncode addition
35132            var uncode_body_borders = parseFloat($('.body-borders').attr('data-border')) || 0;
35133            //End Uncode addition
35134
35135            if (type === 'top') {
35136                return scroller.y >= 0 && !scrollable.scrollTop();
35137            } else if (type === 'bottom') {
35138                //Uncode change
35139                // return (0 - scroller.y) + scrollable.scrollTop() + 1 + scrollable.innerHeight() >= scrollable[0].scrollHeight;
35140                return (0 - scroller.y) + scrollable.scrollTop() + 1 + ( uncode_body_borders * 2 ) + scrollable.innerHeight() >= scrollable[0].scrollHeight;
35141                //End Uncode change
35142            }
35143        },
35144
35145        /**
35146         * Returns the scrollable element for the given section.
35147         * If there are landscape slides, will only return a scrollable element
35148         * if it is in the active slide.
35149         *
35150         * @param  {Object}  activeSection jQuery object containing current section
35151         * @return {Boolean}
35152         */
35153        scrollable: function(activeSection){
35154            // if there are landscape slides, we check if the scrolling bar is in the current one or not
35155            if (activeSection.find(SLIDES_WRAPPER_SEL).length) {
35156                return activeSection.find(SLIDE_ACTIVE_SEL).find(SCROLLABLE_SEL);
35157            }
35158            return activeSection.find(SCROLLABLE_SEL);
35159        },
35160
35161        /**
35162         * Returns the scroll height of the wrapped content.
35163         * If this is larger than the window height minus section padding,
35164         * overflow scrolling is needed.
35165         *
35166         * @param  {Object} element jQuery object containing current section
35167         * @return {Number}
35168         */
35169        scrollHeight: function(element) {
35170            return element.find(SCROLLABLE_SEL).children().first().get(0).scrollHeight;
35171        },
35172
35173        /**
35174         * Called when overflow scrolling is no longer needed for a section.
35175         *
35176         * @param  {Object}
vendor: 5,435 bytes, lines 35176-35327
35176 element      jQuery object containing current section
35177         */
35178        remove: function(element) {
35179            var scrollable = element.find(SCROLLABLE_SEL);
35180            if (scrollable.length) {
35181                var iScrollInstance = scrollable.data('iscrollInstance');
35182                iScrollInstance.destroy();
35183
35184                scrollable.data('iscrollInstance', null);
35185            }
35186            element.find(SCROLLABLE_SEL).children().first().children().first().unwrap().unwrap();
35187        },
35188
35189        /**
35190         * Called when overflow scrolling has already been setup but the
35191         * window height has potentially changed.
35192         *
35193         * @param  {Object} element      jQuery object containing current section
35194         * @param  {Number} scrollHeight Current window height in pixels
35195         */
35196        update: function(element, scrollHeight) {
35197            //using a timeout in order to execute the refresh function only once when `update` is called multiple times in a
35198            //short period of time.
35199            //it also comes on handy because iScroll requires the use of timeout when using `refresh`.
35200            clearTimeout(iscrollHandler.refreshId);
35201            iscrollHandler.refreshId = setTimeout(function(){
35202                $.each(iscrollHandler.iScrollInstances, function(){
35203                    $(this).get(0).refresh();
35204                });
35205            }, 150);
35206
35207            //updating the wrappers height
35208            element.find(SCROLLABLE_SEL).css('height', scrollHeight + 'px').parent().css('height', scrollHeight + 'px');
35209        },
35210
35211        /**
35212         * Called to get any additional elements needed to wrap the section
35213         * content in order to facilitate overflow scrolling.
35214         *
35215         * @return {String|Object} Can be a string containing HTML,
35216         *                         a DOM element, or jQuery object.
35217         */
35218        wrapContent: function() {
35219            return '<div class="' + SCROLLABLE + '"><div class="fp-scroller"></div></div>';
35220        }
35221    };
35222});
35223
35224(function (global, factory) {
35225	typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
35226	typeof define === 'function' && define.amd ? define(['exports'], factory) :
35227	(global = global || self, factory(global.window = global.window || {}));
35228  }(this, (function (exports) { 'use strict';
35229  
35230	function _defineProperties(target, props) {
35231	  for (var i = 0; i < props.length; i++) {
35232		var descriptor = props[i];
35233		descriptor.enumerable = descriptor.enumerable || false;
35234		descriptor.configurable = true;
35235		if ("value" in descriptor) descriptor.writable = true;
35236		Object.defineProperty(target, descriptor.key, descriptor);
35237	  }
35238	}
35239  
35240	function _createClass(Constructor, protoProps, staticProps) {
35241	  if (protoProps) _defineProperties(Constructor.prototype, protoProps);
35242	  if (staticProps) _defineProperties(Constructor, staticProps);
35243	  return Constructor;
35244	}
35245  
35246	/*!
35247	 * Observer 3.12.5
35248	 * https://gsap.com
35249	 *
35250	 * @license Copyright 2008-2024, GreenSock. All rights reserved.
35251	 * Subject to the terms at https://gsap.com/standard-license or for
35252	 * Club GSAP members, the agreement issued with that membership.
35253	 * @author: Jack Doyle, [email protected]
35254	*/
35255	var gsap,
35256		_coreInitted,
35257		_clamp,
35258		_win,
35259		_doc,
35260		_docEl,
35261		_body,
35262		_isTouch,
35263		_pointerType,
35264		ScrollTrigger,
35265		_root,
35266		_normalizer,
35267		_eventTypes,
35268		_context,
35269		_getGSAP = function _getGSAP() {
35270	  return gsap || typeof window !== "undefined" && (gsap = window.gsap) && gsap.registerPlugin && gsap;
35271	},
35272		_startup = 1,
35273		_observers = [],
35274		_scrollers = [],
35275		_proxies = [],
35276		_getTime = Date.now,
35277		_bridge = function _bridge(name, value) {
35278	  return value;
35279	},
35280		_integrate = function _integrate() {
35281	  var core = ScrollTrigger.core,
35282		  data = core.bridge || {},
35283		  scrollers = core._scrollers,
35284		  proxies = core._proxies;
35285	  scrollers.push.apply(scrollers, _scrollers);
35286	  proxies.push.apply(proxies, _proxies);
35287	  _scrollers = scrollers;
35288	  _proxies = proxies;
35289  
35290	  _bridge = function _bridge(name, value) {
35291		return data[name](value);
35292	  };
35293	},
35294		_getProxyProp = function _getProxyProp(element, property) {
35295	  return ~_proxies.indexOf(element) && _proxies[_proxies.indexOf(element) + 1][property];
35296	},
35297		_isViewport = function _isViewport(el) {
35298	  return !!~_root.indexOf(el);
35299	},
35300		_addListener = function _addListener(element, type, func, passive, capture) {
35301	  return element.addEventListener(type, func, {
35302		passive: passive !== false,
35303		capture: !!capture
35304	  });
35305	},
35306		_removeListener = function _removeListener(element, type, func, capture) {
35307	  return element.removeEventListener(type, func, !!capture);
35308	},
35309		_scrollLeft = "scrollLeft",
35310		_scrollTop = "scrollTop",
35311		_onScroll = function _onScroll() {
35312	  return _normalizer && _normalizer.isPressed || _scrollers.cache++;
35313	},
35314		_scrollCacheFunc = function _scrollCacheFunc(f, doNotCache) {
35315	  var cachingFunc = function cachingFunc(value) {
35316		if (value || value === 0) {
35317		  _startup && (_win.history.scrollRestoration = "manual");
35318		  var isNormalizing = _normalizer && _normalizer.isPressed;
35319		  value = cachingFunc.v = Math.round(value) || (_normalizer && _normalizer.iOS ? 1 : 0);
35320		  f(value);
35321		  cachingFunc.cacheID = _scrollers.cache;
35322		  isNormalizing && _bridge("ss", value);
35323		} else if (doNotCache || _scrollers.cache !== cachingFunc.cacheID || _bridge("ref")) {
35324		  cachingFunc.cacheID = _scrollers.cache;
35325		  cachingFunc.v = f();
35326		}
35327  
vendor: 13,754 bytes, lines 35328-35781
35328		return cachingFunc.v + cachingFunc.offset;
35329	  };
35330  
35331	  cachingFunc.offset = 0;
35332	  return f && cachingFunc;
35333	},
35334		_horizontal = {
35335	  s: _scrollLeft,
35336	  p: "left",
35337	  p2: "Left",
35338	  os: "right",
35339	  os2: "Right",
35340	  d: "width",
35341	  d2: "Width",
35342	  a: "x",
35343	  sc: _scrollCacheFunc(function (value) {
35344		return arguments.length ? _win.scrollTo(value, _vertical.sc()) : _win.pageXOffset || _doc[_scrollLeft] || _docEl[_scrollLeft] || _body[_scrollLeft] || 0;
35345	  })
35346	},
35347		_vertical = {
35348	  s: _scrollTop,
35349	  p: "top",
35350	  p2: "Top",
35351	  os: "bottom",
35352	  os2: "Bottom",
35353	  d: "height",
35354	  d2: "Height",
35355	  a: "y",
35356	  op: _horizontal,
35357	  sc: _scrollCacheFunc(function (value) {
35358		return arguments.length ? _win.scrollTo(_horizontal.sc(), value) : _win.pageYOffset || _doc[_scrollTop] || _docEl[_scrollTop] || _body[_scrollTop] || 0;
35359	  })
35360	},
35361		_getTarget = function _getTarget(t, self) {
35362	  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);
35363	},
35364		_getScrollFunc = function _getScrollFunc(element, _ref) {
35365	  var s = _ref.s,
35366		  sc = _ref.sc;
35367	  _isViewport(element) && (element = _doc.scrollingElement || _docEl);
35368  
35369	  var i = _scrollers.indexOf(element),
35370		  offset = sc === _vertical.sc ? 1 : 2;
35371  
35372	  !~i && (i = _scrollers.push(element) - 1);
35373	  _scrollers[i + offset] || _addListener(element, "scroll", _onScroll);
35374	  var prev = _scrollers[i + offset],
35375		  func = prev || (_scrollers[i + offset] = _scrollCacheFunc(_getProxyProp(element, s), true) || (_isViewport(element) ? sc : _scrollCacheFunc(function (value) {
35376		return arguments.length ? element[s] = value : element[s];
35377	  })));
35378	  func.target = element;
35379	  prev || (func.smooth = gsap.getProperty(element, "scrollBehavior") === "smooth");
35380	  return func;
35381	},
35382		_getVelocityProp = function _getVelocityProp(value, minTimeRefresh, useDelta) {
35383	  var v1 = value,
35384		  v2 = value,
35385		  t1 = _getTime(),
35386		  t2 = t1,
35387		  min = minTimeRefresh || 50,
35388		  dropToZeroTime = Math.max(500, min * 3),
35389		  update = function update(value, force) {
35390		var t = _getTime();
35391  
35392		if (force || t - t1 > min) {
35393		  v2 = v1;
35394		  v1 = value;
35395		  t2 = t1;
35396		  t1 = t;
35397		} else if (useDelta) {
35398		  v1 += value;
35399		} else {
35400		  v1 = v2 + (value - v2) / (t - t2) * (t1 - t2);
35401		}
35402	  },
35403		  reset = function reset() {
35404		v2 = v1 = useDelta ? 0 : v1;
35405		t2 = t1 = 0;
35406	  },
35407		  getVelocity = function getVelocity(latestValue) {
35408		var tOld = t2,
35409			vOld = v2,
35410			t = _getTime();
35411  
35412		(latestValue || latestValue === 0) && latestValue !== v1 && update(latestValue);
35413		return t1 === t2 || t - t2 > dropToZeroTime ? 0 : (v1 + (useDelta ? vOld : -vOld)) / ((useDelta ? t : t1) - tOld) * 1000;
35414	  };
35415  
35416	  return {
35417		update: update,
35418		reset: reset,
35419		getVelocity: getVelocity
35420	  };
35421	},
35422		_getEvent = function _getEvent(e, preventDefault) {
35423	  preventDefault && !e._gsapAllow && e.preventDefault();
35424	  return e.changedTouches ? e.changedTouches[0] : e;
35425	},
35426		_getAbsoluteMax = function _getAbsoluteMax(a) {
35427	  var max = Math.max.apply(Math, a),
35428		  min = Math.min.apply(Math, a);
35429	  return Math.abs(max) >= Math.abs(min) ? max : min;
35430	},
35431		_setScrollTrigger = function _setScrollTrigger() {
35432	  ScrollTrigger = gsap.core.globals().ScrollTrigger;
35433	  ScrollTrigger && ScrollTrigger.core && _integrate();
35434	},
35435		_initCore = function _initCore(core) {
35436	  gsap = core || _getGSAP();
35437  
35438	  if (!_coreInitted && gsap && typeof document !== "undefined" && document.body) {
35439		_win = window;
35440		_doc = document;
35441		_docEl = _doc.documentElement;
35442		_body = _doc.body;
35443		_root = [_win, _doc, _docEl, _body];
35444		_clamp = gsap.utils.clamp;
35445  
35446		_context = gsap.core.context || function () {};
35447  
35448		_pointerType = "onpointerenter" in _body ? "pointer" : "mouse";
35449		_isTouch = Observer.isTouch = _win.matchMedia && _win.matchMedia("(hover: none), (pointer: coarse)").matches ? 1 : "ontouchstart" in _win || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0 ? 2 : 0;
35450		_eventTypes = Observer.eventTypes = ("ontouchstart" in _docEl ? "touchstart,touchmove,touchcancel,touchend" : !("onpointerdown" in _docEl) ? "mousedown,mousemove,mouseup,mouseup" : "pointerdown,pointermove,pointercancel,pointerup").split(",");
35451		setTimeout(function () {
35452		  return _startup = 0;
35453		}, 500);
35454  
35455		_setScrollTrigger();
35456  
35457		_coreInitted = 1;
35458	  }
35459  
35460	  return _coreInitted;
35461	};
35462  
35463	_horizontal.op = _vertical;
35464	_scrollers.cache = 0;
35465	var Observer = function () {
35466	  function Observer(vars) {
35467		this.init(vars);
35468	  }
35469  
35470	  var _proto = Observer.prototype;
35471  
35472	  _proto.init = function init(vars) {
35473		_coreInitted || _initCore(gsap) || console.warn("Please gsap.registerPlugin(Observer)");
35474		ScrollTrigger || _setScrollTrigger();
35475		var tolerance = vars.tolerance,
35476			dragMinimum = vars.dragMinimum,
35477			type = vars.type,
35478			target = vars.target,
35479			lineHeight = vars.lineHeight,
35480			debounce = vars.debounce,
35481			preventDefault = vars.preventDefault,
35482			onStop = vars.onStop,
35483			onStopDelay = vars.onStopDelay,
35484			ignore = vars.ignore,
35485			wheelSpeed = vars.wheelSpeed,
35486			event = vars.event,
35487			onDragStart = vars.onDragStart,
35488			onDragEnd = vars.onDragEnd,
35489			onDrag = vars.onDrag,
35490			onPress = vars.onPress,
35491			onRelease = vars.onRelease,
35492			onRight = vars.onRight,
35493			onLeft = vars.onLeft,
35494			onUp = vars.onUp,
35495			onDown = vars.onDown,
35496			onChangeX = vars.onChangeX,
35497			onChangeY = vars.onChangeY,
35498			onChange = vars.onChange,
35499			onToggleX = vars.onToggleX,
35500			onToggleY = vars.onToggleY,
35501			onHover = vars.onHover,
35502			onHoverEnd = vars.onHoverEnd,
35503			onMove = vars.onMove,
35504			ignoreCheck = vars.ignoreCheck,
35505			isNormalizer = vars.isNormalizer,
35506			onGestureStart = vars.onGestureStart,
35507			onGestureEnd = vars.onGestureEnd,
35508			onWheel = vars.onWheel,
35509			onEnable = vars.onEnable,
35510			onDisable = vars.onDisable,
35511			onClick = vars.onClick,
35512			scrollSpeed = vars.scrollSpeed,
35513			capture = vars.capture,
35514			allowClicks = vars.allowClicks,
35515			lockAxis = vars.lockAxis,
35516			onLockAxis = vars.onLockAxis;
35517		this.target = target = _getTarget(target) || _docEl;
35518		this.vars = vars;
35519		ignore && (ignore = gsap.utils.toArray(ignore));
35520		tolerance = tolerance || 1e-9;
35521		dragMinimum = dragMinimum || 0;
35522		wheelSpeed = wheelSpeed || 1;
35523		scrollSpeed = scrollSpeed || 1;
35524		type = type || "wheel,touch,pointer";
35525		debounce = debounce !== false;
35526		lineHeight || (lineHeight = parseFloat(_win.getComputedStyle(_body).lineHeight) || 22);
35527  
35528		var id,
35529			onStopDelayedCall,
35530			dragged,
35531			moved,
35532			wheeled,
35533			locked,
35534			axis,
35535			self = this,
35536			prevDeltaX = 0,
35537			prevDeltaY = 0,
35538			passive = vars.passive || !preventDefault,
35539			scrollFuncX = _getScrollFunc(target, _horizontal),
35540			scrollFuncY = _getScrollFunc(target, _vertical),
35541			scrollX = scrollFuncX(),
35542			scrollY = scrollFuncY(),
35543			limitToTouch = ~type.indexOf("touch") && !~type.indexOf("pointer") && _eventTypes[0] === "pointerdown",
35544			isViewport = _isViewport(target),
35545			ownerDoc = target.ownerDocument || _doc,
35546			deltaX = [0, 0, 0],
35547			deltaY = [0, 0, 0],
35548			onClickTime = 0,
35549			clickCapture = function clickCapture() {
35550		  return onClickTime = _getTime();
35551		},
35552			_ignoreCheck = function _ignoreCheck(e, isPointerOrTouch) {
35553		  return (self.event = e) && ignore && ~ignore.indexOf(e.target) || isPointerOrTouch && limitToTouch && e.pointerType !== "touch" || ignoreCheck && ignoreCheck(e, isPointerOrTouch);
35554		},
35555			onStopFunc = function onStopFunc() {
35556		  self._vx.reset();
35557  
35558		  self._vy.reset();
35559  
35560		  onStopDelayedCall.pause();
35561		  onStop && onStop(self);
35562		},
35563			update = function update() {
35564		  var dx = self.deltaX = _getAbsoluteMax(deltaX),
35565			  dy = self.deltaY = _getAbsoluteMax(deltaY),
35566			  changedX = Math.abs(dx) >= tolerance,
35567			  changedY = Math.abs(dy) >= tolerance;
35568  
35569		  onChange && (changedX || changedY) && onChange(self, dx, dy, deltaX, deltaY);
35570  
35571		  if (changedX) {
35572			onRight && self.deltaX > 0 && onRight(self);
35573			onLeft && self.deltaX < 0 && onLeft(self);
35574			onChangeX && onChangeX(self);
35575			onToggleX && self.deltaX < 0 !== prevDeltaX < 0 && onToggleX(self);
35576			prevDeltaX = self.deltaX;
35577			deltaX[0] = deltaX[1] = deltaX[2] = 0;
35578		  }
35579  
35580		  if (changedY) {
35581			onDown && self.deltaY > 0 && onDown(self);
35582			onUp && self.deltaY < 0 && onUp(self);
35583			onChangeY && onChangeY(self);
35584			onToggleY && self.deltaY < 0 !== prevDeltaY < 0 && onToggleY(self);
35585			prevDeltaY = self.deltaY;
35586			deltaY[0] = deltaY[1] = deltaY[2] = 0;
35587		  }
35588  
35589		  if (moved || dragged) {
35590			onMove && onMove(self);
35591  
35592			if (dragged) {
35593			  onDrag(self);
35594			  dragged = false;
35595			}
35596  
35597			moved = false;
35598		  }
35599  
35600		  locked && !(locked = false) && onLockAxis && onLockAxis(self);
35601  
35602		  if (wheeled) {
35603			onWheel(self);
35604			wheeled = false;
35605		  }
35606  
35607		  id = 0;
35608		},
35609			onDelta = function onDelta(x, y, index) {
35610		  deltaX[index] += x;
35611		  deltaY[index] += y;
35612  
35613		  self._vx.update(x);
35614  
35615		  self._vy.update(y);
35616  
35617		  debounce ? id || (id = requestAnimationFrame(update)) : update();
35618		},
35619			onTouchOrPointerDelta = function onTouchOrPointerDelta(x, y) {
35620		  if (lockAxis && !axis) {
35621			self.axis = axis = Math.abs(x) > Math.abs(y) ? "x" : "y";
35622			locked = true;
35623		  }
35624  
35625		  if (axis !== "y") {
35626			deltaX[2] += x;
35627  
35628			self._vx.update(x, true);
35629		  }
35630  
35631		  if (axis !== "x") {
35632			deltaY[2] += y;
35633  
35634			self._vy.update(y, true);
35635		  }
35636  
35637		  debounce ? id || (id = requestAnimationFrame(update)) : update();
35638		},
35639			_onDrag = function _onDrag(e) {
35640		  if (_ignoreCheck(e, 1)) {
35641			return;
35642		  }
35643  
35644		  e = _getEvent(e, preventDefault);
35645		  var x = e.clientX,
35646			  y = e.clientY,
35647			  dx = x - self.x,
35648			  dy = y - self.y,
35649			  isDragging = self.isDragging;
35650		  self.x = x;
35651		  self.y = y;
35652  
35653		  if (isDragging || Math.abs(self.startX - x) >= dragMinimum || Math.abs(self.startY - y) >= dragMinimum) {
35654			onDrag && (dragged = true);
35655			isDragging || (self.isDragging = true);
35656			onTouchOrPointerDelta(dx, dy);
35657			isDragging || onDragStart && onDragStart(self);
35658		  }
35659		},
35660			_onPress = self.onPress = function (e) {
35661		  if (_ignoreCheck(e, 1) || e && e.button) {
35662			return;
35663		  }
35664  
35665		  self.axis = axis = null;
35666		  onStopDelayedCall.pause();
35667		  self.isPressed = true;
35668		  e = _getEvent(e);
35669		  prevDeltaX = prevDeltaY = 0;
35670		  self.startX = self.x = e.clientX;
35671		  self.startY = self.y = e.clientY;
35672  
35673		  self._vx.reset();
35674  
35675		  self._vy.reset();
35676  
35677		  _addListener(isNormalizer ? target : ownerDoc, _eventTypes[1], _onDrag, passive, true);
35678  
35679		  self.deltaX = self.deltaY = 0;
35680		  onPress && onPress(self);
35681		},
35682			_onRelease = self.onRelease = function (e) {
35683		  if (_ignoreCheck(e, 1)) {
35684			return;
35685		  }
35686  
35687		  _removeListener(isNormalizer ? target : ownerDoc, _eventTypes[1], _onDrag, true);
35688  
35689		  var isTrackingDrag = !isNaN(self.y - self.startY),
35690			  wasDragging = self.isDragging,
35691			  isDragNotClick = wasDragging && (Math.abs(self.x - self.startX) > 3 || Math.abs(self.y - self.startY) > 3),
35692			  eventData = _getEvent(e);
35693  
35694		  if (!isDragNotClick && isTrackingDrag) {
35695			self._vx.reset();
35696  
35697			self._vy.reset();
35698  
35699			if (preventDefault && allowClicks) {
35700			  gsap.delayedCall(0.08, function () {
35701				if (_getTime() - onClickTime > 300 && !e.defaultPrevented) {
35702				  if (e.target.click) {
35703					e.target.click();
35704				  } else if (ownerDoc.createEvent) {
35705					var syntheticEvent = ownerDoc.createEvent("MouseEvents");
35706					syntheticEvent.initMouseEvent("click", true, true, _win, 1, eventData.screenX, eventData.screenY, eventData.clientX, eventData.clientY, false, false, false, false, 0, null);
35707					e.target.dispatchEvent(syntheticEvent);
35708				  }
35709				}
35710			  });
35711			}
35712		  }
35713  
35714		  self.isDragging = self.isGesturing = self.isPressed = false;
35715		  onStop && wasDragging && !isNormalizer && onStopDelayedCall.restart(true);
35716		  onDragEnd && wasDragging && onDragEnd(self);
35717		  onRelease && onRelease(self, isDragNotClick);
35718		},
35719			_onGestureStart = function _onGestureStart(e) {
35720		  return e.touches && e.touches.length > 1 && (self.isGesturing = true) && onGestureStart(e, self.isDragging);
35721		},
35722			_onGestureEnd = function _onGestureEnd() {
35723		  return (self.isGesturing = false) || onGestureEnd(self);
35724		},
35725			onScroll = function onScroll(e) {
35726		  if (_ignoreCheck(e)) {
35727			return;
35728		  }
35729  
35730		  var x = scrollFuncX(),
35731			  y = scrollFuncY();
35732		  onDelta((x - scrollX) * scrollSpeed, (y - scrollY) * scrollSpeed, 1);
35733		  scrollX = x;
35734		  scrollY = y;
35735		  onStop && onStopDelayedCall.restart(true);
35736		},
35737			_onWheel = function _onWheel(e) {
35738		  if (_ignoreCheck(e)) {
35739			return;
35740		  }
35741  
35742		  e = _getEvent(e, preventDefault);
35743		  onWheel && (wheeled = true);
35744		  var multiplier = (e.deltaMode === 1 ? lineHeight : e.deltaMode === 2 ? _win.innerHeight : 1) * wheelSpeed;
35745		  onDelta(e.deltaX * multiplier, e.deltaY * multiplier, 0);
35746		  onStop && !isNormalizer && onStopDelayedCall.restart(true);
35747		},
35748			_onMove = function _onMove(e) {
35749		  if (_ignoreCheck(e)) {
35750			return;
35751		  }
35752  
35753		  var x = e.clientX,
35754			  y = e.clientY,
35755			  dx = x - self.x,
35756			  dy = y - self.y;
35757		  self.x = x;
35758		  self.y = y;
35759		  moved = true;
35760		  onStop && onStopDelayedCall.restart(true);
35761		  (dx || dy) && onTouchOrPointerDelta(dx, dy);
35762		},
35763			_onHover = function _onHover(e) {
35764		  self.event = e;
35765		  onHover(self);
35766		},
35767			_onHoverEnd = function _onHoverEnd(e) {
35768		  self.event = e;
35769		  onHoverEnd(self);
35770		},
35771			_onClick = function _onClick(e) {
35772		  return _ignoreCheck(e) || _getEvent(e, preventDefault) && onClick(self);
35773		};
35774  
35775		onStopDelayedCall = self._dc = gsap.delayedCall(onStopDelay || 0.25, onStopFunc).pause();
35776		self.deltaX = self.deltaY = 0;
35777		self._vx = _getVelocityProp(0, 50, true);
35778		self._vy = _getVelocityProp(0, 50, true);
35779		self.scrollX = scrollFuncX;
35780		self.scrollY = scrollFuncY;
35781		self.isDragging = self.isGesturing = self.isPressed = false;
vendor: 7,173 bytes, lines 35782-36024
35782  
35783		_context(this);
35784  
35785		self.enable = function (e) {
35786		  if (!self.isEnabled) {
35787			_addListener(isViewport ? ownerDoc : target, "scroll", _onScroll);
35788  
35789			type.indexOf("scroll") >= 0 && _addListener(isViewport ? ownerDoc : target, "scroll", onScroll, passive, capture);
35790			type.indexOf("wheel") >= 0 && _addListener(target, "wheel", _onWheel, passive, capture);
35791  
35792			if (type.indexOf("touch") >= 0 && _isTouch || type.indexOf("pointer") >= 0) {
35793			  _addListener(target, _eventTypes[0], _onPress, passive, capture);
35794  
35795			  _addListener(ownerDoc, _eventTypes[2], _onRelease);
35796  
35797			  _addListener(ownerDoc, _eventTypes[3], _onRelease);
35798  
35799			  allowClicks && _addListener(target, "click", clickCapture, true, true);
35800			  onClick && _addListener(target, "click", _onClick);
35801			  onGestureStart && _addListener(ownerDoc, "gesturestart", _onGestureStart);
35802			  onGestureEnd && _addListener(ownerDoc, "gestureend", _onGestureEnd);
35803			  onHover && _addListener(target, _pointerType + "enter", _onHover);
35804			  onHoverEnd && _addListener(target, _pointerType + "leave", _onHoverEnd);
35805			  onMove && _addListener(target, _pointerType + "move", _onMove);
35806			}
35807  
35808			self.isEnabled = true;
35809			e && e.type && _onPress(e);
35810			onEnable && onEnable(self);
35811		  }
35812  
35813		  return self;
35814		};
35815  
35816		self.disable = function () {
35817		  if (self.isEnabled) {
35818			_observers.filter(function (o) {
35819			  return o !== self && _isViewport(o.target);
35820			}).length || _removeListener(isViewport ? ownerDoc : target, "scroll", _onScroll);
35821  
35822			if (self.isPressed) {
35823			  self._vx.reset();
35824  
35825			  self._vy.reset();
35826  
35827			  _removeListener(isNormalizer ? target : ownerDoc, _eventTypes[1], _onDrag, true);
35828			}
35829  
35830			_removeListener(isViewport ? ownerDoc : target, "scroll", onScroll, capture);
35831  
35832			_removeListener(target, "wheel", _onWheel, capture);
35833  
35834			_removeListener(target, _eventTypes[0], _onPress, capture);
35835  
35836			_removeListener(ownerDoc, _eventTypes[2], _onRelease);
35837  
35838			_removeListener(ownerDoc, _eventTypes[3], _onRelease);
35839  
35840			_removeListener(target, "click", clickCapture, true);
35841  
35842			_removeListener(target, "click", _onClick);
35843  
35844			_removeListener(ownerDoc, "gesturestart", _onGestureStart);
35845  
35846			_removeListener(ownerDoc, "gestureend", _onGestureEnd);
35847  
35848			_removeListener(target, _pointerType + "enter", _onHover);
35849  
35850			_removeListener(target, _pointerType + "leave", _onHoverEnd);
35851  
35852			_removeListener(target, _pointerType + "move", _onMove);
35853  
35854			self.isEnabled = self.isPressed = self.isDragging = false;
35855			onDisable && onDisable(self);
35856		  }
35857		};
35858  
35859		self.kill = self.revert = function () {
35860		  self.disable();
35861  
35862		  var i = _observers.indexOf(self);
35863  
35864		  i >= 0 && _observers.splice(i, 1);
35865		  _normalizer === self && (_normalizer = 0);
35866		};
35867  
35868		_observers.push(self);
35869  
35870		isNormalizer && _isViewport(target) && (_normalizer = self);
35871		self.enable(event);
35872	  };
35873  
35874	  _createClass(Observer, [{
35875		key: "velocityX",
35876		get: function get() {
35877		  return this._vx.getVelocity();
35878		}
35879	  }, {
35880		key: "velocityY",
35881		get: function get() {
35882		  return this._vy.getVelocity();
35883		}
35884	  }]);
35885  
35886	  return Observer;
35887	}();
35888	Observer.version = "3.12.5";
35889  
35890	Observer.create = function (vars) {
35891	  return new Observer(vars);
35892	};
35893  
35894	Observer.register = _initCore;
35895  
35896	Observer.getAll = function () {
35897	  return _observers.slice();
35898	};
35899  
35900	Observer.getById = function (id) {
35901	  return _observers.filter(function (o) {
35902		return o.vars.id === id;
35903	  })[0];
35904	};
35905  
35906	_getGSAP() && gsap.registerPlugin(Observer);
35907  
35908	/*!
35909	 * ScrollTrigger 3.12.5
35910	 * https://gsap.com
35911	 *
35912	 * @license Copyright 2008-2024, GreenSock. All rights reserved.
35913	 * Subject to the terms at https://gsap.com/standard-license or for
35914	 * Club GSAP members, the agreement issued with that membership.
35915	 * @author: Jack Doyle, [email protected]
35916	*/
35917  
35918	var gsap$1,
35919		_coreInitted$1,
35920		_win$1,
35921		_doc$1,
35922		_docEl$1,
35923		_body$1,
35924		_root$1,
35925		_resizeDelay,
35926		_toArray,
35927		_clamp$1,
35928		_time2,
35929		_syncInterval,
35930		_refreshing,
35931		_pointerIsDown,
35932		_transformProp,
35933		_i,
35934		_prevWidth,
35935		_prevHeight,
35936		_autoRefresh,
35937		_sort,
35938		_suppressOverwrites,
35939		_ignoreResize,
35940		_normalizer$1,
35941		_ignoreMobileResize,
35942		_baseScreenHeight,
35943		_baseScreenWidth,
35944		_fixIOSBug,
35945		_context$1,
35946		_scrollRestoration,
35947		_div100vh,
35948		_100vh,
35949		_isReverted,
35950		_clampingMax,
35951		_limitCallbacks,
35952		_startup$1 = 1,
35953		_getTime$1 = Date.now,
35954		_time1 = _getTime$1(),
35955		_lastScrollTime = 0,
35956		_enabled = 0,
35957		_parseClamp = function _parseClamp(value, type, self) {
35958	  var clamp = _isString(value) && (value.substr(0, 6) === "clamp(" || value.indexOf("max") > -1);
35959	  self["_" + type + "Clamp"] = clamp;
35960	  return clamp ? value.substr(6, value.length - 7) : value;
35961	},
35962		_keepClamp = function _keepClamp(value, clamp) {
35963	  return clamp && (!_isString(value) || value.substr(0, 6) !== "clamp(") ? "clamp(" + value + ")" : value;
35964	},
35965		_rafBugFix = function _rafBugFix() {
35966	  return _enabled && requestAnimationFrame(_rafBugFix);
35967	},
35968		_pointerDownHandler = function _pointerDownHandler() {
35969	  return _pointerIsDown = 1;
35970	},
35971		_pointerUpHandler = function _pointerUpHandler() {
35972	  return _pointerIsDown = 0;
35973	},
35974		_passThrough = function _passThrough(v) {
35975	  return v;
35976	},
35977		_round = function _round(value) {
35978	  return Math.round(value * 100000) / 100000 || 0;
35979	},
35980		_windowExists = function _windowExists() {
35981	  return typeof window !== "undefined";
35982	},
35983		_getGSAP$1 = function _getGSAP() {
35984	  return gsap$1 || _windowExists() && (gsap$1 = window.gsap) && gsap$1.registerPlugin && gsap$1;
35985	},
35986		_isViewport$1 = function _isViewport(e) {
35987	  return !!~_root$1.indexOf(e);
35988	},
35989		_getViewportDimension = function _getViewportDimension(dimensionProperty) {
35990	  return (dimensionProperty === "Height" ? _100vh : _win$1["inner" + dimensionProperty]) || _docEl$1["client" + dimensionProperty] || _body$1["client" + dimensionProperty];
35991	},
35992		_getBoundsFunc = function _getBoundsFunc(element) {
35993	  return _getProxyProp(element, "getBoundingClientRect") || (_isViewport$1(element) ? function () {
35994		_winOffsets.width = _win$1.innerWidth;
35995		_winOffsets.height = _100vh;
35996		return _winOffsets;
35997	  } : function () {
35998		return _getBounds(element);
35999	  });
36000	},
36001		_getSizeFunc = function _getSizeFunc(scroller, isViewport, _ref) {
36002	  var d = _ref.d,
36003		  d2 = _ref.d2,
36004		  a = _ref.a;
36005	  return (a = _getProxyProp(scroller, "getBoundingClientRect")) ? function () {
36006		return a()[d];
36007	  } : function () {
36008		return (isViewport ? _getViewportDimension(d2) : scroller["client" + d2]) || 0;
36009	  };
36010	},
36011		_getOffsetsFunc = function _getOffsetsFunc(element, isViewport) {
36012	  return !isViewport || ~_proxies.indexOf(element) ? _getBoundsFunc(element) : function () {
36013		return _winOffsets;
36014	  };
36015	},
36016		_maxScroll = function _maxScroll(element, _ref2) {
36017	  var s = _ref2.s,
36018		  d2 = _ref2.d2,
36019		  d = _ref2.d,
36020		  a = _ref2.a;
36021	  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]);
36022	},
36023		_iterateAutoRefresh = function _iterateAutoRefresh(func, events) {
36024	  for (var i = 0; i < _autoRefresh.length; i += 3) {
vendor: 4,900 bytes, lines 36025-36206
36025		(!events || ~events.indexOf(_autoRefresh[i + 1])) && func(_autoRefresh[i], _autoRefresh[i + 1], _autoRefresh[i + 2]);
36026	  }
36027	},
36028		_isString = function _isString(value) {
36029	  return typeof value === "string";
36030	},
36031		_isFunction = function _isFunction(value) {
36032	  return typeof value === "function";
36033	},
36034		_isNumber = function _isNumber(value) {
36035	  return typeof value === "number";
36036	},
36037		_isObject = function _isObject(value) {
36038	  return typeof value === "object";
36039	},
36040		_endAnimation = function _endAnimation(animation, reversed, pause) {
36041	  return animation && animation.progress(reversed ? 0 : 1) && pause && animation.pause();
36042	},
36043		_callback = function _callback(self, func) {
36044	  if (self.enabled) {
36045		var result = self._ctx ? self._ctx.add(function () {
36046		  return func(self);
36047		}) : func(self);
36048		result && result.totalTime && (self.callbackAnimation = result);
36049	  }
36050	},
36051		_abs = Math.abs,
36052		_left = "left",
36053		_top = "top",
36054		_right = "right",
36055		_bottom = "bottom",
36056		_width = "width",
36057		_height = "height",
36058		_Right = "Right",
36059		_Left = "Left",
36060		_Top = "Top",
36061		_Bottom = "Bottom",
36062		_padding = "padding",
36063		_margin = "margin",
36064		_Width = "Width",
36065		_Height = "Height",
36066		_px = "px",
36067		_getComputedStyle = function _getComputedStyle(element) {
36068	  return _win$1.getComputedStyle(element);
36069	},
36070		_makePositionable = function _makePositionable(element) {
36071	  var position = _getComputedStyle(element).position;
36072  
36073	  element.style.position = position === "absolute" || position === "fixed" ? position : "relative";
36074	},
36075		_setDefaults = function _setDefaults(obj, defaults) {
36076	  for (var p in defaults) {
36077		p in obj || (obj[p] = defaults[p]);
36078	  }
36079  
36080	  return obj;
36081	},
36082		_getBounds = function _getBounds(element, withoutTransforms) {
36083	  var tween = withoutTransforms && _getComputedStyle(element)[_transformProp] !== "matrix(1, 0, 0, 1, 0, 0)" && gsap$1.to(element, {
36084		x: 0,
36085		y: 0,
36086		xPercent: 0,
36087		yPercent: 0,
36088		rotation: 0,
36089		rotationX: 0,
36090		rotationY: 0,
36091		scale: 1,
36092		skewX: 0,
36093		skewY: 0
36094	  }).progress(1),
36095		  bounds = element.getBoundingClientRect();
36096	  tween && tween.progress(0).kill();
36097	  return bounds;
36098	},
36099		_getSize = function _getSize(element, _ref3) {
36100	  var d2 = _ref3.d2;
36101	  return element["offset" + d2] || element["client" + d2] || 0;
36102	},
36103		_getLabelRatioArray = function _getLabelRatioArray(timeline) {
36104	  var a = [],
36105		  labels = timeline.labels,
36106		  duration = timeline.duration(),
36107		  p;
36108  
36109	  for (p in labels) {
36110		a.push(labels[p] / duration);
36111	  }
36112  
36113	  return a;
36114	},
36115		_getClosestLabel = function _getClosestLabel(animation) {
36116	  return function (value) {
36117		return gsap$1.utils.snap(_getLabelRatioArray(animation), value);
36118	  };
36119	},
36120		_snapDirectional = function _snapDirectional(snapIncrementOrArray) {
36121	  var snap = gsap$1.utils.snap(snapIncrementOrArray),
36122		  a = Array.isArray(snapIncrementOrArray) && snapIncrementOrArray.slice(0).sort(function (a, b) {
36123		return a - b;
36124	  });
36125	  return a ? function (value, direction, threshold) {
36126		if (threshold === void 0) {
36127		  threshold = 1e-3;
36128		}
36129  
36130		var i;
36131  
36132		if (!direction) {
36133		  return snap(value);
36134		}
36135  
36136		if (direction > 0) {
36137		  value -= threshold;
36138  
36139		  for (i = 0; i < a.length; i++) {
36140			if (a[i] >= value) {
36141			  return a[i];
36142			}
36143		  }
36144  
36145		  return a[i - 1];
36146		} else {
36147		  i = a.length;
36148		  value += threshold;
36149  
36150		  while (i--) {
36151			if (a[i] <= value) {
36152			  return a[i];
36153			}
36154		  }
36155		}
36156  
36157		return a[0];
36158	  } : function (value, direction, threshold) {
36159		if (threshold === void 0) {
36160		  threshold = 1e-3;
36161		}
36162  
36163		var snapped = snap(value);
36164		return !direction || Math.abs(snapped - value) < threshold || snapped - value < 0 === direction < 0 ? snapped : snap(direction < 0 ? value - snapIncrementOrArray : value + snapIncrementOrArray);
36165	  };
36166	},
36167		_getLabelAtDirection = function _getLabelAtDirection(timeline) {
36168	  return function (value, st) {
36169		return _snapDirectional(_getLabelRatioArray(timeline))(value, st.direction);
36170	  };
36171	},
36172		_multiListener = function _multiListener(func, element, types, callback) {
36173	  return types.split(",").forEach(function (type) {
36174		return func(element, type, callback);
36175	  });
36176	},
36177		_addListener$1 = function _addListener(element, type, func, nonPassive, capture) {
36178	  return element.addEventListener(type, func, {
36179		passive: !nonPassive,
36180		capture: !!capture
36181	  });
36182	},
36183		_removeListener$1 = function _removeListener(element, type, func, capture) {
36184	  return element.removeEventListener(type, func, !!capture);
36185	},
36186		_wheelListener = function _wheelListener(func, el, scrollFunc) {
36187	  scrollFunc = scrollFunc && scrollFunc.wheelHandler;
36188  
36189	  if (scrollFunc) {
36190		func(el, "wheel", scrollFunc);
36191		func(el, "touchmove", scrollFunc);
36192	  }
36193	},
36194		_markerDefaults = {
36195	  startColor: "green",
36196	  endColor: "red",
36197	  indent: 0,
36198	  fontSize: "16px",
36199	  fontWeight: "normal"
36200	},
36201		_defaults = {
36202	  toggleActions: "play",
36203	  anticipatePin: 0
36204	},
36205		_keywords = {
36206	  top: 0,
vendor: 14,119 bytes, lines 36207-36647
36207	  left: 0,
36208	  center: 0.5,
36209	  bottom: 1,
36210	  right: 1
36211	},
36212		_offsetToPx = function _offsetToPx(value, size) {
36213	  if (_isString(value)) {
36214		var eqIndex = value.indexOf("="),
36215			relative = ~eqIndex ? +(value.charAt(eqIndex - 1) + 1) * parseFloat(value.substr(eqIndex + 1)) : 0;
36216  
36217		if (~eqIndex) {
36218		  value.indexOf("%") > eqIndex && (relative *= size / 100);
36219		  value = value.substr(0, eqIndex - 1);
36220		}
36221  
36222		value = relative + (value in _keywords ? _keywords[value] * size : ~value.indexOf("%") ? parseFloat(value) * size / 100 : parseFloat(value) || 0);
36223	  }
36224  
36225	  return value;
36226	},
36227		_createMarker = function _createMarker(type, name, container, direction, _ref4, offset, matchWidthEl, containerAnimation) {
36228	  var startColor = _ref4.startColor,
36229		  endColor = _ref4.endColor,
36230		  fontSize = _ref4.fontSize,
36231		  indent = _ref4.indent,
36232		  fontWeight = _ref4.fontWeight;
36233  
36234	  var e = _doc$1.createElement("div"),
36235		  useFixedPosition = _isViewport$1(container) || _getProxyProp(container, "pinType") === "fixed",
36236		  isScroller = type.indexOf("scroller") !== -1,
36237		  parent = useFixedPosition ? _body$1 : container,
36238		  isStart = type.indexOf("start") !== -1,
36239		  color = isStart ? startColor : endColor,
36240		  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;";
36241  
36242	  css += "position:" + ((isScroller || containerAnimation) && useFixedPosition ? "fixed;" : "absolute;");
36243	  (isScroller || containerAnimation || !useFixedPosition) && (css += (direction === _vertical ? _right : _bottom) + ":" + (offset + parseFloat(indent)) + "px;");
36244	  matchWidthEl && (css += "box-sizing:border-box;text-align:left;width:" + matchWidthEl.offsetWidth + "px;");
36245	  e._isStart = isStart;
36246	  e.setAttribute("class", "gsap-marker-" + type + (name ? " marker-" + name : ""));
36247	  e.style.cssText = css;
36248	  e.innerText = name || name === 0 ? type + "-" + name : type;
36249	  parent.children[0] ? parent.insertBefore(e, parent.children[0]) : parent.appendChild(e);
36250	  e._offset = e["offset" + direction.op.d2];
36251  
36252	  _positionMarker(e, 0, direction, isStart);
36253  
36254	  return e;
36255	},
36256		_positionMarker = function _positionMarker(marker, start, direction, flipped) {
36257	  var vars = {
36258		display: "block"
36259	  },
36260		  side = direction[flipped ? "os2" : "p2"],
36261		  oppositeSide = direction[flipped ? "p2" : "os2"];
36262	  marker._isFlipped = flipped;
36263	  vars[direction.a + "Percent"] = flipped ? -100 : 0;
36264	  vars[direction.a] = flipped ? "1px" : 0;
36265	  vars["border" + side + _Width] = 1;
36266	  vars["border" + oppositeSide + _Width] = 0;
36267	  vars[direction.p] = start + "px";
36268	  gsap$1.set(marker, vars);
36269	},
36270		_triggers = [],
36271		_ids = {},
36272		_rafID,
36273		_sync = function _sync() {
36274	  return _getTime$1() - _lastScrollTime > 34 && (_rafID || (_rafID = requestAnimationFrame(_updateAll)));
36275	},
36276		_onScroll$1 = function _onScroll() {
36277	  if (!_normalizer$1 || !_normalizer$1.isPressed || _normalizer$1.startX > _body$1.clientWidth) {
36278		_scrollers.cache++;
36279  
36280		if (_normalizer$1) {
36281		  _rafID || (_rafID = requestAnimationFrame(_updateAll));
36282		} else {
36283		  _updateAll();
36284		}
36285  
36286		_lastScrollTime || _dispatch("scrollStart");
36287		_lastScrollTime = _getTime$1();
36288	  }
36289	},
36290		_setBaseDimensions = function _setBaseDimensions() {
36291	  _baseScreenWidth = _win$1.innerWidth;
36292	  _baseScreenHeight = _win$1.innerHeight;
36293	},
36294		_onResize = function _onResize() {
36295	  _scrollers.cache++;
36296	  !_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);
36297	},
36298		_listeners = {},
36299		_emptyArray = [],
36300		_softRefresh = function _softRefresh() {
36301	  return _removeListener$1(ScrollTrigger$1, "scrollEnd", _softRefresh) || _refreshAll(true);
36302	},
36303		_dispatch = function _dispatch(type) {
36304	  return _listeners[type] && _listeners[type].map(function (f) {
36305		return f();
36306	  }) || _emptyArray;
36307	},
36308		_savedStyles = [],
36309		_revertRecorded = function _revertRecorded(media) {
36310	  for (var i = 0; i < _savedStyles.length; i += 5) {
36311		if (!media || _savedStyles[i + 4] && _savedStyles[i + 4].query === media) {
36312		  _savedStyles[i].style.cssText = _savedStyles[i + 1];
36313		  _savedStyles[i].getBBox && _savedStyles[i].setAttribute("transform", _savedStyles[i + 2] || "");
36314		  _savedStyles[i + 3].uncache = 1;
36315		}
36316	  }
36317	},
36318		_revertAll = function _revertAll(kill, media) {
36319	  var trigger;
36320  
36321	  for (_i = 0; _i < _triggers.length; _i++) {
36322		trigger = _triggers[_i];
36323  
36324		if (trigger && (!media || trigger._ctx === media)) {
36325		  if (kill) {
36326			trigger.kill(1);
36327		  } else {
36328			trigger.revert(true, true);
36329		  }
36330		}
36331	  }
36332  
36333	  _isReverted = true;
36334	  media && _revertRecorded(media);
36335	  media || _dispatch("revert");
36336	},
36337		_clearScrollMemory = function _clearScrollMemory(scrollRestoration, force) {
36338	  _scrollers.cache++;
36339	  (force || !_refreshingAll) && _scrollers.forEach(function (obj) {
36340		return _isFunction(obj) && obj.cacheID++ && (obj.rec = 0);
36341	  });
36342	  _isString(scrollRestoration) && (_win$1.history.scrollRestoration = _scrollRestoration = scrollRestoration);
36343	},
36344		_refreshingAll,
36345		_refreshID = 0,
36346		_queueRefreshID,
36347		_queueRefreshAll = function _queueRefreshAll() {
36348	  if (_queueRefreshID !== _refreshID) {
36349		var id = _queueRefreshID = _refreshID;
36350		requestAnimationFrame(function () {
36351		  return id === _refreshID && _refreshAll(true);
36352		});
36353	  }
36354	},
36355		_refresh100vh = function _refresh100vh() {
36356	  _body$1.appendChild(_div100vh);
36357  
36358	  _100vh = !_normalizer$1 && _div100vh.offsetHeight || _win$1.innerHeight;
36359  
36360	  _body$1.removeChild(_div100vh);
36361	},
36362		_hideAllMarkers = function _hideAllMarkers(hide) {
36363	  return _toArray(".gsap-marker-start, .gsap-marker-end, .gsap-marker-scroller-start, .gsap-marker-scroller-end").forEach(function (el) {
36364		return el.style.display = hide ? "none" : "block";
36365	  });
36366	},
36367		_refreshAll = function _refreshAll(force, skipRevert) {
36368	  if (_lastScrollTime && !force && !_isReverted) {
36369		_addListener$1(ScrollTrigger$1, "scrollEnd", _softRefresh);
36370  
36371		return;
36372	  }
36373  
36374	  _refresh100vh();
36375  
36376	  _refreshingAll = ScrollTrigger$1.isRefreshing = true;
36377  
36378	  _scrollers.forEach(function (obj) {
36379		return _isFunction(obj) && ++obj.cacheID && (obj.rec = obj());
36380	  });
36381  
36382	  var refreshInits = _dispatch("refreshInit");
36383  
36384	  _sort && ScrollTrigger$1.sort();
36385	  skipRevert || _revertAll();
36386  
36387	  _scrollers.forEach(function (obj) {
36388		if (_isFunction(obj)) {
36389		  obj.smooth && (obj.target.style.scrollBehavior = "auto");
36390		  obj(0);
36391		}
36392	  });
36393  
36394	  _triggers.slice(0).forEach(function (t) {
36395		return t.refresh();
36396	  });
36397  
36398	  _isReverted = false;
36399  
36400	  _triggers.forEach(function (t) {
36401		if (t._subPinOffset && t.pin) {
36402		  var prop = t.vars.horizontal ? "offsetWidth" : "offsetHeight",
36403			  original = t.pin[prop];
36404		  t.revert(true, 1);
36405		  t.adjustPinSpacing(t.pin[prop] - original);
36406		  t.refresh();
36407		}
36408	  });
36409  
36410	  _clampingMax = 1;
36411  
36412	  _hideAllMarkers(true);
36413  
36414	  _triggers.forEach(function (t) {
36415		var max = _maxScroll(t.scroller, t._dir),
36416			endClamp = t.vars.end === "max" || t._endClamp && t.end > max,
36417			startClamp = t._startClamp && t.start >= max;
36418  
36419		(endClamp || startClamp) && t.setPositions(startClamp ? max - 1 : t.start, endClamp ? Math.max(startClamp ? max : t.start + 1, max) : t.end, true);
36420	  });
36421  
36422	  _hideAllMarkers(false);
36423  
36424	  _clampingMax = 0;
36425	  refreshInits.forEach(function (result) {
36426		return result && result.render && result.render(-1);
36427	  });
36428  
36429	  _scrollers.forEach(function (obj) {
36430		if (_isFunction(obj)) {
36431		  obj.smooth && requestAnimationFrame(function () {
36432			return obj.target.style.scrollBehavior = "smooth";
36433		  });
36434		  obj.rec && obj(obj.rec);
36435		}
36436	  });
36437  
36438	  _clearScrollMemory(_scrollRestoration, 1);
36439  
36440	  _resizeDelay.pause();
36441  
36442	  _refreshID++;
36443	  _refreshingAll = 2;
36444  
36445	  _updateAll(2);
36446  
36447	  _triggers.forEach(function (t) {
36448		return _isFunction(t.vars.onRefresh) && t.vars.onRefresh(t);
36449	  });
36450  
36451	  _refreshingAll = ScrollTrigger$1.isRefreshing = false;
36452  
36453	  _dispatch("refresh");
36454	},
36455		_lastScroll = 0,
36456		_direction = 1,
36457		_primary,
36458		_updateAll = function _updateAll(force) {
36459	  if (force === 2 || !_refreshingAll && !_isReverted) {
36460		ScrollTrigger$1.isUpdating = true;
36461		_primary && _primary.update(0);
36462  
36463		var l = _triggers.length,
36464			time = _getTime$1(),
36465			recordVelocity = time - _time1 >= 50,
36466			scroll = l && _triggers[0].scroll();
36467  
36468		_direction = _lastScroll > scroll ? -1 : 1;
36469		_refreshingAll || (_lastScroll = scroll);
36470  
36471		if (recordVelocity) {
36472		  if (_lastScrollTime && !_pointerIsDown && time - _lastScrollTime > 200) {
36473			_lastScrollTime = 0;
36474  
36475			_dispatch("scrollEnd");
36476		  }
36477  
36478		  _time2 = _time1;
36479		  _time1 = time;
36480		}
36481  
36482		if (_direction < 0) {
36483		  _i = l;
36484  
36485		  while (_i-- > 0) {
36486			_triggers[_i] && _triggers[_i].update(0, recordVelocity);
36487		  }
36488  
36489		  _direction = 1;
36490		} else {
36491		  for (_i = 0; _i < l; _i++) {
36492			_triggers[_i] && _triggers[_i].update(0, recordVelocity);
36493		  }
36494		}
36495  
36496		ScrollTrigger$1.isUpdating = false;
36497	  }
36498  
36499	  _rafID = 0;
36500	},
36501		_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"],
36502		_stateProps = _propNamesToCopy.concat([_width, _height, "boxSizing", "max" + _Width, "max" + _Height, "position", _margin, _padding, _padding + _Top, _padding + _Right, _padding + _Bottom, _padding + _Left]),
36503		_swapPinOut = function _swapPinOut(pin, spacer, state) {
36504	  _setState(state);
36505  
36506	  var cache = pin._gsap;
36507  
36508	  if (cache.spacerIsNative) {
36509		_setState(cache.spacerState);
36510	  } else if (pin._gsap.swappedIn) {
36511		var parent = spacer.parentNode;
36512  
36513		if (parent) {
36514		  parent.insertBefore(pin, spacer);
36515		  parent.removeChild(spacer);
36516		}
36517	  }
36518  
36519	  pin._gsap.swappedIn = false;
36520	},
36521		_swapPinIn = function _swapPinIn(pin, spacer, cs, spacerState) {
36522	  if (!pin._gsap.swappedIn) {
36523		var i = _propNamesToCopy.length,
36524			spacerStyle = spacer.style,
36525			pinStyle = pin.style,
36526			p;
36527  
36528		while (i--) {
36529		  p = _propNamesToCopy[i];
36530		  spacerStyle[p] = cs[p];
36531		}
36532  
36533		spacerStyle.position = cs.position === "absolute" ? "absolute" : "relative";
36534		cs.display === "inline" && (spacerStyle.display = "inline-block");
36535		pinStyle[_bottom] = pinStyle[_right] = "auto";
36536		spacerStyle.flexBasis = cs.flexBasis || "auto";
36537		spacerStyle.overflow = "visible";
36538		spacerStyle.boxSizing = "border-box";
36539		spacerStyle[_width] = _getSize(pin, _horizontal) + _px;
36540		spacerStyle[_height] = _getSize(pin, _vertical) + _px;
36541		spacerStyle[_padding] = pinStyle[_margin] = pinStyle[_top] = pinStyle[_left] = "0";
36542  
36543		_setState(spacerState);
36544  
36545		pinStyle[_width] = pinStyle["max" + _Width] = cs[_width];
36546		pinStyle[_height] = pinStyle["max" + _Height] = cs[_height];
36547		pinStyle[_padding] = cs[_padding];
36548  
36549		if (pin.parentNode !== spacer) {
36550		  pin.parentNode.insertBefore(spacer, pin);
36551		  spacer.appendChild(pin);
36552		}
36553  
36554		pin._gsap.swappedIn = true;
36555	  }
36556	},
36557		_capsExp = /([A-Z])/g,
36558		_setState = function _setState(state) {
36559	  if (state) {
36560		var style = state.t.style,
36561			l = state.length,
36562			i = 0,
36563			p,
36564			value;
36565		(state.t._gsap || gsap$1.core.getCache(state.t)).uncache = 1;
36566  
36567		for (; i < l; i += 2) {
36568		  value = state[i + 1];
36569		  p = state[i];
36570  
36571		  if (value) {
36572			style[p] = value;
36573		  } else if (style[p]) {
36574			style.removeProperty(p.replace(_capsExp, "-$1").toLowerCase());
36575		  }
36576		}
36577	  }
36578	},
36579		_getState = function _getState(element) {
36580	  var l = _stateProps.length,
36581		  style = element.style,
36582		  state = [],
36583		  i = 0;
36584  
36585	  for (; i < l; i++) {
36586		state.push(_stateProps[i], style[_stateProps[i]]);
36587	  }
36588  
36589	  state.t = element;
36590	  return state;
36591	},
36592		_copyState = function _copyState(state, override, omitOffsets) {
36593	  var result = [],
36594		  l = state.length,
36595		  i = omitOffsets ? 8 : 0,
36596		  p;
36597  
36598	  for (; i < l; i += 2) {
36599		p = state[i];
36600		result.push(p, p in override ? override[p] : state[i + 1]);
36601	  }
36602  
36603	  result.t = state.t;
36604	  return result;
36605	},
36606		_winOffsets = {
36607	  left: 0,
36608	  top: 0
36609	},
36610		_parsePosition = function _parsePosition(value, trigger, scrollerSize, direction, scroll, marker, markerScroller, self, scrollerBounds, borderWidth, useFixedPosition, scrollerMax, containerAnimation, clampZeroProp) {
36611	  _isFunction(value) && (value = value(self));
36612  
36613	  if (_isString(value) && value.substr(0, 3) === "max") {
36614		value = scrollerMax + (value.charAt(4) === "=" ? _offsetToPx("0" + value.substr(3), scrollerSize) : 0);
36615	  }
36616  
36617	  var time = containerAnimation ? containerAnimation.time() : 0,
36618		  p1,
36619		  p2,
36620		  element;
36621	  containerAnimation && containerAnimation.seek(0);
36622	  isNaN(value) || (value = +value);
36623  
36624	  if (!_isNumber(value)) {
36625		_isFunction(trigger) && (trigger = trigger(self));
36626		var offsets = (value || "0").split(" "),
36627			bounds,
36628			localOffset,
36629			globalOffset,
36630			display;
36631		element = _getTarget(trigger, self) || _body$1;
36632		bounds = _getBounds(element) || {};
36633  
36634		if ((!bounds || !bounds.left && !bounds.top) && _getComputedStyle(element).display === "none") {
36635		  display = element.style.display;
36636		  element.style.display = "block";
36637		  bounds = _getBounds(element);
36638		  display ? element.style.display = display : element.style.removeProperty("display");
36639		}
36640  
36641		localOffset = _offsetToPx(offsets[0], bounds[direction.d]);
36642		globalOffset = _offsetToPx(offsets[1] || "0", scrollerSize);
36643		value = bounds[direction.p] - scrollerBounds[direction.p] - borderWidth + localOffset + scroll - globalOffset;
36644		markerScroller && _positionMarker(markerScroller, globalOffset, direction, scrollerSize - globalOffset < 20 || markerScroller._isStart && globalOffset > 20);
36645		scrollerSize -= scrollerSize - globalOffset;
36646	  } else {
36647		containerAnimation && (value = gsap$1.utils.mapRange(containerAnimation.scrollTrigger.start, containerAnimation.scrollTrigger.end, 0, scrollerMa
vendor: 4,541 bytes, lines 36647-36803
36647x, value));
36648		markerScroller && _positionMarker(markerScroller, scrollerSize, direction, true);
36649	  }
36650  
36651	  if (clampZeroProp) {
36652		self[clampZeroProp] = value || -0.001;
36653		value < 0 && (value = 0);
36654	  }
36655  
36656	  if (marker) {
36657		var position = value + scrollerSize,
36658			isStart = marker._isStart;
36659		p1 = "scroll" + direction.d2;
36660  
36661		_positionMarker(marker, position, direction, isStart && position > 20 || !isStart && (useFixedPosition ? Math.max(_body$1[p1], _docEl$1[p1]) : marker.parentNode[p1]) <= position + 1);
36662  
36663		if (useFixedPosition) {
36664		  scrollerBounds = _getBounds(markerScroller);
36665		  useFixedPosition && (marker.style[direction.op.p] = scrollerBounds[direction.op.p] - direction.op.m - marker._offset + _px);
36666		}
36667	  }
36668  
36669	  if (containerAnimation && element) {
36670		p1 = _getBounds(element);
36671		containerAnimation.seek(scrollerMax);
36672		p2 = _getBounds(element);
36673		containerAnimation._caScrollDist = p1[direction.p] - p2[direction.p];
36674		value = value / containerAnimation._caScrollDist * scrollerMax;
36675	  }
36676  
36677	  containerAnimation && containerAnimation.seek(time);
36678	  return containerAnimation ? value : Math.round(value);
36679	},
36680		_prefixExp = /(webkit|moz|length|cssText|inset)/i,
36681		_reparent = function _reparent(element, parent, top, left) {
36682	  if (element.parentNode !== parent) {
36683		var style = element.style,
36684			p,
36685			cs;
36686  
36687		if (parent === _body$1) {
36688		  element._stOrig = style.cssText;
36689		  cs = _getComputedStyle(element);
36690  
36691		  for (p in cs) {
36692			if (!+p && !_prefixExp.test(p) && cs[p] && typeof style[p] === "string" && p !== "0") {
36693			  style[p] = cs[p];
36694			}
36695		  }
36696  
36697		  style.top = top;
36698		  style.left = left;
36699		} else {
36700		  style.cssText = element._stOrig;
36701		}
36702  
36703		gsap$1.core.getCache(element).uncache = 1;
36704		parent.appendChild(element);
36705	  }
36706	},
36707		_interruptionTracker = function _interruptionTracker(getValueFunc, initialValue, onInterrupt) {
36708	  var last1 = initialValue,
36709		  last2 = last1;
36710	  return function (value) {
36711		var current = Math.round(getValueFunc());
36712  
36713		if (current !== last1 && current !== last2 && Math.abs(current - last1) > 3 && Math.abs(current - last2) > 3) {
36714		  value = current;
36715		  onInterrupt && onInterrupt();
36716		}
36717  
36718		last2 = last1;
36719		last1 = value;
36720		return value;
36721	  };
36722	},
36723		_shiftMarker = function _shiftMarker(marker, direction, value) {
36724	  var vars = {};
36725	  vars[direction.p] = "+=" + value;
36726	  gsap$1.set(marker, vars);
36727	},
36728		_getTweenCreator = function _getTweenCreator(scroller, direction) {
36729	  var getScroll = _getScrollFunc(scroller, direction),
36730		  prop = "_scroll" + direction.p2,
36731		  getTween = function getTween(scrollTo, vars, initialValue, change1, change2) {
36732		var tween = getTween.tween,
36733			onComplete = vars.onComplete,
36734			modifiers = {};
36735		initialValue = initialValue || getScroll();
36736  
36737		var checkForInterruption = _interruptionTracker(getScroll, initialValue, function () {
36738		  tween.kill();
36739		  getTween.tween = 0;
36740		});
36741  
36742		change2 = change1 && change2 || 0;
36743		change1 = change1 || scrollTo - initialValue;
36744		tween && tween.kill();
36745		vars[prop] = scrollTo;
36746		vars.inherit = false;
36747		vars.modifiers = modifiers;
36748  
36749		modifiers[prop] = function () {
36750		  return checkForInterruption(initialValue + change1 * tween.ratio + change2 * tween.ratio * tween.ratio);
36751		};
36752  
36753		vars.onUpdate = function () {
36754		  _scrollers.cache++;
36755		  getTween.tween && _updateAll();
36756		};
36757  
36758		vars.onComplete = function () {
36759		  getTween.tween = 0;
36760		  onComplete && onComplete.call(tween);
36761		};
36762  
36763		tween = getTween.tween = gsap$1.to(scroller, vars);
36764		return tween;
36765	  };
36766  
36767	  scroller[prop] = getScroll;
36768  
36769	  getScroll.wheelHandler = function () {
36770		return getTween.tween && getTween.tween.kill() && (getTween.tween = 0);
36771	  };
36772  
36773	  _addListener$1(scroller, "wheel", getScroll.wheelHandler);
36774  
36775	  ScrollTrigger$1.isTouch && _addListener$1(scroller, "touchmove", getScroll.wheelHandler);
36776	  return getTween;
36777	};
36778  
36779	var ScrollTrigger$1 = function () {
36780	  function ScrollTrigger(vars, animation) {
36781		_coreInitted$1 || ScrollTrigger.register(gsap$1) || console.warn("Please gsap.registerPlugin(ScrollTrigger)");
36782  
36783		_context$1(this);
36784  
36785		this.init(vars, animation);
36786	  }
36787  
36788	  var _proto = ScrollTrigger.prototype;
36789  
36790	  _proto.init = function init(vars, animation) {
36791		this.progress = this.start = 0;
36792		this.vars && this.kill(true, true);
36793  
36794		if (!_enabled) {
36795		  this.update = this.refresh = this.kill = _passThrough;
36796		  return;
36797		}
36798  
36799		vars = _setDefaults(_isString(vars) || _isNumber(vars) || vars.nodeType ? {
36800		  trigger: vars
36801		} : vars, _defaults);
36802  
36803		var _vars = vars,
vendor: 4,184 bytes, lines 36804-36944
36804			onUpdate = _vars.onUpdate,
36805			toggleClass = _vars.toggleClass,
36806			id = _vars.id,
36807			onToggle = _vars.onToggle,
36808			onRefresh = _vars.onRefresh,
36809			scrub = _vars.scrub,
36810			trigger = _vars.trigger,
36811			pin = _vars.pin,
36812			pinSpacing = _vars.pinSpacing,
36813			invalidateOnRefresh = _vars.invalidateOnRefresh,
36814			anticipatePin = _vars.anticipatePin,
36815			onScrubComplete = _vars.onScrubComplete,
36816			onSnapComplete = _vars.onSnapComplete,
36817			once = _vars.once,
36818			snap = _vars.snap,
36819			pinReparent = _vars.pinReparent,
36820			pinSpacer = _vars.pinSpacer,
36821			containerAnimation = _vars.containerAnimation,
36822			fastScrollEnd = _vars.fastScrollEnd,
36823			preventOverlaps = _vars.preventOverlaps,
36824			direction = vars.horizontal || vars.containerAnimation && vars.horizontal !== false ? _horizontal : _vertical,
36825			isToggle = !scrub && scrub !== 0,
36826			scroller = _getTarget(vars.scroller || _win$1),
36827			scrollerCache = gsap$1.core.getCache(scroller),
36828			isViewport = _isViewport$1(scroller),
36829			useFixedPosition = ("pinType" in vars ? vars.pinType : _getProxyProp(scroller, "pinType") || isViewport && "fixed") === "fixed",
36830			callbacks = [vars.onEnter, vars.onLeave, vars.onEnterBack, vars.onLeaveBack],
36831			toggleActions = isToggle && vars.toggleActions.split(" "),
36832			markers = "markers" in vars ? vars.markers : _defaults.markers,
36833			borderWidth = isViewport ? 0 : parseFloat(_getComputedStyle(scroller)["border" + direction.p2 + _Width]) || 0,
36834			self = this,
36835			onRefreshInit = vars.onRefreshInit && function () {
36836		  return vars.onRefreshInit(self);
36837		},
36838			getScrollerSize = _getSizeFunc(scroller, isViewport, direction),
36839			getScrollerOffsets = _getOffsetsFunc(scroller, isViewport),
36840			lastSnap = 0,
36841			lastRefresh = 0,
36842			prevProgress = 0,
36843			scrollFunc = _getScrollFunc(scroller, direction),
36844			tweenTo,
36845			pinCache,
36846			snapFunc,
36847			scroll1,
36848			scroll2,
36849			start,
36850			end,
36851			markerStart,
36852			markerEnd,
36853			markerStartTrigger,
36854			markerEndTrigger,
36855			markerVars,
36856			executingOnRefresh,
36857			change,
36858			pinOriginalState,
36859			pinActiveState,
36860			pinState,
36861			spacer,
36862			offset,
36863			pinGetter,
36864			pinSetter,
36865			pinStart,
36866			pinChange,
36867			spacingStart,
36868			spacerState,
36869			markerStartSetter,
36870			pinMoves,
36871			markerEndSetter,
36872			cs,
36873			snap1,
36874			snap2,
36875			scrubTween,
36876			scrubSmooth,
36877			snapDurClamp,
36878			snapDelayedCall,
36879			prevScroll,
36880			prevAnimProgress,
36881			caMarkerSetter,
36882			customRevertReturn;
36883  
36884		self._startClamp = self._endClamp = false;
36885		self._dir = direction;
36886		anticipatePin *= 45;
36887		self.scroller = scroller;
36888		self.scroll = containerAnimation ? containerAnimation.time.bind(containerAnimation) : scrollFunc;
36889		scroll1 = scrollFunc();
36890		self.vars = vars;
36891		animation = animation || vars.animation;
36892  
36893		if ("refreshPriority" in vars) {
36894		  _sort = 1;
36895		  vars.refreshPriority === -9999 && (_primary = self);
36896		}
36897  
36898		scrollerCache.tweenScroll = scrollerCache.tweenScroll || {
36899		  top: _getTweenCreator(scroller, _vertical),
36900		  left: _getTweenCreator(scroller, _horizontal)
36901		};
36902		self.tweenTo = tweenTo = scrollerCache.tweenScroll[direction.p];
36903  
36904		self.scrubDuration = function (value) {
36905		  scrubSmooth = _isNumber(value) && value;
36906  
36907		  if (!scrubSmooth) {
36908			scrubTween && scrubTween.progress(1).kill();
36909			scrubTween = 0;
36910		  } else {
36911			scrubTween ? scrubTween.duration(value) : scrubTween = gsap$1.to(animation, {
36912			  ease: "expo",
36913			  totalProgress: "+=0",
36914			  inherit: false,
36915			  duration: scrubSmooth,
36916			  paused: true,
36917			  onComplete: function onComplete() {
36918				return onScrubComplete && onScrubComplete(self);
36919			  }
36920			});
36921		  }
36922		};
36923  
36924		if (animation) {
36925		  animation.vars.lazy = false;
36926		  animation._initted && !self.isReverted || animation.vars.immediateRender !== false && vars.immediateRender !== false && animation.duration() && animation.render(0, true, true);
36927		  self.animation = animation.pause();
36928		  animation.scrollTrigger = self;
36929		  self.scrubDuration(scrub);
36930		  snap1 = 0;
36931		  id || (id = animation.vars.id);
36932		}
36933  
36934		if (snap) {
36935		  if (!_isObject(snap) || snap.push) {
36936			snap = {
36937			  snapTo: snap
36938			};
36939		  }
36940  
36941		  "scrollBehavior" in _body$1.style && gsap$1.set(isViewport ? [_body$1, _docEl$1] : scroller, {
36942			scrollBehavior: "auto"
36943		  });
36944  
vendor: 4,259 bytes, lines 36945-37040
36945		  _scrollers.forEach(function (o) {
36946			return _isFunction(o) && o.target === (isViewport ? _doc$1.scrollingElement || _docEl$1 : scroller) && (o.smooth = false);
36947		  });
36948  
36949		  snapFunc = _isFunction(snap.snapTo) ? snap.snapTo : snap.snapTo === "labels" ? _getClosestLabel(animation) : snap.snapTo === "labelsDirectional" ? _getLabelAtDirection(animation) : snap.directional !== false ? function (value, st) {
36950			return _snapDirectional(snap.snapTo)(value, _getTime$1() - lastRefresh < 500 ? 0 : st.direction);
36951		  } : gsap$1.utils.snap(snap.snapTo);
36952		  snapDurClamp = snap.duration || {
36953			min: 0.1,
36954			max: 2
36955		  };
36956		  snapDurClamp = _isObject(snapDurClamp) ? _clamp$1(snapDurClamp.min, snapDurClamp.max) : _clamp$1(snapDurClamp, snapDurClamp);
36957		  snapDelayedCall = gsap$1.delayedCall(snap.delay || scrubSmooth / 2 || 0.1, function () {
36958			var scroll = scrollFunc(),
36959				refreshedRecently = _getTime$1() - lastRefresh < 500,
36960				tween = tweenTo.tween;
36961  
36962			if ((refreshedRecently || Math.abs(self.getVelocity()) < 10) && !tween && !_pointerIsDown && lastSnap !== scroll) {
36963			  var progress = (scroll - start) / change,
36964				  totalProgress = animation && !isToggle ? animation.totalProgress() : progress,
36965				  velocity = refreshedRecently ? 0 : (totalProgress - snap2) / (_getTime$1() - _time2) * 1000 || 0,
36966				  change1 = gsap$1.utils.clamp(-progress, 1 - progress, _abs(velocity / 2) * velocity / 0.185),
36967				  naturalEnd = progress + (snap.inertia === false ? 0 : change1),
36968				  endValue,
36969				  endScroll,
36970				  _snap = snap,
36971				  onStart = _snap.onStart,
36972				  _onInterrupt = _snap.onInterrupt,
36973				  _onComplete = _snap.onComplete;
36974			  endValue = snapFunc(naturalEnd, self);
36975			  _isNumber(endValue) || (endValue = naturalEnd);
36976			  endScroll = Math.round(start + endValue * change);
36977  
36978			  if (scroll <= end && scroll >= start && endScroll !== scroll) {
36979				if (tween && !tween._initted && tween.data <= _abs(endScroll - scroll)) {
36980				  return;
36981				}
36982  
36983				if (snap.inertia === false) {
36984				  change1 = endValue - progress;
36985				}
36986  
36987				tweenTo(endScroll, {
36988				  duration: snapDurClamp(_abs(Math.max(_abs(naturalEnd - totalProgress), _abs(endValue - totalProgress)) * 0.185 / velocity / 0.05 || 0)),
36989				  ease: snap.ease || "power3",
36990				  data: _abs(endScroll - scroll),
36991				  onInterrupt: function onInterrupt() {
36992					return snapDelayedCall.restart(true) && _onInterrupt && _onInterrupt(self);
36993				  },
36994				  onComplete: function onComplete() {
36995					self.update();
36996					lastSnap = scrollFunc();
36997  
36998					if (animation) {
36999					  scrubTween ? scrubTween.resetTo("totalProgress", endValue, animation._tTime / animation._tDur) : animation.progress(endValue);
37000					}
37001  
37002					snap1 = snap2 = animation && !isToggle ? animation.totalProgress() : self.progress;
37003					onSnapComplete && onSnapComplete(self);
37004					_onComplete && _onComplete(self);
37005				  }
37006				}, scroll, change1 * change, endScroll - scroll - change1 * change);
37007				onStart && onStart(self, tweenTo.tween);
37008			  }
37009			} else if (self.isActive && lastSnap !== scroll) {
37010			  snapDelayedCall.restart(true);
37011			}
37012		  }).pause();
37013		}
37014  
37015		id && (_ids[id] = self);
37016		trigger = self.trigger = _getTarget(trigger || pin !== true && pin);
37017		customRevertReturn = trigger && trigger._gsap && trigger._gsap.stRevert;
37018		customRevertReturn && (customRevertReturn = customRevertReturn(self));
37019		pin = pin === true ? trigger : _getTarget(pin);
37020		_isString(toggleClass) && (toggleClass = {
37021		  targets: trigger,
37022		  className: toggleClass
37023		});
37024  
37025		if (pin) {
37026		  pinSpacing === false || pinSpacing === _margin || (pinSpacing = !pinSpacing && pin.parentNode && pin.parentNode.style && _getComputedStyle(pin.parentNode).display === "flex" ? false : _padding);
37027		  self.pin = pin;
37028		  pinCache = gsap$1.core.getCache(pin);
37029  
37030		  if (!pinCache.spacer) {
37031			if (pinSpacer) {
37032			  pinSpacer = _getTarget(pinSpacer);
37033			  pinSpacer && !pinSpacer.nodeType && (pinSpacer = pinSpacer.current || pinSpacer.nativeElement);
37034			  pinCache.spacerIsNative = !!pinSpacer;
37035			  pinSpacer && (pinCache.spacerState = _getState(pinSpacer));
37036			}
37037  
37038			pinCache.spacer = spacer = pinSpacer || _doc$1.createElement("div");
37039			spacer.classList.add("pin-spacer");
37040			id && spacer.classList.add("pin-spacer-" + id);
vendor: 4,987 bytes, lines 37041-37195
37041			pinCache.pinState = pinOriginalState = _getState(pin);
37042		  } else {
37043			pinOriginalState = pinCache.pinState;
37044		  }
37045  
37046		  vars.force3D !== false && gsap$1.set(pin, {
37047			force3D: true
37048		  });
37049		  self.spacer = spacer = pinCache.spacer;
37050		  cs = _getComputedStyle(pin);
37051		  spacingStart = cs[pinSpacing + direction.os2];
37052		  pinGetter = gsap$1.getProperty(pin);
37053		  pinSetter = gsap$1.quickSetter(pin, direction.a, _px);
37054  
37055		  _swapPinIn(pin, spacer, cs);
37056  
37057		  pinState = _getState(pin);
37058		}
37059  
37060		if (markers) {
37061		  markerVars = _isObject(markers) ? _setDefaults(markers, _markerDefaults) : _markerDefaults;
37062		  markerStartTrigger = _createMarker("scroller-start", id, scroller, direction, markerVars, 0);
37063		  markerEndTrigger = _createMarker("scroller-end", id, scroller, direction, markerVars, 0, markerStartTrigger);
37064		  offset = markerStartTrigger["offset" + direction.op.d2];
37065  
37066		  var content = _getTarget(_getProxyProp(scroller, "content") || scroller);
37067  
37068		  markerStart = this.markerStart = _createMarker("start", id, content, direction, markerVars, offset, 0, containerAnimation);
37069		  markerEnd = this.markerEnd = _createMarker("end", id, content, direction, markerVars, offset, 0, containerAnimation);
37070		  containerAnimation && (caMarkerSetter = gsap$1.quickSetter([markerStart, markerEnd], direction.a, _px));
37071  
37072		  if (!useFixedPosition && !(_proxies.length && _getProxyProp(scroller, "fixedMarkers") === true)) {
37073			_makePositionable(isViewport ? _body$1 : scroller);
37074  
37075			gsap$1.set([markerStartTrigger, markerEndTrigger], {
37076			  force3D: true
37077			});
37078			markerStartSetter = gsap$1.quickSetter(markerStartTrigger, direction.a, _px);
37079			markerEndSetter = gsap$1.quickSetter(markerEndTrigger, direction.a, _px);
37080		  }
37081		}
37082  
37083		if (containerAnimation) {
37084		  var oldOnUpdate = containerAnimation.vars.onUpdate,
37085			  oldParams = containerAnimation.vars.onUpdateParams;
37086		  containerAnimation.eventCallback("onUpdate", function () {
37087			self.update(0, 0, 1);
37088			oldOnUpdate && oldOnUpdate.apply(containerAnimation, oldParams || []);
37089		  });
37090		}
37091  
37092		self.previous = function () {
37093		  return _triggers[_triggers.indexOf(self) - 1];
37094		};
37095  
37096		self.next = function () {
37097		  return _triggers[_triggers.indexOf(self) + 1];
37098		};
37099  
37100		self.revert = function (revert, temp) {
37101		  if (!temp) {
37102			return self.kill(true);
37103		  }
37104  
37105		  var r = revert !== false || !self.enabled,
37106			  prevRefreshing = _refreshing;
37107  
37108		  if (r !== self.isReverted) {
37109			if (r) {
37110			  prevScroll = Math.max(scrollFunc(), self.scroll.rec || 0);
37111			  prevProgress = self.progress;
37112			  prevAnimProgress = animation && animation.progress();
37113			}
37114  
37115			markerStart && [markerStart, markerEnd, markerStartTrigger, markerEndTrigger].forEach(function (m) {
37116			  return m.style.display = r ? "none" : "block";
37117			});
37118  
37119			if (r) {
37120			  _refreshing = self;
37121			  self.update(r);
37122			}
37123  
37124			if (pin && (!pinReparent || !self.isActive)) {
37125			  if (r) {
37126				_swapPinOut(pin, spacer, pinOriginalState);
37127			  } else {
37128				_swapPinIn(pin, spacer, _getComputedStyle(pin), spacerState);
37129			  }
37130			}
37131  
37132			r || self.update(r);
37133			_refreshing = prevRefreshing;
37134			self.isReverted = r;
37135		  }
37136		};
37137  
37138		self.refresh = function (soft, force, position, pinOffset) {
37139		  if ((_refreshing || !self.enabled) && !force) {
37140			return;
37141		  }
37142  
37143		  if (pin && soft && _lastScrollTime) {
37144			_addListener$1(ScrollTrigger, "scrollEnd", _softRefresh);
37145  
37146			return;
37147		  }
37148  
37149		  !_refreshingAll && onRefreshInit && onRefreshInit(self);
37150		  _refreshing = self;
37151  
37152		  if (tweenTo.tween && !position) {
37153			tweenTo.tween.kill();
37154			tweenTo.tween = 0;
37155		  }
37156  
37157		  scrubTween && scrubTween.pause();
37158		  invalidateOnRefresh && animation && animation.revert({
37159			kill: false
37160		  }).invalidate();
37161		  self.isReverted || self.revert(true, true);
37162		  self._subPinOffset = false;
37163  
37164		  var size = getScrollerSize(),
37165			  scrollerBounds = getScrollerOffsets(),
37166			  max = containerAnimation ? containerAnimation.duration() : _maxScroll(scroller, direction),
37167			  isFirstRefresh = change <= 0.01,
37168			  offset = 0,
37169			  otherPinOffset = pinOffset || 0,
37170			  parsedEnd = _isObject(position) ? position.end : vars.end,
37171			  parsedEndTrigger = vars.endTrigger || trigger,
37172			  parsedStart = _isObject(position) ? position.start : vars.start || (vars.start === 0 || !trigger ? 0 : pin ? "0 0" : "0 100%"),
37173			  pinnedContainer = self.pinnedContainer = vars.pinnedContainer && _getTarget(vars.pinnedContainer, self),
37174			  triggerIndex = trigger && Math.max(0, _triggers.indexOf(self)) || 0,
37175			  i = triggerIndex,
37176			  cs,
37177			  bounds,
37178			  scroll,
37179			  isVertical,
37180			  override,
37181			  curTrigger,
37182			  curPin,
37183			  oppositeScroll,
37184			  initted,
37185			  revertedPins,
37186			  forcedOverflow,
37187			  markerStartOffset,
37188			  markerEndOffset;
37189  
37190		  if (markers && _isObject(position)) {
37191			markerStartOffset = gsap$1.getProperty(markerStartTrigger, direction.p);
37192			markerEndOffset = gsap$1.getProperty(markerEndTrigger, direction.p);
37193		  }
37194  
37195		  while (i--) {
vendor: 4,360 bytes, lines 37196-37307
37196			curTrigger = _triggers[i];
37197			curTrigger.end || curTrigger.refresh(0, 1) || (_refreshing = self);
37198			curPin = curTrigger.pin;
37199  
37200			if (curPin && (curPin === trigger || curPin === pin || curPin === pinnedContainer) && !curTrigger.isReverted) {
37201			  revertedPins || (revertedPins = []);
37202			  revertedPins.unshift(curTrigger);
37203			  curTrigger.revert(true, true);
37204			}
37205  
37206			if (curTrigger !== _triggers[i]) {
37207			  triggerIndex--;
37208			  i--;
37209			}
37210		  }
37211  
37212		  _isFunction(parsedStart) && (parsedStart = parsedStart(self));
37213		  parsedStart = _parseClamp(parsedStart, "start", self);
37214		  start = _parsePosition(parsedStart, trigger, size, direction, scrollFunc(), markerStart, markerStartTrigger, self, scrollerBounds, borderWidth, useFixedPosition, max, containerAnimation, self._startClamp && "_startClamp") || (pin ? -0.001 : 0);
37215		  _isFunction(parsedEnd) && (parsedEnd = parsedEnd(self));
37216  
37217		  if (_isString(parsedEnd) && !parsedEnd.indexOf("+=")) {
37218			if (~parsedEnd.indexOf(" ")) {
37219			  parsedEnd = (_isString(parsedStart) ? parsedStart.split(" ")[0] : "") + parsedEnd;
37220			} else {
37221			  offset = _offsetToPx(parsedEnd.substr(2), size);
37222			  parsedEnd = _isString(parsedStart) ? parsedStart : (containerAnimation ? gsap$1.utils.mapRange(0, containerAnimation.duration(), containerAnimation.scrollTrigger.start, containerAnimation.scrollTrigger.end, start) : start) + offset;
37223			  parsedEndTrigger = trigger;
37224			}
37225		  }
37226  
37227		  parsedEnd = _parseClamp(parsedEnd, "end", self);
37228		  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;
37229		  offset = 0;
37230		  i = triggerIndex;
37231  
37232		  while (i--) {
37233			curTrigger = _triggers[i];
37234			curPin = curTrigger.pin;
37235  
37236			if (curPin && curTrigger.start - curTrigger._pinPush <= start && !containerAnimation && curTrigger.end > 0) {
37237			  cs = curTrigger.end - (self._startClamp ? Math.max(0, curTrigger.start) : curTrigger.start);
37238  
37239			  if ((curPin === trigger && curTrigger.start - curTrigger._pinPush < start || curPin === pinnedContainer) && isNaN(parsedStart)) {
37240				offset += cs * (1 - curTrigger.progress);
37241			  }
37242  
37243			  curPin === pin && (otherPinOffset += cs);
37244			}
37245		  }
37246  
37247		  start += offset;
37248		  end += offset;
37249		  self._startClamp && (self._startClamp += offset);
37250  
37251		  if (self._endClamp && !_refreshingAll) {
37252			self._endClamp = end || -0.001;
37253			end = Math.min(end, _maxScroll(scroller, direction));
37254		  }
37255  
37256		  change = end - start || (start -= 0.01) && 0.001;
37257  
37258		  if (isFirstRefresh) {
37259			prevProgress = gsap$1.utils.clamp(0, 1, gsap$1.utils.normalize(start, end, prevScroll));
37260		  }
37261  
37262		  self._pinPush = otherPinOffset;
37263  
37264		  if (markerStart && offset) {
37265			cs = {};
37266			cs[direction.a] = "+=" + offset;
37267			pinnedContainer && (cs[direction.p] = "-=" + scrollFunc());
37268			gsap$1.set([markerStart, markerEnd], cs);
37269		  }
37270  
37271		  if (pin && !(_clampingMax && self.end >= _maxScroll(scroller, direction))) {
37272			cs = _getComputedStyle(pin);
37273			isVertical = direction === _vertical;
37274			scroll = scrollFunc();
37275			pinStart = parseFloat(pinGetter(direction.a)) + otherPinOffset;
37276  
37277			if (!max && end > 1) {
37278			  forcedOverflow = (isViewport ? _doc$1.scrollingElement || _docEl$1 : scroller).style;
37279			  forcedOverflow = {
37280				style: forcedOverflow,
37281				value: forcedOverflow["overflow" + direction.a.toUpperCase()]
37282			  };
37283  
37284			  if (isViewport && _getComputedStyle(_body$1)["overflow" + direction.a.toUpperCase()] !== "scroll") {
37285				forcedOverflow.style["overflow" + direction.a.toUpperCase()] = "scroll";
37286			  }
37287			}
37288  
37289			_swapPinIn(pin, spacer, cs);
37290  
37291			pinState = _getState(pin);
37292			bounds = _getBounds(pin, true);
37293			oppositeScroll = useFixedPosition && _getScrollFunc(scroller, isVertical ? _horizontal : _vertical)();
37294  
37295			if (pinSpacing) {
37296			  spacerState = [pinSpacing + direction.os2, change + otherPinOffset + _px];
37297			  spacerState.t = spacer;
37298			  i = pinSpacing === _padding ? _getSize(pin, direction) + change + otherPinOffset : 0;
37299  
37300			  if (i) {
37301				spacerState.push(direction.d, i + _px);
37302				spacer.style.flexBasis !== "auto" && (spacer.style.flexBasis = i + _px);
37303			  }
37304  
37305			  _setState(spacerState);
37306  
37307			  if (pinnedContainer) {
vendor: 28,838 bytes, lines 37308-38198
37308				_triggers.forEach(function (t) {
37309				  if (t.pin === pinnedContainer && t.vars.pinSpacing !== false) {
37310					t._subPinOffset = true;
37311				  }
37312				});
37313			  }
37314  
37315			  useFixedPosition && scrollFunc(prevScroll);
37316			} else {
37317			  i = _getSize(pin, direction);
37318			  i && spacer.style.flexBasis !== "auto" && (spacer.style.flexBasis = i + _px);
37319			}
37320  
37321			if (useFixedPosition) {
37322			  override = {
37323				top: bounds.top + (isVertical ? scroll - start : oppositeScroll) + _px,
37324				left: bounds.left + (isVertical ? oppositeScroll : scroll - start) + _px,
37325				boxSizing: "border-box",
37326				position: "fixed"
37327			  };
37328			  override[_width] = override["max" + _Width] = Math.ceil(bounds.width) + _px;
37329			  override[_height] = override["max" + _Height] = Math.ceil(bounds.height) + _px;
37330			  override[_margin] = override[_margin + _Top] = override[_margin + _Right] = override[_margin + _Bottom] = override[_margin + _Left] = "0";
37331			  override[_padding] = cs[_padding];
37332			  override[_padding + _Top] = cs[_padding + _Top];
37333			  override[_padding + _Right] = cs[_padding + _Right];
37334			  override[_padding + _Bottom] = cs[_padding + _Bottom];
37335			  override[_padding + _Left] = cs[_padding + _Left];
37336			  pinActiveState = _copyState(pinOriginalState, override, pinReparent);
37337			  _refreshingAll && scrollFunc(0);
37338			}
37339  
37340			if (animation) {
37341			  initted = animation._initted;
37342  
37343			  _suppressOverwrites(1);
37344  
37345			  animation.render(animation.duration(), true, true);
37346			  pinChange = pinGetter(direction.a) - pinStart + change + otherPinOffset;
37347			  pinMoves = Math.abs(change - pinChange) > 1;
37348			  useFixedPosition && pinMoves && pinActiveState.splice(pinActiveState.length - 2, 2);
37349			  animation.render(0, true, true);
37350			  initted || animation.invalidate(true);
37351			  animation.parent || animation.totalTime(animation.totalTime());
37352  
37353			  _suppressOverwrites(0);
37354			} else {
37355			  pinChange = change;
37356			}
37357  
37358			forcedOverflow && (forcedOverflow.value ? forcedOverflow.style["overflow" + direction.a.toUpperCase()] = forcedOverflow.value : forcedOverflow.style.removeProperty("overflow-" + direction.a));
37359		  } else if (trigger && scrollFunc() && !containerAnimation) {
37360			bounds = trigger.parentNode;
37361  
37362			while (bounds && bounds !== _body$1) {
37363			  if (bounds._pinOffset) {
37364				start -= bounds._pinOffset;
37365				end -= bounds._pinOffset;
37366			  }
37367  
37368			  bounds = bounds.parentNode;
37369			}
37370		  }
37371  
37372		  revertedPins && revertedPins.forEach(function (t) {
37373			return t.revert(false, true);
37374		  });
37375		  self.start = start;
37376		  self.end = end;
37377		  scroll1 = scroll2 = _refreshingAll ? prevScroll : scrollFunc();
37378  
37379		  if (!containerAnimation && !_refreshingAll) {
37380			scroll1 < prevScroll && scrollFunc(prevScroll);
37381			self.scroll.rec = 0;
37382		  }
37383  
37384		  self.revert(false, true);
37385		  lastRefresh = _getTime$1();
37386  
37387		  if (snapDelayedCall) {
37388			lastSnap = -1;
37389			snapDelayedCall.restart(true);
37390		  }
37391  
37392		  _refreshing = 0;
37393		  animation && isToggle && (animation._initted || prevAnimProgress) && animation.progress() !== prevAnimProgress && animation.progress(prevAnimProgress || 0, true).render(animation.time(), true, true);
37394  
37395		  if (isFirstRefresh || prevProgress !== self.progress || containerAnimation || invalidateOnRefresh) {
37396			animation && !isToggle && animation.totalProgress(containerAnimation && start < -0.001 && !prevProgress ? gsap$1.utils.normalize(start, end, 0) : prevProgress, true);
37397			self.progress = isFirstRefresh || (scroll1 - start) / change === prevProgress ? 0 : prevProgress;
37398		  }
37399  
37400		  pin && pinSpacing && (spacer._pinOffset = Math.round(self.progress * pinChange));
37401		  scrubTween && scrubTween.invalidate();
37402  
37403		  if (!isNaN(markerStartOffset)) {
37404			markerStartOffset -= gsap$1.getProperty(markerStartTrigger, direction.p);
37405			markerEndOffset -= gsap$1.getProperty(markerEndTrigger, direction.p);
37406  
37407			_shiftMarker(markerStartTrigger, direction, markerStartOffset);
37408  
37409			_shiftMarker(markerStart, direction, markerStartOffset - (pinOffset || 0));
37410  
37411			_shiftMarker(markerEndTrigger, direction, markerEndOffset);
37412  
37413			_shiftMarker(markerEnd, direction, markerEndOffset - (pinOffset || 0));
37414		  }
37415  
37416		  isFirstRefresh && !_refreshingAll && self.update();
37417  
37418		  if (onRefresh && !_refreshingAll && !executingOnRefresh) {
37419			executingOnRefresh = true;
37420			onRefresh(self);
37421			executingOnRefresh = false;
37422		  }
37423		};
37424  
37425		self.getVelocity = function () {
37426		  return (scrollFunc() - scroll2) / (_getTime$1() - _time2) * 1000 || 0;
37427		};
37428  
37429		self.endAnimation = function () {
37430		  _endAnimation(self.callbackAnimation);
37431  
37432		  if (animation) {
37433			scrubTween ? scrubTween.progress(1) : !animation.paused() ? _endAnimation(animation, animation.reversed()) : isToggle || _endAnimation(animation, self.direction < 0, 1);
37434		  }
37435		};
37436  
37437		self.labelToScroll = function (label) {
37438		  return animation && animation.labels && (start || self.refresh() || start) + animation.labels[label] / animation.duration() * change || 0;
37439		};
37440  
37441		self.getTrailing = function (name) {
37442		  var i = _triggers.indexOf(self),
37443			  a = self.direction > 0 ? _triggers.slice(0, i).reverse() : _triggers.slice(i + 1);
37444  
37445		  return (_isString(name) ? a.filter(function (t) {
37446			return t.vars.preventOverlaps === name;
37447		  }) : a).filter(function (t) {
37448			return self.direction > 0 ? t.end <= start : t.start >= end;
37449		  });
37450		};
37451  
37452		self.update = function (reset, recordVelocity, forceFake) {
37453		  if (containerAnimation && !forceFake && !reset) {
37454			return;
37455		  }
37456  
37457		  var scroll = _refreshingAll === true ? prevScroll : self.scroll(),
37458			  p = reset ? 0 : (scroll - start) / change,
37459			  clipped = p < 0 ? 0 : p > 1 ? 1 : p || 0,
37460			  prevProgress = self.progress,
37461			  isActive,
37462			  wasActive,
37463			  toggleState,
37464			  action,
37465			  stateChanged,
37466			  toggled,
37467			  isAtMax,
37468			  isTakingAction;
37469  
37470		  if (recordVelocity) {
37471			scroll2 = scroll1;
37472			scroll1 = containerAnimation ? scrollFunc() : scroll;
37473  
37474			if (snap) {
37475			  snap2 = snap1;
37476			  snap1 = animation && !isToggle ? animation.totalProgress() : clipped;
37477			}
37478		  }
37479  
37480		  if (anticipatePin && pin && !_refreshing && !_startup$1 && _lastScrollTime) {
37481			if (!clipped && start < scroll + (scroll - scroll2) / (_getTime$1() - _time2) * anticipatePin) {
37482			  clipped = 0.0001;
37483			} else if (clipped === 1 && end > scroll + (scroll - scroll2) / (_getTime$1() - _time2) * anticipatePin) {
37484			  clipped = 0.9999;
37485			}
37486		  }
37487  
37488		  if (clipped !== prevProgress && self.enabled) {
37489			isActive = self.isActive = !!clipped && clipped < 1;
37490			wasActive = !!prevProgress && prevProgress < 1;
37491			toggled = isActive !== wasActive;
37492			stateChanged = toggled || !!clipped !== !!prevProgress;
37493			self.direction = clipped > prevProgress ? 1 : -1;
37494			self.progress = clipped;
37495  
37496			if (stateChanged && !_refreshing) {
37497			  toggleState = clipped && !prevProgress ? 0 : clipped === 1 ? 1 : prevProgress === 1 ? 2 : 3;
37498  
37499			  if (isToggle) {
37500				action = !toggled && toggleActions[toggleState + 1] !== "none" && toggleActions[toggleState + 1] || toggleActions[toggleState];
37501				isTakingAction = animation && (action === "complete" || action === "reset" || action in animation);
37502			  }
37503			}
37504  
37505			preventOverlaps && (toggled || isTakingAction) && (isTakingAction || scrub || !animation) && (_isFunction(preventOverlaps) ? preventOverlaps(self) : self.getTrailing(preventOverlaps).forEach(function (t) {
37506			  return t.endAnimation();
37507			}));
37508  
37509			if (!isToggle) {
37510			  if (scrubTween && !_refreshing && !_startup$1) {
37511				scrubTween._dp._time - scrubTween._start !== scrubTween._time && scrubTween.render(scrubTween._dp._time - scrubTween._start);
37512  
37513				if (scrubTween.resetTo) {
37514				  scrubTween.resetTo("totalProgress", clipped, animation._tTime / animation._tDur);
37515				} else {
37516				  scrubTween.vars.totalProgress = clipped;
37517				  scrubTween.invalidate().restart();
37518				}
37519			  } else if (animation) {
37520				animation.totalProgress(clipped, !!(_refreshing && (lastRefresh || reset)));
37521			  }
37522			}
37523  
37524			if (pin) {
37525			  reset && pinSpacing && (spacer.style[pinSpacing + direction.os2] = spacingStart);
37526  
37527			  if (!useFixedPosition) {
37528				pinSetter(_round(pinStart + pinChange * clipped));
37529			  } else if (stateChanged) {
37530				isAtMax = !reset && clipped > prevProgress && end + 1 > scroll && scroll + 1 >= _maxScroll(scroller, direction);
37531  
37532				if (pinReparent) {
37533				  if (!reset && (isActive || isAtMax)) {
37534					var bounds = _getBounds(pin, true),
37535						_offset = scroll - start;
37536  
37537					_reparent(pin, _body$1, bounds.top + (direction === _vertical ? _offset : 0) + _px, bounds.left + (direction === _vertical ? 0 : _offset) + _px);
37538				  } else {
37539					_reparent(pin, spacer);
37540				  }
37541				}
37542  
37543				_setState(isActive || isAtMax ? pinActiveState : pinState);
37544  
37545				pinMoves && clipped < 1 && isActive || pinSetter(pinStart + (clipped === 1 && !isAtMax ? pinChange : 0));
37546			  }
37547			}
37548  
37549			snap && !tweenTo.tween && !_refreshing && !_startup$1 && snapDelayedCall.restart(true);
37550			toggleClass && (toggled || once && clipped && (clipped < 1 || !_limitCallbacks)) && _toArray(toggleClass.targets).forEach(function (el) {
37551			  return el.classList[isActive || once ? "add" : "remove"](toggleClass.className);
37552			});
37553			onUpdate && !isToggle && !reset && onUpdate(self);
37554  
37555			if (stateChanged && !_refreshing) {
37556			  if (isToggle) {
37557				if (isTakingAction) {
37558				  if (action === "complete") {
37559					animation.pause().totalProgress(1);
37560				  } else if (action === "reset") {
37561					animation.restart(true).pause();
37562				  } else if (action === "restart") {
37563					animation.restart(true);
37564				  } else {
37565					animation[action]();
37566				  }
37567				}
37568  
37569				onUpdate && onUpdate(self);
37570			  }
37571  
37572			  if (toggled || !_limitCallbacks) {
37573				onToggle && toggled && _callback(self, onToggle);
37574				callbacks[toggleState] && _callback(self, callbacks[toggleState]);
37575				once && (clipped === 1 ? self.kill(false, 1) : callbacks[toggleState] = 0);
37576  
37577				if (!toggled) {
37578				  toggleState = clipped === 1 ? 1 : 3;
37579				  callbacks[toggleState] && _callback(self, callbacks[toggleState]);
37580				}
37581			  }
37582  
37583			  if (fastScrollEnd && !isActive && Math.abs(self.getVelocity()) > (_isNumber(fastScrollEnd) ? fastScrollEnd : 2500)) {
37584				_endAnimation(self.callbackAnimation);
37585  
37586				scrubTween ? scrubTween.progress(1) : _endAnimation(animation, action === "reverse" ? 1 : !clipped, 1);
37587			  }
37588			} else if (isToggle && onUpdate && !_refreshing) {
37589			  onUpdate(self);
37590			}
37591		  }
37592  
37593		  if (markerEndSetter) {
37594			var n = containerAnimation ? scroll / containerAnimation.duration() * (containerAnimation._caScrollDist || 0) : scroll;
37595			markerStartSetter(n + (markerStartTrigger._isFlipped ? 1 : 0));
37596			markerEndSetter(n);
37597		  }
37598  
37599		  caMarkerSetter && caMarkerSetter(-scroll / containerAnimation.duration() * (containerAnimation._caScrollDist || 0));
37600		};
37601  
37602		self.enable = function (reset, refresh) {
37603		  if (!self.enabled) {
37604			self.enabled = true;
37605  
37606			_addListener$1(scroller, "resize", _onResize);
37607  
37608			isViewport || _addListener$1(scroller, "scroll", _onScroll$1);
37609			onRefreshInit && _addListener$1(ScrollTrigger, "refreshInit", onRefreshInit);
37610  
37611			if (reset !== false) {
37612			  self.progress = prevProgress = 0;
37613			  scroll1 = scroll2 = lastSnap = scrollFunc();
37614			}
37615  
37616			refresh !== false && self.refresh();
37617		  }
37618		};
37619  
37620		self.getTween = function (snap) {
37621		  return snap && tweenTo ? tweenTo.tween : scrubTween;
37622		};
37623  
37624		self.setPositions = function (newStart, newEnd, keepClamp, pinOffset) {
37625		  if (containerAnimation) {
37626			var st = containerAnimation.scrollTrigger,
37627				duration = containerAnimation.duration(),
37628				_change = st.end - st.start;
37629  
37630			newStart = st.start + _change * newStart / duration;
37631			newEnd = st.start + _change * newEnd / duration;
37632		  }
37633  
37634		  self.refresh(false, false, {
37635			start: _keepClamp(newStart, keepClamp && !!self._startClamp),
37636			end: _keepClamp(newEnd, keepClamp && !!self._endClamp)
37637		  }, pinOffset);
37638		  self.update();
37639		};
37640  
37641		self.adjustPinSpacing = function (amount) {
37642		  if (spacerState && amount) {
37643			var i = spacerState.indexOf(direction.d) + 1;
37644			spacerState[i] = parseFloat(spacerState[i]) + amount + _px;
37645			spacerState[1] = parseFloat(spacerState[1]) + amount + _px;
37646  
37647			_setState(spacerState);
37648		  }
37649		};
37650  
37651		self.disable = function (reset, allowAnimation) {
37652		  if (self.enabled) {
37653			reset !== false && self.revert(true, true);
37654			self.enabled = self.isActive = false;
37655			allowAnimation || scrubTween && scrubTween.pause();
37656			prevScroll = 0;
37657			pinCache && (pinCache.uncache = 1);
37658			onRefreshInit && _removeListener$1(ScrollTrigger, "refreshInit", onRefreshInit);
37659  
37660			if (snapDelayedCall) {
37661			  snapDelayedCall.pause();
37662			  tweenTo.tween && tweenTo.tween.kill() && (tweenTo.tween = 0);
37663			}
37664  
37665			if (!isViewport) {
37666			  var i = _triggers.length;
37667  
37668			  while (i--) {
37669				if (_triggers[i].scroller === scroller && _triggers[i] !== self) {
37670				  return;
37671				}
37672			  }
37673  
37674			  _removeListener$1(scroller, "resize", _onResize);
37675  
37676			  isViewport || _removeListener$1(scroller, "scroll", _onScroll$1);
37677			}
37678		  }
37679		};
37680  
37681		self.kill = function (revert, allowAnimation) {
37682		  self.disable(revert, allowAnimation);
37683		  scrubTween && !allowAnimation && scrubTween.kill();
37684		  id && delete _ids[id];
37685  
37686		  var i = _triggers.indexOf(self);
37687  
37688		  i >= 0 && _triggers.splice(i, 1);
37689		  i === _i && _direction > 0 && _i--;
37690		  i = 0;
37691  
37692		  _triggers.forEach(function (t) {
37693			return t.scroller === self.scroller && (i = 1);
37694		  });
37695  
37696		  i || _refreshingAll || (self.scroll.rec = 0);
37697  
37698		  if (animation) {
37699			animation.scrollTrigger = null;
37700			revert && animation.revert({
37701			  kill: false
37702			});
37703			allowAnimation || animation.kill();
37704		  }
37705  
37706		  markerStart && [markerStart, markerEnd, markerStartTrigger, markerEndTrigger].forEach(function (m) {
37707			return m.parentNode && m.parentNode.removeChild(m);
37708		  });
37709		  _primary === self && (_primary = 0);
37710  
37711		  if (pin) {
37712			pinCache && (pinCache.uncache = 1);
37713			i = 0;
37714  
37715			_triggers.forEach(function (t) {
37716			  return t.pin === pin && i++;
37717			});
37718  
37719			i || (pinCache.spacer = 0);
37720		  }
37721  
37722		  vars.onKill && vars.onKill(self);
37723		};
37724  
37725		_triggers.push(self);
37726  
37727		self.enable(false, false);
37728		customRevertReturn && customRevertReturn(self);
37729  
37730		if (animation && animation.add && !change) {
37731		  var updateFunc = self.update;
37732  
37733		  self.update = function () {
37734			self.update = updateFunc;
37735			start || end || self.refresh();
37736		  };
37737  
37738		  gsap$1.delayedCall(0.01, self.update);
37739		  change = 0.01;
37740		  start = end = 0;
37741		} else {
37742		  self.refresh();
37743		}
37744  
37745		pin && _queueRefreshAll();
37746	  };
37747  
37748	  ScrollTrigger.register = function register(core) {
37749		if (!_coreInitted$1) {
37750		  gsap$1 = core || _getGSAP$1();
37751		  _windowExists() && window.document && ScrollTrigger.enable();
37752		  _coreInitted$1 = _enabled;
37753		}
37754  
37755		return _coreInitted$1;
37756	  };
37757  
37758	  ScrollTrigger.defaults = function defaults(config) {
37759		if (config) {
37760		  for (var p in config) {
37761			_defaults[p] = config[p];
37762		  }
37763		}
37764  
37765		return _defaults;
37766	  };
37767  
37768	  ScrollTrigger.disable = function disable(reset, kill) {
37769		_enabled = 0;
37770  
37771		_triggers.forEach(function (trigger) {
37772		  return trigger[kill ? "kill" : "disable"](reset);
37773		});
37774  
37775		_removeListener$1(_win$1, "wheel", _onScroll$1);
37776  
37777		_removeListener$1(_doc$1, "scroll", _onScroll$1);
37778  
37779		clearInterval(_syncInterval);
37780  
37781		_removeListener$1(_doc$1, "touchcancel", _passThrough);
37782  
37783		_removeListener$1(_body$1, "touchstart", _passThrough);
37784  
37785		_multiListener(_removeListener$1, _doc$1, "pointerdown,touchstart,mousedown", _pointerDownHandler);
37786  
37787		_multiListener(_removeListener$1, _doc$1, "pointerup,touchend,mouseup", _pointerUpHandler);
37788  
37789		_resizeDelay.kill();
37790  
37791		_iterateAutoRefresh(_removeListener$1);
37792  
37793		for (var i = 0; i < _scrollers.length; i += 3) {
37794		  _wheelListener(_removeListener$1, _scrollers[i], _scrollers[i + 1]);
37795  
37796		  _wheelListener(_removeListener$1, _scrollers[i], _scrollers[i + 2]);
37797		}
37798	  };
37799  
37800	  ScrollTrigger.enable = function enable() {
37801		_win$1 = window;
37802		_doc$1 = document;
37803		_docEl$1 = _doc$1.documentElement;
37804		_body$1 = _doc$1.body;
37805  
37806		if (gsap$1) {
37807		  _toArray = gsap$1.utils.toArray;
37808		  _clamp$1 = gsap$1.utils.clamp;
37809		  _context$1 = gsap$1.core.context || _passThrough;
37810		  _suppressOverwrites = gsap$1.core.suppressOverwrites || _passThrough;
37811		  _scrollRestoration = _win$1.history.scrollRestoration || "auto";
37812		  _lastScroll = _win$1.pageYOffset;
37813		  gsap$1.core.globals("ScrollTrigger", ScrollTrigger);
37814  
37815		  if (_body$1) {
37816			_enabled = 1;
37817			_div100vh = document.createElement("div");
37818			_div100vh.style.height = "100vh";
37819			_div100vh.style.position = "absolute";
37820  
37821			_refresh100vh();
37822  
37823			_rafBugFix();
37824  
37825			Observer.register(gsap$1);
37826			ScrollTrigger.isTouch = Observer.isTouch;
37827			_fixIOSBug = Observer.isTouch && /(iPad|iPhone|iPod|Mac)/g.test(navigator.userAgent);
37828			_ignoreMobileResize = Observer.isTouch === 1;
37829  
37830			_addListener$1(_win$1, "wheel", _onScroll$1);
37831  
37832			_root$1 = [_win$1, _doc$1, _docEl$1, _body$1];
37833  
37834			if (gsap$1.matchMedia) {
37835			  ScrollTrigger.matchMedia = function (vars) {
37836				var mm = gsap$1.matchMedia(),
37837					p;
37838  
37839				for (p in vars) {
37840				  mm.add(p, vars[p]);
37841				}
37842  
37843				return mm;
37844			  };
37845  
37846			  gsap$1.addEventListener("matchMediaInit", function () {
37847				return _revertAll();
37848			  });
37849			  gsap$1.addEventListener("matchMediaRevert", function () {
37850				return _revertRecorded();
37851			  });
37852			  gsap$1.addEventListener("matchMedia", function () {
37853				_refreshAll(0, 1);
37854  
37855				_dispatch("matchMedia");
37856			  });
37857			  gsap$1.matchMedia("(orientation: portrait)", function () {
37858				_setBaseDimensions();
37859  
37860				return _setBaseDimensions;
37861			  });
37862			} else {
37863			  console.warn("Requires GSAP 3.11.0 or later");
37864			}
37865  
37866			_setBaseDimensions();
37867  
37868			_addListener$1(_doc$1, "scroll", _onScroll$1);
37869  
37870			var bodyStyle = _body$1.style,
37871				border = bodyStyle.borderTopStyle,
37872				AnimationProto = gsap$1.core.Animation.prototype,
37873				bounds,
37874				i;
37875			AnimationProto.revert || Object.defineProperty(AnimationProto, "revert", {
37876			  value: function value() {
37877				return this.time(-0.01, true);
37878			  }
37879			});
37880			bodyStyle.borderTopStyle = "solid";
37881			bounds = _getBounds(_body$1);
37882			_vertical.m = Math.round(bounds.top + _vertical.sc()) || 0;
37883			_horizontal.m = Math.round(bounds.left + _horizontal.sc()) || 0;
37884			border ? bodyStyle.borderTopStyle = border : bodyStyle.removeProperty("border-top-style");
37885			_syncInterval = setInterval(_sync, 250);
37886			gsap$1.delayedCall(0.5, function () {
37887			  return _startup$1 = 0;
37888			});
37889  
37890			_addListener$1(_doc$1, "touchcancel", _passThrough);
37891  
37892			_addListener$1(_body$1, "touchstart", _passThrough);
37893  
37894			_multiListener(_addListener$1, _doc$1, "pointerdown,touchstart,mousedown", _pointerDownHandler);
37895  
37896			_multiListener(_addListener$1, _doc$1, "pointerup,touchend,mouseup", _pointerUpHandler);
37897  
37898			_transformProp = gsap$1.utils.checkPrefix("transform");
37899  
37900			_stateProps.push(_transformProp);
37901  
37902			_coreInitted$1 = _getTime$1();
37903			_resizeDelay = gsap$1.delayedCall(0.2, _refreshAll).pause();
37904			_autoRefresh = [_doc$1, "visibilitychange", function () {
37905			  var w = _win$1.innerWidth,
37906				  h = _win$1.innerHeight;
37907  
37908			  if (_doc$1.hidden) {
37909				_prevWidth = w;
37910				_prevHeight = h;
37911			  } else if (_prevWidth !== w || _prevHeight !== h) {
37912				_onResize();
37913			  }
37914			}, _doc$1, "DOMContentLoaded", _refreshAll, _win$1, "load", _refreshAll, _win$1, "resize", _onResize];
37915  
37916			_iterateAutoRefresh(_addListener$1);
37917  
37918			_triggers.forEach(function (trigger) {
37919			  return trigger.enable(0, 1);
37920			});
37921  
37922			for (i = 0; i < _scrollers.length; i += 3) {
37923			  _wheelListener(_removeListener$1, _scrollers[i], _scrollers[i + 1]);
37924  
37925			  _wheelListener(_removeListener$1, _scrollers[i], _scrollers[i + 2]);
37926			}
37927		  }
37928		}
37929	  };
37930  
37931	  ScrollTrigger.config = function config(vars) {
37932		"limitCallbacks" in vars && (_limitCallbacks = !!vars.limitCallbacks);
37933		var ms = vars.syncInterval;
37934		ms && clearInterval(_syncInterval) || (_syncInterval = ms) && setInterval(_sync, ms);
37935		"ignoreMobileResize" in vars && (_ignoreMobileResize = ScrollTrigger.isTouch === 1 && vars.ignoreMobileResize);
37936  
37937		if ("autoRefreshEvents" in vars) {
37938		  _iterateAutoRefresh(_removeListener$1) || _iterateAutoRefresh(_addListener$1, vars.autoRefreshEvents || "none");
37939		  _ignoreResize = (vars.autoRefreshEvents + "").indexOf("resize") === -1;
37940		}
37941	  };
37942  
37943	  ScrollTrigger.scrollerProxy = function scrollerProxy(target, vars) {
37944		var t = _getTarget(target),
37945			i = _scrollers.indexOf(t),
37946			isViewport = _isViewport$1(t);
37947  
37948		if (~i) {
37949		  _scrollers.splice(i, isViewport ? 6 : 2);
37950		}
37951  
37952		if (vars) {
37953		  isViewport ? _proxies.unshift(_win$1, vars, _body$1, vars, _docEl$1, vars) : _proxies.unshift(t, vars);
37954		}
37955	  };
37956  
37957	  ScrollTrigger.clearMatchMedia = function clearMatchMedia(query) {
37958		_triggers.forEach(function (t) {
37959		  return t._ctx && t._ctx.query === query && t._ctx.kill(true, true);
37960		});
37961	  };
37962  
37963	  ScrollTrigger.isInViewport = function isInViewport(element, ratio, horizontal) {
37964		var bounds = (_isString(element) ? _getTarget(element) : element).getBoundingClientRect(),
37965			offset = bounds[horizontal ? _width : _height] * ratio || 0;
37966		return horizontal ? bounds.right - offset > 0 && bounds.left + offset < _win$1.innerWidth : bounds.bottom - offset > 0 && bounds.top + offset < _win$1.innerHeight;
37967	  };
37968  
37969	  ScrollTrigger.positionInViewport = function positionInViewport(element, referencePoint, horizontal) {
37970		_isString(element) && (element = _getTarget(element));
37971		var bounds = element.getBoundingClientRect(),
37972			size = bounds[horizontal ? _width : _height],
37973			offset = referencePoint == null ? size / 2 : referencePoint in _keywords ? _keywords[referencePoint] * size : ~referencePoint.indexOf("%") ? parseFloat(referencePoint) * size / 100 : parseFloat(referencePoint) || 0;
37974		return horizontal ? (bounds.left + offset) / _win$1.innerWidth : (bounds.top + offset) / _win$1.innerHeight;
37975	  };
37976  
37977	  ScrollTrigger.killAll = function killAll(allowListeners) {
37978		_triggers.slice(0).forEach(function (t) {
37979		  return t.vars.id !== "ScrollSmoother" && t.kill();
37980		});
37981  
37982		if (allowListeners !== true) {
37983		  var listeners = _listeners.killAll || [];
37984		  _listeners = {};
37985		  listeners.forEach(function (f) {
37986			return f();
37987		  });
37988		}
37989	  };
37990  
37991	  return ScrollTrigger;
37992	}();
37993	ScrollTrigger$1.version = "3.12.5";
37994  
37995	ScrollTrigger$1.saveStyles = function (targets) {
37996	  return targets ? _toArray(targets).forEach(function (target) {
37997		if (target && target.style) {
37998		  var i = _savedStyles.indexOf(target);
37999  
38000		  i >= 0 && _savedStyles.splice(i, 5);
38001  
38002		  _savedStyles.push(target, target.style.cssText, target.getBBox && target.getAttribute("transform"), gsap$1.core.getCache(target), _context$1());
38003		}
38004	  }) : _savedStyles;
38005	};
38006  
38007	ScrollTrigger$1.revert = function (soft, media) {
38008	  return _revertAll(!soft, media);
38009	};
38010  
38011	ScrollTrigger$1.create = function (vars, animation) {
38012	  return new ScrollTrigger$1(vars, animation);
38013	};
38014  
38015	ScrollTrigger$1.refresh = function (safe) {
38016	  return safe ? _onResize() : (_coreInitted$1 || ScrollTrigger$1.register()) && _refreshAll(true);
38017	};
38018  
38019	ScrollTrigger$1.update = function (force) {
38020	  return ++_scrollers.cache && _updateAll(force === true ? 2 : 0);
38021	};
38022  
38023	ScrollTrigger$1.clearScrollMemory = _clearScrollMemory;
38024  
38025	ScrollTrigger$1.maxScroll = function (element, horizontal) {
38026	  return _maxScroll(element, horizontal ? _horizontal : _vertical);
38027	};
38028  
38029	ScrollTrigger$1.getScrollFunc = function (element, horizontal) {
38030	  return _getScrollFunc(_getTarget(element), horizontal ? _horizontal : _vertical);
38031	};
38032  
38033	ScrollTrigger$1.getById = function (id) {
38034	  return _ids[id];
38035	};
38036  
38037	ScrollTrigger$1.getAll = function () {
38038	  return _triggers.filter(function (t) {
38039		return t.vars.id !== "ScrollSmoother";
38040	  });
38041	};
38042  
38043	ScrollTrigger$1.isScrolling = function () {
38044	  return !!_lastScrollTime;
38045	};
38046  
38047	ScrollTrigger$1.snapDirectional = _snapDirectional;
38048  
38049	ScrollTrigger$1.addEventListener = function (type, callback) {
38050	  var a = _listeners[type] || (_listeners[type] = []);
38051	  ~a.indexOf(callback) || a.push(callback);
38052	};
38053  
38054	ScrollTrigger$1.removeEventListener = function (type, callback) {
38055	  var a = _listeners[type],
38056		  i = a && a.indexOf(callback);
38057	  i >= 0 && a.splice(i, 1);
38058	};
38059  
38060	ScrollTrigger$1.batch = function (targets, vars) {
38061	  var result = [],
38062		  varsCopy = {},
38063		  interval = vars.interval || 0.016,
38064		  batchMax = vars.batchMax || 1e9,
38065		  proxyCallback = function proxyCallback(type, callback) {
38066		var elements = [],
38067			triggers = [],
38068			delay = gsap$1.delayedCall(interval, function () {
38069		  callback(elements, triggers);
38070		  elements = [];
38071		  triggers = [];
38072		}).pause();
38073		return function (self) {
38074		  elements.length || delay.restart(true);
38075		  elements.push(self.trigger);
38076		  triggers.push(self);
38077		  batchMax <= elements.length && delay.progress(1);
38078		};
38079	  },
38080		  p;
38081  
38082	  for (p in vars) {
38083		varsCopy[p] = p.substr(0, 2) === "on" && _isFunction(vars[p]) && p !== "onRefreshInit" ? proxyCallback(p, vars[p]) : vars[p];
38084	  }
38085  
38086	  if (_isFunction(batchMax)) {
38087		batchMax = batchMax();
38088  
38089		_addListener$1(ScrollTrigger$1, "refresh", function () {
38090		  return batchMax = vars.batchMax();
38091		});
38092	  }
38093  
38094	  _toArray(targets).forEach(function (target) {
38095		var config = {};
38096  
38097		for (p in varsCopy) {
38098		  config[p] = varsCopy[p];
38099		}
38100  
38101		config.trigger = target;
38102		result.push(ScrollTrigger$1.create(config));
38103	  });
38104  
38105	  return result;
38106	};
38107  
38108	var _clampScrollAndGetDurationMultiplier = function _clampScrollAndGetDurationMultiplier(scrollFunc, current, end, max) {
38109	  current > max ? scrollFunc(max) : current < 0 && scrollFunc(0);
38110	  return end > max ? (max - current) / (end - current) : end < 0 ? current / (current - end) : 1;
38111	},
38112		_allowNativePanning = function _allowNativePanning(target, direction) {
38113	  if (direction === true) {
38114		target.style.removeProperty("touch-action");
38115	  } else {
38116		target.style.touchAction = direction === true ? "auto" : direction ? "pan-" + direction + (Observer.isTouch ? " pinch-zoom" : "") : "none";
38117	  }
38118  
38119	  target === _docEl$1 && _allowNativePanning(_body$1, direction);
38120	},
38121		_overflow = {
38122	  auto: 1,
38123	  scroll: 1
38124	},
38125		_nestedScroll = function _nestedScroll(_ref5) {
38126	  var event = _ref5.event,
38127		  target = _ref5.target,
38128		  axis = _ref5.axis;
38129  
38130	  var node = (event.changedTouches ? event.changedTouches[0] : event).target,
38131		  cache = node._gsap || gsap$1.core.getCache(node),
38132		  time = _getTime$1(),
38133		  cs;
38134  
38135	  if (!cache._isScrollT || time - cache._isScrollT > 2000) {
38136		while (node && node !== _body$1 && (node.scrollHeight <= node.clientHeight && node.scrollWidth <= node.clientWidth || !(_overflow[(cs = _getComputedStyle(node)).overflowY] || _overflow[cs.overflowX]))) {
38137		  node = node.parentNode;
38138		}
38139  
38140		cache._isScroll = node && node !== target && !_isViewport$1(node) && (_overflow[(cs = _getComputedStyle(node)).overflowY] || _overflow[cs.overflowX]);
38141		cache._isScrollT = time;
38142	  }
38143  
38144	  if (cache._isScroll || axis === "x") {
38145		event.stopPropagation();
38146		event._gsapAllow = true;
38147	  }
38148	},
38149		_inputObserver = function _inputObserver(target, type, inputs, nested) {
38150	  return Observer.create({
38151		target: target,
38152		capture: true,
38153		debounce: false,
38154		lockAxis: true,
38155		type: type,
38156		onWheel: nested = nested && _nestedScroll,
38157		onPress: nested,
38158		onDrag: nested,
38159		onScroll: nested,
38160		onEnable: function onEnable() {
38161		  return inputs && _addListener$1(_doc$1, Observer.eventTypes[0], _captureInputs, false, true);
38162		},
38163		onDisable: function onDisable() {
38164		  return _removeListener$1(_doc$1, Observer.eventTypes[0], _captureInputs, true);
38165		}
38166	  });
38167	},
38168		_inputExp = /(input|label|select|textarea)/i,
38169		_inputIsFocused,
38170		_captureInputs = function _captureInputs(e) {
38171	  var isInput = _inputExp.test(e.target.tagName);
38172  
38173	  if (isInput || _inputIsFocused) {
38174		e._gsapAllow = true;
38175		_inputIsFocused = isInput;
38176	  }
38177	},
38178		_getScrollNormalizer = function _getScrollNormalizer(vars) {
38179	  _isObject(vars) || (vars = {});
38180	  vars.preventDefault = vars.isNormalizer = vars.allowClicks = true;
38181	  vars.type || (vars.type = "wheel,touch");
38182	  vars.debounce = !!vars.debounce;
38183	  vars.id = vars.id || "normalizer";
38184  
38185	  var _vars2 = vars,
38186		  normalizeScrollX = _vars2.normalizeScrollX,
38187		  momentum = _vars2.momentum,
38188		  allowNestedScroll = _vars2.allowNestedScroll,
38189		  onRelease = _vars2.onRelease,
38190		  self,
38191		  maxY,
38192		  target = _getTarget(vars.target) || _docEl$1,
38193		  smoother = gsap$1.core.globals().ScrollSmoother,
38194		  smootherInstance = smoother && smoother.get(),
38195		  content = _fixIOSBug && (vars.content && _getTarget(vars.content) || smootherInstance && vars.content !== false && !smootherInstance.smooth() && smootherInstance.content()),
38196		  scrollFuncY = _getScrollFunc(target, _vertical),
38197		  scrollFuncX = _getScrollFunc(target, _horizontal),
38198		  scale = 1,
vendor: 4,132 bytes, lines 38199-38320
38199		  initialScale = (Observer.isTouch && _win$1.visualViewport ? _win$1.visualViewport.scale * _win$1.visualViewport.width : _win$1.outerWidth) / _win$1.innerWidth,
38200		  wheelRefresh = 0,
38201		  resolveMomentumDuration = _isFunction(momentum) ? function () {
38202		return momentum(self);
38203	  } : function () {
38204		return momentum || 2.8;
38205	  },
38206		  lastRefreshID,
38207		  skipTouchMove,
38208		  inputObserver = _inputObserver(target, vars.type, true, allowNestedScroll),
38209		  resumeTouchMove = function resumeTouchMove() {
38210		return skipTouchMove = false;
38211	  },
38212		  scrollClampX = _passThrough,
38213		  scrollClampY = _passThrough,
38214		  updateClamps = function updateClamps() {
38215		maxY = _maxScroll(target, _vertical);
38216		scrollClampY = _clamp$1(_fixIOSBug ? 1 : 0, maxY);
38217		normalizeScrollX && (scrollClampX = _clamp$1(0, _maxScroll(target, _horizontal)));
38218		lastRefreshID = _refreshID;
38219	  },
38220		  removeContentOffset = function removeContentOffset() {
38221		content._gsap.y = _round(parseFloat(content._gsap.y) + scrollFuncY.offset) + "px";
38222		content.style.transform = "matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, " + parseFloat(content._gsap.y) + ", 0, 1)";
38223		scrollFuncY.offset = scrollFuncY.cacheID = 0;
38224	  },
38225		  ignoreDrag = function ignoreDrag() {
38226		if (skipTouchMove) {
38227		  requestAnimationFrame(resumeTouchMove);
38228  
38229		  var offset = _round(self.deltaY / 2),
38230			  scroll = scrollClampY(scrollFuncY.v - offset);
38231  
38232		  if (content && scroll !== scrollFuncY.v + scrollFuncY.offset) {
38233			scrollFuncY.offset = scroll - scrollFuncY.v;
38234  
38235			var y = _round((parseFloat(content && content._gsap.y) || 0) - scrollFuncY.offset);
38236  
38237			content.style.transform = "matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, " + y + ", 0, 1)";
38238			content._gsap.y = y + "px";
38239			scrollFuncY.cacheID = _scrollers.cache;
38240  
38241			_updateAll();
38242		  }
38243  
38244		  return true;
38245		}
38246  
38247		scrollFuncY.offset && removeContentOffset();
38248		skipTouchMove = true;
38249	  },
38250		  tween,
38251		  startScrollX,
38252		  startScrollY,
38253		  onStopDelayedCall,
38254		  onResize = function onResize() {
38255		updateClamps();
38256  
38257		if (tween.isActive() && tween.vars.scrollY > maxY) {
38258		  scrollFuncY() > maxY ? tween.progress(1) && scrollFuncY(maxY) : tween.resetTo("scrollY", maxY);
38259		}
38260	  };
38261  
38262	  content && gsap$1.set(content, {
38263		y: "+=0"
38264	  });
38265  
38266	  vars.ignoreCheck = function (e) {
38267		return _fixIOSBug && e.type === "touchmove" && ignoreDrag() || scale > 1.05 && e.type !== "touchstart" || self.isGesturing || e.touches && e.touches.length > 1;
38268	  };
38269  
38270	  vars.onPress = function () {
38271		skipTouchMove = false;
38272		var prevScale = scale;
38273		scale = _round((_win$1.visualViewport && _win$1.visualViewport.scale || 1) / initialScale);
38274		tween.pause();
38275		prevScale !== scale && _allowNativePanning(target, scale > 1.01 ? true : normalizeScrollX ? false : "x");
38276		startScrollX = scrollFuncX();
38277		startScrollY = scrollFuncY();
38278		updateClamps();
38279		lastRefreshID = _refreshID;
38280	  };
38281  
38282	  vars.onRelease = vars.onGestureStart = function (self, wasDragging) {
38283		scrollFuncY.offset && removeContentOffset();
38284  
38285		if (!wasDragging) {
38286		  onStopDelayedCall.restart(true);
38287		} else {
38288		  _scrollers.cache++;
38289		  var dur = resolveMomentumDuration(),
38290			  currentScroll,
38291			  endScroll;
38292  
38293		  if (normalizeScrollX) {
38294			currentScroll = scrollFuncX();
38295			endScroll = currentScroll + dur * 0.05 * -self.velocityX / 0.227;
38296			dur *= _clampScrollAndGetDurationMultiplier(scrollFuncX, currentScroll, endScroll, _maxScroll(target, _horizontal));
38297			tween.vars.scrollX = scrollClampX(endScroll);
38298		  }
38299  
38300		  currentScroll = scrollFuncY();
38301		  endScroll = currentScroll + dur * 0.05 * -self.velocityY / 0.227;
38302		  dur *= _clampScrollAndGetDurationMultiplier(scrollFuncY, currentScroll, endScroll, _maxScroll(target, _vertical));
38303		  tween.vars.scrollY = scrollClampY(endScroll);
38304		  tween.invalidate().duration(dur).play(0.01);
38305  
38306		  if (_fixIOSBug && tween.vars.scrollY >= maxY || currentScroll >= maxY - 1) {
38307			gsap$1.to({}, {
38308			  onUpdate: onResize,
38309			  duration: dur
38310			});
38311		  }
38312		}
38313  
38314		onRelease && onRelease(self);
38315	  };
38316  
38317	  vars.onWheel = function () {
38318		tween._ts && tween.pause();
38319  
38320		if (_getTime$1() - wheelRefresh > 1000) {
vendor: 28,617 bytes, lines 38321-39375
38321		  lastRefreshID = 0;
38322		  wheelRefresh = _getTime$1();
38323		}
38324	  };
38325  
38326	  vars.onChange = function (self, dx, dy, xArray, yArray) {
38327		_refreshID !== lastRefreshID && updateClamps();
38328		dx && normalizeScrollX && scrollFuncX(scrollClampX(xArray[2] === dx ? startScrollX + (self.startX - self.x) : scrollFuncX() + dx - xArray[1]));
38329  
38330		if (dy) {
38331		  scrollFuncY.offset && removeContentOffset();
38332		  var isTouch = yArray[2] === dy,
38333			  y = isTouch ? startScrollY + self.startY - self.y : scrollFuncY() + dy - yArray[1],
38334			  yClamped = scrollClampY(y);
38335		  isTouch && y !== yClamped && (startScrollY += yClamped - y);
38336		  scrollFuncY(yClamped);
38337		}
38338  
38339		(dy || dx) && _updateAll();
38340	  };
38341  
38342	  vars.onEnable = function () {
38343		_allowNativePanning(target, normalizeScrollX ? false : "x");
38344  
38345		ScrollTrigger$1.addEventListener("refresh", onResize);
38346  
38347		_addListener$1(_win$1, "resize", onResize);
38348  
38349		if (scrollFuncY.smooth) {
38350		  scrollFuncY.target.style.scrollBehavior = "auto";
38351		  scrollFuncY.smooth = scrollFuncX.smooth = false;
38352		}
38353  
38354		inputObserver.enable();
38355	  };
38356  
38357	  vars.onDisable = function () {
38358		_allowNativePanning(target, true);
38359  
38360		_removeListener$1(_win$1, "resize", onResize);
38361  
38362		ScrollTrigger$1.removeEventListener("refresh", onResize);
38363		inputObserver.kill();
38364	  };
38365  
38366	  vars.lockAxis = vars.lockAxis !== false;
38367	  self = new Observer(vars);
38368	  self.iOS = _fixIOSBug;
38369	  _fixIOSBug && !scrollFuncY() && scrollFuncY(1);
38370	  _fixIOSBug && gsap$1.ticker.add(_passThrough);
38371	  onStopDelayedCall = self._dc;
38372	  tween = gsap$1.to(self, {
38373		ease: "power4",
38374		paused: true,
38375		inherit: false,
38376		scrollX: normalizeScrollX ? "+=0.1" : "+=0",
38377		scrollY: "+=0.1",
38378		modifiers: {
38379		  scrollY: _interruptionTracker(scrollFuncY, scrollFuncY(), function () {
38380			return tween.pause();
38381		  })
38382		},
38383		onUpdate: _updateAll,
38384		onComplete: onStopDelayedCall.vars.onComplete
38385	  });
38386	  return self;
38387	};
38388  
38389	ScrollTrigger$1.sort = function (func) {
38390	  return _triggers.sort(func || function (a, b) {
38391		return (a.vars.refreshPriority || 0) * -1e6 + a.start - (b.start + (b.vars.refreshPriority || 0) * -1e6);
38392	  });
38393	};
38394  
38395	ScrollTrigger$1.observe = function (vars) {
38396	  return new Observer(vars);
38397	};
38398  
38399	ScrollTrigger$1.normalizeScroll = function (vars) {
38400	  if (typeof vars === "undefined") {
38401		return _normalizer$1;
38402	  }
38403  
38404	  if (vars === true && _normalizer$1) {
38405		return _normalizer$1.enable();
38406	  }
38407  
38408	  if (vars === false) {
38409		_normalizer$1 && _normalizer$1.kill();
38410		_normalizer$1 = vars;
38411		return;
38412	  }
38413  
38414	  var normalizer = vars instanceof Observer ? vars : _getScrollNormalizer(vars);
38415	  _normalizer$1 && _normalizer$1.target === normalizer.target && _normalizer$1.kill();
38416	  _isViewport$1(normalizer.target) && (_normalizer$1 = normalizer);
38417	  return normalizer;
38418	};
38419  
38420	ScrollTrigger$1.core = {
38421	  _getVelocityProp: _getVelocityProp,
38422	  _inputObserver: _inputObserver,
38423	  _scrollers: _scrollers,
38424	  _proxies: _proxies,
38425	  bridge: {
38426		ss: function ss() {
38427		  _lastScrollTime || _dispatch("scrollStart");
38428		  _lastScrollTime = _getTime$1();
38429		},
38430		ref: function ref() {
38431		  return _refreshing;
38432		}
38433	  }
38434	};
38435	_getGSAP$1() && gsap$1.registerPlugin(ScrollTrigger$1);
38436  
38437	exports.ScrollTrigger = ScrollTrigger$1;
38438	exports.default = ScrollTrigger$1;
38439  
38440	if (typeof(window) === 'undefined' || window !== exports) {Object.defineProperty(exports, '__esModule', { value: true });} else {delete window.default;}
38441  
38442  })));
38443
38444/*!
38445 * CustomEase 3.12.7
38446 * https://gsap.com
38447 * 
38448 * @license Copyright 2025, GreenSock. All rights reserved.
38449 * Subject to the terms at https://gsap.com/standard-license or for Club GSAP members, the agreement issued with that membership.
38450 * @author: Jack Doyle, [email protected]
38451 */
38452
38453  (function (global, factory) {
38454	typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
38455	typeof define === 'function' && define.amd ? define(['exports'], factory) :
38456	(global = global || self, factory(global.window = global.window || {}));
38457}(this, (function (exports) { 'use strict';
38458
38459	var _svgPathExp = /[achlmqstvz]|(-?\d*\.?\d*(?:e[\-+]?\d+)?)[0-9]/ig,
38460	    _scientific = /[\+\-]?\d*\.?\d+e[\+\-]?\d+/ig,
38461	    _DEG2RAD = Math.PI / 180,
38462	    _sin = Math.sin,
38463	    _cos = Math.cos,
38464	    _abs = Math.abs,
38465	    _sqrt = Math.sqrt,
38466	    _isNumber = function _isNumber(value) {
38467	  return typeof value === "number";
38468	},
38469	    _roundingNum = 1e5,
38470	    _round = function _round(value) {
38471	  return Math.round(value * _roundingNum) / _roundingNum || 0;
38472	};
38473	function transformRawPath(rawPath, a, b, c, d, tx, ty) {
38474	  var j = rawPath.length,
38475	      segment,
38476	      l,
38477	      i,
38478	      x,
38479	      y;
38480
38481	  while (--j > -1) {
38482	    segment = rawPath[j];
38483	    l = segment.length;
38484
38485	    for (i = 0; i < l; i += 2) {
38486	      x = segment[i];
38487	      y = segment[i + 1];
38488	      segment[i] = x * a + y * c + tx;
38489	      segment[i + 1] = x * b + y * d + ty;
38490	    }
38491	  }
38492
38493	  rawPath._dirty = 1;
38494	  return rawPath;
38495	}
38496
38497	function arcToSegment(lastX, lastY, rx, ry, angle, largeArcFlag, sweepFlag, x, y) {
38498	  if (lastX === x && lastY === y) {
38499	    return;
38500	  }
38501
38502	  rx = _abs(rx);
38503	  ry = _abs(ry);
38504
38505	  var angleRad = angle % 360 * _DEG2RAD,
38506	      cosAngle = _cos(angleRad),
38507	      sinAngle = _sin(angleRad),
38508	      PI = Math.PI,
38509	      TWOPI = PI * 2,
38510	      dx2 = (lastX - x) / 2,
38511	      dy2 = (lastY - y) / 2,
38512	      x1 = cosAngle * dx2 + sinAngle * dy2,
38513	      y1 = -sinAngle * dx2 + cosAngle * dy2,
38514	      x1_sq = x1 * x1,
38515	      y1_sq = y1 * y1,
38516	      radiiCheck = x1_sq / (rx * rx) + y1_sq / (ry * ry);
38517
38518	  if (radiiCheck > 1) {
38519	    rx = _sqrt(radiiCheck) * rx;
38520	    ry = _sqrt(radiiCheck) * ry;
38521	  }
38522
38523	  var rx_sq = rx * rx,
38524	      ry_sq = ry * ry,
38525	      sq = (rx_sq * ry_sq - rx_sq * y1_sq - ry_sq * x1_sq) / (rx_sq * y1_sq + ry_sq * x1_sq);
38526
38527	  if (sq < 0) {
38528	    sq = 0;
38529	  }
38530
38531	  var coef = (largeArcFlag === sweepFlag ? -1 : 1) * _sqrt(sq),
38532	      cx1 = coef * (rx * y1 / ry),
38533	      cy1 = coef * -(ry * x1 / rx),
38534	      sx2 = (lastX + x) / 2,
38535	      sy2 = (lastY + y) / 2,
38536	      cx = sx2 + (cosAngle * cx1 - sinAngle * cy1),
38537	      cy = sy2 + (sinAngle * cx1 + cosAngle * cy1),
38538	      ux = (x1 - cx1) / rx,
38539	      uy = (y1 - cy1) / ry,
38540	      vx = (-x1 - cx1) / rx,
38541	      vy = (-y1 - cy1) / ry,
38542	      temp = ux * ux + uy * uy,
38543	      angleStart = (uy < 0 ? -1 : 1) * Math.acos(ux / _sqrt(temp)),
38544	      angleExtent = (ux * vy - uy * vx < 0 ? -1 : 1) * Math.acos((ux * vx + uy * vy) / _sqrt(temp * (vx * vx + vy * vy)));
38545
38546	  isNaN(angleExtent) && (angleExtent = PI);
38547
38548	  if (!sweepFlag && angleExtent > 0) {
38549	    angleExtent -= TWOPI;
38550	  } else if (sweepFlag && angleExtent < 0) {
38551	    angleExtent += TWOPI;
38552	  }
38553
38554	  angleStart %= TWOPI;
38555	  angleExtent %= TWOPI;
38556
38557	  var segments = Math.ceil(_abs(angleExtent) / (TWOPI / 4)),
38558	      rawPath = [],
38559	      angleIncrement = angleExtent / segments,
38560	      controlLength = 4 / 3 * _sin(angleIncrement / 2) / (1 + _cos(angleIncrement / 2)),
38561	      ma = cosAngle * rx,
38562	      mb = sinAngle * rx,
38563	      mc = sinAngle * -ry,
38564	      md = cosAngle * ry,
38565	      i;
38566
38567	  for (i = 0; i < segments; i++) {
38568	    angle = angleStart + i * angleIncrement;
38569	    x1 = _cos(angle);
38570	    y1 = _sin(angle);
38571	    ux = _cos(angle += angleIncrement);
38572	    uy = _sin(angle);
38573	    rawPath.push(x1 - controlLength * y1, y1 + controlLength * x1, ux + controlLength * uy, uy - controlLength * ux, ux, uy);
38574	  }
38575
38576	  for (i = 0; i < rawPath.length; i += 2) {
38577	    x1 = rawPath[i];
38578	    y1 = rawPath[i + 1];
38579	    rawPath[i] = x1 * ma + y1 * mc + cx;
38580	    rawPath[i + 1] = x1 * mb + y1 * md + cy;
38581	  }
38582
38583	  rawPath[i - 2] = x;
38584	  rawPath[i - 1] = y;
38585	  return rawPath;
38586	}
38587
38588	function stringToRawPath(d) {
38589	  var a = (d + "").replace(_scientific, function (m) {
38590	    var n = +m;
38591	    return n < 0.0001 && n > -0.0001 ? 0 : n;
38592	  }).match(_svgPathExp) || [],
38593	      path = [],
38594	      relativeX = 0,
38595	      relativeY = 0,
38596	      twoThirds = 2 / 3,
38597	      elements = a.length,
38598	      points = 0,
38599	      errorMessage = "ERROR: malformed path: " + d,
38600	      i,
38601	      j,
38602	      x,
38603	      y,
38604	      command,
38605	      isRelative,
38606	      segment,
38607	      startX,
38608	      startY,
38609	      difX,
38610	      difY,
38611	      beziers,
38612	      prevCommand,
38613	      flag1,
38614	      flag2,
38615	      line = function line(sx, sy, ex, ey) {
38616	    difX = (ex - sx) / 3;
38617	    difY = (ey - sy) / 3;
38618	    segment.push(sx + difX, sy + difY, ex - difX, ey - difY, ex, ey);
38619	  };
38620
38621	  if (!d || !isNaN(a[0]) || isNaN(a[1])) {
38622	    console.log(errorMessage);
38623	    return path;
38624	  }
38625
38626	  for (i = 0; i < elements; i++) {
38627	    prevCommand = command;
38628
38629	    if (isNaN(a[i])) {
38630	      command = a[i].toUpperCase();
38631	      isRelative = command !== a[i];
38632	    } else {
38633	      i--;
38634	    }
38635
38636	    x = +a[i + 1];
38637	    y = +a[i + 2];
38638
38639	    if (isRelative) {
38640	      x += relativeX;
38641	      y += relativeY;
38642	    }
38643
38644	    if (!i) {
38645	      startX = x;
38646	      startY = y;
38647	    }
38648
38649	    if (command === "M") {
38650	      if (segment) {
38651	        if (segment.length < 8) {
38652	          path.length -= 1;
38653	        } else {
38654	          points += segment.length;
38655	        }
38656	      }
38657
38658	      relativeX = startX = x;
38659	      relativeY = startY = y;
38660	      segment = [x, y];
38661	      path.push(segment);
38662	      i += 2;
38663	      command = "L";
38664	    } else if (command === "C") {
38665	      if (!segment) {
38666	        segment = [0, 0];
38667	      }
38668
38669	      if (!isRelative) {
38670	        relativeX = relativeY = 0;
38671	      }
38672
38673	      segment.push(x, y, relativeX + a[i + 3] * 1, relativeY + a[i + 4] * 1, relativeX += a[i + 5] * 1, relativeY += a[i + 6] * 1);
38674	      i += 6;
38675	    } else if (command === "S") {
38676	      difX = relativeX;
38677	      difY = relativeY;
38678
38679	      if (prevCommand === "C" || prevCommand === "S") {
38680	        difX += relativeX - segment[segment.length - 4];
38681	        difY += relativeY - segment[segment.length - 3];
38682	      }
38683
38684	      if (!isRelative) {
38685	        relativeX = relativeY = 0;
38686	      }
38687
38688	      segment.push(difX, difY, x, y, relativeX += a[i + 3] * 1, relativeY += a[i + 4] * 1);
38689	      i += 4;
38690	    } else if (command === "Q") {
38691	      difX = relativeX + (x - relativeX) * twoThirds;
38692	      difY = relativeY + (y - relativeY) * twoThirds;
38693
38694	      if (!isRelative) {
38695	        relativeX = relativeY = 0;
38696	      }
38697
38698	      relativeX += a[i + 3] * 1;
38699	      relativeY += a[i + 4] * 1;
38700	      segment.push(difX, difY, relativeX + (x - relativeX) * twoThirds, relativeY + (y - relativeY) * twoThirds, relativeX, relativeY);
38701	      i += 4;
38702	    } else if (command === "T") {
38703	      difX = relativeX - segment[segment.length - 4];
38704	      difY = relativeY - segment[segment.length - 3];
38705	      segment.push(relativeX + difX, relativeY + difY, x + (relativeX + difX * 1.5 - x) * twoThirds, y + (relativeY + difY * 1.5 - y) * twoThirds, relativeX = x, relativeY = y);
38706	      i += 2;
38707	    } else if (command === "H") {
38708	      line(relativeX, relativeY, relativeX = x, relativeY);
38709	      i += 1;
38710	    } else if (command === "V") {
38711	      line(relativeX, relativeY, relativeX, relativeY = x + (isRelative ? relativeY - relativeX : 0));
38712	      i += 1;
38713	    } else if (command === "L" || command === "Z") {
38714	      if (command === "Z") {
38715	        x = startX;
38716	        y = startY;
38717	        segment.closed = true;
38718	      }
38719
38720	      if (command === "L" || _abs(relativeX - x) > 0.5 || _abs(relativeY - y) > 0.5) {
38721	        line(relativeX, relativeY, x, y);
38722
38723	        if (command === "L") {
38724	          i += 2;
38725	        }
38726	      }
38727
38728	      relativeX = x;
38729	      relativeY = y;
38730	    } else if (command === "A") {
38731	      flag1 = a[i + 4];
38732	      flag2 = a[i + 5];
38733	      difX = a[i + 6];
38734	      difY = a[i + 7];
38735	      j = 7;
38736
38737	      if (flag1.length > 1) {
38738	        if (flag1.length < 3) {
38739	          difY = difX;
38740	          difX = flag2;
38741	          j--;
38742	        } else {
38743	          difY = flag2;
38744	          difX = flag1.substr(2);
38745	          j -= 2;
38746	        }
38747
38748	        flag2 = flag1.charAt(1);
38749	        flag1 = flag1.charAt(0);
38750	      }
38751
38752	      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);
38753	      i += j;
38754
38755	      if (beziers) {
38756	        for (j = 0; j < beziers.length; j++) {
38757	          segment.push(beziers[j]);
38758	        }
38759	      }
38760
38761	      relativeX = segment[segment.length - 2];
38762	      relativeY = segment[segment.length - 1];
38763	    } else {
38764	      console.log(errorMessage);
38765	    }
38766	  }
38767
38768	  i = segment.length;
38769
38770	  if (i < 6) {
38771	    path.pop();
38772	    i = 0;
38773	  } else if (segment[0] === segment[i - 2] && segment[1] === segment[i - 1]) {
38774	    segment.closed = true;
38775	  }
38776
38777	  path.totalPoints = points + i;
38778	  return path;
38779	}
38780	function rawPathToString(rawPath) {
38781	  if (_isNumber(rawPath[0])) {
38782	    rawPath = [rawPath];
38783	  }
38784
38785	  var result = "",
38786	      l = rawPath.length,
38787	      sl,
38788	      s,
38789	      i,
38790	      segment;
38791
38792	  for (s = 0; s < l; s++) {
38793	    segment = rawPath[s];
38794	    result += "M" + _round(segment[0]) + "," + _round(segment[1]) + " C";
38795	    sl = segment.length;
38796
38797	    for (i = 2; i < sl; i++) {
38798	      result += _round(segment[i++]) + "," + _round(segment[i++]) + " " + _round(segment[i++]) + "," + _round(segment[i++]) + " " + _round(segment[i++]) + "," + _round(segment[i]) + " ";
38799	    }
38800
38801	    if (segment.closed) {
38802	      result += "z";
38803	    }
38804	  }
38805
38806	  return result;
38807	}
38808
38809	/*!
38810	 * CustomEase 3.12.7
38811	 * https://gsap.com
38812	 *
38813	 * @license Copyright 2008-2025, GreenSock. All rights reserved.
38814	 * Subject to the terms at https://gsap.com/standard-license or for
38815	 * Club GSAP members, the agreement issued with that membership.
38816	 * @author: Jack Doyle, [email protected]
38817	*/
38818
38819	var gsap,
38820	    _coreInitted,
38821	    _getGSAP = function _getGSAP() {
38822	  return gsap || typeof window !== "undefined" && (gsap = window.gsap) && gsap.registerPlugin && gsap;
38823	},
38824	    _initCore = function _initCore() {
38825	  gsap = _getGSAP();
38826
38827	  if (gsap) {
38828	    gsap.registerEase("_CE", CustomEase.create);
38829	    _coreInitted = 1;
38830	  } else {
38831	    console.warn("Please gsap.registerPlugin(CustomEase)");
38832	  }
38833	},
38834	    _bigNum = 1e20,
38835	    _round$1 = function _round(value) {
38836	  return ~~(value * 1000 + (value < 0 ? -.5 : .5)) / 1000;
38837	},
38838	    _numExp = /[-+=.]*\d+[.e\-+]*\d*[e\-+]*\d*/gi,
38839	    _needsParsingExp = /[cLlsSaAhHvVtTqQ]/g,
38840	    _findMinimum = function _findMinimum(values) {
38841	  var l = values.length,
38842	      min = _bigNum,
38843	      i;
38844
38845	  for (i = 1; i < l; i += 6) {
38846	    +values[i] < min && (min = +values[i]);
38847	  }
38848
38849	  return min;
38850	},
38851	    _normalize = function _normalize(values, height, originY) {
38852	  if (!originY && originY !== 0) {
38853	    originY = Math.max(+values[values.length - 1], +values[1]);
38854	  }
38855
38856	  var tx = +values[0] * -1,
38857	      ty = -originY,
38858	      l = values.length,
38859	      sx = 1 / (+values[l - 2] + tx),
38860	      sy = -height || (Math.abs(+values[l - 1] - +values[1]) < 0.01 * (+values[l - 2] - +values[0]) ? _findMinimum(values) + ty : +values[l - 1] + ty),
38861	      i;
38862
38863	  if (sy) {
38864	    sy = 1 / sy;
38865	  } else {
38866	    sy = -sx;
38867	  }
38868
38869	  for (i = 0; i < l; i += 2) {
38870	    values[i] = (+values[i] + tx) * sx;
38871	    values[i + 1] = (+values[i + 1] + ty) * sy;
38872	  }
38873	},
38874	    _bezierToPoints = function _bezierToPoints(x1, y1, x2, y2, x3, y3, x4, y4, threshold, points, index) {
38875	  var x12 = (x1 + x2) / 2,
38876	      y12 = (y1 + y2) / 2,
38877	      x23 = (x2 + x3) / 2,
38878	      y23 = (y2 + y3) / 2,
38879	      x34 = (x3 + x4) / 2,
38880	      y34 = (y3 + y4) / 2,
38881	      x123 = (x12 + x23) / 2,
38882	      y123 = (y12 + y23) / 2,
38883	      x234 = (x23 + x34) / 2,
38884	      y234 = (y23 + y34) / 2,
38885	      x1234 = (x123 + x234) / 2,
38886	      y1234 = (y123 + y234) / 2,
38887	      dx = x4 - x1,
38888	      dy = y4 - y1,
38889	      d2 = Math.abs((x2 - x4) * dy - (y2 - y4) * dx),
38890	      d3 = Math.abs((x3 - x4) * dy - (y3 - y4) * dx),
38891	      length;
38892
38893	  if (!points) {
38894	    points = [{
38895	      x: x1,
38896	      y: y1
38897	    }, {
38898	      x: x4,
38899	      y: y4
38900	    }];
38901	    index = 1;
38902	  }
38903
38904	  points.splice(index || points.length - 1, 0, {
38905	    x: x1234,
38906	    y: y1234
38907	  });
38908
38909	  if ((d2 + d3) * (d2 + d3) > threshold * (dx * dx + dy * dy)) {
38910	    length = points.length;
38911
38912	    _bezierToPoints(x1, y1, x12, y12, x123, y123, x1234, y1234, threshold, points, index);
38913
38914	    _bezierToPoints(x1234, y1234, x234, y234, x34, y34, x4, y4, threshold, points, index + 1 + (points.length - length));
38915	  }
38916
38917	  return points;
38918	};
38919
38920	var CustomEase = function () {
38921	  function CustomEase(id, data, config) {
38922	    _coreInitted || _initCore();
38923	    this.id = id;
38924	     this.setData(data, config);
38925	  }
38926
38927	  var _proto = CustomEase.prototype;
38928
38929	  _proto.setData = function setData(data, config) {
38930	    config = config || {};
38931	    data = data || "0,0,1,1";
38932	    var values = data.match(_numExp),
38933	        closest = 1,
38934	        points = [],
38935	        lookup = [],
38936	        precision = config.precision || 1,
38937	        fast = precision <= 1,
38938	        l,
38939	        a1,
38940	        a2,
38941	        i,
38942	        inc,
38943	        j,
38944	        point,
38945	        prevPoint,
38946	        p;
38947	    this.data = data;
38948
38949	    if (_needsParsingExp.test(data) || ~data.indexOf("M") && data.indexOf("C") < 0) {
38950	      values = stringToRawPath(data)[0];
38951	    }
38952
38953	    l = values.length;
38954
38955	    if (l === 4) {
38956	      values.unshift(0, 0);
38957	      values.push(1, 1);
38958	      l = 8;
38959	    } else if ((l - 2) % 6) {
38960	      throw "Invalid CustomEase";
38961	    }
38962
38963	    if (+values[0] !== 0 || +values[l - 2] !== 1) {
38964	      _normalize(values, config.height, config.originY);
38965	    }
38966
38967	    this.segment = values;
38968
38969	    for (i = 2; i < l; i += 6) {
38970	      a1 = {
38971	        x: +values[i - 2],
38972	        y: +values[i - 1]
38973	      };
38974	      a2 = {
38975	        x: +values[i + 4],
38976	        y: +values[i + 5]
38977	      };
38978	      points.push(a1, a2);
38979
38980	      _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);
38981	    }
38982
38983	    l = points.length;
38984
38985	    for (i = 0; i < l; i++) {
38986	      point = points[i];
38987	      prevPoint = points[i - 1] || point;
38988
38989	      if ((point.x > prevPoint.x || prevPoint.y !== point.y && prevPoint.x === point.x || point === prevPoint) && point.x <= 1) {
38990	        prevPoint.cx = point.x - prevPoint.x;
38991	        prevPoint.cy = point.y - prevPoint.y;
38992	        prevPoint.n = point;
38993	        prevPoint.nx = point.x;
38994
38995	        if (fast && i > 1 && Math.abs(prevPoint.cy / prevPoint.cx - points[i - 2].cy / points[i - 2].cx) > 2) {
38996	          fast = 0;
38997	        }
38998
38999	        if (prevPoint.cx < closest) {
39000	          if (!prevPoint.cx) {
39001	            prevPoint.cx = 0.001;
39002
39003	            if (i === l - 1) {
39004	              prevPoint.x -= 0.001;
39005	              closest = Math.min(closest, 0.001);
39006	              fast = 0;
39007	            }
39008	          } else {
39009	            closest = prevPoint.cx;
39010	          }
39011	        }
39012	      } else {
39013	        points.splice(i--, 1);
39014	        l--;
39015	      }
39016	    }
39017
39018	    l = 1 / closest + 1 | 0;
39019	    inc = 1 / l;
39020	    j = 0;
39021	    point = points[0];
39022
39023	    if (fast) {
39024	      for (i = 0; i < l; i++) {
39025	        p = i * inc;
39026
39027	        if (point.nx < p) {
39028	          point = points[++j];
39029	        }
39030
39031	        a1 = point.y + (p - point.x) / point.cx * point.cy;
39032	        lookup[i] = {
39033	          x: p,
39034	          cx: inc,
39035	          y: a1,
39036	          cy: 0,
39037	          nx: 9
39038	        };
39039
39040	        if (i) {
39041	          lookup[i - 1].cy = a1 - lookup[i - 1].y;
39042	        }
39043	      }
39044
39045	      j = points[points.length - 1];
39046	      lookup[l - 1].cy = j.y - a1;
39047	      lookup[l - 1].cx = j.x - lookup[lookup.length - 1].x;
39048	    } else {
39049	      for (i = 0; i < l; i++) {
39050	        if (point.nx < i * inc) {
39051	          point = points[++j];
39052	        }
39053
39054	        lookup[i] = point;
39055	      }
39056
39057	      if (j < points.length - 1) {
39058	        lookup[i - 1] = points[points.length - 2];
39059	      }
39060	    }
39061
39062	    this.ease = function (p) {
39063	      var point = lookup[p * l | 0] || lookup[l - 1];
39064
39065	      if (point.nx < p) {
39066	        point = point.n;
39067	      }
39068
39069	      return point.y + (p - point.x) / point.cx * point.cy;
39070	    };
39071
39072	    this.ease.custom = this;
39073	    this.id && gsap && gsap.registerEase(this.id, this.ease);
39074	    return this;
39075	  };
39076
39077	  _proto.getSVGData = function getSVGData(config) {
39078	    return CustomEase.getSVGData(this, config);
39079	  };
39080
39081	  CustomEase.create = function create(id, data, config) {
39082	    return new CustomEase(id, data, config).ease;
39083	  };
39084
39085	  CustomEase.register = function register(core) {
39086	    gsap = core;
39087
39088	    _initCore();
39089	  };
39090
39091	  CustomEase.get = function get(id) {
39092	    return gsap.parseEase(id);
39093	  };
39094
39095	  CustomEase.getSVGData = function getSVGData(ease, config) {
39096	    config = config || {};
39097	    var width = config.width || 100,
39098	        height = config.height || 100,
39099	        x = config.x || 0,
39100	        y = (config.y || 0) + height,
39101	        e = gsap.utils.toArray(config.path)[0],
39102	        a,
39103	        slope,
39104	        i,
39105	        inc,
39106	        tx,
39107	        ty,
39108	        precision,
39109	        threshold,
39110	        prevX,
39111	        prevY;
39112
39113	    if (config.invert) {
39114	      height = -height;
39115	      y = 0;
39116	    }
39117
39118	    if (typeof ease === "string") {
39119	      ease = gsap.parseEase(ease);
39120	    }
39121
39122	    if (ease.custom) {
39123	      ease = ease.custom;
39124	    }
39125
39126	    if (ease instanceof CustomEase) {
39127	      a = rawPathToString(transformRawPath([ease.segment], width, 0, 0, -height, x, y));
39128	    } else {
39129	      a = [x, y];
39130	      precision = Math.max(5, (config.precision || 1) * 200);
39131	      inc = 1 / precision;
39132	      precision += 2;
39133	      threshold = 5 / precision;
39134	      prevX = _round$1(x + inc * width);
39135	      prevY = _round$1(y + ease(inc) * -height);
39136	      slope = (prevY - y) / (prevX - x);
39137
39138	      for (i = 2; i < precision; i++) {
39139	        tx = _round$1(x + i * inc * width);
39140	        ty = _round$1(y + ease(i * inc) * -height);
39141
39142	        if (Math.abs((ty - prevY) / (tx - prevX) - slope) > threshold || i === precision - 1) {
39143	          a.push(prevX, prevY);
39144	          slope = (ty - prevY) / (tx - prevX);
39145	        }
39146
39147	        prevX = tx;
39148	        prevY = ty;
39149	      }
39150
39151	      a = "M" + a.join(",");
39152	    }
39153
39154	    e && e.setAttribute("d", a);
39155	    return a;
39156	  };
39157
39158	  return CustomEase;
39159	}();
39160	CustomEase.version = "3.12.7";
39161	CustomEase.headless = true;
39162	_getGSAP() && gsap.registerPlugin(CustomEase);
39163
39164	exports.CustomEase = CustomEase;
39165	exports.default = CustomEase;
39166
39167	Object.defineProperty(exports, '__esModule', { value: true });
39168
39169})));
39170(function (global, factory) {
39171  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
39172  typeof define === 'function' && define.amd ? define(['exports'], factory) :
39173  (global = global || self, factory(global.window = global.window || {}));
39174}(this, (function (exports) { 'use strict';
39175
39176  function _inheritsLoose(subClass, superClass) {
39177    subClass.prototype = Object.create(superClass.prototype);
39178    subClass.prototype.constructor = subClass;
39179    subClass.__proto__ = superClass;
39180  }
39181
39182  function _assertThisInitialized(self) {
39183    if (self === void 0) {
39184      throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
39185    }
39186
39187    return self;
39188  }
39189
39190  var _doc,
39191      _win,
39192      _docElement,
39193      _body,
39194      _divContainer,
39195      _svgContainer,
39196      _identityMatrix,
39197      _gEl,
39198      _transformProp = "transform",
39199      _transformOriginProp = _transformProp + "Origin",
39200      _hasOffsetBug,
39201      _setDoc = function _setDoc(element) {
39202    var doc = element.ownerDocument || element;
39203
39204    if (!(_transformProp in element.style) && "msTransform" in element.style) {
39205      _transformProp = "msTransform";
39206      _transformOriginProp = _transformProp + "Origin";
39207    }
39208
39209    while (doc.parentNode && (doc = doc.parentNode)) {}
39210
39211    _win = window;
39212    _identityMatrix = new Matrix2D();
39213
39214    if (doc) {
39215      _doc = doc;
39216      _docElement = doc.documentElement;
39217      _body = doc.body;
39218      _gEl = _doc.createElementNS("http://www.w3.org/2000/svg", "g");
39219      _gEl.style.transform = "none";
39220      var d1 = doc.createElement("div"),
39221          d2 = doc.createElement("div"),
39222          root = doc && (doc.body || doc.firstElementChild);
39223
39224      if (root && root.appendChild) {
39225        root.appendChild(d1);
39226        d1.appendChild(d2);
39227        d1.setAttribute("style", "position:static;transform:translate3d(0,0,1px)");
39228        _hasOffsetBug = d2.offsetParent !== d1;
39229        root.removeChild(d1);
39230      }
39231    }
39232
39233    return doc;
39234  },
39235      _forceNonZeroScale = function _forceNonZeroScale(e) {
39236    var a, cache;
39237
39238    while (e && e !== _body) {
39239      cache = e._gsap;
39240      cache && cache.uncache && cache.get(e, "x");
39241
39242      if (cache && !cache.scaleX && !cache.scaleY && cache.renderTransform) {
39243        cache.scaleX = cache.scaleY = 1e-4;
39244        cache.renderTransform(1, cache);
39245        a ? a.push(cache) : a = [cache];
39246      }
39247
39248      e = e.parentNode;
39249    }
39250
39251    return a;
39252  },
39253      _svgTemps = [],
39254      _divTemps = [],
39255      _getDocScrollTop = function _getDocScrollTop() {
39256    return _win.pageYOffset || _doc.scrollTop || _docElement.scrollTop || _body.scrollTop || 0;
39257  },
39258      _getDocScrollLeft = function _getDocScrollLeft() {
39259    return _win.pageXOffset || _doc.scrollLeft || _docElement.scrollLeft || _body.scrollLeft || 0;
39260  },
39261      _svgOwner = function _svgOwner(element) {
39262    return element.ownerSVGElement || ((element.tagName + "").toLowerCase() === "svg" ? element : null);
39263  },
39264      _isFixed = function _isFixed(element) {
39265    if (_win.getComputedStyle(element).position === "fixed") {
39266      return true;
39267    }
39268
39269    element = element.parentNode;
39270
39271    if (element && element.nodeType === 1) {
39272      return _isFixed(element);
39273    }
39274  },
39275      _createSibling = function _createSibling(element, i) {
39276    if (element.parentNode && (_doc || _setDoc(element))) {
39277      var svg = _svgOwner(element),
39278          ns = svg ? svg.getAttribute("xmlns") || "http://www.w3.org/2000/svg" : "http://www.w3.org/1999/xhtml",
39279          type = svg ? i ? "rect" : "g" : "div",
39280          x = i !== 2 ? 0 : 100,
39281          y = i === 3 ? 100 : 0,
39282          css = "position:absolute;display:block;pointer-events:none;margin:0;padding:0;",
39283          e = _doc.createElementNS ? _doc.createElementNS(ns.replace(/^https/, "http"), type) : _doc.createElement(type);
39284
39285      if (i) {
39286        if (!svg) {
39287          if (!_divContainer) {
39288            _divContainer = _createSibling(element);
39289            _divContainer.style.cssText = css;
39290          }
39291
39292          e.style.cssText = css + "width:0.1px;height:0.1px;top:" + y + "px;left:" + x + "px";
39293
39294          _divContainer.appendChild(e);
39295        } else {
39296          _svgContainer || (_svgContainer = _createSibling(element));
39297          e.setAttribute("width", 0.01);
39298          e.setAttribute("height", 0.01);
39299          e.setAttribute("transform", "translate(" + x + "," + y + ")");
39300
39301          _svgContainer.appendChild(e);
39302        }
39303      }
39304
39305      return e;
39306    }
39307
39308    throw "Need document and parent.";
39309  },
39310      _consolidate = function _consolidate(m) {
39311    var c = new Matrix2D(),
39312        i = 0;
39313
39314    for (; i < m.numberOfItems; i++) {
39315      c.multiply(m.getItem(i).matrix);
39316    }
39317
39318    return c;
39319  },
39320      _getCTM = function _getCTM(svg) {
39321    var m = svg.getCTM(),
39322        transform;
39323
39324    if (!m) {
39325      transform = svg.style[_transformProp];
39326      svg.style[_transformProp] = "none";
39327      svg.appendChild(_gEl);
39328      m = _gEl.getCTM();
39329      svg.removeChild(_gEl);
39330      transform ? svg.style[_transformProp] = transform : svg.style.removeProperty(_transformProp.replace(/([A-Z])/g, "-$1").toLowerCase());
39331    }
39332
39333    return m || _identityMatrix.clone();
39334  },
39335      _placeSiblings = function _placeSiblings(element, adjustGOffset) {
39336    var svg = _svgOwner(element),
39337        isRootSVG = element === svg,
39338        siblings = svg ? _svgTemps : _divTemps,
39339        parent = element.parentNode,
39340        container,
39341        m,
39342        b,
39343        x,
39344        y,
39345        cs;
39346
39347    if (element === _win) {
39348      return element;
39349    }
39350
39351    siblings.length || siblings.push(_createSibling(element, 1), _createSibling(element, 2), _createSibling(element, 3));
39352    container = svg ? _svgContainer : _divContainer;
39353
39354    if (svg) {
39355      if (isRootSVG) {
39356        b = _getCTM(element);
39357        x = -b.e / b.a;
39358        y = -b.f / b.d;
39359        m = _identityMatrix;
39360      } else if (element.getBBox) {
39361        b = element.getBBox();
39362        m = element.transform ? element.transform.baseVal : {};
39363        m = !m.numberOfItems ? _identityMatrix : m.numberOfItems > 1 ? _consolidate(m) : m.getItem(0).matrix;
39364        x = m.a * b.x + m.c * b.y;
39365        y = m.b * b.x + m.d * b.y;
39366      } else {
39367        m = new Matrix2D();
39368        x = y = 0;
39369      }
39370
39371      if (adjustGOffset && element.tagName.toLowerCase() === "g") {
39372        x = y = 0;
39373      }
39374
39375      (isRootSVG ? svg : parent).appendChild(container);
vendor: 1,139 bytes, lines 39376-39411
39376      container.setAttribute("transform", "matrix(" + m.a + "," + m.b + "," + m.c + "," + m.d + "," + (m.e + x) + "," + (m.f + y) + ")");
39377    } else {
39378      x = y = 0;
39379
39380      if (_hasOffsetBug) {
39381        m = element.offsetParent;
39382        b = element;
39383
39384        while (b && (b = b.parentNode) && b !== m && b.parentNode) {
39385          if ((_win.getComputedStyle(b)[_transformProp] + "").length > 4) {
39386            x = b.offsetLeft;
39387            y = b.offsetTop;
39388            b = 0;
39389          }
39390        }
39391      }
39392
39393      cs = _win.getComputedStyle(element);
39394
39395      if (cs.position !== "absolute" && cs.position !== "fixed") {
39396        m = element.offsetParent;
39397
39398        while (parent && parent !== m) {
39399          x += parent.scrollLeft || 0;
39400          y += parent.scrollTop || 0;
39401          parent = parent.parentNode;
39402        }
39403      }
39404
39405      b = container.style;
39406      b.top = element.offsetTop - y + "px";
39407      b.left = element.offsetLeft - x + "px";
39408      b[_transformProp] = cs[_transformProp];
39409      b[_transformOriginProp] = cs[_transformOriginProp];
39410      b.position = cs.position === "fixed" ? "fixed" : "absolute";
39411      element.parentNode
vendor: 37,456 bytes, lines 39411-40666
39411.appendChild(container);
39412    }
39413
39414    return container;
39415  },
39416      _setMatrix = function _setMatrix(m, a, b, c, d, e, f) {
39417    m.a = a;
39418    m.b = b;
39419    m.c = c;
39420    m.d = d;
39421    m.e = e;
39422    m.f = f;
39423    return m;
39424  };
39425
39426  var Matrix2D = function () {
39427    function Matrix2D(a, b, c, d, e, f) {
39428      if (a === void 0) {
39429        a = 1;
39430      }
39431
39432      if (b === void 0) {
39433        b = 0;
39434      }
39435
39436      if (c === void 0) {
39437        c = 0;
39438      }
39439
39440      if (d === void 0) {
39441        d = 1;
39442      }
39443
39444      if (e === void 0) {
39445        e = 0;
39446      }
39447
39448      if (f === void 0) {
39449        f = 0;
39450      }
39451
39452      _setMatrix(this, a, b, c, d, e, f);
39453    }
39454
39455    var _proto = Matrix2D.prototype;
39456
39457    _proto.inverse = function inverse() {
39458      var a = this.a,
39459          b = this.b,
39460          c = this.c,
39461          d = this.d,
39462          e = this.e,
39463          f = this.f,
39464          determinant = a * d - b * c || 1e-10;
39465      return _setMatrix(this, d / determinant, -b / determinant, -c / determinant, a / determinant, (c * f - d * e) / determinant, -(a * f - b * e) / determinant);
39466    };
39467
39468    _proto.multiply = function multiply(matrix) {
39469      var a = this.a,
39470          b = this.b,
39471          c = this.c,
39472          d = this.d,
39473          e = this.e,
39474          f = this.f,
39475          a2 = matrix.a,
39476          b2 = matrix.c,
39477          c2 = matrix.b,
39478          d2 = matrix.d,
39479          e2 = matrix.e,
39480          f2 = matrix.f;
39481      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);
39482    };
39483
39484    _proto.clone = function clone() {
39485      return new Matrix2D(this.a, this.b, this.c, this.d, this.e, this.f);
39486    };
39487
39488    _proto.equals = function equals(matrix) {
39489      var a = this.a,
39490          b = this.b,
39491          c = this.c,
39492          d = this.d,
39493          e = this.e,
39494          f = this.f;
39495      return a === matrix.a && b === matrix.b && c === matrix.c && d === matrix.d && e === matrix.e && f === matrix.f;
39496    };
39497
39498    _proto.apply = function apply(point, decoratee) {
39499      if (decoratee === void 0) {
39500        decoratee = {};
39501      }
39502
39503      var x = point.x,
39504          y = point.y,
39505          a = this.a,
39506          b = this.b,
39507          c = this.c,
39508          d = this.d,
39509          e = this.e,
39510          f = this.f;
39511      decoratee.x = x * a + y * c + e || 0;
39512      decoratee.y = x * b + y * d + f || 0;
39513      return decoratee;
39514    };
39515
39516    return Matrix2D;
39517  }();
39518  function getGlobalMatrix(element, inverse, adjustGOffset, includeScrollInFixed) {
39519    if (!element || !element.parentNode || (_doc || _setDoc(element)).documentElement === element) {
39520      return new Matrix2D();
39521    }
39522
39523    var zeroScales = _forceNonZeroScale(element),
39524        svg = _svgOwner(element),
39525        temps = svg ? _svgTemps : _divTemps,
39526        container = _placeSiblings(element, adjustGOffset),
39527        b1 = temps[0].getBoundingClientRect(),
39528        b2 = temps[1].getBoundingClientRect(),
39529        b3 = temps[2].getBoundingClientRect(),
39530        parent = container.parentNode,
39531        isFixed = !includeScrollInFixed && _isFixed(element),
39532        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()));
39533
39534    parent.removeChild(container);
39535
39536    if (zeroScales) {
39537      b1 = zeroScales.length;
39538
39539      while (b1--) {
39540        b2 = zeroScales[b1];
39541        b2.scaleX = b2.scaleY = 0;
39542        b2.renderTransform(1, b2);
39543      }
39544    }
39545
39546    return inverse ? m.inverse() : m;
39547  }
39548
39549  var gsap,
39550      _win$1,
39551      _doc$1,
39552      _docElement$1,
39553      _body$1,
39554      _tempDiv,
39555      _placeholderDiv,
39556      _coreInitted,
39557      _checkPrefix,
39558      _toArray,
39559      _supportsPassive,
39560      _isTouchDevice,
39561      _touchEventLookup,
39562      _isMultiTouching,
39563      _isAndroid,
39564      InertiaPlugin,
39565      _defaultCursor,
39566      _supportsPointer,
39567      _context,
39568      _getStyleSaver,
39569      _dragCount = 0,
39570      _windowExists = function _windowExists() {
39571    return typeof window !== "undefined";
39572  },
39573      _getGSAP = function _getGSAP() {
39574    return gsap || _windowExists() && (gsap = window.gsap) && gsap.registerPlugin && gsap;
39575  },
39576      _isFunction = function _isFunction(value) {
39577    return typeof value === "function";
39578  },
39579      _isObject = function _isObject(value) {
39580    return typeof value === "object";
39581  },
39582      _isUndefined = function _isUndefined(value) {
39583    return typeof value === "undefined";
39584  },
39585      _emptyFunc = function _emptyFunc() {
39586    return false;
39587  },
39588      _transformProp$1 = "transform",
39589      _transformOriginProp$1 = "transformOrigin",
39590      _round = function _round(value) {
39591    return Math.round(value * 10000) / 10000;
39592  },
39593      _isArray = Array.isArray,
39594      _createElement = function _createElement(type, ns) {
39595    var e = _doc$1.createElementNS ? _doc$1.createElementNS((ns || "http://www.w3.org/1999/xhtml").replace(/^https/, "http"), type) : _doc$1.createElement(type);
39596    return e.style ? e : _doc$1.createElement(type);
39597  },
39598      _RAD2DEG = 180 / Math.PI,
39599      _bigNum = 1e20,
39600      _identityMatrix$1 = new Matrix2D(),
39601      _getTime = Date.now || function () {
39602    return new Date().getTime();
39603  },
39604      _renderQueue = [],
39605      _lookup = {},
39606      _lookupCount = 0,
39607      _clickableTagExp = /^(?:a|input|textarea|button|select)$/i,
39608      _lastDragTime = 0,
39609      _temp1 = {},
39610      _windowProxy = {},
39611      _copy = function _copy(obj, factor) {
39612    var copy = {},
39613        p;
39614
39615    for (p in obj) {
39616      copy[p] = factor ? obj[p] * factor : obj[p];
39617    }
39618
39619    return copy;
39620  },
39621      _extend = function _extend(obj, defaults) {
39622    for (var p in defaults) {
39623      if (!(p in obj)) {
39624        obj[p] = defaults[p];
39625      }
39626    }
39627
39628    return obj;
39629  },
39630      _setTouchActionForAllDescendants = function _setTouchActionForAllDescendants(elements, value) {
39631    var i = elements.length,
39632        children;
39633
39634    while (i--) {
39635      value ? elements[i].style.touchAction = value : elements[i].style.removeProperty("touch-action");
39636      children = elements[i].children;
39637      children && children.length && _setTouchActionForAllDescendants(children, value);
39638    }
39639  },
39640      _renderQueueTick = function _renderQueueTick() {
39641    return _renderQueue.forEach(function (func) {
39642      return func();
39643    });
39644  },
39645      _addToRenderQueue = function _addToRenderQueue(func) {
39646    _renderQueue.push(func);
39647
39648    if (_renderQueue.length === 1) {
39649      gsap.ticker.add(_renderQueueTick);
39650    }
39651  },
39652      _renderQueueTimeout = function _renderQueueTimeout() {
39653    return !_renderQueue.length && gsap.ticker.remove(_renderQueueTick);
39654  },
39655      _removeFromRenderQueue = function _removeFromRenderQueue(func) {
39656    var i = _renderQueue.length;
39657
39658    while (i--) {
39659      if (_renderQueue[i] === func) {
39660        _renderQueue.splice(i, 1);
39661      }
39662    }
39663
39664    gsap.to(_renderQueueTimeout, {
39665      overwrite: true,
39666      delay: 15,
39667      duration: 0,
39668      onComplete: _renderQueueTimeout,
39669      data: "_draggable"
39670    });
39671  },
39672      _setDefaults = function _setDefaults(obj, defaults) {
39673    for (var p in defaults) {
39674      if (!(p in obj)) {
39675        obj[p] = defaults[p];
39676      }
39677    }
39678
39679    return obj;
39680  },
39681      _addListener = function _addListener(element, type, func, capture) {
39682    if (element.addEventListener) {
39683      var touchType = _touchEventLookup[type];
39684      capture = capture || (_supportsPassive ? {
39685        passive: false
39686      } : null);
39687      element.addEventListener(touchType || type, func, capture);
39688      touchType && type !== touchType && element.addEventListener(type, func, capture);
39689    }
39690  },
39691      _removeListener = function _removeListener(element, type, func, capture) {
39692    if (element.removeEventListener) {
39693      var touchType = _touchEventLookup[type];
39694      element.removeEventListener(touchType || type, func, capture);
39695      touchType && type !== touchType && element.removeEventListener(type, func, capture);
39696    }
39697  },
39698      _preventDefault = function _preventDefault(event) {
39699    event.preventDefault && event.preventDefault();
39700    event.preventManipulation && event.preventManipulation();
39701  },
39702      _hasTouchID = function _hasTouchID(list, ID) {
39703    var i = list.length;
39704
39705    while (i--) {
39706      if (list[i].identifier === ID) {
39707        return true;
39708      }
39709    }
39710  },
39711      _onMultiTouchDocumentEnd = function _onMultiTouchDocumentEnd(event) {
39712    _isMultiTouching = event.touches && _dragCount < event.touches.length;
39713
39714    _removeListener(event.target, "touchend", _onMultiTouchDocumentEnd);
39715  },
39716      _onMultiTouchDocument = function _onMultiTouchDocument(event) {
39717    _isMultiTouching = event.touches && _dragCount < event.touches.length;
39718
39719    _addListener(event.target, "touchend", _onMultiTouchDocumentEnd);
39720  },
39721      _getDocScrollTop$1 = function _getDocScrollTop(doc) {
39722    return _win$1.pageYOffset || doc.scrollTop || doc.documentElement.scrollTop || doc.body.scrollTop || 0;
39723  },
39724      _getDocScrollLeft$1 = function _getDocScrollLeft(doc) {
39725    return _win$1.pageXOffset || doc.scrollLeft || doc.documentElement.scrollLeft || doc.body.scrollLeft || 0;
39726  },
39727      _addScrollListener = function _addScrollListener(e, callback) {
39728    _addListener(e, "scroll", callback);
39729
39730    if (!_isRoot(e.parentNode)) {
39731      _addScrollListener(e.parentNode, callback);
39732    }
39733  },
39734      _removeScrollListener = function _removeScrollListener(e, callback) {
39735    _removeListener(e, "scroll", callback);
39736
39737    if (!_isRoot(e.parentNode)) {
39738      _removeScrollListener(e.parentNode, callback);
39739    }
39740  },
39741      _isRoot = function _isRoot(e) {
39742    return !!(!e || e === _docElement$1 || e.nodeType === 9 || e === _doc$1.body || e === _win$1 || !e.nodeType || !e.parentNode);
39743  },
39744      _getMaxScroll = function _getMaxScroll(element, axis) {
39745    var dim = axis === "x" ? "Width" : "Height",
39746        scroll = "scroll" + dim,
39747        client = "client" + dim;
39748    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]);
39749  },
39750      _recordMaxScrolls = function _recordMaxScrolls(e, skipCurrent) {
39751    var x = _getMaxScroll(e, "x"),
39752        y = _getMaxScroll(e, "y");
39753
39754    if (_isRoot(e)) {
39755      e = _windowProxy;
39756    } else {
39757      _recordMaxScrolls(e.parentNode, skipCurrent);
39758    }
39759
39760    e._gsMaxScrollX = x;
39761    e._gsMaxScrollY = y;
39762
39763    if (!skipCurrent) {
39764      e._gsScrollX = e.scrollLeft || 0;
39765      e._gsScrollY = e.scrollTop || 0;
39766    }
39767  },
39768      _setStyle = function _setStyle(element, property, value) {
39769    var style = element.style;
39770
39771    if (!style) {
39772      return;
39773    }
39774
39775    if (_isUndefined(style[property])) {
39776      property = _checkPrefix(property, element) || property;
39777    }
39778
39779    if (value == null) {
39780      style.removeProperty && style.removeProperty(property.replace(/([A-Z])/g, "-$1").toLowerCase());
39781    } else {
39782      style[property] = value;
39783    }
39784  },
39785      _getComputedStyle = function _getComputedStyle(element) {
39786    return _win$1.getComputedStyle(element instanceof Element ? element : element.host || (element.parentNode || {}).host || element);
39787  },
39788      _tempRect = {},
39789      _parseRect = function _parseRect(e) {
39790    if (e === _win$1) {
39791      _tempRect.left = _tempRect.top = 0;
39792      _tempRect.width = _tempRect.right = _docElement$1.clientWidth || e.innerWidth || _body$1.clientWidth || 0;
39793      _tempRect.height = _tempRect.bottom = (e.innerHeight || 0) - 20 < _docElement$1.clientHeight ? _docElement$1.clientHeight : e.innerHeight || _body$1.clientHeight || 0;
39794      return _tempRect;
39795    }
39796
39797    var doc = e.ownerDocument || _doc$1,
39798        r = !_isUndefined(e.pageX) ? {
39799      left: e.pageX - _getDocScrollLeft$1(doc),
39800      top: e.pageY - _getDocScrollTop$1(doc),
39801      right: e.pageX - _getDocScrollLeft$1(doc) + 1,
39802      bottom: e.pageY - _getDocScrollTop$1(doc) + 1
39803    } : !e.nodeType && !_isUndefined(e.left) && !_isUndefined(e.top) ? e : _toArray(e)[0].getBoundingClientRect();
39804
39805    if (_isUndefined(r.right) && !_isUndefined(r.width)) {
39806      r.right = r.left + r.width;
39807      r.bottom = r.top + r.height;
39808    } else if (_isUndefined(r.width)) {
39809      r = {
39810        width: r.right - r.left,
39811        height: r.bottom - r.top,
39812        right: r.right,
39813        left: r.left,
39814        bottom: r.bottom,
39815        top: r.top
39816      };
39817    }
39818
39819    return r;
39820  },
39821      _dispatchEvent = function _dispatchEvent(target, type, callbackName) {
39822    var vars = target.vars,
39823        callback = vars[callbackName],
39824        listeners = target._listeners[type],
39825        result;
39826
39827    if (_isFunction(callback)) {
39828      result = callback.apply(vars.callbackScope || target, vars[callbackName + "Params"] || [target.pointerEvent]);
39829    }
39830
39831    if (listeners && target.dispatchEvent(type) === false) {
39832      result = false;
39833    }
39834
39835    return result;
39836  },
39837      _getBounds = function _getBounds(target, context) {
39838    var e = _toArray(target)[0],
39839        top,
39840        left,
39841        offset;
39842
39843    if (!e.nodeType && e !== _win$1) {
39844      if (!_isUndefined(target.left)) {
39845        offset = {
39846          x: 0,
39847          y: 0
39848        };
39849        return {
39850          left: target.left - offset.x,
39851          top: target.top - offset.y,
39852          width: target.width,
39853          height: target.height
39854        };
39855      }
39856
39857      left = target.min || target.minX || target.minRotation || 0;
39858      top = target.min || target.minY || 0;
39859      return {
39860        left: left,
39861        top: top,
39862        width: (target.max || target.maxX || target.maxRotation || 0) - left,
39863        height: (target.max || target.maxY || 0) - top
39864      };
39865    }
39866
39867    return _getElementBounds(e, context);
39868  },
39869      _point1 = {},
39870      _getElementBounds = function _getElementBounds(element, context) {
39871    context = _toArray(context)[0];
39872    var isSVG = element.getBBox && element.ownerSVGElement,
39873        doc = element.ownerDocument || _doc$1,
39874        left,
39875        right,
39876        top,
39877        bottom,
39878        matrix,
39879        p1,
39880        p2,
39881        p3,
39882        p4,
39883        bbox,
39884        width,
39885        height,
39886        cs;
39887
39888    if (element === _win$1) {
39889      top = _getDocScrollTop$1(doc);
39890      left = _getDocScrollLeft$1(doc);
39891      right = left + (doc.documentElement.clientWidth || element.innerWidth || doc.body.clientWidth || 0);
39892      bottom = top + ((element.innerHeight || 0) - 20 < doc.documentElement.clientHeight ? doc.documentElement.clientHeight : element.innerHeight || doc.body.clientHeight || 0);
39893    } else if (context === _win$1 || _isUndefined(context)) {
39894      return element.getBoundingClientRect();
39895    } else {
39896      left = top = 0;
39897
39898      if (isSVG) {
39899        bbox = element.getBBox();
39900        width = bbox.width;
39901        height = bbox.height;
39902      } else {
39903        if (element.viewBox && (bbox = element.viewBox.baseVal)) {
39904          left = bbox.x || 0;
39905          top = bbox.y || 0;
39906          width = bbox.width;
39907          height = bbox.height;
39908        }
39909
39910        if (!width) {
39911          cs = _getComputedStyle(element);
39912          bbox = cs.boxSizing === "border-box";
39913          width = (parseFloat(cs.width) || element.clientWidth || 0) + (bbox ? 0 : parseFloat(cs.borderLeftWidth) + parseFloat(cs.borderRightWidth));
39914          height = (parseFloat(cs.height) || element.clientHeight || 0) + (bbox ? 0 : parseFloat(cs.borderTopWidth) + parseFloat(cs.borderBottomWidth));
39915        }
39916      }
39917
39918      right = width;
39919      bottom = height;
39920    }
39921
39922    if (element === context) {
39923      return {
39924        left: left,
39925        top: top,
39926        width: right - left,
39927        height: bottom - top
39928      };
39929    }
39930
39931    matrix = getGlobalMatrix(context, true).multiply(getGlobalMatrix(element));
39932    p1 = matrix.apply({
39933      x: left,
39934      y: top
39935    });
39936    p2 = matrix.apply({
39937      x: right,
39938      y: top
39939    });
39940    p3 = matrix.apply({
39941      x: right,
39942      y: bottom
39943    });
39944    p4 = matrix.apply({
39945      x: left,
39946      y: bottom
39947    });
39948    left = Math.min(p1.x, p2.x, p3.x, p4.x);
39949    top = Math.min(p1.y, p2.y, p3.y, p4.y);
39950    return {
39951      left: left,
39952      top: top,
39953      width: Math.max(p1.x, p2.x, p3.x, p4.x) - left,
39954      height: Math.max(p1.y, p2.y, p3.y, p4.y) - top
39955    };
39956  },
39957      _parseInertia = function _parseInertia(draggable, snap, max, min, factor, forceZeroVelocity) {
39958    var vars = {},
39959        a,
39960        i,
39961        l;
39962
39963    if (snap) {
39964      if (factor !== 1 && snap instanceof Array) {
39965        vars.end = a = [];
39966        l = snap.length;
39967
39968        if (_isObject(snap[0])) {
39969          for (i = 0; i < l; i++) {
39970            a[i] = _copy(snap[i], factor);
39971          }
39972        } else {
39973          for (i = 0; i < l; i++) {
39974            a[i] = snap[i] * factor;
39975          }
39976        }
39977
39978        max += 1.1;
39979        min -= 1.1;
39980      } else if (_isFunction(snap)) {
39981        vars.end = function (value) {
39982          var result = snap.call(draggable, value),
39983              copy,
39984              p;
39985
39986          if (factor !== 1) {
39987            if (_isObject(result)) {
39988              copy = {};
39989
39990              for (p in result) {
39991                copy[p] = result[p] * factor;
39992              }
39993
39994              result = copy;
39995            } else {
39996              result *= factor;
39997            }
39998          }
39999
40000          return result;
40001        };
40002      } else {
40003        vars.end = snap;
40004      }
40005    }
40006
40007    if (max || max === 0) {
40008      vars.max = max;
40009    }
40010
40011    if (min || min === 0) {
40012      vars.min = min;
40013    }
40014
40015    if (forceZeroVelocity) {
40016      vars.velocity = 0;
40017    }
40018
40019    return vars;
40020  },
40021      _isClickable = function _isClickable(element) {
40022    var data;
40023    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);
40024  },
40025      _setSelectable = function _setSelectable(elements, selectable) {
40026    var i = elements.length,
40027        e;
40028
40029    while (i--) {
40030      e = elements[i];
40031      e.ondragstart = e.onselectstart = selectable ? null : _emptyFunc;
40032      gsap.set(e, {
40033        lazy: true,
40034        userSelect: selectable ? "text" : "none"
40035      });
40036    }
40037  },
40038      _isFixed$1 = function _isFixed(element) {
40039    if (_getComputedStyle(element).position === "fixed") {
40040      return true;
40041    }
40042
40043    element = element.parentNode;
40044
40045    if (element && element.nodeType === 1) {
40046      return _isFixed(element);
40047    }
40048  },
40049      _supports3D,
40050      _addPaddingBR,
40051      ScrollProxy = function ScrollProxy(element, vars) {
40052    element = gsap.utils.toArray(element)[0];
40053    vars = vars || {};
40054    var content = document.createElement("div"),
40055        style = content.style,
40056        node = element.firstChild,
40057        offsetTop = 0,
40058        offsetLeft = 0,
40059        prevTop = element.scrollTop,
40060        prevLeft = element.scrollLeft,
40061        scrollWidth = element.scrollWidth,
40062        scrollHeight = element.scrollHeight,
40063        extraPadRight = 0,
40064        maxLeft = 0,
40065        maxTop = 0,
40066        elementWidth,
40067        elementHeight,
40068        contentHeight,
40069        nextNode,
40070        transformStart,
40071        transformEnd;
40072
40073    if (_supports3D && vars.force3D !== false) {
40074      transformStart = "translate3d(";
40075      transformEnd = "px,0px)";
40076    } else if (_transformProp$1) {
40077      transformStart = "translate(";
40078      transformEnd = "px)";
40079    }
40080
40081    this.scrollTop = function (value, force) {
40082      if (!arguments.length) {
40083        return -this.top();
40084      }
40085
40086      this.top(-value, force);
40087    };
40088
40089    this.scrollLeft = function (value, force) {
40090      if (!arguments.length) {
40091        return -this.left();
40092      }
40093
40094      this.left(-value, force);
40095    };
40096
40097    this.left = function (value, force) {
40098      if (!arguments.length) {
40099        return -(element.scrollLeft + offsetLeft);
40100      }
40101
40102      var dif = element.scrollLeft - prevLeft,
40103          oldOffset = offsetLeft;
40104
40105      if ((dif > 2 || dif < -2) && !force) {
40106        prevLeft = element.scrollLeft;
40107        gsap.killTweensOf(this, {
40108          left: 1,
40109          scrollLeft: 1
40110        });
40111        this.left(-prevLeft);
40112
40113        if (vars.onKill) {
40114          vars.onKill();
40115        }
40116
40117        return;
40118      }
40119
40120      value = -value;
40121
40122      if (value < 0) {
40123        offsetLeft = value - 0.5 | 0;
40124        value = 0;
40125      } else if (value > maxLeft) {
40126        offsetLeft = value - maxLeft | 0;
40127        value = maxLeft;
40128      } else {
40129        offsetLeft = 0;
40130      }
40131
40132      if (offsetLeft || oldOffset) {
40133        if (!this._skip) {
40134          style[_transformProp$1] = transformStart + -offsetLeft + "px," + -offsetTop + transformEnd;
40135        }
40136
40137        if (offsetLeft + extraPadRight >= 0) {
40138          style.paddingRight = offsetLeft + extraPadRight + "px";
40139        }
40140      }
40141
40142      element.scrollLeft = value | 0;
40143      prevLeft = element.scrollLeft;
40144    };
40145
40146    this.top = function (value, force) {
40147      if (!arguments.length) {
40148        return -(element.scrollTop + offsetTop);
40149      }
40150
40151      var dif = element.scrollTop - prevTop,
40152          oldOffset = offsetTop;
40153
40154      if ((dif > 2 || dif < -2) && !force) {
40155        prevTop = element.scrollTop;
40156        gsap.killTweensOf(this, {
40157          top: 1,
40158          scrollTop: 1
40159        });
40160        this.top(-prevTop);
40161
40162        if (vars.onKill) {
40163          vars.onKill();
40164        }
40165
40166        return;
40167      }
40168
40169      value = -value;
40170
40171      if (value < 0) {
40172        offsetTop = value - 0.5 | 0;
40173        value = 0;
40174      } else if (value > maxTop) {
40175        offsetTop = value - maxTop | 0;
40176        value = maxTop;
40177      } else {
40178        offsetTop = 0;
40179      }
40180
40181      if (offsetTop || oldOffset) {
40182        if (!this._skip) {
40183          style[_transformProp$1] = transformStart + -offsetLeft + "px," + -offsetTop + transformEnd;
40184        }
40185      }
40186
40187      element.scrollTop = value | 0;
40188      prevTop = element.scrollTop;
40189    };
40190
40191    this.maxScrollTop = function () {
40192      return maxTop;
40193    };
40194
40195    this.maxScrollLeft = function () {
40196      return maxLeft;
40197    };
40198
40199    this.disable = function () {
40200      node = content.firstChild;
40201
40202      while (node) {
40203        nextNode = node.nextSibling;
40204        element.appendChild(node);
40205        node = nextNode;
40206      }
40207
40208      if (element === content.parentNode) {
40209        element.removeChild(content);
40210      }
40211    };
40212
40213    this.enable = function () {
40214      node = element.firstChild;
40215
40216      if (node === content) {
40217        return;
40218      }
40219
40220      while (node) {
40221        nextNode = node.nextSibling;
40222        content.appendChild(node);
40223        node = nextNode;
40224      }
40225
40226      element.appendChild(content);
40227      this.calibrate();
40228    };
40229
40230    this.calibrate = function (force) {
40231      var widthMatches = element.clientWidth === elementWidth,
40232          cs,
40233          x,
40234          y;
40235      prevTop = element.scrollTop;
40236      prevLeft = element.scrollLeft;
40237
40238      if (widthMatches && element.clientHeight === elementHeight && content.offsetHeight === contentHeight && scrollWidth === element.scrollWidth && scrollHeight === element.scrollHeight && !force) {
40239        return;
40240      }
40241
40242      if (offsetTop || offsetLeft) {
40243        x = this.left();
40244        y = this.top();
40245        this.left(-element.scrollLeft);
40246        this.top(-element.scrollTop);
40247      }
40248
40249      cs = _getComputedStyle(element);
40250
40251      if (!widthMatches || force) {
40252        style.display = "block";
40253        style.width = "auto";
40254        style.paddingRight = "0px";
40255        extraPadRight = Math.max(0, element.scrollWidth - element.clientWidth);
40256
40257        if (extraPadRight) {
40258          extraPadRight += parseFloat(cs.paddingLeft) + (_addPaddingBR ? parseFloat(cs.paddingRight) : 0);
40259        }
40260      }
40261
40262      style.display = "inline-block";
40263      style.position = "relative";
40264      style.overflow = "visible";
40265      style.verticalAlign = "top";
40266      style.boxSizing = "content-box";
40267      style.width = "100%";
40268      style.paddingRight = extraPadRight + "px";
40269
40270      if (_addPaddingBR) {
40271        style.paddingBottom = cs.paddingBottom;
40272      }
40273
40274      elementWidth = element.clientWidth;
40275      elementHeight = element.clientHeight;
40276      scrollWidth = element.scrollWidth;
40277      scrollHeight = element.scrollHeight;
40278      maxLeft = element.scrollWidth - elementWidth;
40279      maxTop = element.scrollHeight - elementHeight;
40280      contentHeight = content.offsetHeight;
40281      style.display = "block";
40282
40283      if (x || y) {
40284        this.left(x);
40285        this.top(y);
40286      }
40287    };
40288
40289    this.content = content;
40290    this.element = element;
40291    this._skip = false;
40292    this.enable();
40293  },
40294      _initCore = function _initCore(required) {
40295    if (_windowExists() && document.body) {
40296      var nav = window && window.navigator;
40297      _win$1 = window;
40298      _doc$1 = document;
40299      _docElement$1 = _doc$1.documentElement;
40300      _body$1 = _doc$1.body;
40301      _tempDiv = _createElement("div");
40302      _supportsPointer = !!window.PointerEvent;
40303      _placeholderDiv = _createElement("div");
40304      _placeholderDiv.style.cssText = "visibility:hidden;height:1px;top:-1px;pointer-events:none;position:relative;clear:both;cursor:grab";
40305      _defaultCursor = _placeholderDiv.style.cursor === "grab" ? "grab" : "move";
40306      _isAndroid = nav && nav.userAgent.toLowerCase().indexOf("android") !== -1;
40307      _isTouchDevice = "ontouchstart" in _docElement$1 && "orientation" in _win$1 || nav && (nav.MaxTouchPoints > 0 || nav.msMaxTouchPoints > 0);
40308
40309      _addPaddingBR = function () {
40310        var div = _createElement("div"),
40311            child = _createElement("div"),
40312            childStyle = child.style,
40313            parent = _body$1,
40314            val;
40315
40316        childStyle.display = "inline-block";
40317        childStyle.position = "relative";
40318        div.style.cssText = "width:90px;height:40px;padding:10px;overflow:auto;visibility:hidden";
40319        div.appendChild(child);
40320        parent.appendChild(div);
40321        val = child.offsetHeight + 18 > div.scrollHeight;
40322        parent.removeChild(div);
40323        return val;
40324      }();
40325
40326      _touchEventLookup = function (types) {
40327        var standard = types.split(","),
40328            converted = ("onpointerdown" in _tempDiv ? "pointerdown,pointermove,pointerup,pointercancel" : "onmspointerdown" in _tempDiv ? "MSPointerDown,MSPointerMove,MSPointerUp,MSPointerCancel" : types).split(","),
40329            obj = {},
40330            i = 4;
40331
40332        while (--i > -1) {
40333          obj[standard[i]] = converted[i];
40334          obj[converted[i]] = standard[i];
40335        }
40336
40337        try {
40338          _docElement$1.addEventListener("test", null, Object.defineProperty({}, "passive", {
40339            get: function get() {
40340              _supportsPassive = 1;
40341            }
40342          }));
40343        } catch (e) {}
40344
40345        return obj;
40346      }("touchstart,touchmove,touchend,touchcancel");
40347
40348      _addListener(_doc$1, "touchcancel", _emptyFunc);
40349
40350      _addListener(_win$1, "touchmove", _emptyFunc);
40351
40352      _body$1 && _body$1.addEventListener("touchstart", _emptyFunc);
40353
40354      _addListener(_doc$1, "contextmenu", function () {
40355        for (var p in _lookup) {
40356          if (_lookup[p].isPressed) {
40357            _lookup[p].endDrag();
40358          }
40359        }
40360      });
40361
40362      gsap = _coreInitted = _getGSAP();
40363    }
40364
40365    if (gsap) {
40366      InertiaPlugin = gsap.plugins.inertia;
40367
40368      _context = gsap.core.context || function () {};
40369
40370      _checkPrefix = gsap.utils.checkPrefix;
40371      _transformProp$1 = _checkPrefix(_transformProp$1);
40372      _transformOriginProp$1 = _checkPrefix(_transformOriginProp$1);
40373      _toArray = gsap.utils.toArray;
40374      _getStyleSaver = gsap.core.getStyleSaver;
40375      _supports3D = !!_checkPrefix("perspective");
40376    } else if (required) {
40377      console.warn("Please gsap.registerPlugin(Draggable)");
40378    }
40379  };
40380
40381  var EventDispatcher = function () {
40382    function EventDispatcher(target) {
40383      this._listeners = {};
40384      this.target = target || this;
40385    }
40386
40387    var _proto = EventDispatcher.prototype;
40388
40389    _proto.addEventListener = function addEventListener(type, callback) {
40390      var list = this._listeners[type] || (this._listeners[type] = []);
40391
40392      if (!~list.indexOf(callback)) {
40393        list.push(callback);
40394      }
40395    };
40396
40397    _proto.removeEventListener = function removeEventListener(type, callback) {
40398      var list = this._listeners[type],
40399          i = list && list.indexOf(callback);
40400      i >= 0 && list.splice(i, 1);
40401    };
40402
40403    _proto.dispatchEvent = function dispatchEvent(type) {
40404      var _this = this;
40405
40406      var result;
40407      (this._listeners[type] || []).forEach(function (callback) {
40408        return callback.call(_this, {
40409          type: type,
40410          target: _this.target
40411        }) === false && (result = false);
40412      });
40413      return result;
40414    };
40415
40416    return EventDispatcher;
40417  }();
40418
40419  var Draggable = function (_EventDispatcher) {
40420    _inheritsLoose(Draggable, _EventDispatcher);
40421
40422    function Draggable(target, vars) {
40423      var _this2;
40424
40425      _this2 = _EventDispatcher.call(this) || this;
40426      _coreInitted || _initCore(1);
40427      target = _toArray(target)[0];
40428      _this2.styles = _getStyleSaver && _getStyleSaver(target, "transform,left,top");
40429
40430      if (!InertiaPlugin) {
40431        InertiaPlugin = gsap.plugins.inertia;
40432      }
40433
40434      _this2.vars = vars = _copy(vars || {});
40435      _this2.target = target;
40436      _this2.x = _this2.y = _this2.rotation = 0;
40437      _this2.dragResistance = parseFloat(vars.dragResistance) || 0;
40438      _this2.edgeResistance = isNaN(vars.edgeResistance) ? 1 : parseFloat(vars.edgeResistance) || 0;
40439      _this2.lockAxis = vars.lockAxis;
40440      _this2.autoScroll = vars.autoScroll || 0;
40441      _this2.lockedAxis = null;
40442      _this2.allowEventDefault = !!vars.allowEventDefault;
40443      gsap.getProperty(target, "x");
40444
40445      var type = (vars.type || "x,y").toLowerCase(),
40446          xyMode = ~type.indexOf("x") || ~type.indexOf("y"),
40447          rotationMode = type.indexOf("rotation") !== -1,
40448          xProp = rotationMode ? "rotation" : xyMode ? "x" : "left",
40449          yProp = xyMode ? "y" : "top",
40450          allowX = !!(~type.indexOf("x") || ~type.indexOf("left") || type === "scroll"),
40451          allowY = !!(~type.indexOf("y") || ~type.indexOf("top") || type === "scroll"),
40452          minimumMovement = vars.minimumMovement || 2,
40453          self = _assertThisInitialized(_this2),
40454          triggers = _toArray(vars.trigger || vars.handle || target),
40455          killProps = {},
40456          dragEndTime = 0,
40457          checkAutoScrollBounds = false,
40458          autoScrollMarginTop = vars.autoScrollMarginTop || 40,
40459          autoScrollMarginRight = vars.autoScrollMarginRight || 40,
40460          autoScrollMarginBottom = vars.autoScrollMarginBottom || 40,
40461          autoScrollMarginLeft = vars.autoScrollMarginLeft || 40,
40462          isClickable = vars.clickableTest || _isClickable,
40463          clickTime = 0,
40464          gsCache = target._gsap || gsap.core.getCache(target),
40465          isFixed = _isFixed$1(target),
40466          getPropAsNum = function getPropAsNum(property, unit) {
40467        return parseFloat(gsCache.get(target, property, unit));
40468      },
40469          ownerDoc = target.ownerDocument || _doc$1,
40470          enabled,
40471          scrollProxy,
40472          startPointerX,
40473          startPointerY,
40474          startElementX,
40475          startElementY,
40476          hasBounds,
40477          hasDragCallback,
40478          hasMoveCallback,
40479          maxX,
40480          minX,
40481          maxY,
40482          minY,
40483          touch,
40484          touchID,
40485          rotationOrigin,
40486          dirty,
40487          old,
40488          snapX,
40489          snapY,
40490          snapXY,
40491          isClicking,
40492          touchEventTarget,
40493          matrix,
40494          interrupted,
40495          allowNativeTouchScrolling,
40496          touchDragAxis,
40497          isDispatching,
40498          clickDispatch,
40499          trustedClickDispatch,
40500          isPreventingDefault,
40501          innerMatrix,
40502          dragged,
40503          onContextMenu = function onContextMenu(e) {
40504        _preventDefault(e);
40505
40506        e.stopImmediatePropagation && e.stopImmediatePropagation();
40507        return false;
40508      },
40509          render = function render(suppressEvents) {
40510        if (self.autoScroll && self.isDragging && (checkAutoScrollBounds || dirty)) {
40511          var e = target,
40512              autoScrollFactor = self.autoScroll * 15,
40513              parent,
40514              isRoot,
40515              rect,
40516              pointerX,
40517              pointerY,
40518              changeX,
40519              changeY,
40520              gap;
40521          checkAutoScrollBounds = false;
40522          _windowProxy.scrollTop = _win$1.pageYOffset != null ? _win$1.pageYOffset : ownerDoc.documentElement.scrollTop != null ? ownerDoc.documentElement.scrollTop : ownerDoc.body.scrollTop;
40523          _windowProxy.scrollLeft = _win$1.pageXOffset != null ? _win$1.pageXOffset : ownerDoc.documentElement.scrollLeft != null ? ownerDoc.documentElement.scrollLeft : ownerDoc.body.scrollLeft;
40524          pointerX = self.pointerX - _windowProxy.scrollLeft;
40525          pointerY = self.pointerY - _windowProxy.scrollTop;
40526
40527          while (e && !isRoot) {
40528            isRoot = _isRoot(e.parentNode);
40529            parent = isRoot ? _windowProxy : e.parentNode;
40530            rect = isRoot ? {
40531              bottom: Math.max(_docElement$1.clientHeight, _win$1.innerHeight || 0),
40532              right: Math.max(_docElement$1.clientWidth, _win$1.innerWidth || 0),
40533              left: 0,
40534              top: 0
40535            } : parent.getBoundingClientRect();
40536            changeX = changeY = 0;
40537
40538            if (allowY) {
40539              gap = parent._gsMaxScrollY - parent.scrollTop;
40540
40541              if (gap < 0) {
40542                changeY = gap;
40543              } else if (pointerY > rect.bottom - autoScrollMarginBottom && gap) {
40544                checkAutoScrollBounds = true;
40545                changeY = Math.min(gap, autoScrollFactor * (1 - Math.max(0, rect.bottom - pointerY) / autoScrollMarginBottom) | 0);
40546              } else if (pointerY < rect.top + autoScrollMarginTop && parent.scrollTop) {
40547                checkAutoScrollBounds = true;
40548                changeY = -Math.min(parent.scrollTop, autoScrollFactor * (1 - Math.max(0, pointerY - rect.top) / autoScrollMarginTop) | 0);
40549              }
40550
40551              if (changeY) {
40552                parent.scrollTop += changeY;
40553              }
40554            }
40555
40556            if (allowX) {
40557              gap = parent._gsMaxScrollX - parent.scrollLeft;
40558
40559              if (gap < 0) {
40560                changeX = gap;
40561              } else if (pointerX > rect.right - autoScrollMarginRight && gap) {
40562                checkAutoScrollBounds = true;
40563                changeX = Math.min(gap, autoScrollFactor * (1 - Math.max(0, rect.right - pointerX) / autoScrollMarginRight) | 0);
40564              } else if (pointerX < rect.left + autoScrollMarginLeft && parent.scrollLeft) {
40565                checkAutoScrollBounds = true;
40566                changeX = -Math.min(parent.scrollLeft, autoScrollFactor * (1 - Math.max(0, pointerX - rect.left) / autoScrollMarginLeft) | 0);
40567              }
40568
40569              if (changeX) {
40570                parent.scrollLeft += changeX;
40571              }
40572            }
40573
40574            if (isRoot && (changeX || changeY)) {
40575              _win$1.scrollTo(parent.scrollLeft, parent.scrollTop);
40576
40577              setPointerPosition(self.pointerX + changeX, self.pointerY + changeY);
40578            }
40579
40580            e = parent;
40581          }
40582        }
40583
40584        if (dirty) {
40585          var x = self.x,
40586              y = self.y;
40587
40588          if (rotationMode) {
40589            self.deltaX = x - parseFloat(gsCache.rotation);
40590            self.rotation = x;
40591            gsCache.rotation = x + "deg";
40592            gsCache.renderTransform(1, gsCache);
40593          } else {
40594            if (scrollProxy) {
40595              if (allowY) {
40596                self.deltaY = y - scrollProxy.top();
40597                scrollProxy.top(y);
40598              }
40599
40600              if (allowX) {
40601                self.deltaX = x - scrollProxy.left();
40602                scrollProxy.left(x);
40603              }
40604            } else if (xyMode) {
40605              if (allowY) {
40606                self.deltaY = y - parseFloat(gsCache.y);
40607                gsCache.y = y + "px";
40608              }
40609
40610              if (allowX) {
40611                self.deltaX = x - parseFloat(gsCache.x);
40612                gsCache.x = x + "px";
40613              }
40614
40615              gsCache.renderTransform(1, gsCache);
40616            } else {
40617              if (allowY) {
40618                self.deltaY = y - parseFloat(target.style.top || 0);
40619                target.style.top = y + "px";
40620              }
40621
40622              if (allowX) {
40623                self.deltaX = x - parseFloat(target.style.left || 0);
40624                target.style.left = x + "px";
40625              }
40626            }
40627          }
40628
40629          if (hasDragCallback && !suppressEvents && !isDispatching) {
40630            isDispatching = true;
40631
40632            if (_dispatchEvent(self, "drag", "onDrag") === false) {
40633              if (allowX) {
40634                self.x -= self.deltaX;
40635              }
40636
40637              if (allowY) {
40638                self.y -= self.deltaY;
40639              }
40640
40641              render(true);
40642            }
40643
40644            isDispatching = false;
40645          }
40646        }
40647
40648        dirty = false;
40649      },
40650          syncXY = function syncXY(skipOnUpdate, skipSnap) {
40651        var x = self.x,
40652            y = self.y,
40653            snappedValue,
40654            cs;
40655
40656        if (!target._gsap) {
40657          gsCache = gsap.core.getCache(target);
40658        }
40659
40660        gsCache.uncache && gsap.getProperty(target, "x");
40661
40662        if (xyMode) {
40663          self.x = parseFloat(gsCache.x);
40664          self.y = parseFloat(gsCache.y);
40665        } else if (rotationMode) {
40666          self.x = self.rotation = 
40666parseFloat(gsCache.rotation
vendor: 18,327 bytes, lines 40666-41216
40666);
40667        } else if (scrollProxy) {
40668          self.y = scrollProxy.top();
40669          self.x = scrollProxy.left();
40670        } else {
40671          self.y = parseFloat(target.style.top || (cs = _getComputedStyle(target)) && cs.top) || 0;
40672          self.x = parseFloat(target.style.left || (cs || {}).left) || 0;
40673        }
40674
40675        if ((snapX || snapY || snapXY) && !skipSnap && (self.isDragging || self.isThrowing)) {
40676          if (snapXY) {
40677            _temp1.x = self.x;
40678            _temp1.y = self.y;
40679            snappedValue = snapXY(_temp1);
40680
40681            if (snappedValue.x !== self.x) {
40682              self.x = snappedValue.x;
40683              dirty = true;
40684            }
40685
40686            if (snappedValue.y !== self.y) {
40687              self.y = snappedValue.y;
40688              dirty = true;
40689            }
40690          }
40691
40692          if (snapX) {
40693            snappedValue = snapX(self.x);
40694
40695            if (snappedValue !== self.x) {
40696              self.x = snappedValue;
40697
40698              if (rotationMode) {
40699                self.rotation = snappedValue;
40700              }
40701
40702              dirty = true;
40703            }
40704          }
40705
40706          if (snapY) {
40707            snappedValue = snapY(self.y);
40708
40709            if (snappedValue !== self.y) {
40710              self.y = snappedValue;
40711            }
40712
40713            dirty = true;
40714          }
40715        }
40716
40717        dirty && render(true);
40718
40719        if (!skipOnUpdate) {
40720          self.deltaX = self.x - x;
40721          self.deltaY = self.y - y;
40722
40723          _dispatchEvent(self, "throwupdate", "onThrowUpdate");
40724        }
40725      },
40726          buildSnapFunc = function buildSnapFunc(snap, min, max, factor) {
40727        if (min == null) {
40728          min = -_bigNum;
40729        }
40730
40731        if (max == null) {
40732          max = _bigNum;
40733        }
40734
40735        if (_isFunction(snap)) {
40736          return function (n) {
40737            var edgeTolerance = !self.isPressed ? 1 : 1 - self.edgeResistance;
40738            return snap.call(self, (n > max ? max + (n - max) * edgeTolerance : n < min ? min + (n - min) * edgeTolerance : n) * factor) * factor;
40739          };
40740        }
40741
40742        if (_isArray(snap)) {
40743          return function (n) {
40744            var i = snap.length,
40745                closest = 0,
40746                absDif = _bigNum,
40747                val,
40748                dif;
40749
40750            while (--i > -1) {
40751              val = snap[i];
40752              dif = val - n;
40753
40754              if (dif < 0) {
40755                dif = -dif;
40756              }
40757
40758              if (dif < absDif && val >= min && val <= max) {
40759                closest = i;
40760                absDif = dif;
40761              }
40762            }
40763
40764            return snap[closest];
40765          };
40766        }
40767
40768        return isNaN(snap) ? function (n) {
40769          return n;
40770        } : function () {
40771          return snap * factor;
40772        };
40773      },
40774          buildPointSnapFunc = function buildPointSnapFunc(snap, minX, maxX, minY, maxY, radius, factor) {
40775        radius = radius && radius < _bigNum ? radius * radius : _bigNum;
40776
40777        if (_isFunction(snap)) {
40778          return function (point) {
40779            var edgeTolerance = !self.isPressed ? 1 : 1 - self.edgeResistance,
40780                x = point.x,
40781                y = point.y,
40782                result,
40783                dx,
40784                dy;
40785            point.x = x = x > maxX ? maxX + (x - maxX) * edgeTolerance : x < minX ? minX + (x - minX) * edgeTolerance : x;
40786            point.y = y = y > maxY ? maxY + (y - maxY) * edgeTolerance : y < minY ? minY + (y - minY) * edgeTolerance : y;
40787            result = snap.call(self, point);
40788
40789            if (result !== point) {
40790              point.x = result.x;
40791              point.y = result.y;
40792            }
40793
40794            if (factor !== 1) {
40795              point.x *= factor;
40796              point.y *= factor;
40797            }
40798
40799            if (radius < _bigNum) {
40800              dx = point.x - x;
40801              dy = point.y - y;
40802
40803              if (dx * dx + dy * dy > radius) {
40804                point.x = x;
40805                point.y = y;
40806              }
40807            }
40808
40809            return point;
40810          };
40811        }
40812
40813        if (_isArray(snap)) {
40814          return function (p) {
40815            var i = snap.length,
40816                closest = 0,
40817                minDist = _bigNum,
40818                x,
40819                y,
40820                point,
40821                dist;
40822
40823            while (--i > -1) {
40824              point = snap[i];
40825              x = point.x - p.x;
40826              y = point.y - p.y;
40827              dist = x * x + y * y;
40828
40829              if (dist < minDist) {
40830                closest = i;
40831                minDist = dist;
40832              }
40833            }
40834
40835            return minDist <= radius ? snap[closest] : p;
40836          };
40837        }
40838
40839        return function (n) {
40840          return n;
40841        };
40842      },
40843          calculateBounds = function calculateBounds() {
40844        var bounds, targetBounds, snap, snapIsRaw;
40845        hasBounds = false;
40846
40847        if (scrollProxy) {
40848          scrollProxy.calibrate();
40849          self.minX = minX = -scrollProxy.maxScrollLeft();
40850          self.minY = minY = -scrollProxy.maxScrollTop();
40851          self.maxX = maxX = self.maxY = maxY = 0;
40852          hasBounds = true;
40853        } else if (!!vars.bounds) {
40854          bounds = _getBounds(vars.bounds, target.parentNode);
40855
40856          if (rotationMode) {
40857            self.minX = minX = bounds.left;
40858            self.maxX = maxX = bounds.left + bounds.width;
40859            self.minY = minY = self.maxY = maxY = 0;
40860          } else if (!_isUndefined(vars.bounds.maxX) || !_isUndefined(vars.bounds.maxY)) {
40861            bounds = vars.bounds;
40862            self.minX = minX = bounds.minX;
40863            self.minY = minY = bounds.minY;
40864            self.maxX = maxX = bounds.maxX;
40865            self.maxY = maxY = bounds.maxY;
40866          } else {
40867            targetBounds = _getBounds(target, target.parentNode);
40868            self.minX = minX = Math.round(getPropAsNum(xProp, "px") + bounds.left - targetBounds.left);
40869            self.minY = minY = Math.round(getPropAsNum(yProp, "px") + bounds.top - targetBounds.top);
40870            self.maxX = maxX = Math.round(minX + (bounds.width - targetBounds.width));
40871            self.maxY = maxY = Math.round(minY + (bounds.height - targetBounds.height));
40872          }
40873
40874          if (minX > maxX) {
40875            self.minX = maxX;
40876            self.maxX = maxX = minX;
40877            minX = self.minX;
40878          }
40879
40880          if (minY > maxY) {
40881            self.minY = maxY;
40882            self.maxY = maxY = minY;
40883            minY = self.minY;
40884          }
40885
40886          if (rotationMode) {
40887            self.minRotation = minX;
40888            self.maxRotation = maxX;
40889          }
40890
40891          hasBounds = true;
40892        }
40893
40894        if (vars.liveSnap) {
40895          snap = vars.liveSnap === true ? vars.snap || {} : vars.liveSnap;
40896          snapIsRaw = _isArray(snap) || _isFunction(snap);
40897
40898          if (rotationMode) {
40899            snapX = buildSnapFunc(snapIsRaw ? snap : snap.rotation, minX, maxX, 1);
40900            snapY = null;
40901          } else {
40902            if (snap.points) {
40903              snapXY = buildPointSnapFunc(snapIsRaw ? snap : snap.points, minX, maxX, minY, maxY, snap.radius, scrollProxy ? -1 : 1);
40904            } else {
40905              if (allowX) {
40906                snapX = buildSnapFunc(snapIsRaw ? snap : snap.x || snap.left || snap.scrollLeft, minX, maxX, scrollProxy ? -1 : 1);
40907              }
40908
40909              if (allowY) {
40910                snapY = buildSnapFunc(snapIsRaw ? snap : snap.y || snap.top || snap.scrollTop, minY, maxY, scrollProxy ? -1 : 1);
40911              }
40912            }
40913          }
40914        }
40915      },
40916          onThrowComplete = function onThrowComplete() {
40917        self.isThrowing = false;
40918
40919        _dispatchEvent(self, "throwcomplete", "onThrowComplete");
40920      },
40921          onThrowInterrupt = function onThrowInterrupt() {
40922        self.isThrowing = false;
40923      },
40924          animate = function animate(inertia, forceZeroVelocity) {
40925        var snap, snapIsRaw, tween, overshootTolerance;
40926
40927        if (inertia && InertiaPlugin) {
40928          if (inertia === true) {
40929            snap = vars.snap || vars.liveSnap || {};
40930            snapIsRaw = _isArray(snap) || _isFunction(snap);
40931            inertia = {
40932              resistance: (vars.throwResistance || vars.resistance || 1000) / (rotationMode ? 10 : 1)
40933            };
40934
40935            if (rotationMode) {
40936              inertia.rotation = _parseInertia(self, snapIsRaw ? snap : snap.rotation, maxX, minX, 1, forceZeroVelocity);
40937            } else {
40938              if (allowX) {
40939                inertia[xProp] = _parseInertia(self, snapIsRaw ? snap : snap.points || snap.x || snap.left, maxX, minX, scrollProxy ? -1 : 1, forceZeroVelocity || self.lockedAxis === "x");
40940              }
40941
40942              if (allowY) {
40943                inertia[yProp] = _parseInertia(self, snapIsRaw ? snap : snap.points || snap.y || snap.top, maxY, minY, scrollProxy ? -1 : 1, forceZeroVelocity || self.lockedAxis === "y");
40944              }
40945
40946              if (snap.points || _isArray(snap) && _isObject(snap[0])) {
40947                inertia.linkedProps = xProp + "," + yProp;
40948                inertia.radius = snap.radius;
40949              }
40950            }
40951          }
40952
40953          self.isThrowing = true;
40954          overshootTolerance = !isNaN(vars.overshootTolerance) ? vars.overshootTolerance : vars.edgeResistance === 1 ? 0 : 1 - self.edgeResistance + 0.2;
40955
40956          if (!inertia.duration) {
40957            inertia.duration = {
40958              max: Math.max(vars.minDuration || 0, "maxDuration" in vars ? vars.maxDuration : 2),
40959              min: !isNaN(vars.minDuration) ? vars.minDuration : overshootTolerance === 0 || _isObject(inertia) && inertia.resistance > 1000 ? 0 : 0.5,
40960              overshoot: overshootTolerance
40961            };
40962          }
40963
40964          self.tween = tween = gsap.to(scrollProxy || target, {
40965            inertia: inertia,
40966            data: "_draggable",
40967            inherit: false,
40968            onComplete: onThrowComplete,
40969            onInterrupt: onThrowInterrupt,
40970            onUpdate: vars.fastMode ? _dispatchEvent : syncXY,
40971            onUpdateParams: vars.fastMode ? [self, "onthrowupdate", "onThrowUpdate"] : snap && snap.radius ? [false, true] : []
40972          });
40973
40974          if (!vars.fastMode) {
40975            if (scrollProxy) {
40976              scrollProxy._skip = true;
40977            }
40978
40979            tween.render(1e9, true, true);
40980            syncXY(true, true);
40981            self.endX = self.x;
40982            self.endY = self.y;
40983
40984            if (rotationMode) {
40985              self.endRotation = self.x;
40986            }
40987
40988            tween.play(0);
40989            syncXY(true, true);
40990
40991            if (scrollProxy) {
40992              scrollProxy._skip = false;
40993            }
40994          }
40995        } else if (hasBounds) {
40996          self.applyBounds();
40997        }
40998      },
40999          updateMatrix = function updateMatrix(shiftStart) {
41000        var start = matrix,
41001            p;
41002        matrix = getGlobalMatrix(target.parentNode, true);
41003
41004        if (shiftStart && self.isPressed && !matrix.equals(start || new Matrix2D())) {
41005          p = start.inverse().apply({
41006            x: startPointerX,
41007            y: startPointerY
41008          });
41009          matrix.apply(p, p);
41010          startPointerX = p.x;
41011          startPointerY = p.y;
41012        }
41013
41014        if (matrix.equals(_identityMatrix$1)) {
41015          matrix = null;
41016        }
41017      },
41018          recordStartPositions = function recordStartPositions() {
41019        var edgeTolerance = 1 - self.edgeResistance,
41020            offsetX = isFixed ? _getDocScrollLeft$1(ownerDoc) : 0,
41021            offsetY = isFixed ? _getDocScrollTop$1(ownerDoc) : 0,
41022            parsedOrigin,
41023            x,
41024            y;
41025
41026        if (xyMode) {
41027          gsCache.x = getPropAsNum(xProp, "px") + "px";
41028          gsCache.y = getPropAsNum(yProp, "px") + "px";
41029          gsCache.renderTransform();
41030        }
41031
41032        updateMatrix(false);
41033        _point1.x = self.pointerX - offsetX;
41034        _point1.y = self.pointerY - offsetY;
41035        matrix && matrix.apply(_point1, _point1);
41036        startPointerX = _point1.x;
41037        startPointerY = _point1.y;
41038
41039        if (dirty) {
41040          setPointerPosition(self.pointerX, self.pointerY);
41041          render(true);
41042        }
41043
41044        innerMatrix = getGlobalMatrix(target);
41045
41046        if (scrollProxy) {
41047          calculateBounds();
41048          startElementY = scrollProxy.top();
41049          startElementX = scrollProxy.left();
41050        } else {
41051          if (isTweening()) {
41052            syncXY(true, true);
41053            calculateBounds();
41054          } else {
41055            self.applyBounds();
41056          }
41057
41058          if (rotationMode) {
41059            parsedOrigin = target.ownerSVGElement ? [gsCache.xOrigin - target.getBBox().x, gsCache.yOrigin - target.getBBox().y] : (_getComputedStyle(target)[_transformOriginProp$1] || "0 0").split(" ");
41060            rotationOrigin = self.rotationOrigin = getGlobalMatrix(target).apply({
41061              x: parseFloat(parsedOrigin[0]) || 0,
41062              y: parseFloat(parsedOrigin[1]) || 0
41063            });
41064            syncXY(true, true);
41065            x = self.pointerX - rotationOrigin.x - offsetX;
41066            y = rotationOrigin.y - self.pointerY + offsetY;
41067            startElementX = self.x;
41068            startElementY = self.y = Math.atan2(y, x) * _RAD2DEG;
41069          } else {
41070            startElementY = getPropAsNum(yProp, "px");
41071            startElementX = getPropAsNum(xProp, "px");
41072          }
41073        }
41074
41075        if (hasBounds && edgeTolerance) {
41076          if (startElementX > maxX) {
41077            startElementX = maxX + (startElementX - maxX) / edgeTolerance;
41078          } else if (startElementX < minX) {
41079            startElementX = minX - (minX - startElementX) / edgeTolerance;
41080          }
41081
41082          if (!rotationMode) {
41083            if (startElementY > maxY) {
41084              startElementY = maxY + (startElementY - maxY) / edgeTolerance;
41085            } else if (startElementY < minY) {
41086              startElementY = minY - (minY - startElementY) / edgeTolerance;
41087            }
41088          }
41089        }
41090
41091        self.startX = startElementX = _round(startElementX);
41092        self.startY = startElementY = _round(startElementY);
41093      },
41094          isTweening = function isTweening() {
41095        return self.tween && self.tween.isActive();
41096      },
41097          removePlaceholder = function removePlaceholder() {
41098        if (_placeholderDiv.parentNode && !isTweening() && !self.isDragging) {
41099          _placeholderDiv.parentNode.removeChild(_placeholderDiv);
41100        }
41101      },
41102          onPress = function onPress(e, force) {
41103        var i;
41104
41105        if (!enabled || self.isPressed || !e || (e.type === "mousedown" || e.type === "pointerdown") && !force && _getTime() - clickTime < 30 && _touchEventLookup[self.pointerEvent.type]) {
41106          isPreventingDefault && e && enabled && _preventDefault(e);
41107          return;
41108        }
41109
41110        interrupted = isTweening();
41111        dragged = false;
41112        self.pointerEvent = e;
41113
41114        if (_touchEventLookup[e.type]) {
41115          touchEventTarget = ~e.type.indexOf("touch") ? e.currentTarget || e.target : ownerDoc;
41116
41117          _addListener(touchEventTarget, "touchend", onRelease);
41118
41119          _addListener(touchEventTarget, "touchmove", onMove);
41120
41121          _addListener(touchEventTarget, "touchcancel", onRelease);
41122
41123          _addListener(ownerDoc, "touchstart", _onMultiTouchDocument);
41124        } else {
41125          touchEventTarget = null;
41126
41127          _addListener(ownerDoc, "mousemove", onMove);
41128        }
41129
41130        touchDragAxis = null;
41131
41132        if (!_supportsPointer || !touchEventTarget) {
41133          _addListener(ownerDoc, "mouseup", onRelease);
41134
41135          e && e.target && _addListener(e.target, "mouseup", onRelease);
41136        }
41137
41138        isClicking = isClickable.call(self, e.target) && vars.dragClickables === false && !force;
41139
41140        if (isClicking) {
41141          _addListener(e.target, "change", onRelease);
41142
41143          _dispatchEvent(self, "pressInit", "onPressInit");
41144
41145          _dispatchEvent(self, "press", "onPress");
41146
41147          _setSelectable(triggers, true);
41148
41149          isPreventingDefault = false;
41150          return;
41151        }
41152
41153        allowNativeTouchScrolling = !touchEventTarget || allowX === allowY || self.vars.allowNativeTouchScrolling === false || self.vars.allowContextMenu && e && (e.ctrlKey || e.which > 2) ? false : allowX ? "y" : "x";
41154        isPreventingDefault = !allowNativeTouchScrolling && !self.allowEventDefault;
41155
41156        if (isPreventingDefault) {
41157          _preventDefault(e);
41158
41159          _addListener(_win$1, "touchforcechange", _preventDefault);
41160        }
41161
41162        if (e.changedTouches) {
41163          e = touch = e.changedTouches[0];
41164          touchID = e.identifier;
41165        } else if (e.pointerId) {
41166          touchID = e.pointerId;
41167        } else {
41168          touch = touchID = null;
41169        }
41170
41171        _dragCount++;
41172
41173        _addToRenderQueue(render);
41174
41175        startPointerY = self.pointerY = e.pageY;
41176        startPointerX = self.pointerX = e.pageX;
41177
41178        _dispatchEvent(self, "pressInit", "onPressInit");
41179
41180        if (allowNativeTouchScrolling || self.autoScroll) {
41181          _recordMaxScrolls(target.parentNode);
41182        }
41183
41184        if (target.parentNode && self.autoScroll && !scrollProxy && !rotationMode && target.parentNode._gsMaxScrollX && !_placeholderDiv.parentNode && !target.getBBox) {
41185          _placeholderDiv.style.width = target.parentNode.scrollWidth + "px";
41186          target.parentNode.appendChild(_placeholderDiv);
41187        }
41188
41189        recordStartPositions();
41190        self.tween && self.tween.kill();
41191        self.isThrowing = false;
41192        gsap.killTweensOf(scrollProxy || target, killProps, true);
41193        scrollProxy && gsap.killTweensOf(target, {
41194          scrollTo: 1
41195        }, true);
41196        self.tween = self.lockedAxis = null;
41197
41198        if (vars.zIndexBoost || !rotationMode && !scrollProxy && vars.zIndexBoost !== false) {
41199          target.style.zIndex = Draggable.zIndex++;
41200        }
41201
41202        self.isPressed = true;
41203        hasDragCallback = !!(vars.onDrag || self._listeners.drag);
41204        hasMoveCallback = !!(vars.onMove || self._listeners.move);
41205
41206        if (vars.cursor !== false || vars.activeCursor) {
41207          i = triggers.length;
41208
41209          while (--i > -1) {
41210            gsap.set(triggers[i], {
41211              cursor: vars.activeCursor || vars.cursor || (_defaultCursor === "grab" ? "grabbing" : _defaultCursor)
41212            });
41213          }
41214        }
41215
41216        _dispatchEvent(self, "press", "onPress");
vendor: 2,447 bytes, lines 41217-41284
41217      },
41218          onMove = function onMove(e) {
41219        var originalEvent = e,
41220            touches,
41221            pointerX,
41222            pointerY,
41223            i,
41224            dx,
41225            dy;
41226
41227        if (!enabled || _isMultiTouching || !self.isPressed || !e) {
41228          isPreventingDefault && e && enabled && _preventDefault(e);
41229          return;
41230        }
41231
41232        self.pointerEvent = e;
41233        touches = e.changedTouches;
41234
41235        if (touches) {
41236          e = touches[0];
41237
41238          if (e !== touch && e.identifier !== touchID) {
41239            i = touches.length;
41240
41241            while (--i > -1 && (e = touches[i]).identifier !== touchID && e.target !== target) {}
41242
41243            if (i < 0) {
41244              return;
41245            }
41246          }
41247        } else if (e.pointerId && touchID && e.pointerId !== touchID) {
41248          return;
41249        }
41250
41251        if (touchEventTarget && allowNativeTouchScrolling && !touchDragAxis) {
41252          _point1.x = e.pageX - (isFixed ? _getDocScrollLeft$1(ownerDoc) : 0);
41253          _point1.y = e.pageY - (isFixed ? _getDocScrollTop$1(ownerDoc) : 0);
41254          matrix && matrix.apply(_point1, _point1);
41255          pointerX = _point1.x;
41256          pointerY = _point1.y;
41257          dx = Math.abs(pointerX - startPointerX);
41258          dy = Math.abs(pointerY - startPointerY);
41259
41260          if (dx !== dy && (dx > minimumMovement || dy > minimumMovement) || _isAndroid && allowNativeTouchScrolling === touchDragAxis) {
41261            touchDragAxis = dx > dy && allowX ? "x" : "y";
41262
41263            if (allowNativeTouchScrolling && touchDragAxis !== allowNativeTouchScrolling) {
41264              _addListener(_win$1, "touchforcechange", _preventDefault);
41265            }
41266
41267            if (self.vars.lockAxisOnTouchScroll !== false && allowX && allowY) {
41268              self.lockedAxis = touchDragAxis === "x" ? "y" : "x";
41269              _isFunction(self.vars.onLockAxis) && self.vars.onLockAxis.call(self, originalEvent);
41270            }
41271
41272            if (_isAndroid && allowNativeTouchScrolling === touchDragAxis) {
41273              onRelease(originalEvent);
41274              return;
41275            }
41276          }
41277        }
41278
41279        if (!self.allowEventDefault && (!allowNativeTouchScrolling || touchDragAxis && allowNativeTouchScrolling !== touchDragAxis) && originalEvent.cancelable !== false) {
41280          _preventDefault(originalEvent);
41281
41282          isPreventingDefault = true;
41283        } else if (isPreventingDefault) {
41284          isPreventingDefault = false;
vendor: 3,917 bytes, lines 41285-41413
41285        }
41286
41287        if (self.autoScroll) {
41288          checkAutoScrollBounds = true;
41289        }
41290
41291        setPointerPosition(e.pageX, e.pageY, hasMoveCallback);
41292      },
41293          setPointerPosition = function setPointerPosition(pointerX, pointerY, invokeOnMove) {
41294        var dragTolerance = 1 - self.dragResistance,
41295            edgeTolerance = 1 - self.edgeResistance,
41296            prevPointerX = self.pointerX,
41297            prevPointerY = self.pointerY,
41298            prevStartElementY = startElementY,
41299            prevX = self.x,
41300            prevY = self.y,
41301            prevEndX = self.endX,
41302            prevEndY = self.endY,
41303            prevEndRotation = self.endRotation,
41304            prevDirty = dirty,
41305            xChange,
41306            yChange,
41307            x,
41308            y,
41309            dif,
41310            temp;
41311        self.pointerX = pointerX;
41312        self.pointerY = pointerY;
41313
41314        if (isFixed) {
41315          pointerX -= _getDocScrollLeft$1(ownerDoc);
41316          pointerY -= _getDocScrollTop$1(ownerDoc);
41317        }
41318
41319        if (rotationMode) {
41320          y = Math.atan2(rotationOrigin.y - pointerY, pointerX - rotationOrigin.x) * _RAD2DEG;
41321          dif = self.y - y;
41322
41323          if (dif > 180) {
41324            startElementY -= 360;
41325            self.y = y;
41326          } else if (dif < -180) {
41327            startElementY += 360;
41328            self.y = y;
41329          }
41330
41331          if (self.x !== startElementX || Math.abs(startElementY - y) > minimumMovement) {
41332            self.y = y;
41333            x = startElementX + (startElementY - y) * dragTolerance;
41334          } else {
41335            x = startElementX;
41336          }
41337        } else {
41338          if (matrix) {
41339            temp = pointerX * matrix.a + pointerY * matrix.c + matrix.e;
41340            pointerY = pointerX * matrix.b + pointerY * matrix.d + matrix.f;
41341            pointerX = temp;
41342          }
41343
41344          yChange = pointerY - startPointerY;
41345          xChange = pointerX - startPointerX;
41346
41347          if (yChange < minimumMovement && yChange > -minimumMovement) {
41348            yChange = 0;
41349          }
41350
41351          if (xChange < minimumMovement && xChange > -minimumMovement) {
41352            xChange = 0;
41353          }
41354
41355          if ((self.lockAxis || self.lockedAxis) && (xChange || yChange)) {
41356            temp = self.lockedAxis;
41357
41358            if (!temp) {
41359              self.lockedAxis = temp = allowX && Math.abs(xChange) > Math.abs(yChange) ? "y" : allowY ? "x" : null;
41360
41361              if (temp && _isFunction(self.vars.onLockAxis)) {
41362                self.vars.onLockAxis.call(self, self.pointerEvent);
41363              }
41364            }
41365
41366            if (temp === "y") {
41367              yChange = 0;
41368            } else if (temp === "x") {
41369              xChange = 0;
41370            }
41371          }
41372
41373          x = _round(startElementX + xChange * dragTolerance);
41374          y = _round(startElementY + yChange * dragTolerance);
41375        }
41376
41377        if ((snapX || snapY || snapXY) && (self.x !== x || self.y !== y && !rotationMode)) {
41378          if (snapXY) {
41379            _temp1.x = x;
41380            _temp1.y = y;
41381            temp = snapXY(_temp1);
41382            x = _round(temp.x);
41383            y = _round(temp.y);
41384          }
41385
41386          if (snapX) {
41387            x = _round(snapX(x));
41388          }
41389
41390          if (snapY) {
41391            y = _round(snapY(y));
41392          }
41393        }
41394
41395        if (hasBounds) {
41396          if (x > maxX) {
41397            x = maxX + Math.round((x - maxX) * edgeTolerance);
41398          } else if (x < minX) {
41399            x = minX + Math.round((x - minX) * edgeTolerance);
41400          }
41401
41402          if (!rotationMode) {
41403            if (y > maxY) {
41404              y = Math.round(maxY + (y - maxY) * edgeTolerance);
41405            } else if (y < minY) {
41406              y = Math.round(minY + (y - minY) * edgeTolerance);
41407            }
41408          }
41409        }
41410
41411        if (self.x !== x || self.y !== y && !rotationMode) {
41412          if (rotationMode) {
41413            self.endRotation = self.x = self.endX = x
vendor: 13,666 bytes, lines 41413-41820
41413;
41414            dirty = true;
41415          } else {
41416            if (allowY) {
41417              self.y = self.endY = y;
41418              dirty = true;
41419            }
41420
41421            if (allowX) {
41422              self.x = self.endX = x;
41423              dirty = true;
41424            }
41425          }
41426
41427          if (!invokeOnMove || _dispatchEvent(self, "move", "onMove") !== false) {
41428            if (!self.isDragging && self.isPressed) {
41429              self.isDragging = dragged = true;
41430
41431              _dispatchEvent(self, "dragstart", "onDragStart");
41432            }
41433          } else {
41434            self.pointerX = prevPointerX;
41435            self.pointerY = prevPointerY;
41436            startElementY = prevStartElementY;
41437            self.x = prevX;
41438            self.y = prevY;
41439            self.endX = prevEndX;
41440            self.endY = prevEndY;
41441            self.endRotation = prevEndRotation;
41442            dirty = prevDirty;
41443          }
41444        }
41445      },
41446          onRelease = function onRelease(e, force) {
41447        if (!enabled || !self.isPressed || e && touchID != null && !force && (e.pointerId && e.pointerId !== touchID && e.target !== target || e.changedTouches && !_hasTouchID(e.changedTouches, touchID))) {
41448          isPreventingDefault && e && enabled && _preventDefault(e);
41449          return;
41450        }
41451
41452        self.isPressed = false;
41453        var originalEvent = e,
41454            wasDragging = self.isDragging,
41455            isContextMenuRelease = self.vars.allowContextMenu && e && (e.ctrlKey || e.which > 2),
41456            placeholderDelayedCall = gsap.delayedCall(0.001, removePlaceholder),
41457            touches,
41458            i,
41459            syntheticEvent,
41460            eventTarget,
41461            syntheticClick;
41462
41463        if (touchEventTarget) {
41464          _removeListener(touchEventTarget, "touchend", onRelease);
41465
41466          _removeListener(touchEventTarget, "touchmove", onMove);
41467
41468          _removeListener(touchEventTarget, "touchcancel", onRelease);
41469
41470          _removeListener(ownerDoc, "touchstart", _onMultiTouchDocument);
41471        } else {
41472          _removeListener(ownerDoc, "mousemove", onMove);
41473        }
41474
41475        _removeListener(_win$1, "touchforcechange", _preventDefault);
41476
41477        if (!_supportsPointer || !touchEventTarget) {
41478          _removeListener(ownerDoc, "mouseup", onRelease);
41479
41480          e && e.target && _removeListener(e.target, "mouseup", onRelease);
41481        }
41482
41483        dirty = false;
41484
41485        if (wasDragging) {
41486          dragEndTime = _lastDragTime = _getTime();
41487          self.isDragging = false;
41488        }
41489
41490        _removeFromRenderQueue(render);
41491
41492        if (isClicking && !isContextMenuRelease) {
41493          if (e) {
41494            _removeListener(e.target, "change", onRelease);
41495
41496            self.pointerEvent = originalEvent;
41497          }
41498
41499          _setSelectable(triggers, false);
41500
41501          _dispatchEvent(self, "release", "onRelease");
41502
41503          _dispatchEvent(self, "click", "onClick");
41504
41505          isClicking = false;
41506          return;
41507        }
41508
41509        i = triggers.length;
41510
41511        while (--i > -1) {
41512          _setStyle(triggers[i], "cursor", vars.cursor || (vars.cursor !== false ? _defaultCursor : null));
41513        }
41514
41515        _dragCount--;
41516
41517        if (e) {
41518          touches = e.changedTouches;
41519
41520          if (touches) {
41521            e = touches[0];
41522
41523            if (e !== touch && e.identifier !== touchID) {
41524              i = touches.length;
41525
41526              while (--i > -1 && (e = touches[i]).identifier !== touchID && e.target !== target) {}
41527
41528              if (i < 0 && !force) {
41529                return;
41530              }
41531            }
41532          }
41533
41534          self.pointerEvent = originalEvent;
41535          self.pointerX = e.pageX;
41536          self.pointerY = e.pageY;
41537        }
41538
41539        if (isContextMenuRelease && originalEvent) {
41540          _preventDefault(originalEvent);
41541
41542          isPreventingDefault = true;
41543
41544          _dispatchEvent(self, "release", "onRelease");
41545        } else if (originalEvent && !wasDragging) {
41546          isPreventingDefault = false;
41547
41548          if (interrupted && (vars.snap || vars.bounds)) {
41549            animate(vars.inertia || vars.throwProps);
41550          }
41551
41552          _dispatchEvent(self, "release", "onRelease");
41553
41554          if ((!_isAndroid || originalEvent.type !== "touchmove") && originalEvent.type.indexOf("cancel") === -1) {
41555            _dispatchEvent(self, "click", "onClick");
41556
41557            if (_getTime() - clickTime < 300) {
41558              _dispatchEvent(self, "doubleclick", "onDoubleClick");
41559            }
41560
41561            eventTarget = originalEvent.target || target;
41562            clickTime = _getTime();
41563
41564            syntheticClick = function syntheticClick() {
41565              if (clickTime !== clickDispatch && self.enabled() && !self.isPressed && !originalEvent.defaultPrevented) {
41566                if (eventTarget.click) {
41567                  eventTarget.click();
41568                } else if (ownerDoc.createEvent) {
41569                  syntheticEvent = ownerDoc.createEvent("MouseEvents");
41570                  syntheticEvent.initMouseEvent("click", true, true, _win$1, 1, self.pointerEvent.screenX, self.pointerEvent.screenY, self.pointerX, self.pointerY, false, false, false, false, 0, null);
41571                  eventTarget.dispatchEvent(syntheticEvent);
41572                }
41573              }
41574            };
41575
41576            if (!_isAndroid && !originalEvent.defaultPrevented) {
41577              gsap.delayedCall(0.05, syntheticClick);
41578            }
41579          }
41580        } else {
41581          animate(vars.inertia || vars.throwProps);
41582
41583          if (!self.allowEventDefault && originalEvent && (vars.dragClickables !== false || !isClickable.call(self, originalEvent.target)) && wasDragging && (!allowNativeTouchScrolling || touchDragAxis && allowNativeTouchScrolling === touchDragAxis) && originalEvent.cancelable !== false) {
41584            isPreventingDefault = true;
41585
41586            _preventDefault(originalEvent);
41587          } else {
41588            isPreventingDefault = false;
41589          }
41590
41591          _dispatchEvent(self, "release", "onRelease");
41592        }
41593
41594        isTweening() && placeholderDelayedCall.duration(self.tween.duration());
41595        wasDragging && _dispatchEvent(self, "dragend", "onDragEnd");
41596        return true;
41597      },
41598          updateScroll = function updateScroll(e) {
41599        if (e && self.isDragging && !scrollProxy) {
41600          var parent = e.target || target.parentNode,
41601              deltaX = parent.scrollLeft - parent._gsScrollX,
41602              deltaY = parent.scrollTop - parent._gsScrollY;
41603
41604          if (deltaX || deltaY) {
41605            if (matrix) {
41606              startPointerX -= deltaX * matrix.a + deltaY * matrix.c;
41607              startPointerY -= deltaY * matrix.d + deltaX * matrix.b;
41608            } else {
41609              startPointerX -= deltaX;
41610              startPointerY -= deltaY;
41611            }
41612
41613            parent._gsScrollX += deltaX;
41614            parent._gsScrollY += deltaY;
41615            setPointerPosition(self.pointerX, self.pointerY);
41616          }
41617        }
41618      },
41619          onClick = function onClick(e) {
41620        var time = _getTime(),
41621            recentlyClicked = time - clickTime < 100,
41622            recentlyDragged = time - dragEndTime < 50,
41623            alreadyDispatched = recentlyClicked && clickDispatch === clickTime,
41624            defaultPrevented = self.pointerEvent && self.pointerEvent.defaultPrevented,
41625            alreadyDispatchedTrusted = recentlyClicked && trustedClickDispatch === clickTime,
41626            trusted = e.isTrusted || e.isTrusted == null && recentlyClicked && alreadyDispatched;
41627
41628        if ((alreadyDispatched || recentlyDragged && self.vars.suppressClickOnDrag !== false) && e.stopImmediatePropagation) {
41629          e.stopImmediatePropagation();
41630        }
41631
41632        if (recentlyClicked && !(self.pointerEvent && self.pointerEvent.defaultPrevented) && (!alreadyDispatched || trusted && !alreadyDispatchedTrusted)) {
41633          if (trusted && alreadyDispatched) {
41634            trustedClickDispatch = clickTime;
41635          }
41636
41637          clickDispatch = clickTime;
41638          return;
41639        }
41640
41641        if (self.isPressed || recentlyDragged || recentlyClicked) {
41642          if (!trusted || !e.detail || !recentlyClicked || defaultPrevented) {
41643            _preventDefault(e);
41644          }
41645        }
41646
41647        if (!recentlyClicked && !recentlyDragged && !dragged) {
41648          e && e.target && (self.pointerEvent = e);
41649
41650          _dispatchEvent(self, "click", "onClick");
41651        }
41652      },
41653          localizePoint = function localizePoint(p) {
41654        return matrix ? {
41655          x: p.x * matrix.a + p.y * matrix.c + matrix.e,
41656          y: p.x * matrix.b + p.y * matrix.d + matrix.f
41657        } : {
41658          x: p.x,
41659          y: p.y
41660        };
41661      };
41662
41663      old = Draggable.get(target);
41664      old && old.kill();
41665
41666      _this2.startDrag = function (event, align) {
41667        var r1, r2, p1, p2;
41668        onPress(event || self.pointerEvent, true);
41669
41670        if (align && !self.hitTest(event || self.pointerEvent)) {
41671          r1 = _parseRect(event || self.pointerEvent);
41672          r2 = _parseRect(target);
41673          p1 = localizePoint({
41674            x: r1.left + r1.width / 2,
41675            y: r1.top + r1.height / 2
41676          });
41677          p2 = localizePoint({
41678            x: r2.left + r2.width / 2,
41679            y: r2.top + r2.height / 2
41680          });
41681          startPointerX -= p1.x - p2.x;
41682          startPointerY -= p1.y - p2.y;
41683        }
41684
41685        if (!self.isDragging) {
41686          self.isDragging = dragged = true;
41687
41688          _dispatchEvent(self, "dragstart", "onDragStart");
41689        }
41690      };
41691
41692      _this2.drag = onMove;
41693
41694      _this2.endDrag = function (e) {
41695        return onRelease(e || self.pointerEvent, true);
41696      };
41697
41698      _this2.timeSinceDrag = function () {
41699        return self.isDragging ? 0 : (_getTime() - dragEndTime) / 1000;
41700      };
41701
41702      _this2.timeSinceClick = function () {
41703        return (_getTime() - clickTime) / 1000;
41704      };
41705
41706      _this2.hitTest = function (target, threshold) {
41707        return Draggable.hitTest(self.target, target, threshold);
41708      };
41709
41710      _this2.getDirection = function (from, diagonalThreshold) {
41711        var mode = from === "velocity" && InertiaPlugin ? from : _isObject(from) && !rotationMode ? "element" : "start",
41712            xChange,
41713            yChange,
41714            ratio,
41715            direction,
41716            r1,
41717            r2;
41718
41719        if (mode === "element") {
41720          r1 = _parseRect(self.target);
41721          r2 = _parseRect(from);
41722        }
41723
41724        xChange = mode === "start" ? self.x - startElementX : mode === "velocity" ? InertiaPlugin.getVelocity(target, xProp) : r1.left + r1.width / 2 - (r2.left + r2.width / 2);
41725
41726        if (rotationMode) {
41727          return xChange < 0 ? "counter-clockwise" : "clockwise";
41728        } else {
41729          diagonalThreshold = diagonalThreshold || 2;
41730          yChange = mode === "start" ? self.y - startElementY : mode === "velocity" ? InertiaPlugin.getVelocity(target, yProp) : r1.top + r1.height / 2 - (r2.top + r2.height / 2);
41731          ratio = Math.abs(xChange / yChange);
41732          direction = ratio < 1 / diagonalThreshold ? "" : xChange < 0 ? "left" : "right";
41733
41734          if (ratio < diagonalThreshold) {
41735            if (direction !== "") {
41736              direction += "-";
41737            }
41738
41739            direction += yChange < 0 ? "up" : "down";
41740          }
41741        }
41742
41743        return direction;
41744      };
41745
41746      _this2.applyBounds = function (newBounds, sticky) {
41747        var x, y, forceZeroVelocity, e, parent, isRoot;
41748
41749        if (newBounds && vars.bounds !== newBounds) {
41750          vars.bounds = newBounds;
41751          return self.update(true, sticky);
41752        }
41753
41754        syncXY(true);
41755        calculateBounds();
41756
41757        if (hasBounds && !isTweening()) {
41758          x = self.x;
41759          y = self.y;
41760
41761          if (x > maxX) {
41762            x = maxX;
41763          } else if (x < minX) {
41764            x = minX;
41765          }
41766
41767          if (y > maxY) {
41768            y = maxY;
41769          } else if (y < minY) {
41770            y = minY;
41771          }
41772
41773          if (self.x !== x || self.y !== y) {
41774            forceZeroVelocity = true;
41775            self.x = self.endX = x;
41776
41777            if (rotationMode) {
41778              self.endRotation = x;
41779            } else {
41780              self.y = self.endY = y;
41781            }
41782
41783            dirty = true;
41784            render(true);
41785
41786            if (self.autoScroll && !self.isDragging) {
41787              _recordMaxScrolls(target.parentNode);
41788
41789              e = target;
41790              _windowProxy.scrollTop = _win$1.pageYOffset != null ? _win$1.pageYOffset : ownerDoc.documentElement.scrollTop != null ? ownerDoc.documentElement.scrollTop : ownerDoc.body.scrollTop;
41791              _windowProxy.scrollLeft = _win$1.pageXOffset != null ? _win$1.pageXOffset : ownerDoc.documentElement.scrollLeft != null ? ownerDoc.documentElement.scrollLeft : ownerDoc.body.scrollLeft;
41792
41793              while (e && !isRoot) {
41794                isRoot = _isRoot(e.parentNode);
41795                parent = isRoot ? _windowProxy : e.parentNode;
41796
41797                if (allowY && parent.scrollTop > parent._gsMaxScrollY) {
41798                  parent.scrollTop = parent._gsMaxScrollY;
41799                }
41800
41801                if (allowX && parent.scrollLeft > parent._gsMaxScrollX) {
41802                  parent.scrollLeft = parent._gsMaxScrollX;
41803                }
41804
41805                e = parent;
41806              }
41807            }
41808          }
41809
41810          if (self.isThrowing && (forceZeroVelocity || self.endX > maxX || self.endX < minX || self.endY > maxY || self.endY < minY)) {
41811            animate(vars.inertia || vars.throwProps, forceZeroVelocity);
41812          }
41813        }
41814
41815        return self;
41816      };
41817
41818      _this2.update = function (applyBounds, sticky, ignoreExternalChanges) {
41819        if (sticky && self.isPressed) {
41820          
vendor: 3,070 bytes, lines 41820-41921
41820var m = getGlobalMatrix(target),
41821              p = innerMatrix.apply({
41822            x: self.x - startElementX,
41823            y: self.y - startElementY
41824          }),
41825              m2 = getGlobalMatrix(target.parentNode, true);
41826          m2.apply({
41827            x: m.e - p.x,
41828            y: m.f - p.y
41829          }, p);
41830          self.x -= p.x - m2.e;
41831          self.y -= p.y - m2.f;
41832          render(true);
41833          recordStartPositions();
41834        }
41835
41836        var x = self.x,
41837            y = self.y;
41838        updateMatrix(!sticky);
41839
41840        if (applyBounds) {
41841          self.applyBounds();
41842        } else {
41843          dirty && ignoreExternalChanges && render(true);
41844          syncXY(true);
41845        }
41846
41847        if (sticky) {
41848          setPointerPosition(self.pointerX, self.pointerY);
41849          dirty && render(true);
41850        }
41851
41852        if (self.isPressed && !sticky && (allowX && Math.abs(x - self.x) > 0.01 || allowY && Math.abs(y - self.y) > 0.01 && !rotationMode)) {
41853          recordStartPositions();
41854        }
41855
41856        if (self.autoScroll) {
41857          _recordMaxScrolls(target.parentNode, self.isDragging);
41858
41859          checkAutoScrollBounds = self.isDragging;
41860          render(true);
41861
41862          _removeScrollListener(target, updateScroll);
41863
41864          _addScrollListener(target, updateScroll);
41865        }
41866
41867        return self;
41868      };
41869
41870      _this2.enable = function (type) {
41871        var setVars = {
41872          lazy: true
41873        },
41874            id,
41875            i,
41876            trigger;
41877
41878        if (vars.cursor !== false) {
41879          setVars.cursor = vars.cursor || _defaultCursor;
41880        }
41881
41882        if (gsap.utils.checkPrefix("touchCallout")) {
41883          setVars.touchCallout = "none";
41884        }
41885
41886        if (type !== "soft") {
41887          _setTouchActionForAllDescendants(triggers, allowX === allowY ? "none" : vars.allowNativeTouchScrolling && target.scrollHeight === target.clientHeight === (target.scrollWidth === target.clientHeight) || vars.allowEventDefault ? "manipulation" : allowX ? "pan-y" : "pan-x");
41888
41889          i = triggers.length;
41890
41891          while (--i > -1) {
41892            trigger = triggers[i];
41893            _supportsPointer || _addListener(trigger, "mousedown", onPress);
41894
41895            _addListener(trigger, "touchstart", onPress);
41896
41897            _addListener(trigger, "click", onClick, true);
41898
41899            gsap.set(trigger, setVars);
41900
41901            if (trigger.getBBox && trigger.ownerSVGElement && allowX !== allowY) {
41902              gsap.set(trigger.ownerSVGElement, {
41903                touchAction: vars.allowNativeTouchScrolling || vars.allowEventDefault ? "manipulation" : allowX ? "pan-y" : "pan-x"
41904              });
41905            }
41906
41907            vars.allowContextMenu || _addListener(trigger, "contextmenu", onContextMenu);
41908          }
41909
41910          _setSelectable(triggers, false);
41911        }
41912
41913        _addScrollListener(target, updateScroll);
41914
41915        enabled = true;
41916
41917        if (InertiaPlugin && type !== "soft") {
41918          InertiaPlugin.track(scrollProxy || target, xyMode ? "x,y" : rotationMode ? "rotation" : "top,left");
41919        }
41920
41921        target._gsDragID = id =
vendor: 5,466 bytes, lines 41921-42127
41921 "d" + _lookupCount++;
41922        _lookup[id] = self;
41923
41924        if (scrollProxy) {
41925          scrollProxy.enable();
41926          scrollProxy.element._gsDragID = id;
41927        }
41928
41929        (vars.bounds || rotationMode) && recordStartPositions();
41930        vars.bounds && self.applyBounds();
41931        return self;
41932      };
41933
41934      _this2.disable = function (type) {
41935        var dragging = self.isDragging,
41936            i = triggers.length,
41937            trigger;
41938
41939        while (--i > -1) {
41940          _setStyle(triggers[i], "cursor", null);
41941        }
41942
41943        if (type !== "soft") {
41944          _setTouchActionForAllDescendants(triggers, null);
41945
41946          i = triggers.length;
41947
41948          while (--i > -1) {
41949            trigger = triggers[i];
41950
41951            _setStyle(trigger, "touchCallout", null);
41952
41953            _removeListener(trigger, "mousedown", onPress);
41954
41955            _removeListener(trigger, "touchstart", onPress);
41956
41957            _removeListener(trigger, "click", onClick, true);
41958
41959            _removeListener(trigger, "contextmenu", onContextMenu);
41960          }
41961
41962          _setSelectable(triggers, true);
41963
41964          if (touchEventTarget) {
41965            _removeListener(touchEventTarget, "touchcancel", onRelease);
41966
41967            _removeListener(touchEventTarget, "touchend", onRelease);
41968
41969            _removeListener(touchEventTarget, "touchmove", onMove);
41970          }
41971
41972          _removeListener(ownerDoc, "mouseup", onRelease);
41973
41974          _removeListener(ownerDoc, "mousemove", onMove);
41975        }
41976
41977        _removeScrollListener(target, updateScroll);
41978
41979        enabled = false;
41980
41981        if (InertiaPlugin && type !== "soft") {
41982          InertiaPlugin.untrack(scrollProxy || target, xyMode ? "x,y" : rotationMode ? "rotation" : "top,left");
41983          self.tween && self.tween.kill();
41984        }
41985
41986        scrollProxy && scrollProxy.disable();
41987
41988        _removeFromRenderQueue(render);
41989
41990        self.isDragging = self.isPressed = isClicking = false;
41991        dragging && _dispatchEvent(self, "dragend", "onDragEnd");
41992        return self;
41993      };
41994
41995      _this2.enabled = function (value, type) {
41996        return arguments.length ? value ? self.enable(type) : self.disable(type) : enabled;
41997      };
41998
41999      _this2.kill = function () {
42000        self.isThrowing = false;
42001        self.tween && self.tween.kill();
42002        self.disable();
42003        gsap.set(triggers, {
42004          clearProps: "userSelect"
42005        });
42006        delete _lookup[target._gsDragID];
42007        return self;
42008      };
42009
42010      _this2.revert = function () {
42011        this.kill();
42012        this.styles && this.styles.revert();
42013      };
42014
42015      if (~type.indexOf("scroll")) {
42016        scrollProxy = _this2.scrollProxy = new ScrollProxy(target, _extend({
42017          onKill: function onKill() {
42018            self.isPressed && onRelease(null);
42019          }
42020        }, vars));
42021        target.style.overflowY = allowY && !_isTouchDevice ? "auto" : "hidden";
42022        target.style.overflowX = allowX && !_isTouchDevice ? "auto" : "hidden";
42023        target = scrollProxy.content;
42024      }
42025
42026      if (rotationMode) {
42027        killProps.rotation = 1;
42028      } else {
42029        if (allowX) {
42030          killProps[xProp] = 1;
42031        }
42032
42033        if (allowY) {
42034          killProps[yProp] = 1;
42035        }
42036      }
42037
42038      gsCache.force3D = "force3D" in vars ? vars.force3D : true;
42039
42040      _context(_assertThisInitialized(_this2));
42041
42042      _this2.enable();
42043
42044      return _this2;
42045    }
42046
42047    Draggable.register = function register(core) {
42048      gsap = core;
42049
42050      _initCore();
42051    };
42052
42053    Draggable.create = function create(targets, vars) {
42054      _coreInitted || _initCore(true);
42055      return _toArray(targets).map(function (target) {
42056        return new Draggable(target, vars);
42057      });
42058    };
42059
42060    Draggable.get = function get(target) {
42061      return _lookup[(_toArray(target)[0] || {})._gsDragID];
42062    };
42063
42064    Draggable.timeSinceDrag = function timeSinceDrag() {
42065      return (_getTime() - _lastDragTime) / 1000;
42066    };
42067
42068    Draggable.hitTest = function hitTest(obj1, obj2, threshold) {
42069      if (obj1 === obj2) {
42070        return false;
42071      }
42072
42073      var r1 = _parseRect(obj1),
42074          r2 = _parseRect(obj2),
42075          top = r1.top,
42076          left = r1.left,
42077          right = r1.right,
42078          bottom = r1.bottom,
42079          width = r1.width,
42080          height = r1.height,
42081          isOutside = r2.left > right || r2.right < left || r2.top > bottom || r2.bottom < top,
42082          overlap,
42083          area,
42084          isRatio;
42085
42086      if (isOutside || !threshold) {
42087        return !isOutside;
42088      }
42089
42090      isRatio = (threshold + "").indexOf("%") !== -1;
42091      threshold = parseFloat(threshold) || 0;
42092      overlap = {
42093        left: Math.max(left, r2.left),
42094        top: Math.max(top, r2.top)
42095      };
42096      overlap.width = Math.min(right, r2.right) - overlap.left;
42097      overlap.height = Math.min(bottom, r2.bottom) - overlap.top;
42098
42099      if (overlap.width < 0 || overlap.height < 0) {
42100        return false;
42101      }
42102
42103      if (isRatio) {
42104        threshold *= 0.01;
42105        area = overlap.width * overlap.height;
42106        return area >= width * height * threshold || area >= r2.width * r2.height * threshold;
42107      }
42108
42109      return overlap.width > threshold && overlap.height > threshold;
42110    };
42111
42112    return Draggable;
42113  }(EventDispatcher);
42114
42115  _setDefaults(Draggable.prototype, {
42116    pointerX: 0,
42117    pointerY: 0,
42118    startX: 0,
42119    startY: 0,
42120    deltaX: 0,
42121    deltaY: 0,
42122    isDragging: false,
42123    isPressed: false
42124  });
42125
42126  Draggable.zIndex = 1000;
42127  Draggable.version = "3.1
421272.5";
42128  _getGSAP() && gsap.registerPlugin(Draggable);
42129
42130  exports.Draggable = Draggable;
42131  exports.default = Draggable;
42132
42133  if (typeof(window) === 'undefined' || window !== exports) {Object.defineProperty(exports, '__esModule', { value: true });} else {delete window.default;}
42134
42135})));
42136/* ========================================================================
42137 * Bootstrap: collapse.js v3.1.1
42138 * http://getbootstrap.com/javascript/#collapse
42139 * ========================================================================
42140 * Copyright 2011-2014 Twitter, Inc.
42141 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
42142 * ======================================================================== */
42143
42144
42145+function ($) {
42146	'use strict';
42147
42148	// COLLAPSE PUBLIC CLASS DEFINITION
42149	// ================================
42150
42151	var Collapse = function (element, options) {
42152		this.$element      = $(element)
42153		this.options       = $.extend({}, Collapse.DEFAULTS, options)
42154		this.transitioning = null
42155
42156		if (this.options.parent) this.$parent = $(this.options.parent)
42157		if (this.options.toggle) this.toggle()
42158	}
42159
42160	Collapse.DEFAULTS = {
42161		toggle: true
42162	}
42163
42164	Collapse.prototype.dimension = function () {
42165		var hasWidth = this.$element.hasClass('width')
42166		return hasWidth ? 'width' : 'height'
42167	}
42168
42169	Collapse.prototype.show = function () {
42170		if (this.transitioning || this.$element.hasClass('in')) return
42171
42172		var startEvent = $.Event('show.bs.collapse')
42173		this.$element.trigger(startEvent)
42174		if (startEvent.isDefaultPrevented()) return
42175
42176		var actives = this.$parent && this.$parent.find('> .panel > .in')
42177
42178		if (actives && actives.length) {
42179			var hasData = actives.data('bs.collapse')
42180			if (hasData && hasData.transitioning) return
42181			//START UNCODE EDIT
42182			var parentNoToggle = this.$parent.data('no-toggle')
42183			if (!parentNoToggle) {
42184				actives.collapse('hide')
42185			}
42186			//END UNCODE EDIT
42187			hasData || actives.data('bs.collapse', null)
42188		}
42189
42190		var dimension = this.dimension()
42191
42192		this.$element
42193			.removeClass('collapse')
42194			.addClass('collapsing')[dimension](0)
42195
42196		this.transitioning = 1
42197
42198		var complete = function (e) {
42199			if (e && e.target != this.$element[0]) return
42200			this.$element
42201				.removeClass('collapsing')
42202				.addClass('collapse in')[dimension]('auto')
42203			this.transitioning = 0
42204			this.$element.trigger('shown.bs.collapse')
42205		}
42206
42207		if (!$.support.transition) return complete.call(this)
42208
42209		var scrollSize = $.camelCase(['scroll', dimension].join('-'))
42210
42211		this.$element
42212			.one($.support.transition.end, $.proxy(complete, this))
42213			.emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize])
42214	}
42215
42216	Collapse.prototype.hide = function () {
42217		if (this.transitioning || !this.$element.hasClass('in')) return
42218
42219		var startEvent = $.Event('hide.bs.collapse')
42220		this.$element.trigger(startEvent)
42221		if (startEvent.isDefaultPrevented()) return
42222
42223		var dimension = this.dimension()
42224
42225		this.$element[dimension](this.$element[dimension]())[0].offsetHeight
42226
42227		this.$element
42228			.addClass('collapsing')
42229			.removeClass('collapse')
42230			.removeClass('in')
42231
42232		this.transitioning = 1
42233
42234		var complete = function (e) {
42235			if (e && e.target != this.$element[0]) return
42236			this.transitioning = 0
42237			this.$element
42238				.trigger('hidden.bs.collapse')
42239				.removeClass('collapsing')
42240				.addClass('collapse')
42241		}
42242
42243		if (!$.support.transition) return complete.call(this)
42244
42245		this.$element
42246			[dimension](0)
42247			.one($.support.transition.end, $.proxy(complete, this))
42248			.emulateTransitionEnd(350)
42249	}
42250
42251	Collapse.prototype.toggle = function () {
42252		this[this.$element.hasClass('in') ? 'hide' : 'show']()
42253	}
42254
42255
42256	// COLLAPSE PLUGIN DEFINITION
42257	// ==========================
42258
42259	var old = $.fn.collapse
42260
42261	$.fn.collapse = function (option) {
42262		return this.each(function () {
42263			var $this   = $(this)
42264			var data    = $this.data('bs.collapse')
42265			var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
42266
42267			if (!data && options.toggle && option == 'show') option = !option
42268			if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
42269			if (typeof option == 'string') data[option]()
42270		})
42271	}
42272
42273	$.fn.collapse.Constructor = Collapse
42274
42275
42276	// COLLAPSE NO CONFLICT
42277	// ====================
42278
42279	$.fn.collapse.noConflict = function () {
42280		$.fn.collapse = old
42281		return this
42282	}
42283
42284
42285	// COLLAPSE DATA-API
42286	// =================
42287
42288	$(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
42289		var $this   = $(this), href
42290		var target  = $this.attr('data-target')
42291				|| e.preventDefault()
42292				|| (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
42293		//Edited by Uncode to replace ID in panel [START]
42294		var _target = href.replace(/^#/, "");
42295		if ( $('[data-id="' + _target + '"]').length ) {
42296			var $target = $('[data-id="' + _target + '"]')
42297		} else {
42298			var $target = $(target)
42299		}
42300		//Edited by Uncode to replace ID in panel [END]
42301		var data    = $target.data('bs.collapse')
42302		var option  = data ? 'toggle' : $this.data()
42303		var parent  = $this.attr('data-parent')
42304		var $parent = parent && $(parent)
42305
42306		if (!data || !data.transitioning) {
42307			if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed')
42308			$this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
42309		}
42310
42311		$target.collapse(option)
42312	})
42313
42314}(jQuery);
42315
42316/* ========================================================================
42317 * Bootstrap: tab.js v3.1.1
42318 * http://getbootstrap.com/javascript/#tabs
42319 * ========================================================================
42320 * Copyright 2011-2014 Twitter, Inc.
42321 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
42322 * ======================================================================== */
42323
42324
42325+function ($) {
42326  'use strict';
42327
42328  // TAB CLASS DEFINITION
42329  // ====================
42330
42331  var Tab = function (element) {
42332    this.element = $(element)
42333  }
42334
42335  Tab.prototype.show = function () {
42336    var $this    = this.element
42337    var $ul      = $this.closest('ul:not(.dropdown-menu)')
42338    var selector = $this.data('target')
42339
42340    if (!selector) {
42341      selector = $this.attr('href')
42342      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
42343    }
42344
42345    if ($this.parent('li').hasClass('active')) return
42346
42347    var previous = $ul.find('.active:last a')[0]
42348    var e        = $.Event('show.bs.tab', {
42349      relatedTarget: previous
42350    })
42351
42352    $this.trigger(e)
42353
42354    if (e.isDefaultPrevented()) return
42355
42356    //Edited by Uncode to replace ID in panel [START]
42357    var _target = selector.replace(/^#/, "");
42358    if ( $('[data-id="' + _target + '"]').length )
42359      var $target = $('[data-id="' + _target + '"]')
42360    else
42361      var $target = $(selector)
42362    //Edited by Uncode to replace ID in panel [END]
42363
42364    this.activate($this.parent('li'), $ul)
42365    this.activate($target, $target.parent(), function () {
42366      $this.trigger({
42367        type: 'shown.bs.tab',
42368        relatedTarget: previous
42369      })
42370    })
42371  }
42372
42373  Tab.prototype.activate = function (element, container, callback) {
42374    var $active    = container.find('> .active').add(container.find('> .active > .active'))
42375    var transition = callback
42376      && $.support.transition
42377      && $active.hasClass('fade')
42378
42379    function next() {
42380      $active
42381        .removeClass('active')
42382        .find('> .dropdown-menu > .active')
42383        .removeClass('active')
42384
42385      $active
42386        .find('.tab-excerpt').slideUp();
42387
42388      element.addClass('active')
42389      $('.tab-excerpt', element).slideDown();
42390
42391      //if (transition) {
42392        element[0].offsetWidth // reflow for transition
42393        element.add($active).addClass('in')
42394      /*} else {
42395        element.removeClass('fade')
42396      }*/
42397
42398      if (element.parent('.dropdown-menu')) {
42399        element.closest('li.dropdown').addClass('active')
42400      }
42401
42402      if ( ! element.is('li') ) {
42403        element.closest('.tab-content').find('> .active').not(element).removeClass('active');
42404      }
42405
42406      callback && callback()
42407    }
42408
42409    transition ?
42410      $active
42411        .one($.support.transition.end, next)
42412        .emulateTransitionEnd(150) :
42413      next()
42414
42415    $active.removeClass('in')
42416  }
42417
42418
42419  // TAB PLUGIN DEFINITION
42420  // =====================
42421
42422  var old = $.fn.tab
42423
42424  $.fn.tab = function ( option ) {
42425    return this.each(function () {
42426      var $this = $(this)
42427      var data  = $this.data('bs.tab')
42428
42429      if (!data) $this.data('bs.tab', (data = new Tab(this)))
42430      if (typeof option == 'string') data[option]()
42431    })
42432  }
42433
42434  $.fn.tab.Constructor = Tab
42435
42436
42437  // TAB NO CONFLICT
42438  // ===============
42439
42440  $.fn.tab.noConflict = function () {
42441    $.fn.tab = old
42442    return this
42443  }
42444
42445
42446  // TAB DATA-API
42447  // ============
42448
42449  $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
42450    e.preventDefault()
42451    $(this).tab('show')
42452  })
42453
42454}(jQuery);
42455
42456/* ========================================================================
42457 * Bootstrap: tooltip.js v3.1.1
42458 * http://getbootstrap.com/javascript/#tooltip
42459 * Inspired by the original jQuery.tipsy by Jason Frame
42460 * ========================================================================
42461 * Copyright 2011-2014 Twitter, Inc.
42462 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
42463 * ======================================================================== */
42464
42465
42466+function ($) {
42467  'use strict';
42468
42469  // TOOLTIP PUBLIC CLASS DEFINITION
42470  // ===============================
42471
42472  var Tooltip = function (element, options) {
42473    this.type       =
42474    this.options    =
42475    this.enabled    =
42476    this.timeout    =
42477    this.hoverState =
42478    this.$element   = null
42479
42480    this.init('tooltip', element, options)
42481  }
42482
42483  Tooltip.DEFAULTS = {
42484    animation: true,
42485    placement: 'top',
42486    selector: false,
42487    template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
42488    trigger: 'hover focus',
42489    title: '',
42490    delay: 0,
42491    html: false,
42492    container: false,
42493    viewport: {
42494      selector: 'body',
42495      padding: 0
42496    }
42497  }
42498
42499  Tooltip.prototype.init = function (type, element, options) {
42500    this.enabled   = true
42501    this.type      = type
42502    this.$element  = $(element)
42503    this.options   = this.getOptions(options)
42504    this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
42505
42506    var triggers = this.options.trigger.split(' ')
42507
42508    for (var i = triggers.length; i--;) {
42509      var trigger = triggers[i]
42510
42511      if (trigger == 'click') {
42512        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
42513      } else if (trigger != 'manual') {
42514        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin'
42515        var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
42516
42517        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
42518        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
42519      }
42520    }
42521
42522    this.options.selector ?
42523      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
42524      this.fixTitle()
42525  }
42526
42527  Tooltip.prototype.getDefaults = function () {
42528    return Tooltip.DEFAULTS
42529  }
42530
42531  Tooltip.prototype.getOptions = function (options) {
42532    options = $.extend({}, this.getDefaults(), this.$element.data(), options)
42533
42534    if (options.delay && typeof options.delay == 'number') {
42535      options.delay = {
42536        show: options.delay,
42537        hide: options.delay
42538      }
42539    }
42540
42541    return options
42542  }
42543
42544  Tooltip.prototype.getDelegateOptions = function () {
42545    var options  = {}
42546    var defaults = this.getDefaults()
42547
42548    this._options && $.each(this._options, function (key, value) {
42549      if (defaults[key] != value) options[key] = value
42550    })
42551
42552    return options
42553  }
42554
42555  Tooltip.prototype.enter = function (obj) {
42556    var self = obj instanceof this.constructor ?
42557      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
42558
42559    clearTimeout(self.timeout)
42560
42561    self.hoverState = 'in'
42562
42563    if (!self.options.delay || !self.options.delay.show) return self.show()
42564
42565    self.timeout = setTimeout(function () {
42566      if (self.hoverState == 'in') self.show()
42567    }, self.options.delay.show)
42568  }
42569
42570  Tooltip.prototype.leave = function (obj) {
42571    var self = obj instanceof this.constructor ?
42572      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
42573
42574    clearTimeout(self.timeout)
42575
42576    self.hoverState = 'out'
42577
42578    if (!self.options.delay || !self.options.delay.hide) return self.hide()
42579
42580    self.timeout = setTimeout(function () {
42581      if (self.hoverState == 'out') self.hide()
42582    }, self.options.delay.hide)
42583  }
42584
42585  Tooltip.prototype.show = function () {
42586    var e = $.Event('show.bs.' + this.type)
42587
42588    if (this.hasContent() && this.enabled) {
42589      this.$element.trigger(e)
42590
42591      if (e.isDefaultPrevented()) return
42592      var that = this;
42593
42594      var $tip = this.tip()
42595
42596      this.setContent()
42597
42598      if (this.options.animation) $tip.addClass('fade')
42599
42600      var placement = typeof this.options.placement == 'function' ?
42601        this.options.placement.call(this, $tip[0], this.$element[0]) :
42602        this.options.placement
42603
42604      var autoToken = /\s?auto?\s?/i
42605      var autoPlace = autoToken.test(placement)
42606      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
42607
42608      $tip
42609        .detach()
42610        .css({ top: 0, left: 0, display: 'block' })
42611        .addClass(placement)
42612
42613      this.options.container ? $tip.appendTo($(document).find(this.options.container)) : $tip.insertAfter(this.$element)
42614
42615      var pos          = this.getPosition()
42616      var actualWidth  = $tip[0].offsetWidth
42617      var actualHeight = $tip[0].offsetHeight
42618
42619      if (autoPlace) {
42620        var orgPlacement = placement
42621        var $parent      = this.$element.parent()
42622        var parentDim    = this.getPosition($parent)
42623
42624        placement = placement == 'bottom' && pos.top   + pos.height       + actualHeight - parentDim.scroll > parentDim.height ? 'top'    :
42625                    placement == 'top'    && pos.top   - parentDim.scroll - actualHeight < 0                                   ? 'bottom' :
42626                    placement == 'right'  && pos.right + actualWidth      > parentDim.width                                    ? 'left'   :
42627                    placement == 'left'   && pos.left  - actualWidth      < parentDim.left                                     ? 'right'  :
42628                    placement
42629
42630        $tip
42631          .removeClass(orgPlacement)
42632          .addClass(placement)
42633      }
42634
42635      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
42636
42637      this.applyPlacement(calculatedOffset, placement)
42638      this.hoverState = null
42639
42640      var complete = function() {
42641        that.$element.trigger('shown.bs.' + that.type)
42642      }
42643
42644      $.support.transition && this.$tip.hasClass('fade') ?
42645        $tip
42646          .one($.support.transition.end, complete)
42647          .emulateTransitionEnd(150) :
42648        complete()
42649    }
42650  }
42651
42652  Tooltip.prototype.applyPlacement = function (offset, placement) {
42653    var $tip   = this.tip()
42654    var width  = $tip[0].offsetWidth
42655    var height = $tip[0].offsetHeight
42656
42657    // manually read margins because getBoundingClientRect includes difference
42658    var marginTop = parseInt($tip.css('margin-top'), 10)
42659    var marginLeft = parseInt($tip.css('margin-left'), 10)
42660
42661    // we must check for NaN for ie 8/9
42662    if (isNaN(marginTop))  marginTop  = 0
42663    if (isNaN(marginLeft)) marginLeft = 0
42664
42665    offset.top  = offset.top  + marginTop
42666    offset.left = offset.left + marginLeft
42667
42668    // $.fn.offset doesn't round pixel values
42669    // so we use setOffset directly with our own function B-0
42670    $.offset.setOffset($tip[0], $.extend({
42671      using: function (props) {
42672        $tip.css({
42673          top: Math.round(props.top),
42674          left: Math.round(props.left)
42675        })
42676      }
42677    }, offset), 0)
42678
42679    $tip.addClass('in')
42680
42681    // check to see if placing tip in new offset caused the tip to resize itself
42682    var actualWidth  = $tip[0].offsetWidth
42683    var actualHeight = $tip[0].offsetHeight
42684
42685    if (placement == 'top' && actualHeight != height) {
42686      offset.top = offset.top + height - actualHeight
42687    }
42688
42689    var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actua
42689lHeight)
42690
42691    if (delta.left) offset.left += delta.left
42692    else offset.top += delta.top
42693
42694    var arrowDelta          = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
42695    var arrowPosition       = delta.left ? 'left'        : 'top'
42696    var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight'
42697
42698    $tip.offset(offset)
42699    this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition)
42700  }
42701
42702  Tooltip.prototype.replaceArrow = function (delta, dimension, position) {
42703    this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '')
42704  }
42705
42706  Tooltip.prototype.setContent = function () {
42707    var $tip  = this.tip()
42708    var title = this.getTitle()
42709
42710    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
42711    $tip.removeClass('fade in top bottom left right')
42712  }
42713
42714  Tooltip.prototype.hide = function () {
42715    var that = this
42716    var $tip = this.tip()
42717    var e    = $.Event('hide.bs.' + this.type)
42718
42719    function complete() {
42720      if (that.hoverState != 'in') $tip.detach()
42721      that.$element.trigger('hidden.bs.' + that.type)
42722    }
42723
42724    this.$element.trigger(e)
42725
42726    if (e.isDefaultPrevented()) return
42727
42728    $tip.removeClass('in')
42729
42730    $.support.transition && this.$tip.hasClass('fade') ?
42731      $tip
42732        .one($.support.transition.end, complete)
42733        .emulateTransitionEnd(150) :
42734      complete()
42735
42736    this.hoverState = null
42737
42738    return this
42739  }
42740
42741  Tooltip.prototype.fixTitle = function () {
42742    var $e = this.$element
42743    if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
42744      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
42745    }
42746  }
42747
42748  Tooltip.prototype.hasContent = function () {
42749    return this.getTitle()
42750  }
42751
42752  Tooltip.prototype.getPosition = function ($element) {
42753    $element   = $element || this.$element
42754    var el     = $element[0]
42755    var isBody = el.tagName == 'BODY'
42756    return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, {
42757      scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(),
42758      width:  isBody ? $(window).width()  : $element.outerWidth(),
42759      height: isBody ? $(window).height() : $element.outerHeight()
42760    }, isBody ? {top: 0, left: 0} : $element.offset())
42761  }
42762
42763  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
42764    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2  } :
42765           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2  } :
42766           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
42767        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width   }
42768
42769  }
42770
42771  Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
42772    var delta = { top: 0, left: 0 }
42773    if (!this.$viewport) return delta
42774
42775    var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
42776    var viewportDimensions = this.getPosition(this.$viewport)
42777
42778    if (/right|left/.test(placement)) {
42779      var topEdgeOffset    = pos.top - viewportPadding - viewportDimensions.scroll
42780      var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
42781      if (topEdgeOffset < viewportDimensions.top) { // top overflow
42782        delta.top = viewportDimensions.top - topEdgeOffset
42783      } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
42784        delta.top = viewportDimensions.top + viewportDimensions.height - bottom
42784EdgeOffset
42785      }
42786    } else {
42787      var leftEdgeOffset  = pos.left - viewportPadding
42788      var rightEdgeOffset = pos.left + viewportPadding + actualWidth
42789      if (leftEdgeOffset < viewportDimensions.left) { // left overflow
42790        delta.left = viewportDimensions.left - leftEdgeOffset
42791      } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
42792        delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
42793      }
42794    }
42795
42796    return delta
42797  }
42798
42799  Tooltip.prototype.getTitle = function () {
42800    var title
42801    var $e = this.$element
42802    var o  = this.options
42803
42804    title = $e.attr('data-original-title')
42805      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
42806
42807    return title
42808  }
42809
42810  Tooltip.prototype.tip = function () {
42811    return this.$tip = this.$tip || $(this.options.template)
42812  }
42813
42814  Tooltip.prototype.arrow = function () {
42815    return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')
42816  }
42817
42818  Tooltip.prototype.validate = function () {
42819    if (!this.$element[0].parentNode) {
42820      this.hide()
42821      this.$element = null
42822      this.options  = null
42823    }
42824  }
42825
42826  Tooltip.prototype.enable = function () {
42827    this.enabled = true
42828  }
42829
42830  Tooltip.prototype.disable = function () {
42831    this.enabled = false
42832  }
42833
42834  Tooltip.prototype.toggleEnabled = function () {
42835    this.enabled = !this.enabled
42836  }
42837
42838  Tooltip.prototype.toggle = function (e) {
42839    var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this
42840    self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
42841  }
42842
42843  Tooltip.prototype.destroy = function () {
42844    clearTimeout(this.timeout)
42845    this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
42846  }
42847
42848
42849  // TOOLTIP PLUGIN DEFINITION
42850  // =========================
42851
42852  var old = $.fn.tooltip
42853
42854  $.fn.tooltip = function (option) {
42855    return this.each(function () {
42856      var $this   = $(this)
42857      var data    = $this.data('bs.tooltip')
42858      var options = typeof option == 'object' && option
42859
42860      if (!data && option == 'destroy') return
42861      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
42862      if (typeof option == 'string') data[option]()
42863    })
42864  }
42865
42866  $.fn.tooltip.Constructor = Tooltip
42867
42868
42869  // TOOLTIP NO CONFLICT
42870  // ===================
42871
42872  $.fn.tooltip.noConflict = function () {
42873    $.fn.tooltip = old
42874    return this
42875  }
42876
42877}(jQuery);
42878
42879/* ========================================================================
42880 * Bootstrap: transition.js v3.1.1
42881 * http://getbootstrap.com/javascript/#transitions
42882 * ========================================================================
42883 * Copyright 2011-2014 Twitter, Inc.
42884 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
42885 * ======================================================================== */
42886
42887
42888+function ($) {
42889  'use strict';
42890
42891  // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
42892  // ============================================================
42893
42894  function transitionEnd() {
42895    var el = document.createElement('bootstrap')
42896
42897    var transEndEventNames = {
42898      WebkitTransition : 'webkitTransitionEnd',
42899      MozTransition    : 'transitionend',
42900      OTransition      : 'oTransitionEnd otransitionend',
42901      transition       : 'transitionend'
42902    }
42903
42904    for (var name in transEndEventNames) {
42905      if (el.style[name] !== undefined) {
42906        return { end: transEndEventNames[name] }
42907      }
42908    }
42909
42910    return false // explicit for ie8 (  ._.)
42911  }
42912
42913  // http://blog.alexmaccaw.com/css-transitions
42914  $.fn.emulateTransitionEnd = function (duration) {
42915    var called = false, $el = this
42916    $(this).one($.support.transition.end, function () { called = true })
42917    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
42918    setTimeout(callback, duration)
42919    return this
42920  }
42921
42922  $(function () {
42923    $.support.transition = transitionEnd()
42924  })
42925
42926}(jQuery);
42927
42928
42929// ------------------------------------------
42930// Rellax.js
42931// Buttery smooth parallax library
42932// Copyright (c) 2016 Moe Amaya (@moeamaya)
42933// MIT license
42934//
42935// Thanks to Paraxify.js and Jaime Cabllero
42936// for parallax concepts
42937// ------------------------------------------
42938
42939(function (root, factory) {
42940	if (typeof define === 'function' && define.amd) {
42941		// AMD. Register as an anonymous module.
42942		define([], factory);
42943	} else if (typeof module === 'object' && module.exports) {
42944		// Node. Does not work with strict CommonJS, but
42945		// only CommonJS-like environments that support module.exports,
42946		// like Node.
42947		module.exports = factory();
42948	} else {
42949		// Browser globals (root is window)
42950		root.Rellax = factory();
42951	}
42952}(typeof window !== "undefined" ? window : global, function () {
42953	var Rellax = function(el, options){
42954		"use strict";
42955
42956		var self = Object.create(Rellax.prototype);
42957
42958		var posY = 0;
42959		var screenY = 0;
42960		var posX = 0;
42961		var screenX = 0;
42962		var blocks = [];
42963		var pause = true;
42964
42965		// check what requestAnimationFrame to use, and if
42966		// it's not supported, use the onscroll event
42967		var loop = window.requestAnimationFrame ||
42968			window.webkitRequestAnimationFrame ||
42969			window.mozRequestAnimationFrame ||
42970			window.msRequestAnimationFrame ||
42971			window.oRequestAnimationFrame ||
42972			function(callback){ return setTimeout(callback, 1000 / 60); };
42973
42974		// store the id for later use
42975		var loopId = null;
42976
42977		// Test via a getter in the options object to see if the passive property is accessed
42978		var supportsPassive = false;
vendor: 10,724 bytes, lines 42979-43280
42979		try {
42980			var opts = Object.defineProperty({}, 'passive', {
42981				get: function() {
42982					supportsPassive = true;
42983				}
42984			});
42985			window.addEventListener("testPassive", null, opts);
42986			window.removeEventListener("testPassive", null, opts);
42987		} catch (e) {}
42988
42989		// check what cancelAnimation method to use
42990		var clearLoop = window.cancelAnimationFrame || window.mozCancelAnimationFrame || clearTimeout;
42991
42992		// check which transform property to use
42993		var transformProp = window.transformProp || (function(){
42994				var testEl = document.createElement('div');
42995				if (testEl.style.transform === null) {
42996					var vendors = ['Webkit', 'Moz', 'ms'];
42997					for (var vendor in vendors) {
42998						if (testEl.style[ vendors[vendor] + 'Transform' ] !== undefined) {
42999							return vendors[vendor] + 'Transform';
43000						}
43001					}
43002				}
43003				return 'transform';
43004			})();
43005
43006		// Default Settings
43007		self.options = {
43008			speed: -2,
43009			verticalSpeed: null,
43010			horizontalSpeed: null,
43011			breakpoints: [576, 768, 1201],
43012			center: false,
43013			wrapper: null,
43014			relativeToWrapper: false,
43015			round: true,
43016			vertical: true,
43017			horizontal: false,
43018			verticalScrollAxis: "y",
43019			horizontalScrollAxis: "x",
43020			callback: function() {},
43021		};
43022
43023		// User defined options (might have more in the future)
43024		if (options){
43025			Object.keys(options).forEach(function(key){
43026				self.options[key] = options[key];
43027			});
43028		}
43029
43030		function validateCustomBreakpoints () {
43031			if (self.options.breakpoints.length === 3 && Array.isArray(self.options.breakpoints)) {
43032				var isAscending = true;
43033				var isNumerical = true;
43034				var lastVal;
43035				self.options.breakpoints.forEach(function (i) {
43036					if (typeof i !== 'number') isNumerical = false;
43037					if (lastVal !== null) {
43038						if (i < lastVal) isAscending = false;
43039					}
43040					lastVal = i;
43041				});
43042				if (isAscending && isNumerical) return;
43043			}
43044			// revert defaults if set incorrectly
43045			self.options.breakpoints = [576, 768, 1201];
43046			console.warn("Rellax: You must pass an array of 3 numbers in ascending order to the breakpoints option. Defaults reverted");
43047		}
43048
43049		if (options && options.breakpoints) {
43050			validateCustomBreakpoints();
43051		}
43052
43053		// By default, rellax class
43054		if (!el) {
43055			el = '.rellax';
43056		}
43057
43058		// check if el is a className or a node
43059		var elements = typeof el === 'string' ? document.querySelectorAll(el) : [el];
43060
43061		// Now query selector
43062		if (elements.length > 0) {
43063			self.elems = elements;
43064		}
43065
43066		// The elements don't exist
43067		else {
43068			console.warn("Rellax: The elements you're trying to select don't exist.");
43069			return;
43070		}
43071
43072		// Has a wrapper and it exists
43073		if (self.options.wrapper) {
43074			if (!self.options.wrapper.nodeType) {
43075				var wrapper = document.querySelector(self.options.wrapper);
43076
43077				if (wrapper) {
43078					self.options.wrapper = wrapper;
43079				} else {
43080					console.warn("Rellax: The wrapper you're trying to use doesn't exist.");
43081					return;
43082				}
43083			}
43084		}
43085
43086		// set a placeholder for the current breakpoint
43087		var currentBreakpoint;
43088
43089		// helper to determine current breakpoint
43090		var getCurrentBreakpoint = function (w) {
43091			var bp = self.options.breakpoints;
43092			if (w < bp[0]) return 'xs';
43093			if (w >= bp[0] && w < bp[1]) return 'sm';
43094			if (w >= bp[1] && w < bp[2]) return 'md';
43095			return 'lg';
43096		};
43097
43098		// Get and cache initial position of all elements
43099		var cacheBlocks = function() {
43100			for (var i = 0; i < self.elems.length; i++){
43101				var block = createBlock(self.elems[i]);
43102				blocks.push(block);
43103			}
43104		};
43105
43106
43107		// Let's kick this script off
43108		// Build array for cached element values
43109		var init = function() {
43110			for (var i = 0; i < blocks.length; i++){
43111				self.elems[i].style.cssText = blocks[i].style;
43112			}
43113
43114			blocks = [];
43115
43116			screenY = window.innerHeight;
43117			screenX = window.innerWidth;
43118			currentBreakpoint = getCurrentBreakpoint(screenX);
43119
43120			setPosition();
43121
43122			cacheBlocks();
43123
43124			animate();
43125
43126			// If paused, unpause and set listener for window resizing events
43127			if (pause) {
43128				window.addEventListener('resize', init);
43129				pause = false;
43130				// Start the loop
43131				update();
43132			}
43133		};
43134
43135		// We want to cache the parallax blocks'
43136		// values: base, top, height, speed
43137		// el: is dom object, return: el cache values
43138		var createBlock = function(el) {
43139			var dataPercentage = el.getAttribute( 'data-rellax-percentage' );
43140			var dataSpeed = el.getAttribute( 'data-rellax-speed' );
43141			var dataXsSpeed = el.getAttribute( 'data-rellax-xs-speed' );
43142			var dataMobileSpeed = el.getAttribute( 'data-rellax-mobile-speed' );
43143			var dataTabletSpeed = el.getAttribute( 'data-rellax-tablet-speed' );
43144			var dataDesktopSpeed = el.getAttribute( 'data-rellax-desktop-speed' );
43145			var dataVerticalSpeed = el.getAttribute('data-rellax-vertical-speed');
43146			var dataHorizontalSpeed = el.getAttribute('data-rellax-horizontal-speed');
43147			var dataVericalScrollAxis = el.getAttribute('data-rellax-vertical-scroll-axis');
43148			var dataHorizontalScrollAxis = el.getAttribute('data-rellax-horizontal-scroll-axis');
43149			var dataZindex = el.getAttribute( 'data-rellax-zindex' ) || 0;
43150			var dataMin = el.getAttribute( 'data-rellax-min' );
43151			var dataMax = el.getAttribute( 'data-rellax-max' );
43152			var dataMinX = el.getAttribute('data-rellax-min-x');
43153			var dataMaxX = el.getAttribute('data-rellax-max-x');
43154			var dataMinY = el.getAttribute('data-rellax-min-y');
43155			var dataMaxY = el.getAttribute('data-rellax-max-y');
43156			var mapBreakpoints;
43157			var breakpoints = true;
43158
43159			if (!dataXsSpeed && !dataMobileSpeed && !dataTabletSpeed && !dataDesktopSpeed) {
43160				breakpoints = false;
43161			} else {
43162				mapBreakpoints = {
43163					'xs': dataXsSpeed,
43164					'sm': dataMobileSpeed,
43165					'md': dataTabletSpeed,
43166					'lg': dataDesktopSpeed
43167				};
43168			}
43169
43170			// initializing at scrollY = 0 (top of browser), scrollX = 0 (left of browser)
43171			// ensures elements are positioned based on HTML layout.
43172			//
43173			// If the element has the percentage attribute, the posY and posX needs to be
43174			// the current scroll position's value, so that the elements are still positioned based on HTML layout
43175			var wrapperPosY = self.options.wrapper ? self.options.wrapper.scrollTop : (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
43176			// If the option relativeToWrapper is true, use the wrappers offset to top, subtracted from the current page scroll.
43177			if (self.options.relativeToWrapper) {
43178				var scrollPosY = (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
43179				wrapperPosY = scrollPosY - self.options.wrapper.offsetTop;
43180			}
43181			var posY = self.options.vertical ? ( dataPercentage || self.options.center ? wrapperPosY : 0 ) : 0;
43182			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;
43183
43184			var blockTop = posY + el.getBoundingClientRect().top;
43185			var blockHeight = el.clientHeight || el.offsetHeight || el.scrollHeight;
43186
43187			var blockLeft = posX + el.getBoundingClientRect().left;
43188			var blockWidth = el.clientWidth || el.offsetWidth || el.scrollWidth;
43189
43190			// apparently parallax equation everyone uses
43191			var percentageY = dataPercentage ? dataPercentage : (posY - blockTop + screenY) / (blockHeight + screenY);
43192			var percentageX = dataPercentage ? dataPercentage : (posX - blockLeft + screenX) / (blockWidth + screenX);
43193			if(self.options.center){ percentageX = 0.5; percentageY = 0.5; }
43194
43195			// Optional individual block speed as data attr, otherwise global speed
43196			var speed = (breakpoints && mapBreakpoints[currentBreakpoint] !== null) ? Number(mapBreakpoints[currentBreakpoint]) : (dataSpeed ? dataSpeed : self.options.speed);
43197			var verticalSpeed = dataVerticalSpeed ? dataVerticalSpeed : self.options.verticalSpeed;
43198			var horizontalSpeed = dataHorizontalSpeed ? dataHorizontalSpeed : self.options.horizontalSpeed;
43199
43200			// Optional individual block movement axis direction as data attr, otherwise global movement direction
43201			var verticalScrollAxis = dataVericalScrollAxis ? dataVericalScrollAxis : self.options.verticalScrollAxis;
43202			var horizontalScrollAxis = dataHorizontalScrollAxis ? dataHorizontalScrollAxis : self.options.horizontalScrollAxis;
43203
43204			var bases = updatePosition(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed);
43205
43206			// ~~Store non-translate3d transforms~~
43207			// Store inline styles and extract transforms
43208			var style = el.style.cssText;
43209			var transform = '';
43210
43211			// Check if there's an inline styled transform
43212			var searchResult = /transform\s*:/i.exec(style);
43213			if (searchResult) {
43214				// Get the index of the transform
43215				var index = searchResult.index;
43216
43217				// Trim the style to the transform point and get the following semi-colon index
43218				var trimmedStyle = style.slice(index);
43219				var delimiter = trimmedStyle.indexOf(';');
43220
43221				// Remove "transform" string and save the attribute
43222				if (delimiter) {
43223					transform = " " + trimmedStyle.slice(11, delimiter).replace(/\s/g,'');
43224				} else {
43225					transform = " " + trimmedStyle.slice(11).replace(/\s/g,'');
43226				}
43227			}
43228
43229			return {
43230				baseX: bases.x,
43231				baseY: bases.y,
43232				top: blockTop,
43233				left: blockLeft,
43234				height: blockHeight,
43235				width: blockWidth,
43236				speed: speed,
43237				verticalSpeed: verticalSpeed,
43238				horizontalSpeed: horizontalSpeed,
43239				verticalScrollAxis: verticalScrollAxis,
43240				horizontalScrollAxis: horizontalScrollAxis,
43241				style: style,
43242				transform: transform,
43243				zindex: dataZindex,
43244				min: dataMin,
43245				max: dataMax,
43246				minX: dataMinX,
43247				maxX: dataMaxX,
43248				minY: dataMinY,
43249				maxY: dataMaxY
43250			};
43251		};
43252
43253		// set scroll position (posY, posX)
43254		// side effect method is not ideal, but okay for now
43255		// returns true if the scroll changed, false if nothing happened
43256		var setPosition = function() {
43257			var oldY = posY;
43258			var oldX = posX;
43259
43260			posY = self.options.wrapper ? self.options.wrapper.scrollTop : (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset;
43261			posX = self.options.wrapper ? self.options.wrapper.scrollLeft : (document.documentElement || document.body.parentNode || document.body).scrollLeft || window.pageXOffset;
43262			// If option relativeToWrapper is true, use relative wrapper value instead.
43263			if (self.options.relativeToWrapper) {
43264				var scrollPosY = (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset;
43265				posY = scrollPosY - self.options.wrapper.offsetTop;
43266			}
43267
43268
43269			if (oldY != posY && self.options.vertical) {
43270				// scroll changed, return true
43271				return true;
43272			}
43273
43274			if (oldX != posX && self.options.horizontal) {
43275				// scroll changed, return true
43276				return true;
43277			}
43278
43279			// scroll did not change
43280			return false;
43281		};
43282
43283		// Ahh a pure function, gets new transform value
43284		// based on scrollPosition and speed
43285		// Allow for decimal pixel values
43286		var updatePosition = function(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed) {
43287			var result = {};
43288			var valueX = ((horizontalSpeed ? horizontalSpeed : speed) * (100 * (1 - percentageX)));
43289			var valueY = ((verticalSpeed ? verticalSpeed : speed) * (100 * (1 - percentageY)));
43290
43291			result.x = self.options.round ? Math.round(valueX) : Math.round(valueX * 100) / 100;
43292			result.y = self.options.round ? Math.round(valueY) : Math.round(valueY * 100) / 100;
43293
43294			return result;
43295		};
43296
43297		// Remove event listeners and loop again
43298		var deferredUpdate = function() {
43299			window.removeEventListener('resize', deferredUpdate);
43300			window.removeEventListener('orientationchange', deferredUpdate);
43301			(self.options.wrapper ? self.options.wrapper : window).removeEventListener('scroll', deferredUpdate);
43302			(self.options.wrapper ? self.options.wrapper : document).removeEventListener('touchmove', deferredUpdate);
43303
43304			// loop again
43305			loopId = loop(update);
43306		};
43307
43308		// Loop
43309		var update = function() {
43310			if (setPosition() && pause === false) {
43311				animate();
43312
43313				// loop again
43314				loopId = loop(update);
43315			} else {
43316				loopId = null;
43317
43318				// Don't animate until we get a position updating event
43319				window.addEventListener('resize', deferredUpdate);
43320				window.addEventListener('orientationchange', deferredUpdate);
43321				(self.options.wrapper ? self.options.wrapper : window).addEventListener('scroll', deferredUpdate, supportsPassive ? { passive: true } : false);
43322				(self.options.wrapper ? self.options.wrapper : document).addEventListener('touchmove', deferredUpdate, supportsPassive ? { passive: true } : false);
43323			}
43324		};
43325
43326		// Transform3d on parallax element
43327		var animate = function() {
43328			var positions;
43329			for (var i = 0; i < self.elems.length; i++){
43330				// Determine relevant movement directions
43331				var verticalScrollAxis = blocks[i].verticalScrollAxis.toLowerCase();
43332				var horizontalScrollAxis = blocks[i].horizontalScrollAxis.toLowerCase();
43333				var verticalScrollX = verticalScrollAxis.indexOf("x") != -1 ? posY : 0;
43334				var verticalScrollY = verticalScrollAxis.indexOf("y") != -1 ? posY : 0;
43335				var horizontalScrollX = horizontalScrollAxis.indexOf("x") != -1 ? posX : 0;
43336				var horizontalScrollY = horizontalScrollAxis.indexOf("y") != -1 ? posX : 0;
43337
43338				var percentageY = ((verticalScrollY + horizontalScrollY - blocks[i].top + screenY) / (blocks[i].height + screenY));
43339				var percentageX = ((verticalScrollX + horizontalScrollX - blocks[i].left + screenX) / (blocks[i].width + screenX));
43340
43341				// Subtracting initialize value, so element stays in same spot as HTML
43342				positions = updatePosition(percentageX, percentageY, blocks[i].speed, blocks[i].verticalSpeed, blocks[i].horizontalSpeed);
43343				var positionY = positions.y - blocks[i].baseY;
43344				var positionX = positions.x - blocks[i].baseX;
43345
43346				// The next two "if" blocks go like this:
43347				// Check if a limit is defined (first "min", then "max");
43348				// Check if we need to change the Y or the X
43349				// (Currently working only if just one of the axes is enabled)
43350				// Then, check if the new position is inside the allowed limit
43351				// If so, use new position. If not, set position to limit.
43352
43353				// Check if a min limit is defined
43354				if (blocks[i].min !== null) {
43355					if (self.options.vertical && !self.options.horizontal) {
43356						positionY = positionY <= blocks[i].min ? blocks[i].min : positionY;
43357					}
43358					if (self.options.horizontal && !self.options.vertical) {
43359						positionX = positionX <= blocks[i].min ? blocks[i].min : positionX;
43360					}
43361				}
43362
43363				// Check if directional min limits are defined
43364				if (blocks[i].minY != null) {
43365						positionY = positionY <= blocks[i].minY ? blocks[i].minY : positionY;
43366				}
43367				if (blocks[i].minX != null) {
43368						positionX = positionX <= blocks[i].minX ? blocks[i].minX : positionX;
43369				}
43370
43371				// Check if a max limit is defined
43372				if (blocks[i].max !== null) {
43373					if (self.options.vertical && !self.options.horizontal) {
43374						positionY = positionY >= blocks[i].max ? blocks[i].max : positionY;
43375					}
43376					if (self.options.horizontal && !self.options.vertical) {
43377						positionX = positionX >= blocks[i].max ? blocks[i].max : positionX;
43378					}
43379				}
43380
43381				// Check if directional max limits are defined
43382				if (blocks[i].maxY != null) {
43383						positionY = positionY >= blocks[i].maxY ? blocks[i].maxY : positionY;
43384				}
43385				if (blocks[i].maxX != null) {
43386						positionX = positionX >= blocks[i].maxX ? blocks[i].maxX : positionX;
43387				}
43388
43389				var zindex = blocks[i].zindex;
43390
43391				// Move that element
43392				// (Set the new translation and append initial inline transforms.)
43393				var translate = 'translate3d(' + (self.options.horizontal ? positionX : '0') + 'px,' + (self.options.vertical ? positionY : '0') + 'px,' + zindex + 'px) ' + blocks[i].transform;
43394				self.elems[i].style[transformProp] = translate;
43395			}
43396			self.options.callback(positions);
43397		};
43398
43399		self.destroy = function() {
43400			for (var i = 0; i < self.elems.length; i++){
43401				self.elems[i].style.cssText = blocks[i].style;
43402			}
43403
43404			// Remove resize event listener if not pause, and pause
43405			if (!pause) {
43406				window.removeEventListener('resize', init);
43407				pause = true;
43408			}
43409
43410			// Clear the animation loop to prevent possible memory leak
43411			clearLoop(loopId);
43412			loopId = null;
43413		};
43414
43415		// Init
43416		init();
43417
43418		// Allow to recalculate the initial values whenever we want
43419		self.refresh = init;
43420
43421		return self;
43422	};
43423	return Rellax;
43424}));
43425
43426/*
43427 * OKVideo by OKFocus v2.3.2
43428 * http://okfoc.us
43429 *
43430 * Copyright 2014, OKFocus
43431 * Licensed under the MIT license.
43432 *
43433 */
43434var player, OKEvents, options, videoWidth, videoHeight, YTplayers, youtubePlayers = new Array();
43435// youtube player ready
43436function onYouTubeIframeAPIReady() {
43437	YTplayers = new Array();
43438	jQuery('.uncode-video-container.video').each(function() {
43439		var playerY;
43440		if (jQuery(this).attr('data-provider') == 'youtube') {
43441			var id = jQuery(this).attr('data-id'),
43442				start = jQuery(this).attr('data-start'),
43443				end = jQuery(this).attr('data-end');
43444			start = typeof start && start !== null ? start : 0;
43445			end = typeof end && end !== null ? end : 0;
43446			options = jQuery(window).data('okoptions-' + id);
43447			if ( typeof options === 'undefined' ) {
43448				return true;
43449			}
43450			options.time = jQuery(this).attr('data-t');
43451			playerY = new YT.Player('okplayer-' + id, {
43452				videoId: options.video ? options.video.id : null,
43453				playerVars: {
43454					'autohide': 1,
43455					'autoplay': jQuery(this).hasClass('is-no-control') ? options.autoplay : 0, //options.autoplay,
43456					'disablekb': 1,
43457					'cc_load_policy': options.captions,
43458					'controls': 0,
43459					'enablejsapi': 1,
43460					'fs': 0,
43461					'modestbranding': 1,
43462					'origin': window.location.origin || (window.location.protocol + '//' + window.location.hostname),
43463					'iv_load_policy': options.annotations,
43464					'loop': options.loop,
43465					'showinfo': 0,
43466					'rel': 0,
43467					'wmode': 'opaque',
43468					'hd': options.hd,
43469					'mute': 1,
43470					'start': start,
43471					'end': end
43472				},
43473				events: {
43474					'onReady': OKEvents.yt.ready,
43475					'onStateChange': OKEvents.yt.onStateChange,
43476					'onError': OKEvents.yt.error
43477				}
43478			});
43479			YTplayers[id] = playerY;
43480			playerY.videoId = id;
43481		}
43482
43483	});
43484}
43485// vimeo player ready
43486function vimeoPlayerReady(id) {
43487	options = jQuery(window).data('okoptions-' + id);
43488	if ( typeof options === 'undefined' ) {
43489		return true;
43490	}
43491	var jIframe = options.jobject,
43492		iframe = jIframe[0];
43493
43494	jIframe.attr('src', jIframe.data('src'));
43495	var playerV = new Vimeo.Player(iframe);
43496	// hide player until Vimeo hides controls...
43497	playerV.on('loaded', function(e) {
43498		OKEvents.v.onReady(iframe);
43499		var carouselContainer = jQuery(iframe).closest('.owl-carousel');
43500		if (carouselContainer.length) {
43501			UNCODE.owlPlayVideo(carouselContainer);
43502		}
43503		// "Do not try to add listeners or call functions before receiving this event."
43504		if (OKEvents.utils.isMobile()) {
43505			// mobile devices cannot listen for play event
43506			OKEvents.v.onPlay(playerV);
43507		} else {
43508			playerV.on('play', function(){
43509				OKEvents.v.onPlay(playerV);
43510				jQuery(window).trigger('okevents.v.play', [playerV]);
43511			});
43512			playerV.on('pause', function(){
43513				OKEvents.v.onPause;
43514				jQuery(window).trigger('okevents.v.pause', [playerV]);
43515			});
43516			playerV.on('ended', function(){
43517				OKEvents.v.onFinish
43518				jQuery(window).trigger('okevents.v.ended', [playerV]);
43519			});
43520		}
43521		if (options.time != null) {
43522			var optsTimeStr = (options.time).replace('t=', ''),
43523				timeV = '';
43524
43525			if ( /[a-zA-Z]/g.test(optsTimeStr) ) {
43526				var timeArr = optsTimeStr.split(/([^\d.-])/);
43527				for ( var i = 0; i < timeArr.length; i++ ) {
43528					if ( timeArr[i] === 'h' ) {
43529						timeV += parseFloat(timeArr[i-1]) * 3600;
43530					} else if ( timeArr[i] === 'm' ) {
43531						timeV += parseFloat(timeArr[i-1]) * 60;
43532					} else if ( timeArr[i] === 's' ) {
43533						timeV += parseFloat(timeArr[i-1]);
43534					}
43535				}
43536			} else {
43537				timeV = optsTimeStr;
43538			}
43539
43540			playerV.setCurrentTime(timeV);
43541		}
43542
43543		playerV.setVolume(0);
43544		playerV.play();
43545		jQuery(iframe).css({
43546			visibility: 'visible',
43547			opacity: 1
43548		});
43549		jQuery(iframe).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1');
43550		jQuery(iframe).closest('#page-header').addClass('video-started');
43551		jQuery(iframe).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1');
43552
43553		jQuery(window).trigger('okevents.v.loaded', [playerV]);
43554	});
43555}
43556OKEvents = {
43557	yt: {
43558		ready: function(event) {
43559			var id = event.target.videoId,
43560				$video = jQuery('#okplayer-' + id),
43561				options = jQuery(window).data('okoptions-' + id);
43562			if ( typeof options === 'undefined' ) {
43563				return true;
43564			}
43565			youtubePlayers[id] = event.target;
43566			event.target.setVolume(options.volume);
43567			if (options.autoplay === 1) {
43568				if (options.playlist.list) {
43569					player.loadPlaylist(options.playlist.list, options.playlist.index, options.playlist.startSeconds, options.playlist.suggestedQuality);
43570				} else {
43571					var inCarousel = $video.closest('.owl-item');
43572					if (!inCarousel.length || (inCarousel.length && inCarousel.hasClass('active'))) {
43573						if (options.time != null) {
43574							event.target.seekTo(parseInt(options.time));
43575						}
43576						event.target.playVideo();
43577					} else {
43578						event.target.pauseVideo();
43579					}
43580				}
43581			}
43582			OKEvents.utils.isFunction(options.onReady) && options.onReady(event.target);
43583
43584			$video.closest('[data-provider]').on('uncode-resume', function(){
43585				if (options.time != null) {
43586					event.target.seekTo(parseInt(options.time)).playVideo();
43587				} else {
43588					event.target.seekTo(0).playVideo();
43589				}
43590			});
43591
43592			$video.closest('[data-provider]').on('uncode-pause', function(){
43593				if (options.time != null) {
43594					event.target.seekTo(parseInt(options.time)).pauseVideo();
43595				} else {
43596					event.target.seekTo(0).pauseVideo();
43597				}
43598			});
43599			jQuery(window).trigger('okevents.y.loaded', [event]);
43600		},
43601		onStateChange: function(event) {
43602			var id = event.target.videoId,
43603				$video = jQuery('#okplayer-' + id),
43604				options = jQuery(window).data('okoptions-' + id);
43605			if ( typeof options === 'undefined' || typeof event.target.setVolume === 'undefined' ) {
43606				return true;
43607			}
43608			youtubePlayers[id] = event.target;
43609			event.target.setVolume(options.volume);
43610			var $fluid = $video.closest('.fluid-object'),
43611				$tmb = $video.closest('.tmb'),
43612				setTime;
43613			switch (event.data) {
43614				case -1:
43615					OKEvents.utils.isFunction(options.unstarted) && options.unstarted();
43616					break;
43617				case 0:
43618					OKEvents.utils.isFunction(options.onFinished) && options.onFinished();
43619					options.loop && event.target.playVideo();
43620					break;
43621				case 1:
43622					OKEvents.utils.isFunction(options.onPlay) && options.onPlay();
43623					setTimeout(function() {
43624						UNCODE.initVideoComponent(document.body, '.uncode-video-container.video:not(.drop-move), .uncode-video-container.self-video:not(.drop-move)');
43625						jQuery('#okplayer-' + id).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1');
43626						jQuery('#okplayer-' + id).closest('#page-header').addClass('video-started');
43627						jQuery('#okplayer-' + id).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1');
43628					}, 300);
43629				break;
43630				case 2:
43631					OKEvents.utils.isFunction(options.onPause) && options.onPause();
43632					break;
43633				case 3:
43634					OKEvents.utils.isFunction(options.buffering) && options.buffering();
43635					break;
43636				case 5:
43637					OKEvents.utils.isFunction(options.cued) && options.cued();
43638					break;
43639				default:
43640					throw "OKVideo: received invalid data from YT player.";
43641			}
43642
43643			jQuery(window).trigger('okevents.y.change', [event]);
43644		},
43645		error: function(event) {
43646			throw event;
43647		}
43648	},
43649	v: {
43650		onReady: function(target) {
43651			if ( typeof options === 'undefined' ) {
43652				return true;
43653			}
43654			OKEvents.utils.isFunction(options.onReady) && options.onReady(target);
43655		},
43656		onPlay: function(player) {
43657			if ( typeof options === 'undefined' ) {
43658				return true;
43659			}
43660			if (!OKEvents.utils.isMobile()) player.setVolume(options.volume);
43661			OKEvents.utils.isFunction(options.onPlay) && options.onPlay();
43662			jQuery(player.element).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1');
43663			jQuery(player.element).closest('#page-header').addClass('video-started');
43664			jQuery(player.element).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1');
43665		},
43666		onPause: function() {
43667			if ( typeof options === 'undefined' ) {
43668				return true;
43669			}
43670			OKEvents.utils.isFunction(options.onPause) && options.onPause();
43671		},
43672		onFinish: function() {
43673			if ( typeof options === 'undefined' ) {
43674				return true;
43675			}
43676			OKEvents.utils.isFunction(options.onFinish) && options.onFinish();
43677		}
43678	},
43679	utils: {
43680		isFunction: function(func) {
43681			if (typeof func === 'function') {
43682				return true;
43683			} else {
43684				return false;
43685			}
43686		},
43687		isMobile: function() {
43688			if (navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry)/)) {
43689				return true;
43690			} else {
43691				return false;
43692			}
43693		}
43694	}
43695};
43696/**
43697 * vivus - JavaScript library to make drawing animation on SVG
43698 * @version v0.4.4
43699 * @link https://github.com/maxwellito/vivus
43700 * @license MIT
43701 */
43702
43703'use strict';
43704
43705(function () {
43706
43707  'use strict';
43708
43709/**
43710 * Pathformer
43711 * Beta version
43712 *
43713 * Take any SVG version 1.1 and transform
43714 * child elements to 'path' elements
43715 *
43716 * This code is purely forked from
43717 * https://github.com/Waest/SVGPathConverter
43718 */
43719
43720/**
43721 * Class constructor
43722 *
43723 * @param {DOM|String} element Dom element of the SVG or id of it
43724 */
43725function Pathformer(element) {
43726  // Test params
43727  if (typeof element === 'undefined') {
43728	throw new Error('Pathformer [constructor]: "element" parameter is required');
43729  }
43730
43731  // Set the element
43732  if (element.constructor === String) {
43733	element = document.getElementById(element);
43734	if (!element) {
43735	  throw new Error('Pathformer [constructor]: "element" parameter is not related to an existing ID');
43736	}
43737  }
43738  if (element instanceof window.SVGElement ||
43739	  element instanceof window.SVGGElement ||
43740	  /^svg$/i.test(element.nodeName)) {
43741	this.el = element;
43742  } else {
43743	throw new Error('Pathformer [constructor]: "element" parameter must be a string or a SVGelement');
43744  }
43745
43746  // Start
43747  this.scan(element);
43748}
43749
43750/**
43751 * List of tags which can be transformed
43752 * to path elements
43753 *
43754 * @type {Array}
43755 */
43756Pathformer.prototype.TYPES = ['line', 'ellipse', 'circle', 'polygon', 'polyline', 'rect'];
43757
43758/**
43759 * List of attribute names which contain
43760 * data. This array list them to check if
43761 * they contain bad values, like percentage.
43762 *
43763 * @type {Array}
43764 */
43765Pathformer.prototype.ATTR_WATCH = ['cx', 'cy', 'points', 'r', 'rx', 'ry', 'x', 'x1', 'x2', 'y', '
vendor: 24,640 bytes, lines 43765-44563
43765y1', 'y2'];
43766
43767/**
43768 * Finds the elements compatible for transform
43769 * and apply the liked method
43770 *
43771 * @param  {object} options Object from the constructor
43772 */
43773Pathformer.prototype.scan = function (svg) {
43774  var fn, element, pathData, pathDom,
43775	  elements = svg.querySelectorAll(this.TYPES.join(','));
43776
43777  for (var i = 0; i < elements.length; i++) {
43778	element = elements[i];
43779	fn = this[element.tagName.toLowerCase() + 'ToPath'];
43780	pathData = fn(this.parseAttr(element.attributes));
43781	pathDom = this.pathMaker(element, pathData);
43782	element.parentNode.replaceChild(pathDom, element);
43783  }
43784};
43785
43786
43787/**
43788 * Read `line` element to extract and transform
43789 * data, to make it ready for a `path` object.
43790 *
43791 * @param  {DOMelement} element Line element to transform
43792 * @return {object}			 Data for a `path` element
43793 */
43794Pathformer.prototype.lineToPath = function (element) {
43795  var newElement = {},
43796	  x1 = element.x1 || 0,
43797	  y1 = element.y1 || 0,
43798	  x2 = element.x2 || 0,
43799	  y2 = element.y2 || 0;
43800
43801  newElement.d = 'M' + x1 + ',' + y1 + 'L' + x2 + ',' + y2;
43802  return newElement;
43803};
43804
43805/**
43806 * Read `rect` element to extract and transform
43807 * data, to make it ready for a `path` object.
43808 * The radius-border is not taken in charge yet.
43809 * (your help is more than welcomed)
43810 *
43811 * @param  {DOMelement} element Rect element to transform
43812 * @return {object}             Data for a `path` element
43813 */
43814Pathformer.prototype.rectToPath = function (element) {
43815  var newElement = {},
43816      x      = parseFloat(element.x)      || 0,
43817      y      = parseFloat(element.y)      || 0,
43818      width  = parseFloat(element.width)  || 0,
43819      height = parseFloat(element.height) || 0;
43820
43821  if (element.rx || element.ry) {
43822    var rx = parseInt(element.rx, 10) || -1,
43823        ry = parseInt(element.ry, 10) || -1;
43824    rx = Math.min(Math.max(rx < 0 ? ry : rx, 0), width/2);
43825    ry = Math.min(Math.max(ry < 0 ? rx : ry, 0), height/2);
43826
43827    newElement.d = 'M ' + (x + rx) + ',' + y + ' ' +
43828                   'L ' + (x + width - rx) + ',' + y + ' ' +
43829                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + width) + ',' + (y + ry) + ' ' +
43830                   'L ' + (x + width) + ',' + (y + height - ry) + ' ' +
43831                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + width - rx) + ',' + (y + height) + ' ' +
43832                   'L ' + (x + rx) + ',' + (y + height) + ' ' +
43833                   'A ' + rx + ',' + ry + ',0,0,1,' + x + ',' + (y + height - ry) + ' ' +
43834                   'L ' + x + ',' + (y + ry) + ' ' +
43835                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + rx) + ',' + y;
43836  }
43837  else {
43838    newElement.d = 'M' + x + ' ' + y + ' ' +
43839                   'L' + (x + width) + ' ' + y + ' ' +
43840                   'L' + (x + width) + ' ' + (y + height) + ' ' +
43841                   'L' + x + ' ' + (y + height) + ' Z';
43842  }
43843  return newElement;
43844};
43845
43846/**
43847 * Read `polyline` element to extract and transform
43848 * data, to make it ready for a `path` object.
43849 *
43850 * @param  {DOMelement} element Polyline element to transform
43851 * @return {object}             Data for a `path` element
43852 */
43853Pathformer.prototype.polylineToPath = function (element) {
43854  var newElement = {},
43855      points = element.points.trim().split(' '),
43856      i, path;
43857
43858  // Reformatting if points are defined without commas
43859  if (element.points.indexOf(',') === -1) {
43860    var formattedPoints = [];
43861    for (i = 0; i < points.length; i+=2) {
43862      formattedPoints.push(points[i] + ',' + points[i+1]);
43863    }
43864    points = formattedPoints;
43865  }
43866
43867  // Generate the path.d value
43868  path = 'M' + points[0];
43869  for(i = 1; i < points.length; i++) {
43870    if (points[i].indexOf(',') !== -1) {
43871      path += 'L' + points[i];
43872    }
43873  }
43874  newElement.d = path;
43875  return newElement;
43876};
43877
43878/**
43879 * Read `polygon` element to extract and transform
43880 * data, to make it ready for a `path` object.
43881 * This method rely on polylineToPath, because the
43882 * logic is similar. The path created is just closed,
43883 * so it needs an 'Z' at the end.
43884 *
43885 * @param  {DOMelement} element Polygon element to transform
43886 * @return {object}             Data for a `path` element
43887 */
43888Pathformer.prototype.polygonToPath = function (element) {
43889  var newElement = Pathformer.prototype.polylineToPath(element);
43890
43891  newElement.d += 'Z';
43892  return newElement;
43893};
43894
43895/**
43896 * Read `ellipse` element to extract and transform
43897 * data, to make it ready for a `path` object.
43898 *
43899 * @param  {DOMelement} element ellipse element to transform
43900 * @return {object}             Data for a `path` element
43901 */
43902Pathformer.prototype.ellipseToPath = function (element) {
43903  var newElement = {},
43904      rx = parseFloat(element.rx) || 0,
43905      ry = parseFloat(element.ry) || 0,
43906      cx = parseFloat(element.cx) || 0,
43907      cy = parseFloat(element.cy) || 0,
43908      startX = cx - rx,
43909      startY = cy,
43910      endX = parseFloat(cx) + parseFloat(rx),
43911      endY = cy;
43912
43913  newElement.d = 'M' + startX + ',' + startY +
43914                 'A' + rx + ',' + ry + ' 0,1,1 ' + endX + ',' + endY +
43915                 'A' + rx + ',' + ry + ' 0,1,1 ' + startX + ',' + endY;
43916  return newElement;
43917};
43918
43919/**
43920 * Read `circle` element to extract and transform
43921 * data, to make it ready for a `path` object.
43922 *
43923 * @param  {DOMelement} element Circle element to transform
43924 * @return {object}             Data for a `path` element
43925 */
43926Pathformer.prototype.circleToPath = function (element) {
43927  var newElement = {},
43928      r  = parseFloat(element.r)  || 0,
43929      cx = parseFloat(element.cx) || 0,
43930      cy = parseFloat(element.cy) || 0,
43931      startX = cx - r,
43932      startY = cy,
43933      endX = parseFloat(cx) + parseFloat(r),
43934      endY = cy;
43935
43936  newElement.d =  'M' + startX + ',' + startY +
43937                  'A' + r + ',' + r + ' 0,1,1 ' + endX + ',' + endY +
43938                  'A' + r + ',' + r + ' 0,1,1 ' + startX + ',' + endY;
43939  return newElement;
43940};
43941
43942/**
43943 * Create `path` elements form original element
43944 * and prepared objects
43945 *
43946 * @param  {DOMelement} element  Original element to transform
43947 * @param  {object} pathData     Path data (from `toPath` methods)
43948 * @return {DOMelement}          Path element
43949 */
43950Pathformer.prototype.pathMaker = function (element, pathData) {
43951  var i, attr, pathTag = document.createElementNS('http://www.w3.org/2000/svg','path');
43952  for(i = 0; i < element.attributes.length; i++) {
43953    attr = element.attributes[i];
43954    if (this.ATTR_WATCH.indexOf(attr.name) === -1) {
43955      pathTag.setAttribute(attr.name, attr.value);
43956    }
43957  }
43958  for(i in pathData) {
43959    pathTag.setAttribute(i, pathData[i]);
43960  }
43961  return pathTag;
43962};
43963
43964/**
43965 * Parse attributes of a DOM element to
43966 * get an object of attribute => value
43967 *
43968 * @param  {NamedNodeMap} attributes Attributes object from DOM element to parse
43969 * @return {object}                  Object of attributes
43970 */
43971Pathformer.prototype.parseAttr = function (element) {
43972  var attr, output = {};
43973  for (var i = 0; i < element.length; i++) {
43974    attr = element[i];
43975    // Check if no data attribute contains '%', or the transformation is impossible
43976    if (this.ATTR_WATCH.indexOf(attr.name) !== -1 && attr.value.indexOf('%') !== -1) {
43977      throw new Error('Pathformer [parseAttr]: a SVG shape got values in percentage. This cannot be transformed into \'path\' tags. Please use \'viewBox\'.');
43978    }
43979    output[attr.name] = attr.value;
43980  }
43981  return output;
43982};
43983
43984  'use strict';
43985
43986var setupEnv, requestAnimFrame, cancelAnimFrame, parsePositiveInt;
43987
43988/**
43989 * Vivus
43990 * Beta version
43991 *
43992 * Take any SVG and make the animation
43993 * to give give the impression of live drawing
43994 *
43995 * This in more than just inspired from codrops
43996 * At that point, it's a pure fork.
43997 */
43998
43999/**
44000 * Class constructor
44001 * option structure
44002 *   type: 'delayed'|'sync'|'oneByOne'|'script' (to know if the items must be drawn synchronously or not, default: delayed)
44003 *   duration: <int> (in frames)
44004 *   start: 'inViewport'|'manual'|'autostart' (start automatically the animation, default: inViewport)
44005 *   delay: <int> (delay between the drawing of first and last path)
44006 *   dashGap <integer> whitespace extra margin between dashes
44007 *   pathTimingFunction <function> timing animation function for each path element of the SVG
44008 *   animTimingFunction <function> timing animation function for the complete SVG
44009 *   forceRender <boolean> force the browser to re-render all updated path items
44010 *   selfDestroy <boolean> removes all extra styling on the SVG, and leaves it as original
44011 *
44012 * The attribute 'type' is by default on 'delayed'.
44013 *  - 'delayed'
44014 *    all paths are draw at the same time but with a
44015 *    little delay between them before start
44016 *  - 'sync'
44017 *    all path are start and finish at the same time
44018 *  - 'oneByOne'
44019 *    only one path is draw at the time
44020 *    the end of the first one will trigger the draw
44021 *    of the next one
44022 *
44023 * All these values can be overwritten individually
44024 * for each path item in the SVG
44025 * The value of frames will always take the advantage of
44026 * the duration value.
44027 * If you fail somewhere, an error will be thrown.
44028 * Good luck.
44029 *
44030 * @constructor
44031 * @this {Vivus}
44032 * @param {DOM|String}   element  Dom element of the SVG or id of it
44033 * @param {Object}       options  Options about the animation
44034 * @param {Function}     callback Callback for the end of the animation
44035 */
44036function Vivus (element, options, callback) {
44037
44038  setupEnv();
44039
44040  // Setup
44041  this.isReady = false;
44042  this.setElement(element, options);
44043  this.setOptions(options);
44044  this.setCallback(callback);
44045
44046  if (this.isReady) {
44047    this.init();
44048  }
44049}
44050
44051/**
44052 * Timing functions
44053 **************************************
44054 *
44055 * Default functions to help developers.
44056 * It always take a number as parameter (between 0 to 1) then
44057 * return a number (between 0 and 1)
44058 */
44059Vivus.LINEAR          = function (x) {return x;};
44060Vivus.EASE            = function (x) {return -Math.cos(x * Math.PI) / 2 + 0.5;};
44061Vivus.EASE_OUT        = function (x) {return 1 - Math.pow(1-x, 3);};
44062Vivus.EASE_IN         = function (x) {return Math.pow(x, 3);};
44063Vivus.EASE_OUT_BOUNCE = function (x) {
44064  var base = -Math.cos(x * (0.5 * Math.PI)) + 1,
44065    rate = Math.pow(base,1.5),
44066    rateR = Math.pow(1 - x, 2),
44067    progress = -Math.abs(Math.cos(rate * (2.5 * Math.PI) )) + 1;
44068  return (1- rateR) + (progress * rateR);
44069};
44070
44071
44072/**
44073 * Setters
44074 **************************************
44075 */
44076
44077/**
44078 * Check and set the element in the instance
44079 * The method will not return anything, but will throw an
44080 * error if the parameter is invalid
44081 *
44082 * @param {DOM|String}   element  SVG Dom element or id of it
44083 */
44084Vivus.prototype.setElement = function (element, options) {
44085  var onLoad, self;
44086
44087  // Basic check
44088  if (typeof element === 'undefined') {
44089    throw new Error('Vivus [constructor]: "element" parameter is required');
44090  }
44091
44092  // Set the element
44093  if (element.constructor === String) {
44094    element = document.getElementById(element);
44095    if (!element) {
44096      throw new Error('Vivus [constructor]: "element" parameter is not related to an existing ID');
44097    }
44098  }
44099  this.parentEl = element;
44100
44101  // Load the SVG with XMLHttpRequest and extract the SVG
44102  if (options && options.file) {
44103    var self = this;
44104    onLoad = function (e) {
44105      var domSandbox = document.createElement('div');
44106      domSandbox.innerHTML = this.responseText;
44107
44108      var svgTag = domSandbox.querySelector('svg');
44109      if (!svgTag) {
44110        throw new Error('Vivus [load]: Cannot find the SVG in the loaded file : ' + options.file);
44111      }
44112
44113      self.el = svgTag
44114      self.el.setAttribute('width', '100%');
44115      self.el.setAttribute('height', '100%');
44116      self.parentEl.appendChild(self.el)
44117      self.isReady = true;
44118      self.init();
44119      self = null;
44120    }
44121
44122    var oReq = new window.XMLHttpRequest();
44123    oReq.addEventListener('load', onLoad);
44124    oReq.open('GET', options.file);
44125    oReq.send();
44126    return;
44127  }
44128
44129  switch (element.constructor) {
44130  case window.SVGSVGElement:
44131  case window.SVGElement:
44132  case window.SVGGElement:
44133    this.el = element;
44134    this.isReady = true;
44135    break;
44136
44137  case window.HTMLObjectElement:
44138    self = this;
44139    onLoad = function (e) {
44140      if (self.isReady) {
44141        return;
44142      }
44143      self.el = element.contentDocument && element.contentDocument.querySelector('svg');
44144      if (!self.el && e) {
44145        throw new Error('Vivus [constructor]: object loaded does not contain any SVG');
44146      }
44147      else if (self.el) {
44148        if (element.getAttribute('built-by-vivus')) {
44149          self.parentEl.insertBefore(self.el, element);
44150          self.parentEl.removeChild(element);
44151          self.el.setAttribute('width', '100%');
44152          self.el.setAttribute('height', '100%');
44153        }
44154        self.isReady = true;
44155        self.init();
44156        self = null;
44157      }
44158    };
44159
44160    if (!onLoad()) {
44161      element.addEventListener('load', onLoad);
44162    }
44163    break;
44164
44165  default:
44166    throw new Error('Vivus [constructor]: "element" parameter is not valid (or miss the "file" attribute)');
44167  }
44168};
44169
44170/**
44171 * Set up user option to the instance
44172 * The method will not return anything, but will throw an
44173 * error if the parameter is invalid
44174 *
44175 * @param  {object} options Object from the constructor
44176 */
44177Vivus.prototype.setOptions = function (options) {
44178  var allowedTypes = ['delayed', 'sync', 'async', 'nsync', 'oneByOne', 'scenario', 'scenario-sync'];
44179  var allowedStarts =  ['inViewport', 'manual', 'autostart'];
44180
44181  // Basic check
44182  if (options !== undefined && options.constructor !== Object) {
44183    throw new Error('Vivus [constructor]: "options" parameter must be an object');
44184  }
44185  else {
44186    options = options || {};
44187  }
44188
44189  // Set the animation type
44190  if (options.type && allowedTypes.indexOf(options.type) === -1) {
44191    throw new Error('Vivus [constructor]: ' + options.type + ' is not an existing animation `type`');
44192  }
44193  else {
44194    this.type = options.type || allowedTypes[0];
44195  }
44196
44197  // Set the start type
44198  if (options.start && allowedStarts.indexOf(options.start) === -1) {
44199    throw new Error('Vivus [constructor]: ' + options.start + ' is not an existing `start` option');
44200  }
44201  else {
44202    this.start = options.start || allowedStarts[0];
44203  }
44204
44205  this.isIE         = (window.navigator.userAgent.indexOf('MSIE') !== -1 || window.navigator.userAgent.indexOf('Trident/') !== -1 || window.navigator.userAgent.indexOf('Edge/') !== -1 );
44206  this.duration     = parsePositiveInt(options.duration, 120);
44207  this.delay        = parsePositiveInt(options.delay, null);
44208  //Uncode addition
44209  this.delayStart   = parsePositiveInt(options.delayStart, null);
44210  //#END
44211  this.dashGap      = parsePositiveInt(options.dashGap, 1);
44212  this.forceRender  = options.hasOwnProperty('forceRender') ? !!options.forceRender : this.isIE;
44213  this.reverseStack = !!options.reverseStack;
44214  this.selfDestroy  = !!options.selfDestroy;
44215  this.onReady      = options.onReady;
44216  this.map          = [];
44217  this.frameLength  = this.currentFrame = this.delayUnit = this.speed = this.handle = null;
44218
44219  this.ignoreInvisible = options.hasOwnProperty('ignoreInvisible') ? !!options.ignoreInvisible : false;
44220
44221  this.animTimingFunction = options.animTimingFunction || Vivus.LINEAR;
44222  this.pathTimingFunction = options.pathTimingFunction || Vivus.LINEAR;
44223
44224  if (this.delay >= this.duration) {
44225    throw new Error('Vivus [constructor]: delay must be shorter than duration');
44226  }
44227};
44228
44229/**
44230 * Set up callback to the instance
44231 * The method will not return enything, but will throw an
44232 * error if the parameter is invalid
44233 *
44234 * @param  {Function} callback Callback for the animation end
44235 */
44236Vivus.prototype.setCallback = function (callback) {
44237  // Basic check
44238  if (!!callback && callback.constructor !== Function) {
44239    throw new Error('Vivus [constructor]: "callback" parameter must be a function');
44240  }
44241  this.callback = callback || function () {};
44242};
44243
44244
44245/**
44246 * Core
44247 **************************************
44248 */
44249
44250/**
44251 * Map the svg, path by path.
44252 * The method return nothing, it just fill the
44253 * `map` array. Each item in this array represent
44254 * a path element from the SVG, with informations for
44255 * the animation.
44256 *
44257 * ```
44258 * [
44259 *   {
44260 *     el: <DOMobj> the path element
44261 *     length: <number> length of the path line
44262 *     startAt: <number> time start of the path animation (in frames)
44263 *     duration: <number> path animation duration (in frames)
44264 *   },
44265 *   ...
44266 * ]
44267 * ```
44268 *
44269 */
44270Vivus.prototype.mapping = function () {
44271  var i, paths, path, pAttrs, pathObj, totalLength, lengthMeter, timePoint;
44272  timePoint = totalLength = lengthMeter = 0;
44273  paths = this.el.querySelectorAll('path');
44274
44275  for (i = 0; i < paths.length; i++) {
44276    path = paths[i];
44277    if (this.isInvisible(path)) {
44278      continue;
44279    }
44280    pathObj = {
44281      el: path,
44282      length: Math.ceil(path.getTotalLength())
44283    };
44284    // Test if the path length is correct
44285    if (isNaN(pathObj.length)) {
44286      if (window.console && console.warn) {
44287        console.warn('Vivus [mapping]: cannot retrieve a path element length', path);
44288      }
44289      continue;
44290    }
44291    this.map.push(pathObj);
44292    path.style.strokeDasharray  = pathObj.length + ' ' + (pathObj.length + this.dashGap * 2);
44293    path.style.strokeDashoffset = pathObj.length + this.dashGap;
44294    pathObj.length += this.dashGap;
44295    totalLength += pathObj.length;
44296
44297    this.renderPath(i);
44298  }
44299
44300  totalLength = totalLength === 0 ? 1 : totalLength;
44301  this.delay = this.delay === null ? this.duration / 3 : this.delay;
44302  this.delayUnit = this.delay / (paths.length > 1 ? paths.length - 1 : 1);
44303
44304  // Reverse stack if asked
44305  if (this.reverseStack) {
44306    this.map.reverse();
44307  }
44308
44309  for (i = 0; i < this.map.length; i++) {
44310    pathObj = this.map[i];
44311
44312    switch (this.type) {
44313    case 'delayed':
44314      pathObj.startAt = this.delayUnit * i;
44315      pathObj.duration = this.duration - this.delay;
44316      break;
44317
44318    case 'oneByOne':
44319      pathObj.startAt = lengthMeter / totalLength * this.duration;
44320      pathObj.duration = pathObj.length / totalLength * this.duration;
44321      break;
44322
44323    case 'sync':
44324    case 'async':
44325    case 'nsync':
44326      pathObj.startAt = 0;
44327      pathObj.duration = this.duration;
44328      break;
44329
44330    case 'scenario-sync':
44331      path = pathObj.el;
44332      pAttrs = this.parseAttr(path);
44333      pathObj.startAt = timePoint + (parsePositiveInt(pAttrs['data-delay'], this.delayUnit) || 0);
44334      pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration);
44335      timePoint = pAttrs['data-async'] !== undefined ? pathObj.startAt : pathObj.startAt + pathObj.duration;
44336      this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration));
44337      break;
44338
44339    case 'scenario':
44340      path = pathObj.el;
44341      pAttrs = this.parseAttr(path);
44342      pathObj.startAt = parsePositiveInt(pAttrs['data-start'], this.delayUnit) || 0;
44343      pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration);
44344      this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration));
44345      break;
44346    }
44347    lengthMeter += pathObj.length;
44348    this.frameLength = this.frameLength || this.duration;
44349  }
44350};
44351
44352/**
44353 * Interval method to draw the SVG from current
44354 * position of the animation. It update the value of
44355 * `currentFrame` and re-trace the SVG.
44356 *
44357 * It use this.handle to store the requestAnimationFrame
44358 * and clear it one the animation is stopped. So this
44359 * attribute can be used to know if the animation is
44360 * playing.
44361 *
44362 * Once the animation at the end, this method will
44363 * trigger the Vivus callback.
44364 *
44365 */
44366Vivus.prototype.drawer = function () {
44367  var self = this;
44368  this.currentFrame += this.speed;
44369
44370  if (this.currentFrame <= 0) {
44371    this.stop();
44372    this.reset();
44373  } else if (this.currentFrame >= this.frameLength) {
44374    this.stop();
44375    this.currentFrame = this.frameLength;
44376    this.trace();
44377    if (this.selfDestroy) {
44378      this.destroy();
44379    }
44380  } else {
44381    this.trace();
44382    this.handle = requestAnimFrame(function () {
44383      self.drawer();
44384    });
44385    return;
44386  }
44387
44388  this.callback(this);
44389  if (this.instanceCallback) {
44390    this.instanceCallback(this);
44391    this.instanceCallback = null;
44392  }
44393};
44394
44395/**
44396 * Draw the SVG at the current instant from the
44397 * `currentFrame` value. Here is where most of the magic is.
44398 * The trick is to use the `strokeDashoffset` style property.
44399 *
44400 * For optimisation reasons, a new property called `progress`
44401 * is added in each item of `map`. This one contain the current
44402 * progress of the path element. Only if the new value is different
44403 * the new value will be applied to the DOM element. This
44404 * method save a lot of resources to re-render the SVG. And could
44405 * be improved if the animation couldn't be played forward.
44406 *
44407 */
44408Vivus.prototype.trace = function () {
44409  var i, progress, path, currentFrame;
44410  currentFrame = this.animTimingFunction(this.currentFrame / this.frameLength) * this.frameLength;
44411  for (i = 0; i < this.map.length; i++) {
44412    path = this.map[i];
44413    progress = (currentFrame - path.startAt) / path.duration;
44414    progress = this.pathTimingFunction(Math.max(0, Math.min(1, progress)));
44415    if (path.progress !== progress) {
44416      path.progress = progress;
44417      path.el.style.strokeDashoffset = Math.floor(path.length * (1 - progress));
44418      this.renderPath(i);
44419    }
44420  }
44421};
44422
44423/**
44424 * Method forcing the browser to re-render a path element
44425 * from it's index in the map. Depending on the `forceRender`
44426 * value.
44427 * The trick is to replace the path element by it's clone.
44428 * This practice is not recommended because it's asking more
44429 * ressources, too much DOM manupulation..
44430 * but it's the only way to let the magic happen on IE.
44431 * By default, this fallback is only applied on IE.
44432 *
44433 * @param  {Number} index Path index
44434 */
44435Vivus.prototype.renderPath = function (index) {
44436  if (this.forceRender && this.map && this.map[index]) {
44437    var pathObj = this.map[index],
44438        newPath = pathObj.el.cloneNode(true);
44439    pathObj.el.parentNode.replaceChild(newPath, pathObj.el);
44440    pathObj.el = newPath;
44441  }
44442};
44443
44444/**
44445 * When the SVG object is loaded and ready,
44446 * this method will continue the initialisation.
44447 *
44448 * This this mainly due to the case of passing an
44449 * object tag in the constructor. It will wait
44450 * the end of the loading to initialise.
44451 *
44452 */
44453Vivus.prototype.init = function () {
44454  // Set object variables
44455  this.frameLength = 0;
44456  this.currentFrame = 0;
44457  this.map = [];
44458
44459  // Start
44460  new Pathformer(this.el);
44461  this.mapping();
44462  this.starter();
44463
44464  if (this.onReady) {
44465    this.onReady(this);
44466  }
44467};
44468
44469/**
44470 * Trigger to start of the animation.
44471 * Depending on the `start` value, a different script
44472 * will be applied.
44473 *
44474 * If the `start` value is not valid, an error will be thrown.
44475 * Even if technically, this is impossible.
44476 *
44477 */
44478Vivus.prototype.starter = function () {
44479  switch (this.start) {
44480  case 'manual':
44481    return;
44482
44483  case 'autostart':
44484    this.play();
44485    break;
44486
44487  case 'inViewport':
44488    var self = this,
44489    listener = function () {
44490      if (self.isInViewport(self.parentEl, 1)) {
44491        self.play();
44492        window.removeEventListener('scroll', listener);
44493        //Uncode addition
44494        window.removeEventListener('fp-slide-changed', listener);
44495        window.removeEventListener('fp-slide-scroll', listener);
44496        //#END
44497      }
44498    };
44499    window.addEventListener('scroll', listener);
44500    //Uncode addition
44501    window.addEventListener('fp-slide-changed', listener);
44502    window.addEventListener('fp-slide-scroll', listener);
44503    //#END
44504    listener();
44505    break;
44506  }
44507};
44508
44509
44510/**
44511 * Controls
44512 **************************************
44513 */
44514
44515/**
44516 * Get the current status of the animation between
44517 * three different states: 'start', 'progress', 'end'.
44518 * @return {string} Instance status
44519 */
44520Vivus.prototype.getStatus = function () {
44521  return this.currentFrame === 0 ? 'start' : this.currentFrame === this.frameLength ? 'end' : 'progress';
44522};
44523
44524/**
44525 * Reset the instance to the initial state : undraw
44526 * Be careful, it just reset the animation, if you're
44527 * playing the animation, this won't stop it. But just
44528 * make it start from start.
44529 *
44530 */
44531Vivus.prototype.reset = function () {
44532  return this.setFrameProgress(0);
44533};
44534
44535/**
44536 * Set the instance to the final state : drawn
44537 * Be careful, it just set the animation, if you're
44538 * playing the animation on rewind, this won't stop it.
44539 * But just make it start from the end.
44540 *
44541 */
44542Vivus.prototype.finish = function () {
44543  return this.setFrameProgress(1);
44544};
44545
44546/**
44547 * Set the level of progress of the drawing.
44548 *
44549 * @param {number} progress Level of progress to set
44550 */
44551Vivus.prototype.setFrameProgress = function (progress) {
44552  progress = Math.min(1, Math.max(0, progress));
44553  this.currentFrame = Math.round(this.frameLength * progress);
44554  this.trace();
44555  return this;
44556};
44557
44558/**
44559 * Play the animation at the desired speed.
44560 * Speed must be a valid number (no zero).
44561 * By default, the speed value is 1.
44562 * But a negative value is accepted to go forward.
44563 *
44564 * And works with float too.
44565 * But don't forget we are in JavaScript, se be nice
44566 * with him and give him a 1/2^x value.
44567 *
44568 * @param  {number} speed Animation speed [optional]
44569 */
44570Vivus.prototype.play = function (speed, callback) {
44571  this.instanceCallback = null;
44572
44573  if (speed && typeof speed === 'function') {
44574    this.instanceCallback = speed; // first parameter is actually the callback function
44575    speed = null;
44576  }
44577  else if (speed && typeof speed !== 'number') {
44578    throw new Error('Vivus [play]: invalid speed');
44579  }
44580  // if the first parameter wasn't the callback, check if the seconds was
44581  if (callback && typeof(callback) === 'function' && !this.instanceCallback) {
44582    this.instanceCallback = callback;
44583  }
44584
44585
44586  this.speed = speed || 1;
44587  //Uncode addition
44588  if (!this.handle) {
44589    var $this = this,
44590    delay = (this.delayStart != null) ? this.delayStart : 0;
44591    setTimeout(function() {
44592      $this.drawer();
44593    }, delay);
44594  }
44595  //#END
44596  return this;
44597};
44598
44599/**
44600 * Stop the current animation, if on progress.
44601 * Should not trigger any error.
44602 *
44603 */
44604Vivus.prototype.stop = function () {
44605  if (this.handle) {
44606    cancelAnimFrame(this.handle);
44607    this.handle = null;
44608  }
44609  return this;
44610};
44611
44612/**
44613 * Destroy the instance.
44614 * Remove all bad styling attributes on all
44615 * path tags
44616 *
44617 */
44618Vivus.prototype.destroy = function () {
44619  this.stop();
44620  var i, path;
44621  for (i = 0; i < this.map.length; i++) {
44622    path = this.map[i];
44623    path.el.style.strokeDashoffset = null;
44624    path.el.style.strokeDasharray = null;
44625    this.renderPath(i);
44626  }
44627};
44628
44629
44630/**
44631 * Utils methods
44632 * include methods from Codrops
44633 **************************************
44634 */
44635
44636/**
44637 * Method to best guess if a path should added into
44638 * the animation or not.
44639 *
44640 * 1. Use the `data-vivus-ignore` attribute if set
44641 * 2. Check if the instance must ignore invisible paths
44642 * 3. Check if the path is visible
44643 *
44644 * For now the visibility checking is unstable.
44645 * It will be used for a beta phase.
44646 *
44647 * Other improvments are planned. Like detecting
44648 * is the path got a stroke or a valid opacity.
44649 */
44650Vivus.prototype.isInvisible = function (el) {
44651  var rect,
44652    ignoreAttr = el.getAttribute('data-ignore');
44653
44654  if (ignoreAttr !== null) {
44655    return ignoreAttr !== 'false';
44656  }
44657
44658  if (this.ignoreInvisible) {
44659    rect = el.getBoundingClientRect();
44660    return !rect.width && !rect.height;
44661  }
44662  else {
44663    return false;
44664  }
44665};
44666
44667/**
44668 * Parse attributes of a DOM element to
44669 * get an object of {attributeName => attributeValue}
44670 *
44671 * @param  {object} element DOM element to parse
44672 * @return {object}         Object of attributes
44673 */
44674Vivus.prototype.parseAttr = function (element) {
44675  var attr, output = {};
44676  if (element && element.attributes) {
44677    for (var i = 0; i < element.attributes.length; i++) {
44678      attr = element.attributes[i];
44679      output[attr.name] = attr.value;
44680    }
44681  }
44682  return output;
44683};
44684
44685/**
44686 * Reply if an element is in the page viewport
44687 *
44688 * @param  {object} el Element to observe
44689 * @param  {number} h  Percentage of height
44690 * @return {boolean}
44691 */
44692Vivus.prototype.isInViewport = function (el, h) {
44693  var scrolled   = this.scrollY(),
44694    viewed       = scrolled + this.getViewportH(),
44695    elBCR        = el.getBoundingClientRect(),
44696    elHeight     = elBCR.height,
44697    elTop        = scrolled + elBCR.top,
44698    elBottom     = elTop + elHeight;
44699
44700  // if 0, the element is considered in the viewport as soon as it enters.
44701  // if 1, the element is considered in the viewport only when it's fully inside
44702  // value in percentage (1 >= h >= 0)
44703  h = h || 0;
44704
44705  return (elTop + elHeight * h) <= viewed && (elBottom) >= scrolled;
44706};
44707
44708
44709/**
44710 * Get the viewport height in pixels
44711 *
44712 * @return {integer} Viewport height
44713 */
44714Vivus.prototype.getViewportH = function () {
44715  var client = this.docElem.clientHeight,
44716    inner = window.innerHeight;
44717
44718  if (client < inner) {
44719    return inner;
44720  }
44721  else {
44722    return client;
44723  }
44724};
44725
44726/**
44727 * Get the page Y offset
44728 *
44729 * @return {integer} Page Y offset
44730 */
44731Vivus.prototype.scrollY = function () {
44732  return window.pageYOffset || this.docElem.scrollTop;
44733};
44734
44735setupEnv = function () {
44736
44737  if (Vivus.prototype.docElem) {
44738    return;
44739  }
44740
44741  /**
44742   * Alias for document element
44743   *
44744   * @type {DOMelement}
44745   */
44746  Vivus.prototype.docElem = window.document.documentElement;
44747
44748  /**
44749   * Alias for `requestAnimationFrame` or
44750   * `setTimeout` function for deprecated browsers.
44751   *
44752   */
44753  requestAnimFrame = (function () {
44754    return (
44755      window.requestAnimationFrame       ||
44756      window.webkitRequestAnimationFrame ||
44757      window.mozRequestAnimationFrame    ||
44758      window.oRequestAnimationFrame      ||
44759      window.msRequestAnimationFrame     ||
44760      function(/* function */ callback){
44761        return window.setTimeout(callback, 1000 / 60);
44762      }
44763    );
44764  })();
44765
44766  /**
44767   * Alias for `cancelAnimationFrame` or
44768   * `cancelTimeout` function for deprecated browsers.
44769   *
44770   */
44771  cancelAnimFrame = (function () {
44772    return (
44773      window.cancelAnimationFrame       ||
44774      window.webkitCancelAnimationFrame ||
44775      window.mozCancelAnimationFrame    ||
44776      window.oCancelAnimationFrame      ||
44777      window.msCancelAnimationFrame     ||
44778      function(id){
44779        return window.clearTimeout(id);
44780      }
44781    );
44782  })();
44783};
44784
44785/**
44786 * Parse string to integer.
44787 * If the number is not positive or null
44788 * the method will return the default value
44789 * or 0 if undefined
44790 *
44791 * @param {string} value String to parse
44792 * @param {*}
44792 defaultValue Value to return if the result parsed is invalid
44793 * @return {number}
44794 *
44795 */
44796parsePositiveInt = function (value, defaultValue) {
44797  var output = parseInt(value, 10);
44798  return (output >= 0) ? output : defaultValue;
44799};
44800
44801
44802  if (typeof define === 'function' && define.amd) {
44803    // AMD. Register as an anonymous module.
44804    define([], function() {
44805      return Vivus;
44806    });
44807  } else if (typeof exports === 'object') {
44808    // Node. Does not work with strict CommonJS, but
44809    // only CommonJS-like environments that support module.exports,
44810    // like Node.
44811    module.exports = Vivus;
44812  } else {
44813    // Browser globals
44814    window.Vivus = Vivus;
44815  }
44816
44817}());
44818
44819//Noise.js
44820!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)}
44820var 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.