PageSourceSearch

https://fitds.it/wp-content/themes/uncode/library/js/plugins.js?ver=586093486

js fitds.it collected 2026-09-25 08:33:27 UTC 1,461,180 bytes, 44,068 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: 23,480 bytes, lines 7386-8298
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() {
vendor: 13,499 bytes, lines 8299-8867
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        pinterest: {
27678          enabled: true,
27679          url: null,
27680          image: null,
27681          description: null
27682        },
27683        reddit: {
27684          enabled: true,
27685          url: null,
27686          title: null
27687        },
27688        linkedin: {
27689          enabled: true,
27690          url: null,
27691          title: null,
27692          description: null
27693        },
27694        xing: {
27695          enabled: true,
27696          url: null,
27697          title: null,
27698          image: null,
27699          description: null
27700        },
27701        whatsapp: {
27702          enabled: true,
27703          title: null,
27704          url: null
27705        },
27706        email: {
27707          enabled: true,
27708          title: null,
27709          description: null,
27710          url: null
27711        }
27712      }
27713    };
27714    this.setup(element, options);
27715    return this;
27716  }
27717
27718  Share.prototype.setup = function(element, opts) {
27719    var index, instance, instances, _i, _len;
27720    instances = document.querySelectorAll(element);
27721    this.extend(this.config, opts, true);
27722    this.set_global_configuration();
27723    this.normalize_network_configuration();
27724    if (this.config.ui.icon_font) {
27725      this.inject_icons();
27726    }
27727    if (this.config.ui.button_font) {
27728      this.inject_fonts();
27729    }
27730    if (this.config.networks.facebook.enabled && this.config.networks.facebook.load_sdk) {
27731      this.inject_facebook_sdk();
27732    }
27733    for (index = _i = 0, _len = instances.length; _i < _len; index = ++_i) {
27734      instance = instances[index];
27735      this.setup_instance(element, index);
27736    }
27737  };
27738
27739  Share.prototype.setup_instance = function(element, index) {
27740    var button, instance, label, network, networks, _i, _len, _results,
27741      _this = this;
27742    instance = document.querySelectorAll(element)[index];
27743    this.hide(instance);
27744    this.add_class(instance, "sharer-" + index);
27745    instance = document.querySelectorAll(element)[index];
27746    this.inject_css(instance);
27747    this.inject_html(instance);
27748    this.show(instance);
27749    label = instance.getElementsByTagName("label")[0];
27750    button = instance.getElementsByClassName("social")[0];
27751    networks = instance.getElementsByTagName('li');
27752    this.add_class(button, "networks-" + this.config.enabled_networks);
27753    label.addEventListener("click", function() {
27754      return _this.event_toggle(button);
27755    });
27756    _this = this;
27757    _results = [];
27758    for (index = _i = 0, _len = networks.length; _i < _len; index = ++_i) {
27759      network = networks[index];
27760      _results.push(network.addEventListener("click", function() {
27761        _this.event_network(instance, this);
27762        return _this.event_close(button);
27763      }));
27764    }
27765    return _results;
27766  };
27767
27768  Share.prototype.event_toggle = function(button) {
27769    if (this.has_class(button, "active")) {
27770      return this.event_close(button);
27771    } else {
27772      return this.event_open(button);
27773    }
27774  };
27775
27776  Share.prototype.event_open = function(button) {
27777    if (this.has_class(button, "load")) {
27778      this.remove_class(button, "load");
27779    }
27780    return this.add_class(button, "active");
27781  };
27782
27783  Share.prototype.event_close = function(button) {
27784    return this.remove_class(button, "active");
27785  };
27786
27787  Share.prototype.event_network = function(instance, network) {
27788    var name;
27789    name = network.getAttribute("data-network");
27790    this.hook("before", name, instance);
27791    this["network_" + name]();
27792    return this.hook("after", name, instance);
27793  };
27794
27795  Share.prototype.open = function() {
27796    return this["public"]("open");
27797  };
27798
27799  Share.prototype.close = function() {
27800    return this["public"]("close");
27801  };
27802
27803  Share.prototype.toggle = function() {
27804    return this["public"]("toggle");
27805  };
27806
27807  Share.prototype["public"] = function(action) {
27808    var button, index, instance, _i, _len, _ref, _results;
27809    _ref = document.querySelectorAll(this.element);
27810    _results = [];
27811    for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) {
27812      instance = _ref[index];
27813      button = instance.getElementsByClassName("social")[0];
27814      _results.push(this["event_" + action](button));
27815    }
27816    return _results;
27817  };
27818
27819  Share.prototype.network_facebook = function() {
27820    if (this.config.networks.facebook.load_sdk) {
27821      if (!window.FB) {
27822        return console.error("The Facebook JS SDK hasn't loaded yet.");
27823      }
27824      return FB.ui({
27825        method: 'feed',
27826        name: this.config.networks.facebook.title,
27827        link: this.config.networks.facebook.url,
27828        picture: this.config.networks.facebook.image,
27829        caption: this.config.networks.facebook.caption,
27830        description: this.config.networks.facebook.description
27831      });
27832    } else {
27833      return this.popup('https://www.facebook.com/sharer/sharer.php', {
27834        u: this.config.networks.facebook.url
27835      });
27836    }
27837  };
27838
27839  Share.prototype.network_twitter = function() {
27840    return this.popup('https://twitter.com/intent/tweet', {
27841      text: this.config.networks.twitter.title,
27842      url: this.config.networks.twitter.url
27843    });
27844  };
27845
27846  Share.prototype.network_pinterest = function() {
27847    return this.popup('https://www.pinterest.com/pin/create/button', {
27848      url: this.config.networks.pinterest.url,
27849      media: this.config.networks.pinterest.image,
27850      description: this.config.networks.pinterest.description
27851    });
27852  };
27853
27854  Share.prototype.network_linkedin = function() {
27855    return this.popup('https://www.linkedin.com/shareArticle', {
27856      url: this.config.networks.linkedin.url,
27857      title: this.config.networks.linkedin.title,
27858      summary: this.config.networks.linkedin.description
27859    });
27860  }
27861
27862  Share.prototype.network_xing = function() {
27863    return this.popup('https://www.xing.com/spi/shares/new', {
27864      url: this.config.networks.xing.url,
27865      image: this.config.networks.xing.image,
27866      title: this.config.networks.xing.title,
27867      summary: this.config.networks.xing.description
27868    });
27869  }
27870
27871  Share.prototype.network_whatsapp = function() {
27872    return this.popup('https://api.whatsapp.com/send', {
27873      text: this.config.networks.whatsapp.title + '%20' + this.config.networks.whatsapp.url,
27874    });
27875  }
27876
27877  Share.prototype.network_email = function() {
27878    return this.popup('mailto:', {
27879      subject: this.config.networks.email.title,
27880      body: this.config.networks.email.url + '%0A%0A' + this.config.networks.email.description,
27881    });
27882  };
27883
27884  Share.prototype.inject_icons = function() {
27885  //  return this.inject_stylesheet("https://www.sharebutton.co/fonts/v2/entypo.min.css");
27886  };
27887
27888  Share.prototype.inject_fonts = function() {
27889   // return this.inject_stylesheet("http://fonts.googleapis.com/css?family=Lato:900&text=" + this.config.ui.button_text);
27890  };
27891
27892  Share.prototype.inject_stylesheet = function(url) {
27893    var link;
27894    if (!this.el.head.querySelector("link[href=\"" + url + "\"]")) {
27895      link = document.createElement("link");
27896      link.setAttribute("rel", "stylesheet");
27897      link.setAttribute("href", url);
27898      return this.el.head.appendChild(link);
27899    }
27900  };
27901
27902  Share.prototype.inject_css = function(instance) {
27903    var css, meta, selector, style;
27904    selector = "." + (instance.getAttribute('class').split(" ").join("."));
27905    if (!this.el.head.querySelector("meta[name='sharer" + selector + "']")) {
27906      this.config.selector = selector;
27907      css = getStyles(this.config);
27908      style = document.createElement("style");
27909      style.type = "text/css";
27910      if (style.styleSheet) {
27911        style.styleSheet.cssText = css;
27912      } else {
27913        style.appendChild(document.createTextNode(css));
27914      }
27915      this.el.head.appendChild(style);
27916      delete this.config.selector;
27917      meta = document.createElement("meta");
27918      meta.setAttribute("name", "sharer" + selector);
27919      return this.el.head.appendChild(meta);
27920    }
27921  };
27922
27923  Share.prototype.inject_html = function(instance) {
27924    //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>";
27925    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-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-xing' data-network='xing' tabindex='0'></li><li class='social-paper-plane' data-network='email' tabindex='0'></li></ul></div>";
27926  };
27927
27928  Share.prototype.inject_facebook_sdk = function() {
27929    var fb_root, script;
27930    if (!window.FB && this.config.networks.facebook.app_id && !this.el.body.querySelector('#fb-root')) {
27931      script = document.createElement("script");
27932      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')";
27933      fb_root = document.createElement("div");
27934      fb_root.id = "fb-root";
27935      this.el.body.appendChild(fb_root);
27936      return this.el.body.appendChild(script);
27937    }
27938  };
27939
27940  Share.prototype.hook = function(type, network, instance) {
27941    var fn, opts;
27942    fn = this.config.networks[network][type];
27943    if (typeof fn === "function") {
27944      opts = fn.call(this.config.networks[network], instance);
27945      if (opts !== void 0) {
27946        opts = this.normalize_filter_config_updates(opts);
27947        this.extend(this.config.networks[network], opts, true);
27948        this.normalize_network_configuration();
27949      }
27950    }
27951  };
27952
27953  Share.prototype.default_title = function() {
27954    var content;
27955    if (content = document.querySelector('meta[property="og:title"]') || document.querySelector('meta[name="twitter:title"]')) {
27956      return encodeURIComponent(content.getAttribute('content'));
27957    } else if (content = document.querySelector('title')) {
27958      return encodeURIComponent(content.innerText);
27959    }
27960  };
27961
27962  Share.prototype.default_image = function() {
27963    var content;
27964    if (content = document.querySelector('meta[property="og:image"]') || document.querySelector('meta[name="twitter:image"]')) {
27965      return content.getAttribute('content');
27966    }
27967  };
27968
27969  Share.prototype.default_description = function() {
27970    var content;
27971    if (content = document.querySelector('meta[property="og:description"]') || document.querySelector('meta[name="twitter:description"]') || document.querySelector('meta[name="description"]')) {
27972      return encodeURIComponent(content.getAttribute('content'));
27973    } else {
27974      return '';
27975    }
27976  };
27977
27978  Share.prototype.set_global_configuration = function() {
27979    var display, network, option, options, _ref, _results;
27980    _ref = this.config.networks;
27981    _results = [];
27982    for (network in _ref) {
27983      options = _ref[network];
27984      for (option in options) {
27985        if (this.config.networks[network][option] == null) {
27986          this.config.networks[network][option] = this.config[option];
27987        }
27988      }
27989      if (this.config.networks[network].enabled) {
27990        display = 'block';
27991        this.config.enabled_networks += 1;
27992      } else {
27993        display = 'none';
27994      }
27995      _results.push(this.config.networks[network].display = display);
27996    }
27997    return _results;
27998  };
27999
28000  Share.prototype.normalize_network_configuration = function() {
28001    if (!this.config.networks.facebook.app_id) {
28002      this.config.networks.facebook.load_sdk = false;
28003    }
28004    if (!this.is_encoded(this.config.networks.twitter.description)) {
28005      this.config.networks.twitter.description = encodeURIComponent(this.config.networks.twitter.description);
28006    }
28007    if (typeof this.config.networks.facebook.app_id === 'number') {
28008      return this.config.networks.facebook.app_id = this.config.networks.facebook.app_id.toString();
28009    }
28010  };
28011
28012  Share.prototype.normalize_filter_config_updates = function(opts) {
28013    if (this.config.networks.facebook.app_id !== opts.app_id) {
28014      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.");
28015      delete opts.app_id;
28016    }
28017    if (this.config.networks.facebook.load_sdk !== opts.load_sdk) {
28018      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.");
28019      delete opts.app_id;
28020    }
28021    return opts;
28022  };
28023
28024  return Share;
28025
28026})(ShareUtils);
28027 return Share;
28028});
28029
28030// Generated by CoffeeScript 1.9.2
28031
28032// @license Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net
28033
28034(function() {
28035  var $, win;
28036
28037  $ = this.jQuery || window.jQuery;
28038
28039  win = $(window);
28040
28041  $.fn.stick_in_parent = function(opts) {
28042    var doc, elm, enable_bottoming, fn, i, inner_scrolling, len, manual_spacer, offset_top, outer_width, parent_selector, recalc_every, sticky_class;
28043    if (opts == null) {
28044      opts = {};
28045    }
28046    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;
28047    if (offset_top == null) {
28048      offset_top = 0;
28049    }
28050    if (parent_selector == null) {
28051      parent_selector = void 0;
28052    }
28053    if (inner_scrolling == null) {
28054      inner_scrolling = true;
28055    }
28056    if (sticky_class == null) {
28057      sticky_class = "is_stuck";
28058    }
28059    doc = $(document);
28060    if (enable_bottoming == null) {
28061      enable_bottoming = true;
28062    }
28063    outer_width = function(el) {
28064      var _el, computed, w;
28065      if (window.getComputedStyle) {
28066        _el = el[0];
28067        computed = window.getComputedStyle(el[0]);
28068        w = parseFloat(computed.getPropertyValue("width")) + parseFloat(computed.getPropertyValue("margin-left")) + parseFloat(computed.getPropertyValue("margin-right"));
28069        if (computed.getPropertyValue("box-sizing") !== "border-box") {
28070          w += parseFloat(computed.getPropertyValue("border-left-width")) + parseFloat(computed.getPropertyValue("border-right-width")) + parseFloat(computed.getPropertyValue("padding-left")) + parseFloat(computed.getPropertyValue("padding-right"));
28071        }
28072        return w;
28073      } else {
28074        return el.outerWidth(true);
28075      }
28076    };
28077    fn = function(elm, padding_bottom, parent_top, parent_height, top, height, el_float, detached) {
28078      var bottomed, detach, fixed, last_pos, last_scroll_height, offset, parent, recalc, recalc_and_tick, recalc_counter, spacer, tick;
28079      if (elm.data("sticky_kit")) {
28080        return;
28081      }
28082      elm.data("sticky_kit", true);
28083      last_scroll_height = doc.height();
28084      parent = elm.parent();
28085      if (parent_selector != null) {
28086        parent = parent.closest(parent_selector);
28087      }
28088      if (!parent.length) {
28089        throw "failed to find stick parent";
28090      }
28091      fixed = false;
28092      bottomed = false;
28093      spacer = manual_spacer != null ? manual_spacer && elm.closest(manual_spacer) : $("<div />");
28094      if (spacer) {
28095        spacer.css('position', elm.css('position'));
28096      }
28097      recalc = function() {
28098        var border_top, padding_top, restore;
28099        if (detached) {
28100          return;
28101        }
28102        last_scroll_height = doc.height();
28103        border_top = parseInt(parent.css("border-top-width"), 10);
28104        padding_top = parseInt(parent.css("padding-top"), 10);
28105        padding_bottom = parseInt(parent.css("padding-bottom"), 10);
28106        parent_top = parent.offset().top + border_top + padding_top;
28107        parent_height = parent.height();
28108        if (fixed) {
28109          fixed = false;
vendor: 6,068 bytes, lines 28110-28304
28110          bottomed = false;
28111          if (manual_spacer == null) {
28112            elm.insertAfter(spacer);
28113            spacer.detach();
28114          }
28115          elm.css({
28116            position: "",
28117            top: "",
28118            width: "",
28119            bottom: ""
28120          }).removeClass(sticky_class);
28121          restore = true;
28122        }
28123        top = elm.offset().top - (parseInt(elm.css("margin-top"), 10) || 0) - offset_top;
28124        height = elm.outerHeight(true);
28125        el_float = elm.css("float");
28126        if (spacer) {
28127          spacer.css({
28128            width: outer_width(elm),
28129            height: height,
28130            display: elm.css("display"),
28131            "vertical-align": elm.css("vertical-align"),
28132            "float": el_float
28133          });
28134        }
28135        if (restore) {
28136          return tick();
28137        }
28138      };
28139      recalc();
28140      if (height === parent_height) {
28141        return;
28142      }
28143      last_pos = void 0;
28144      offset = offset_top;
28145      recalc_counter = recalc_every;
28146      tick = function() {
28147        var css, delta, recalced, scroll, will_bottom, win_height;
28148        if (detached) {
28149          return;
28150        }
28151        recalced = false;
28152        if (recalc_counter != null) {
28153          recalc_counter -= 1;
28154          if (recalc_counter <= 0) {
28155            recalc_counter = recalc_every;
28156            recalc();
28157            recalced = true;
28158          }
28159        }
28160        if (!recalced && doc.height() !== last_scroll_height) {
28161          recalc();
28162          recalced = true;
28163        }
28164        scroll = win.scrollTop();
28165        if (last_pos != null) {
28166          delta = scroll - last_pos;
28167        }
28168        last_pos = scroll;
28169        if (fixed) {
28170          if (enable_bottoming) {
28171            will_bottom = scroll + height + offset > parent_height + parent_top;
28172            if (bottomed && !will_bottom) {
28173              bottomed = false;
28174              elm.css({
28175                position: "fixed",
28176                bottom: "",
28177                top: offset
28178              }).trigger("sticky_kit:unbottom");
28179            }
28180          }
28181          if (scroll < top) {
28182            fixed = false;
28183            offset = offset_top;
28184            if (manual_spacer == null) {
28185              if (el_float === "left" || el_float === "right") {
28186                elm.insertAfter(spacer);
28187              }
28188              spacer.detach();
28189            }
28190            css = {
28191              position: "",
28192              width: "",
28193              top: ""
28194            };
28195            elm.css(css).removeClass(sticky_class).trigger("sticky_kit:unstick");
28196          }
28197          if (inner_scrolling) {
28198            win_height = win.height();
28199            if (height + offset_top > win_height) {
28200              if (!bottomed) {
28201                offset -= delta;
28202                offset = Math.max(win_height - height, offset);
28203                offset = Math.min(offset_top, offset);
28204                if (fixed) {
28205                  elm.css({
28206                    top: offset + "px"
28207                  });
28208                }
28209              }
28210            }
28211          }
28212        } else {
28213          if (scroll > top) {
28214            fixed = true;
28215            css = {
28216              position: "fixed",
28217              top: offset
28218            };
28219            css.width = elm.css("box-sizing") === "border-box" ? elm.outerWidth() + "px" : elm.width() + "px";
28220            elm.css(css).addClass(sticky_class);
28221            if (manual_spacer == null) {
28222              elm.after(spacer);
28223              if (el_float === "left" || el_float === "right") {
28224                spacer.append(elm);
28225              }
28226            }
28227            elm.trigger("sticky_kit:stick");
28228          }
28229        }
28230        if (fixed && enable_bottoming) {
28231          if (will_bottom == null) {
28232            will_bottom = scroll + height + offset > parent_height + parent_top;
28233          }
28234          if (!bottomed && will_bottom) {
28235            bottomed = true;
28236            if (parent.css("position") === "static") {
28237              parent.css({
28238                position: "relative"
28239              });
28240            }
28241            return elm.css({
28242              position: "absolute",
28243              bottom: padding_bottom,
28244              top: "auto"
28245            }).trigger("sticky_kit:bottom");
28246          }
28247        }
28248      };
28249      recalc_and_tick = function() {
28250        recalc();
28251        return tick();
28252      };
28253      detach = function() {
28254        detached = true;
28255        win.off("touchmove", tick);
28256        win.off("scroll", tick);
28257        win.off("resize", recalc_and_tick);
28258        $(document.body).off("sticky_kit:recalc", recalc_and_tick);
28259        elm.off("sticky_kit:detach", detach);
28260        elm.removeData("sticky_kit");
28261        elm.css({
28262          position: "",
28263          bottom: "",
28264          top: "",
28265          width: ""
28266        });
28267        parent.position("position", "");
28268        if (fixed) {
28269          if (manual_spacer == null) {
28270            if (el_float === "left" || el_float === "right") {
28271              elm.insertAfter(spacer);
28272            }
28273            spacer.remove();
28274          }
28275          return elm.removeClass(sticky_class);
28276        }
28277      };
28278      win.on("touchmove", tick);
28279      win.on("scroll", tick);
28280      win.on("resize", recalc_and_tick);
28281      $(document.body).on("sticky_kit:recalc", recalc_and_tick);
28282      elm.on("sticky_kit:detach", detach);
28283      return setTimeout(tick, 0);
28284    };
28285    for (i = 0, len = this.length; i < len; i++) {
28286      elm = this[i];
28287      fn($(elm));
28288    }
28289    return this;
28290  };
28291
28292}).call(this);
28293/* ==========================================================================
28294 * bootstrap-tab-history.js
28295 * Author: Michael Narayan <[email protected]>
28296 * Repository: https://github.com/mnarayan01/bootstrap-tab-history/
28297 * ==========================================================================
28298 * Licensed under the Apache License, Version 2.0 (the "License"); you may
28299 * not use this file except in compliance with the License. You may obtain a
28300 * copy of the License at
28301 *
28302 * http://www.apache.org/licenses/LICENSE-2.0
28303 *
28304 * Unless required by applicable law or agreed to in writing, softw
28304are
28305 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
28306 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
28307 * License for the specific language governing permissions and limitations
28308 * under the License.
28309 * ========================================================================== */
28310
28311/* ========================================================================== */
28312/* JSHint directives                                                          */
28313/*                                                                            */
28314/* global BootstrapTabHistory: true                                           */
28315/*                                                                            */
28316/* global document                                                            */
28317/* global jQuery                                                              */
28318/* global history                                                             */
28319/* global window                                                              */
28320/* ========================================================================== */
28321
28322/**
28323 * Integrate [HTML5 history state tracking](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history)
28324 * with [`bootstrap/tab.js`](http://getbootstrap.com/javascript/#tabs). To enable tracking on a tab element, simply set
28325 * the `data-tab-history` attribute to true (or a string denoting a tab grouping).
28326 *
28327 * See the README for additional information.
28328 *
28329 * Functionality based upon bootstrap/tab.js v3.1.0; reference it when making any changes.
28330 */
28331
28332BootstrapTabHistory = {
28333  options: {
28334    /**
28335     * When the anchor portion of the URI is used to activate a tab, scroll down to the given offset, rather than the
28336     * element with the given `id` attribute. Set to null to disable. Only relevant if showTabsBasedOnAnchor is true.
28337     *
28338     * May be overriden on a per-element basis by the attribute `data-tab-history-anchor-y-offset`.
28339     *
28340     * @public
28341     * @type {?number}
28342     */
28343    defaultAnchorYOffset: 0,
28344    /**
28345     * Either 'push' or 'replace', for whether to use `history.pushState` or `history.replaceState`, resp.
28346     *
28347     * May be overriden on a per-element basis by the attribute `data-tab-history-changer`.
28348     *
28349     * @public
28350     * @type {string}
28351     */
28352    defaultChanger: 'replace',
28353    /**
28354     * If true, update the URL in onShownTab in the calls to `history.pushState` and `history.replaceState`. Otherwise,
28355     * `null` is passed as the third parameter to these calls.
28356     *
28357     * May be overriden on a per-element basis by the attribute `data-tab-history-update-url`.
28358     *
28359     * @public
28360     * @type {boolean}
28361     */
28362    defaultUpdateURL: false,
28363    /**
28364     * Should the anchor portion of the loaded URI be used to activate a single tab if no history was present on page
28365     * load.
28366     *
28367     * @public
28368     * @type {boolean}
28369     */
28370    showTabsBasedOnAnchor: true
28371  }
28372};
28373
28374(function () {
28375  'use strict';
28376
28377  jQuery(function () {
28378    if(history && history.pushState && history.replaceState) {
28379      var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory;
28380
28381      if(bootstrapTabHistory) {
28382        showTabsBasedOnState(bootstrapTabHistory);
28383      } else {
28384        showTabsBasedOnAnchor();
28385      }
28386
28387      backfillHistoryState();
28388
28389      jQuery(document).on('shown.bs.tab show.bs.collapse', onShownTab);
28390      jQuery(window).on('popstate', onPopState);
28391    } else {
28392      showTabsBasedOnAnchor();
28393    }
28394  });
28395
28396  /**
28397   * Used to prevent onShownTab from registering shown events that we triggered via showTabsBasedOnState.
28398   *
28399   * @type {boolean}
28400   */
28401  var showingTabsBasedOnState = false;
28402
28403  /**
28404   * Used to update `history.state` to reflect the default active tabs on initial page load. This supports proper
28405   * `history.back` handling when `data-tab-history-update-url` is true.
28406   */
28407  function backfillHistoryState() {
28408    var newState = null;
28409
28410    jQuery('li.active > [data-tab-history], .panel-title.active [data-tab-history]').each(function () {//edited by Uncode
28411      var $activeTabElement = jQuery(this);
28412      var selector = getTabSelector($activeTabElement);
28413
28414      if(selector) {
28415        var tabGroup = getTabGroup($activeTabElement);
28416
28417        if(tabGroup) {
28418          newState = createNewHistoryState(newState || history.state, tabGroup, selector);
28419        }
28420      }
28421    });
28422
28423    if(newState) {
28424      history.replaceState(newState, '', null);
28425    }
28426  }
28427
28428  /**
28429   * Clone the existing state, ensure its bootstrapTabHistory attribute is an Object, and add the provided tabGroup to
28430   * said bootstrapTabHistory attribute.
28431   *
28432   * @param {?object} existingState
28433   * @param {!string} tabGroup
28434   * @param {!string} selector
28435   * @returns {!object}
28436   */
28437  function createNewHistoryState(existingState, tabGroup, selector) {
28438    // Clone history.state and ensure it has a bootstrapTabHistory entry.
28439    var newState = jQuery.extend(true, {}, existingState, {
28440      bootstrapTabHistory: {}
28441    });
28442
28443    newState.bootstrapTabHistory[tabGroup] = selector;
28444
28445    return newState;
28446  }
28447
28448  /**
28449   * @param {jQuery} $tab
28450   * @returns {?string}
28451   */
28452  function getTabGroup($tab) {
28453    return parseTruthyAttributeValue($tab.data('tab-history'));
28454  }
28455
28456  /**
28457   * @param {jQuery} $tab
28458   * @returns {?string}
28459   */
28460  function getTabSelector($tab) {
28461    return $tab.data('target') || $tab.attr('href');
28462  }
28463
28464  /**
28465   * Receives the `shown.bs.tab` event. Updates `history.state` as appropriate.
28466   *
28467   * @param {jQuery.Event} shownEvt
28468   */
28469  function onShownTab(shownEvt) {
28470    if(!showingTabsBasedOnState) {
28471      var $activatedTab = jQuery(shownEvt.target);
28472      if ( $activatedTab.hasClass('panel-collapse') )
28473        $activatedTab = $activatedTab.closest('.panel').find('a');
28474      var selector = getTabSelector($activatedTab);
28475
28476      if(selector) {
28477        var tabGroup = getTabGroup($activatedTab);
28478
28479        if(tabGroup) {
28480          var historyChanger = $activatedTab.data('tab-history-changer') || BootstrapTabHistory.options.defaultChanger;
28481          var newState = createNewHistoryState(history.state, tabGroup, selector);
28482          var updateURL = (function ($activatedTab) {
28483            if(selector[0] === '#') {
28484              var elementUpdateURLOption = parseTruthyAttributeValue($activatedTab.data('tab-history-update-url'));
28485
28486              if(elementUpdateURLOption === undefined) {
28487                return BootstrapTabHistory.options.defaultUpdateURL;
28488              } else {
28489                return elementUpdateURLOption;
28490              }
28491            } else {
28492              return false;
28493            }
28494          })($activatedTab);
28495
28496          switch(historyChanger) {
28497            case 'push':
28498              history.pushState(newState, '', updateURL ? selector : null);
28499              break;
28500            case 'replace':
28501              history.replaceState(newState, '', updateURL ? selector : null);
28502              break;
28503            default:
28504              throw new Error('Unknown tab-history-changer: ' + historyChanger);
28505          }
28506        }
28507      }
28508    }
28509  }
28510
28511  /**
28512   * Receives the `popstate` event. Shows tabs based on the value of `history.state` as appropriate.
28513   */
28514  function onPopState() {
28515    var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory;
28516
28517    if(bootstrapTabHistory) {
28518      showTabsBasedOnState(bootstrapTabHistory);
28519    }
28520  }
28521
28522  /**
28523   * Returns the given value, _unless_ that value is an empty string, in which case `true` is returned.
28524   *
28525   * Rationale: HAML data attributes which are set to `true` are rendered as a blank string.
28526   *
28527   * @param {*} value
28528   * @returns {*}
28529   */
28530  function parseTruthyAttributeValue(value) {
28531    if(value) {
28532      return value;
28533    } else if(value === '') {
28534      return true;
28535    } else {
28536      return value;
28537    }
28538  }
28539
28540  /**
28541   * Show tabs based upon the anchor component of `window.location`.
28542   */
28543  function showTabsBasedOnAnchor() {
28544    if(BootstrapTabHistory.options.showTabsBasedOnAnchor) {
28545      var anchor = window.location && window.location.hash;
28546
28547      if(anchor) {
28548        var $tabElement = showTabForSelector(anchor);
28549
28550        if($tabElement && window.addEventListener && window.removeEventListener) {
28551          var anchorYOffset = (function ($tabElement) {
28552            var elementSetting = $tabElement.data('tab-history-anchor-y-offset');
28553
28554            if(elementSetting === undefined) {
28555              return BootstrapTabHistory.options.defaultAnchorYOffset;
28556            } else {
28557              return elementSetting;
28558            }
28559          })($tabElement);
28560
28561          // HACK: This prevents scrolling to the tab on page load. This relies on the fact that we should never get
28562          //   here on `history.forward`, `history.back`, or `location.reload`, since in all those situations the
28563          //   `history.state` object should have been used (unless the browser did not support the modern History API).
28564          if(anchorYOffset || anchorYOffset === 0) {
28565            var scrollListener = function resetAnchorScroll () {
28566              window.removeEventListener('scroll', scrollListener);
28567              window.scrollTo(0, anchorYOffset);
28568            };
28569
28570            window.addEventListener('scroll', scrollListener);
28571          }
28572        }
28573      }
28574    }
28575  }
28576
28577  /**
28578   * Show a tab which corresponds to the provided selector.
28579   *
28580   * @param {string} selector - A CSS selector.
28581   * @returns {?jQuery} - The tab which was found to show (even if said tab was already active).
28582   */
28583  function showTabForSelector(selector) {
28584    var $tabElement = (function (selector) {
28585      var $ret = null;
28586
28587      jQuery('[data-toggle="tab"], [data-toggle="pill"], [data-toggle="collapse"]').each(function () {
28588        var $potentialTab = jQuery(this);
28589
28590        if(($potentialTab.attr('href') === selector || $potentialTab.data('target') === selector ) && getTabGroup($potentialTab)) {
28591          $ret = $potentialTab;
28592          return false;
vendor: 43,483 bytes, lines 28593-29809
28593        } else {
28594         return null;
28595        }
28596      });
28597
28598      return $ret;
28599    })(selector);
28600
28601    if($tabElement) {
28602      if ( !$tabElement.parent().hasClass('active') ) {
28603        $tabElement.trigger('click');
28604      }
28605      //$tabElement.tab('show');
28606    }
28607
28608    return $tabElement;
28609  }
28610
28611  /**
28612   * Iterate through the provided set of tab tab groups, showing the tabs based on the stored selectors.
28613   *
28614   * @param {object} bootstrapTabHistory - Each of the values is passed to showTabForSelector; the keys are actually irrelevant.
28615   */
28616  function showTabsBasedOnState(bootstrapTabHistory) {
28617    showingTabsBasedOnState = true;
28618
28619    try {
28620      for(var k in bootstrapTabHistory) {
28621        if(bootstrapTabHistory.hasOwnProperty(k)) {
28622          showTabForSelector(bootstrapTabHistory[k]);
28623        }
28624      }
28625    } finally {
28626      showingTabsBasedOnState = false;
28627    }
28628  }
28629})();
28630
28631/*!
28632 * justifiedGallery - v3.8.1
28633 * http://miromannino.github.io/Justified-Gallery/
28634 * Copyright (c) 2020 Miro Mannino
28635 * Licensed under the MIT license.
28636 */
28637(function (factory) {
28638  if (typeof define === 'function' && define.amd) {
28639    // AMD. Register as an anonymous module.
28640    define(['jquery'], factory);
28641  } else if (typeof module === 'object' && module.exports) {
28642    // Node/CommonJS
28643    module.exports = function (root, jQuery) {
28644      if (jQuery === undefined) {
28645        // require('jQuery') returns a factory that requires window to
28646        // build a jQuery instance, we normalize how we use modules
28647        // that require this pattern but the window provided is a noop
28648        // if it's defined (how jquery works)
28649        if (typeof window !== 'undefined') {
28650          jQuery = require('jquery');
28651        }
28652        else {
28653          jQuery = require('jquery')(root);
28654        }
28655      }
28656      factory(jQuery);
28657      return jQuery;
28658    };
28659  } else {
28660    // Browser globals
28661    factory(jQuery);
28662  }
28663}(function ($) {
28664
28665  /**
28666   * Justified Gallery controller constructor
28667   *
28668   * @param $gallery the gallery to build
28669   * @param settings the settings (the defaults are in JustifiedGallery.defaults)
28670   * @constructor
28671   */
28672  var JustifiedGallery = function ($gallery, settings) {
28673
28674    this.settings = settings;
28675    this.checkSettings();
28676
28677    this.imgAnalyzerTimeout = null;
28678    this.entries = null;
28679    this.buildingRow = {
28680      entriesBuff: [],
28681      width: 0,
28682      height: 0,
28683      aspectRatio: 0
28684    };
28685    this.lastFetchedEntry = null;
28686    this.lastAnalyzedIndex = -1;
28687    this.yield = {
28688      every: 2, // do a flush every n flushes (must be greater than 1)
28689      flushed: 0 // flushed rows without a yield
28690    };
28691    this.border = settings.border >= 0 ? settings.border : settings.margins;
28692    this.maxRowHeight = this.retrieveMaxRowHeight();
28693    this.suffixRanges = this.retrieveSuffixRanges();
28694    this.offY = this.border;
28695    this.rows = 0;
28696    this.spinner = {
28697      phase: 0,
28698      timeSlot: 150,
28699      $el: $('<div class="jg-spinner"><span></span><span></span><span></span></div>'),
28700      intervalId: null
28701    };
28702    this.scrollBarOn = false;
28703    this.checkWidthIntervalId = null;
28704    this.galleryWidth = $gallery.width();
28705    this.$gallery = $gallery;
28706
28707  };
28708
28709  /** @returns {String} the best suffix given the width and the height */
28710  JustifiedGallery.prototype.getSuffix = function (width, height) {
28711    var longestSide, i;
28712    longestSide = (width > height) ? width : height;
28713    for (i = 0; i < this.suffixRanges.length; i++) {
28714      if (longestSide <= this.suffixRanges[i]) {
28715        return this.settings.sizeRangeSuffixes[this.suffixRanges[i]];
28716      }
28717    }
28718    return this.settings.sizeRangeSuffixes[this.suffixRanges[i - 1]];
28719  };
28720
28721  /**
28722   * Remove the suffix from the string
28723   *
28724   * @returns {string} a new string without the suffix
28725   */
28726  JustifiedGallery.prototype.removeSuffix = function (str, suffix) {
28727    return str.substring(0, str.length - suffix.length);
28728  };
28729
28730  /**
28731   * @returns {boolean} a boolean to say if the suffix is contained in the str or not
28732   */
28733  JustifiedGallery.prototype.endsWith = function (str, suffix) {
28734    return str.indexOf(suffix, str.length - suffix.length) !== -1;
28735  };
28736
28737  /**
28738   * Get the used suffix of a particular url
28739   *
28740   * @param str
28741   * @returns {String} return the used suffix
28742   */
28743  JustifiedGallery.prototype.getUsedSuffix = function (str) {
28744    for (var si in this.settings.sizeRangeSuffixes) {
28745      if (this.settings.sizeRangeSuffixes.hasOwnProperty(si)) {
28746        if (this.settings.sizeRangeSuffixes[si].length === 0) continue;
28747        if (this.endsWith(str, this.settings.sizeRangeSuffixes[si])) return this.settings.sizeRangeSuffixes[si];
28748      }
28749    }
28750    return '';
28751  };
28752
28753  /**
28754   * Given an image src, with the width and the height, returns the new image src with the
28755   * best suffix to show the best quality thumbnail.
28756   *
28757   * @returns {String} the suffix to use
28758   */
28759  JustifiedGallery.prototype.newSrc = function (imageSrc, imgWidth, imgHeight, image) {
28760    var newImageSrc;
28761
28762    if (this.settings.thumbnailPath) {
28763      newImageSrc = this.settings.thumbnailPath(imageSrc, imgWidth, imgHeight, image);
28764    } else {
28765      var matchRes = imageSrc.match(this.settings.extension);
28766      var ext = (matchRes !== null) ? matchRes[0] : '';
28767      newImageSrc = imageSrc.replace(this.settings.extension, '');
28768      newImageSrc = this.removeSuffix(newImageSrc, this.getUsedSuffix(newImageSrc));
28769      newImageSrc += this.getSuffix(imgWidth, imgHeight) + ext;
28770    }
28771
28772    return newImageSrc;
28773  };
28774
28775  /**
28776   * Shows the images that is in the given entry
28777   *
28778   * @param $entry the entry
28779   * @param callback the callback that is called when the show animation is finished
28780   */
28781  JustifiedGallery.prototype.showImg = function ($entry, callback) {
28782    if (this.settings.cssAnimation) {
28783      $entry.addClass('jg-entry-visible');
28784      if (callback) callback();
28785    } else {
28786      $entry.stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback);
28787      $entry.find(this.settings.imgSelector).stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback);
28788    }
28789  };
28790
28791  /**
28792   * Extract the image src form the image, looking from the 'safe-src', and if it can't be found, from the
28793   * 'src' attribute. It saves in the image data the 'jg.originalSrc' field, with the extracted src.
28794   *
28795   * @param $image the image to analyze
28796   * @returns {String} the extracted src
28797   */
28798  JustifiedGallery.prototype.extractImgSrcFromImage = function ($image) {
28799    var imageSrc = $image.data('safe-src');
28800    var imageSrcLoc = 'data-safe-src';
28801    // Begin Uncode edit
28802    if (typeof imageSrc === 'undefined') {
28803    	var imageCurrentSrc = $image[0].currentSrc;
28804    	if (imageCurrentSrc) {
28805    		imageSrc = imageCurrentSrc;
28806    	} else {
28807    		imageSrc = $image.attr('src');
28808    	}
28809		imageSrcLoc = 'src';
28810    }
28811    // End Uncode edit
28812    $image.data('jg.originalSrc', imageSrc); // this is saved for the destroy method
28813    $image.data('jg.src', imageSrc); // this will change overtime
28814    $image.data('jg.originalSrcLoc', imageSrcLoc); // this is saved for the destroy method
28815    return imageSrc;
28816  };
28817
28818  /** @returns {jQuery} the image in the given entry */
28819  JustifiedGallery.prototype.imgFromEntry = function ($entry) {
28820    var $img = $entry.find(this.settings.imgSelector);
28821    if ($img.length === 0) $img = $entry.find('.t-entry-visual-cont img');//hacked by Uncode
28822    return $img.length === 0 ? null : $img;
28823  };
28824
28825  /** @returns {jQuery} the caption in the given entry */
28826  JustifiedGallery.prototype.captionFromEntry = function ($entry) {
28827    var $caption = $entry.find('> .jg-caption');
28828    return $caption.length === 0 ? null : $caption;
28829  };
28830
28831  /**
28832   * Display the entry
28833   *
28834   * @param {jQuery} $entry the entry to display
28835   * @param {int} x the x position where the entry must be positioned
28836   * @param y the y position where the entry must be positioned
28837   * @param imgWidth the image width
28838   * @param imgHeight the image height
28839   * @param rowHeight the row height of the row that owns the entry
28840   */
28841  JustifiedGallery.prototype.displayEntry = function ($entry, x, y, imgWidth, imgHeight, rowHeight) {
28842    $entry.width(imgWidth);
28843    $entry.height(Math.floor(rowHeight));//hacked by Uncode
28844    $entry.css('top', Math.floor(y));//hacked by Uncode
28845    $entry.css('left', x);
28846
28847    var $image = this.imgFromEntry($entry);
28848    if ($image !== null) {
28849      $image.css('width', imgWidth);
28850      $image.css('height', imgHeight);
28851      $image.css('margin-left', - imgWidth / 2);
28852      $image.css('margin-top', - imgHeight / 2);
28853
28854      // Image reloading for an high quality of thumbnails
28855      var imageSrc = $image.data('jg.src');
28856      if (imageSrc) {
28857        imageSrc = this.newSrc(imageSrc, imgWidth, imgHeight, $image[0]);
28858
28859        $image.one('error', function () {
28860           this.resetImgSrc($image); //revert to the original thumbnail
28861        });
28862
28863        var loadNewImage = function () {
28864          // if (imageSrc !== newImageSrc) {
28865            $image.attr('src', imageSrc);
28866          // }
28867        };
28868
28869        if ($entry.data('jg.loaded') === 'skipped' && imageSrc) {
28870          this.onImageEvent(imageSrc, (function() {
28871            this.showImg($entry, loadNewImage); //load the new image after the fadeIn
28872            $entry.data('jg.loaded', true);
28873          }).bind(this));
28874        } else {
28875          this.showImg($entry, loadNewImage); //load the new image after the fadeIn
28876        }
28877
28878      }
28879
28880    } else {
28881      this.showImg($entry);
28882    }
28883
28884    this.displayEntryCaption($entry);
28885  };
28886
28887  /**
28888   * Display the entry caption. If the caption element doesn't exists, it creates the caption using the 'alt'
28889   * or the 'title' attributes.
28890   *
28891   * @param {jQuery} $entry the entry to process
28892   */
28893  JustifiedGallery.prototype.displayEntryCaption = function ($entry) {
28894    var $image = this.imgFromEntry($entry);
28895    if ($image !== null && this.settings.captions) {
28896      var $imgCaption = this.captionFromEntry($entry);
28897
28898      // Create it if it doesn't exists
28899      if ($imgCaption === null) {
28900        var caption = $image.attr('alt');
28901        if (!this.isValidCaption(caption)) caption = $entry.attr('title');
28902        if (this.isValidCaption(caption)) { // Create only we found something
28903          $imgCaption = $('<div class="jg-caption">' + caption + '</div>');
28904          $entry.append($imgCaption);
28905          $entry.data('jg.createdCaption', true);
28906        }
28907      }
28908
28909      // Create events (we check again the $imgCaption because it can be still inexistent)
28910      if ($imgCaption !== null) {
28911        if (!this.settings.cssAnimation) $imgCaption.stop().fadeTo(0, this.settings.captionSettings.nonVisibleOpacity);
28912        this.addCaptionEventsHandlers($entry);
28913      }
28914    } else {
28915      this.removeCaptionEventsHandlers($entry);
28916    }
28917  };
28918
28919  /**
28920   * Validates the caption
28921   *
28922   * @param caption The caption that should be validated
28923   * @return {boolean} Validation result
28924   */
28925  JustifiedGallery.prototype.isValidCaption = function (caption) {
28926    return (typeof caption !== 'undefined' && caption.length > 0);
28927  };
28928
28929  /**
28930   * The callback for the event 'mouseenter'. It assumes that the event currentTarget is an entry.
28931   * It shows the caption using jQuery (or using CSS if it is configured so)
28932   *
28933   * @param {Event} eventObject the event object
28934   */
28935  JustifiedGallery.prototype.onEntryMouseEnterForCaption = function (eventObject) {
28936    var $caption = this.captionFromEntry($(eventObject.currentTarget));
28937    if (this.settings.cssAnimation) {
28938      $caption.addClass('jg-caption-visible').removeClass('jg-caption-hidden');
28939    } else {
28940      $caption.stop().fadeTo(this.settings.captionSettings.animationDuration,
28941        this.settings.captionSettings.visibleOpacity);
28942    }
28943  };
28944
28945  /**
28946   * The callback for the event 'mouseleave'. It assumes that the event currentTarget is an entry.
28947   * It hides the caption using jQuery (or using CSS if it is configured so)
28948   *
28949   * @param {Event} eventObject the event object
28950   */
28951  JustifiedGallery.prototype.onEntryMouseLeaveForCaption = function (eventObject) {
28952    var $caption = this.captionFromEntry($(eventObject.currentTarget));
28953    if (this.settings.cssAnimation) {
28954      $caption.removeClass('jg-caption-visible').removeClass('jg-caption-hidden');
28955    } else {
28956      $caption.stop().fadeTo(this.settings.captionSettings.animationDuration,
28957        this.settings.captionSettings.nonVisibleOpacity);
28958    }
28959  };
28960
28961  /**
28962   * Add the handlers of the entry for the caption
28963   *
28964   * @param $entry the entry to modify
28965   */
28966  JustifiedGallery.prototype.addCaptionEventsHandlers = function ($entry) {
28967    var captionMouseEvents = $entry.data('jg.captionMouseEvents');
28968    if (typeof captionMouseEvents === 'undefined') {
28969      captionMouseEvents = {
28970        mouseenter: $.proxy(this.onEntryMouseEnterForCaption, this),
28971        mouseleave: $.proxy(this.onEntryMouseLeaveForCaption, this)
28972      };
28973      $entry.on('mouseenter', undefined, undefined, captionMouseEvents.mouseenter);
28974      $entry.on('mouseleave', undefined, undefined, captionMouseEvents.mouseleave);
28975      $entry.data('jg.captionMouseEvents', captionMouseEvents);
28976    }
28977  };
28978
28979  /**
28980   * Remove the handlers of the entry for the caption
28981   *
28982   * @param $entry the entry to modify
28983   */
28984  JustifiedGallery.prototype.removeCaptionEventsHandlers = function ($entry) {
28985    var captionMouseEvents = $entry.data('jg.captionMouseEvents');
28986    if (typeof captionMouseEvents !== 'undefined') {
28987      $entry.off('mouseenter', undefined, captionMouseEvents.mouseenter);
28988      $entry.off('mouseleave', undefined, captionMouseEvents.mouseleave);
28989      $entry.removeData('jg.captionMouseEvents');
28990    }
28991  };
28992
28993  /**
28994   * Clear the building row data to be used for a new row
28995   */
28996  JustifiedGallery.prototype.clearBuildingRow = function () {
28997    this.buildingRow.entriesBuff = [];
28998    this.buildingRow.aspectRatio = 0;
28999    this.buildingRow.width = 0;
29000  };
29001
29002  /**
29003   * Justify the building row, preparing it to
29004   *
29005   * @param isLastRow
29006   * @param hiddenRow undefined or false for normal behavior. hiddenRow = true to hide the row.
29007   * @returns a boolean to know if the row has been justified or not
29008   */
29009  JustifiedGallery.prototype.prepareBuildingRow = function (isLastRow, hiddenRow) {
29010    var i, $entry, imgAspectRatio, newImgW, newImgH, justify = true;
29011    var minHeight = 0;
29012    var availableWidth = this.galleryWidth - 2 * this.border - (
29013      (this.buildingRow.entriesBuff.length - 1) * this.settings.margins);
29014    var rowHeight = Math.floor( availableWidth / this.buildingRow.aspectRatio );//hacked by Uncode
29015    var defaultRowHeight = this.settings.rowHeight;
29016    var justifiable = this.buildingRow.width / availableWidth > this.settings.justifyThreshold;
29017
29018    //Skip the last row if we can't justify it and the lastRow == 'hide'
29019    if (hiddenRow || (isLastRow && this.settings.lastRow === 'hide' && !justifiable)) {
29020      for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
29021        $entry = this.buildingRow.entriesBuff[i];
29022        if (this.settings.cssAnimation)
29023          $entry.removeClass('jg-entry-visible');
29024        else {
29025          $entry.stop().fadeTo(0, 0.1);
29026          $entry.find('> img, > a > img').fadeTo(0, 0);
29027        }
29028      }
29029      return -1;
29030    }
29031
29032    // With lastRow = nojustify, justify if is justificable (the images will not become too big)
29033    if (isLastRow && !justifiable && this.settings.lastRow !== 'justify' && this.settings.lastRow !== 'hide') {
29034      justify = false;
29035
29036      if (this.rows > 0) {
29037        defaultRowHeight = (this.offY - this.border - this.settings.margins * this.rows) / this.rows;
29038        justify = defaultRowHeight * this.buildingRow.aspectRatio / availableWidth > this.settings.justifyThreshold;
29039      }
29040    }
29041
29042    for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
29043      $entry = this.buildingRow.entriesBuff[i];
29044      imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height');
29045
29046      if (justify) {
29047        newImgW = (i === this.buildingRow.entriesBuff.length - 1) ? availableWidth : rowHeight * imgAspectRatio;
29048        newImgH = rowHeight;
29049      } else {
29050        newImgW = defaultRowHeight * imgAspectRatio;
29051        newImgH = defaultRowHeight;
29052      }
29053
29054      availableWidth -= Math.round(newImgW);
29055      $entry.data('jg.jwidth', Math.round(newImgW));
29056      $entry.data('jg.jheight', Math.ceil(newImgH));
29057      if (i === 0 || minHeight > newImgH) minHeight = newImgH;
29058    }
29059
29060    this.buildingRow.height = minHeight;
29061    return justify;
29062  };
29063
29064  /**
29065   * Flush a row: justify it, modify the gallery height accordingly to the row height
29066   *
29067   * @param isLastRow
29068   * @param hiddenRow undefined or false for normal behavior. hiddenRow = true to hide the row.
29069   */
29070  JustifiedGallery.prototype.flushRow = function (isLastRow, hiddenRow) {
29071    var settings = this.settings;
29072    var $entry, buildingRowRes, offX = this.border, i;
29073
29074    buildingRowRes = this.prepareBuildingRow(isLastRow, hiddenRow);
29075    if (hiddenRow || (isLastRow && settings.lastRow === 'hide' && buildingRowRes === -1)) {
29076      this.clearBuildingRow();
29077      return;
29078    }
29079
29080    if (this.maxRowHeight) {
29081      if (this.maxRowHeight < this.buildingRow.height) this.buildingRow.height = this.maxRowHeight;
29082    }
29083
29084    //Align last (unjustified) row
29085    if (isLastRow && (settings.lastRow === 'center' || settings.lastRow === 'right')) {
29086      var availableWidth = this.galleryWidth - 2 * this.border - (this.buildingRow.entriesBuff.length - 1) * settings.margins;
29087
29088      for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
29089        $entry = this.buildingRow.entriesBuff[i];
29090        availableWidth -= $entry.data('jg.jwidth');
29091      }
29092
29093      if (settings.lastRow === 'center')
29094        offX += Math.round(availableWidth / 2);
29095      else if (settings.lastRow === 'right')
29096        offX += availableWidth;
29097    }
29098
29099    var lastEntryIdx = this.buildingRow.entriesBuff.length - 1;
29100    for (i = 0; i <= lastEntryIdx; i++) {
29101      $entry = this.buildingRow.entriesBuff[this.settings.rtl ? lastEntryIdx - i : i];
29102      this.displayEntry($entry, offX, this.offY, $entry.data('jg.jwidth'), $entry.data('jg.jheight'), this.buildingRow.height);
29103      offX += $entry.data('jg.jwidth') + settings.margins;
29104    }
29105
29106    //Gallery Height
29107    this.galleryHeightToSet = this.offY + this.buildingRow.height + this.border;
29108    this.setGalleryTempHeight(this.galleryHeightToSet + this.getSpinnerHeight());
29109
29110    if (!isLastRow || (this.buildingRow.height <= settings.rowHeight && buildingRowRes)) {
29111      //Ready for a new row
29112      this.offY += this.buildingRow.height + settings.margins;
29113      this.rows += 1;
29114      this.clearBuildingRow();
29115      this.settings.triggerEvent.call(this, 'jg.rowflush');
29116    }
29117  };
29118
29119
29120  // Scroll position not restoring: https://github.com/miromannino/Justified-Gallery/issues/221
29121  var galleryPrevStaticHeight = 0;
29122
29123  JustifiedGallery.prototype.rememberGalleryHeight = function () {
29124    galleryPrevStaticHeight = this.$gallery.height();
29125    this.$gallery.height(galleryPrevStaticHeight);
29126  };
29127
29128  // grow only
29129  JustifiedGallery.prototype.setGalleryTempHeight = function (height) {
29130    galleryPrevStaticHeight = Math.max(height, galleryPrevStaticHeight);
29131    this.$gallery.height(galleryPrevStaticHeight);
29132  };
29133
29134  JustifiedGallery.prototype.setGalleryFinalHeight = function (height) {
29135    galleryPrevStaticHeight = height;
29136    this.$gallery.height(height);
29137  };
29138
29139  /**
29140   * Checks the width of the gallery container, to know if a new justification is needed
29141   */
29142  JustifiedGallery.prototype.checkWidth = function () {
29143    this.checkWidthIntervalId = setInterval($.proxy(function () {
29144
29145      // if the gallery is not currently visible, abort.
29146      if (!this.$gallery.is(":visible")) return;
29147
29148      var galleryWidth = parseFloat(this.$gallery.width());
29149      if (Math.abs(galleryWidth - this.galleryWidth) > this.settings.refreshSensitivity) {
29150        this.galleryWidth = galleryWidth;
29151        this.rewind();
29152
29153        this.rememberGalleryHeight();
29154
29155        // Restart to analyze
29156        this.startImgAnalyzer(true);
29157      }
29158    }, this), this.settings.refreshTime);
29159  };
29160
29161  /**
29162   * @returns {boolean} a boolean saying if the spinner is active or not
29163   */
29164  JustifiedGallery.prototype.isSpinnerActive = function () {
29165    return this.spinner.intervalId !== null;
29166  };
29167
29168  /**
29169   * @returns {int} the spinner height
29170   */
29171  JustifiedGallery.prototype.getSpinnerHeight = function () {
29172    return this.spinner.$el.innerHeight();
29173  };
29174
29175  /**
29176   * Stops the spinner animation and modify the gallery height to exclude the spinner
29177   */
29178  JustifiedGallery.prototype.stopLoadingSpinnerAnimation = function () {
29179    clearInterval(this.spinner.intervalId);
29180    this.spinner.intervalId = null;
29181    this.setGalleryTempHeight(this.$gallery.height() - this.getSpinnerHeight());
29182    this.spinner.$el.detach();
29183  };
29184
29185  /**
29186   * Starts the spinner animation
29187   */
29188  JustifiedGallery.prototype.startLoadingSpinnerAnimation = function () {
29189    var spinnerContext = this.spinner;
29190    var $spinnerPoints = spinnerContext.$el.find('span');
29191    clearInterval(spinnerContext.intervalId);
29192    this.$gallery.append(spinnerContext.$el);
29193    this.setGalleryTempHeight(this.offY + this.buildingRow.height + this.getSpinnerHeight());
29194    spinnerContext.intervalId = setInterval(function () {
29195      if (spinnerContext.phase < $spinnerPoints.length) {
29196        $spinnerPoints.eq(spinnerContext.phase).fadeTo(spinnerContext.timeSlot, 1);
29197      } else {
29198        $spinnerPoints.eq(spinnerContext.phase - $spinnerPoints.length).fadeTo(spinnerContext.timeSlot, 0);
29199      }
29200      spinnerContext.phase = (spinnerContext.phase + 1) % ($spinnerPoints.length * 2);
29201    }, spinnerContext.timeSlot);
29202  };
29203
29204  /**
29205   * Rewind the image analysis to start from the first entry.
29206   */
29207  JustifiedGallery.prototype.rewind = function () {
29208    this.lastFetchedEntry = null;
29209    this.lastAnalyzedIndex = -1;
29210    this.offY = this.border;
29211    this.rows = 0;
29212    this.clearBuildingRow();
29213  };
29214
29215  /**
29216   * @returns {String} `settings.selector` rejecting spinner element
29217   */
29218  JustifiedGallery.prototype.getSelectorWithoutSpinner = function () {
29219    return this.settings.selector + ', div:not(.jg-spinner)';
29220  };
29221
29222  /**
29223   * @returns {Array} all entries matched by `settings.selector`
29224   */
29225  JustifiedGallery.prototype.getAllEntries = function () {
29226    var selector = this.getSelectorWithoutSpinner();
29227    return this.$gallery.children(selector).toArray();
29228  };
29229
29230  /**
29231   * Update the entries searching it from the justified gallery HTML element
29232   *
29233   * @param norewind if norewind only the new entries will be changed (i.e. randomized, sorted or filtered)
29234   * @returns {boolean} true if some entries has been founded
29235   */
29236  JustifiedGallery.prototype.updateEntries = function (norewind) {
29237    var newEntries;
29238
29239    if (norewind && this.lastFetchedEntry != null) {
29240      var selector = this.getSelectorWithoutSpinner();
29241      newEntries = $(this.lastFetchedEntry).nextAll(selector).toArray();
29242    } else {
29243      this.entries = [];
29244      newEntries = this.getAllEntries();
29245    }
29246
29247    if (newEntries.length > 0) {
29248
29249      // Sort or randomize
29250      if ($.isFunction(this.settings.sort)) {
29251        newEntries = this.sortArray(newEntries);
29252      } else if (this.settings.randomize) {
29253        newEntries = this.shuffleArray(newEntries);
29254      }
29255      this.lastFetchedEntry = newEntries[newEntries.length - 1];
29256
29257      // Filter
29258      if (this.settings.filter) {
29259        newEntries = this.filterArray(newEntries);
29260      } else {
29261        this.resetFilters(newEntries);
29262      }
29263
29264    }
29265
29266    this.entries = this.entries.concat(newEntries);
29267    return true;
29268  };
29269
29270  /**
29271   * Apply the entries order to the DOM, iterating the entries and appending the images
29272   *
29273   * @param entries the entries that has been modified and that must be re-ordered in the DOM
29274   */
29275  JustifiedGallery.prototype.insertToGallery = function (entries) {
29276    var that = this;
29277    $.each(entries, function () {
29278      $(this).appendTo(that.$gallery);
29279    });
29280  };
29281
29282  /**
29283   * Shuffle the array using the Fisher-Yates shuffle algorithm
29284   *
29285   * @param a the array to shuffle
29286   * @return the shuffled array
29287   */
29288  JustifiedGallery.prototype.shuffleArray = function (a) {
29289    var i, j, temp;
29290    for (i = a.length - 1; i > 0; i--) {
29291      j = Math.floor(Math.random() * (i + 1));
29292      temp = a[i];
29293      a[i] = a[j];
29294      a[j] = temp;
29295    }
29296    this.insertToGallery(a);
29297    return a;
29298  };
29299
29300  /**
29301   * Sort the array using settings.comparator as comparator
29302   *
29303   * @param a the array to sort (it is sorted)
29304   * @return the sorted array
29305   */
29306  JustifiedGallery.prototype.sortArray = function (a) {
29307    a.sort(this.settings.sort);
29308    this.insertToGallery(a);
29309    return a;
29310  };
29311
29312  /**
29313   * Reset the filters removing the 'jg-filtered' class from all the entries
29314   *
29315   * @param a the array to reset
29316   */
29317  JustifiedGallery.prototype.resetFilters = function (a) {
29318    for (var i = 0; i < a.length; i++) $(a[i]).removeClass('jg-filtered');
29319  };
29320
29321  /**
29322   * Filter the entries considering theirs classes (if a string has been passed) or using a function for filtering.
29323   *
29324   * @param a the array to filter
29325   * @return the filtered array
29326   */
29327  JustifiedGallery.prototype.filterArray = function (a) {
29328    var settings = this.settings;
29329    if ($.type(settings.filter) === 'string') {
29330      // Filter only keeping the entries passed in the string
29331      return a.filter(function (el) {
29332        var $el = $(el);
29333        if ($el.is(settings.filter)) {
29334          $el.removeClass('jg-filtered');
29335          return true;
29336        } else {
29337          $el.addClass('jg-filtered').removeClass('jg-visible');
29338          return false;
29339        }
29340      });
29341    } else if ($.isFunction(settings.filter)) {
29342      // Filter using the passed function
29343      var filteredArr = a.filter(settings.filter);
29344      for (var i = 0; i < a.length; i++) {
29345        if (filteredArr.indexOf(a[i]) === -1) {
29346          $(a[i]).addClass('jg-filtered').removeClass('jg-visible');
29347        } else {
29348          $(a[i]).removeClass('jg-filtered');
29349        }
29350      }
29351      return filteredArr;
29352    }
29353  };
29354
29355  /**
29356   * Revert the image src to the default value.
29357   */
29358  JustifiedGallery.prototype.resetImgSrc = function ($img) {
29359    if ($img.data('jg.originalSrcLoc') === 'src') {
29360      $img.attr('src', $img.data('jg.originalSrc'));
29361    } else {
29362      $img.attr('src', '');
29363    }
29364  };
29365
29366  /**
29367   * Destroy the Justified Gallery instance.
29368   *
29369   * It clears all the css properties added in the style attributes. We doesn't backup the original
29370   * values for those css attributes, because it costs (performance) and because in general one
29371   * shouldn't use the style attribute for an uniform set of images (where we suppose the use of
29372   * classes). Creating a backup is also difficult because JG could be called multiple times and
29373   * with different style attributes.
29374   */
29375  JustifiedGallery.prototype.destroy = function () {
29376    clearInterval(this.checkWidthIntervalId);
29377    this.stopImgAnalyzerStarter();
29378
29379    // Get fresh entries list since filtered entries are absent in `this.entries`
29380    $.each(this.getAllEntries(), $.proxy(function (_, entry) {
29381      var $entry = $(entry);
29382
29383      // Reset entry style
29384      $entry.css('width', '');
29385      $entry.css('height', '');
29386      $entry.css('top', '');
29387      $entry.css('left', '');
29388      $entry.data('jg.loaded', undefined);
29389      $entry.removeClass('jg-entry jg-filtered jg-entry-visible');
29390
29391      // Reset image style
29392      var $img = this.imgFromEntry($entry);
29393      if ($img) {
29394        $img.css('width', '');
29395        $img.css('height', '');
29396        $img.css('margin-left', '');
29397        $img.css('margin-top', '');
29398        this.resetImgSrc($img);
29399        $img.data('jg.originalSrc', undefined);
29400        $img.data('jg.originalSrcLoc', undefined);
29401        $img.data('jg.src', undefined);
29402      }
29403
29404      // Remove caption
29405      this.removeCaptionEventsHandlers($entry);
29406      var $caption = this.captionFromEntry($entry);
29407      if ($entry.data('jg.createdCaption')) {
29408        // remove also the caption element (if created by jg)
29409        $entry.data('jg.createdCaption', undefined);
29410        if ($caption !== null) $caption.remove();
29411      } else {
29412        if ($caption !== null) $caption.fadeTo(0, 1);
29413      }
29414
29415    }, this));
29416
29417    this.$gallery.css('height', '');
29418    this.$gallery.removeClass('justified-gallery');
29419    this.$gallery.data('jg.controller', undefined);
29420    this.settings.triggerEvent.call(this, 'jg.destroy');
29421  };
29422
29423  /**
29424   * Analyze the images and builds the rows. It returns if it found an image that is not loaded.
29425   *
29426   * @param isForResize if the image analyzer is called for resizing or not, to call a different callback at the end
29427   */
29428  JustifiedGallery.prototype.analyzeImages = function (isForResize) {
29429    for (var i = this.lastAnalyzedIndex + 1; i < this.entries.length; i++) {
29430      var $entry = $(this.entries[i]);
29431      if ($entry.data('jg.loaded') === true || $entry.data('jg.loaded') === 'skipped') {
29432        var availableWidth = this.galleryWidth - 2 * this.border - (
29433          (this.buildingRow.entriesBuff.length - 1) * this.settings.margins);
29434        var imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height');
29435
29436        this.buildingRow.entriesBuff.push($entry);
29437        this.buildingRow.aspectRatio += imgAspectRatio;
29438        this.buildingRow.width += imgAspectRatio * this.settings.rowHeight;
29439        this.lastAnalyzedIndex = i;
29440
29441        if (availableWidth / (this.buildingRow.aspectRatio + imgAspectRatio) < this.settings.rowHeight) {
29442          this.flushRow(false, this.settings.maxRowsCount > 0 && this.rows === this.settings.maxRowsCount);
29443
29444          if (++this.yield.flushed >= this.yield.every) {
29445            this.startImgAnalyzer(isForResize);
29446            return;
29447          }
29448        }
29449      } else if ($entry.data('jg.loaded') !== 'error') {
29450        return;
29451      }
29452    }
29453
29454    // Last row flush (the row is not full)
29455    if (this.buildingRow.entriesBuff.length > 0) {
29456      this.flushRow(true, this.settings.maxRowsCount > 0 && this.rows === this.settings.maxRowsCount);
29457    }
29458
29459    if (this.isSpinnerActive()) {
29460      this.stopLoadingSpinnerAnimation();
29461    }
29462
29463    /* Stop, if there is, the timeout to start the analyzeImages.
29464     This is because an image can be set loaded, and the timeout can be set,
29465     but this image can be analyzed yet.
29466     */
29467    this.stopImgAnalyzerStarter();
29468
29469    this.setGalleryFinalHeight(this.galleryHeightToSet);
29470
29471    //On complete callback
29472    this.settings.triggerEvent.call(this, isForResize ? 'jg.resize' : 'jg.complete');
29473  };
29474
29475  /**
29476   * Stops any ImgAnalyzer starter (that has an assigned timeout)
29477   */
29478  JustifiedGallery.prototype.stopImgAnalyzerStarter = function () {
29479    this.yield.flushed = 0;
29480    if (this.imgAnalyzerTimeout !== null) {
29481      clearTimeout(this.imgAnalyzerTimeout);
29482      this.imgAnalyzerTimeout = null;
29483    }
29484  };
29485
29486  /**
29487   * Starts the image analyzer. It is not immediately called to let the browser to update the view
29488   *
29489   * @param isForResize specifies if the image analyzer must be called for resizing or not
29490   */
29491  JustifiedGallery.prototype.startImgAnalyzer = function (isForResize) {
29492    var that = this;
29493    this.stopImgAnalyzerStarter();
29494    this.imgAnalyzerTimeout = setTimeout(function () {
29495      that.analyzeImages(isForResize);
29496    }, 0.001); // we can't start it immediately due to a IE different behaviour
29497  };
29498
29499  /**
29500   * Checks if the image is loaded or not using another image object. We cannot use the 'complete' image property,
29501   * because some browsers, with a 404 set complete = true.
29502   *
29503   * @param imageSrc the image src to load
29504   * @param onLoad callback that is called when the image has been loaded
29505   * @param onError callback that is called in case of an error
29506   */
29507  JustifiedGallery.prototype.onImageEvent = function (imageSrc, onLoad, onError) {
29508    if (!onLoad && !onError) return;
29509
29510    var memImage = new Image();
29511    var $memImage = $(memImage);
29512    if (onLoad) {
29513      $memImage.one('load', function () {
29514        $memImage.off('load error');
29515        onLoad(memImage);
29516      });
29517    }
29518    if (onError) {
29519      $memImage.one('error', function () {
29520        $memImage.off('load error');
29521        onError(memImage);
29522      });
29523    }
29524    memImage.src = imageSrc;
29525  };
29526
29527  /**
29528   * Init of Justified Gallery controlled
29529   * It analyzes all the entries starting theirs loading and calling the image analyzer (that works with loaded images)
29530   */
29531  JustifiedGallery.prototype.init = function () {
29532    var imagesToLoad = false, skippedImages = false, that = this;
29533    $.each(this.entries, function (index, entry) {
29534      var $entry = $(entry);
29535      var $image = that.imgFromEntry($entry);
29536
29537      $entry.addClass('jg-entry');
29538
29539      if ($entry.data('jg.loaded') !== true && $entry.data('jg.loaded') !== 'skipped') {
29540
29541        // Link Rel global overwrite
29542        if (that.settings.rel !== null) $entry.attr('rel', that.settings.rel);
29543
29544        // Link Target global overwrite
29545        if (that.settings.target !== null) $entry.attr('target', that.settings.target);
29546
29547        if ($image !== null) {
29548
29549          // Image src
29550          var imageSrc = that.extractImgSrcFromImage($image);
29551
29552          /* If we have the height and the width, we don't wait that the image is loaded,
29553             but we start directly with the justification */
29554          if (that.settings.waitThumbnailsLoad === false || !imageSrc) {
29555            var width = parseFloat($image.attr('width'));
29556            var height = parseFloat($image.attr('height'));
29557            if ($image.prop('tagName') === 'svg') {
29558              width = parseFloat($image[0].getBBox().width);
29559              height = parseFloat($image[0].getBBox().height);
29560            }
29561            if (!isNaN(width) && !isNaN(height)) {
29562              $entry.data('jg.width', width);
29563              $entry.data('jg.height', height);
29564              $entry.data('jg.loaded', 'skipped');
29565              skippedImages = true;
29566              that.startImgAnalyzer(false);
29567              return true; // continue
29568            }
29569          }
29570
29571          $entry.data('jg.loaded', false);
29572          imagesToLoad = true;
29573
29574          // Spinner start
29575          if (!that.isSpinnerActive()) that.startLoadingSpinnerAnimation();
29576
29577          that.onImageEvent(imageSrc, function (loadImg) { // image loaded
29578            $entry.data('jg.width', loadImg.width);
29579            $entry.data('jg.height', loadImg.height);
29580            $entry.data('jg.loaded', true);
29581            that.startImgAnalyzer(false);
29582          }, function () { // image load error
29583            $entry.data('jg.loaded', 'error');
29584            that.startImgAnalyzer(false);
29585          });
29586
29587        } else {
29588          $entry.data('jg.loaded', true);
29589          $entry.data('jg.width', $entry.width() | parseFloat($entry.css('width')) | 1);
29590          $entry.data('jg.height', $entry.height() | parseFloat($entry.css('height')) | 1);
29591        }
29592
29593      }
29594
29595    });
29596
29597    if (!imagesToLoad && !skippedImages) this.startImgAnalyzer(false);
29598    this.checkWidth();
29599  };
29600
29601  /**
29602   * Checks that it is a valid number. If a string is passed it is converted to a number
29603   *
29604   * @param settingContainer the object that contains the setting (to allow the conversion)
29605   * @param settingName the setting name
29606   */
29607  JustifiedGallery.prototype.checkOrConvertNumber = function (settingContainer, settingName) {
29608    if ($.type(settingContainer[settingName]) === 'string') {
29609      settingContainer[settingName] = parseFloat(settingContainer[settingName]);
29610    }
29611
29612    if ($.type(settingContainer[settingName]) === 'number') {
29613      if (isNaN(settingContainer[settingName])) throw 'invalid number for ' + settingName;
29614    } else {
29615      throw settingName + ' must be a number';
29616    }
29617  };
29618
29619  /**
29620   * Checks the sizeRangeSuffixes and, if necessary, converts
29621   * its keys from string (e.g. old settings with 'lt100') to int.
29622   */
29623  JustifiedGallery.prototype.checkSizeRangesSuffixes = function () {
29624    if ($.type(this.settings.sizeRangeSuffixes) !== 'object') {
29625      throw 'sizeRangeSuffixes must be defined and must be an object';
29626    }
29627
29628    var suffixRanges = [];
29629    for (var rangeIdx in this.settings.sizeRangeSuffixes) {
29630      if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(rangeIdx);
29631    }
29632
29633    var newSizeRngSuffixes = { 0: '' };
29634    for (var i = 0; i < suffixRanges.length; i++) {
29635      if ($.type(suffixRanges[i]) === 'string') {
29636        try {
29637          var numIdx = parseInt(suffixRanges[i].replace(/^[a-z]+/, ''), 10);
29638          newSizeRngSuffixes[numIdx] = this.settings.sizeRangeSuffixes[suffixRanges[i]];
29639        } catch (e) {
29640          throw 'sizeRangeSuffixes keys must contains correct numbers (' + e + ')';
29641        }
29642      } else {
29643        newSizeRngSuffixes[suffixRanges[i]] = this.settings.sizeRangeSuffixes[suffixRanges[i]];
29644      }
29645    }
29646
29647    this.settings.sizeRangeSuffixes = newSizeRngSuffixes;
29648  };
29649
29650  /**
29651   * check and convert the maxRowHeight setting
29652   * requires rowHeight to be already set
29653   * TODO: should be always called when only rowHeight is changed
29654   * @return number or null
29655   */
29656  JustifiedGallery.prototype.retrieveMaxRowHeight = function () {
29657    var newMaxRowHeight = null;
29658    var rowHeight = this.settings.rowHeight;
29659
29660    if ($.type(this.settings.maxRowHeight) === 'string') {
29661      if (this.settings.maxRowHeight.match(/^[0-9]+%$/)) {
29662        newMaxRowHeight = rowHeight * parseFloat(this.settings.maxRowHeight.match(/^([0-9]+)%$/)[1]) / 100;
29663      } else {
29664        newMaxRowHeight = parseFloat(this.settings.maxRowHeight);
29665      }
29666    } else if ($.type(this.settings.maxRowHeight) === 'number') {
29667      newMaxRowHeight = this.settings.maxRowHeight;
29668    } else if (this.settings.maxRowHeight === false || this.settings.maxRowHeight == null) {
29669      return null;
29670    } else {
29671      throw 'maxRowHeight must be a number or a percentage';
29672    }
29673
29674    // check if the converted value is not a number
29675    if (isNaN(newMaxRowHeight)) throw 'invalid number for maxRowHeight';
29676
29677    // check values, maxRowHeight must be >= rowHeight
29678    if (newMaxRowHeight < rowHeight) newMaxRowHeight = rowHeight;
29679
29680    return newMaxRowHeight;
29681  };
29682
29683  /**
29684   * Checks the settings
29685   */
29686  JustifiedGallery.prototype.checkSettings = function () {
29687    this.checkSizeRangesSuffixes();
29688
29689    this.checkOrConvertNumber(this.settings, 'rowHeight');
29690    this.checkOrConvertNumber(this.settings, 'margins');
29691    this.checkOrConvertNumber(this.settings, 'border');
29692    this.checkOrConvertNumber(this.settings, 'maxRowsCount');
29693
29694    var lastRowModes = [
29695      'justify',
29696      'nojustify',
29697      'left',
29698      'center',
29699      'right',
29700      'hide'
29701    ];
29702    if (lastRowModes.indexOf(this.settings.lastRow) === -1) {
29703      throw 'lastRow must be one of: ' + lastRowModes.join(', ');
29704    }
29705
29706    this.checkOrConvertNumber(this.settings, 'justifyThreshold');
29707    if (this.settings.justifyThreshold < 0 || this.settings.justifyThreshold > 1) {
29708      throw 'justifyThreshold must be in the interval [0,1]';
29709    }
29710    if ($.type(this.settings.cssAnimation) !== 'boolean') {
29711      throw 'cssAnimation must be a boolean';
29712    }
29713
29714    if ($.type(this.settings.captions) !== 'boolean') throw 'captions must be a boolean';
29715    this.checkOrConvertNumber(this.settings.captionSettings, 'animationDuration');
29716
29717    this.checkOrConvertNumber(this.settings.captionSettings, 'visibleOpacity');
29718    if (this.settings.captionSettings.visibleOpacity < 0 ||
29719      this.settings.captionSettings.visibleOpacity > 1) {
29720      throw 'captionSettings.visibleOpacity must be in the interval [0, 1]';
29721    }
29722
29723    this.checkOrConvertNumber(this.settings.captionSettings, 'nonVisibleOpacity');
29724    if (this.settings.captionSettings.nonVisibleOpacity < 0 ||
29725      this.settings.captionSettings.nonVisibleOpacity > 1) {
29726      throw 'captionSettings.nonVisibleOpacity must be in the interval [0, 1]';
29727    }
29728
29729    this.checkOrConvertNumber(this.settings, 'imagesAnimationDuration');
29730    this.checkOrConvertNumber(this.settings, 'refreshTime');
29731    this.checkOrConvertNumber(this.settings, 'refreshSensitivity');
29732    if ($.type(this.settings.randomize) !== 'boolean') throw 'randomize must be a boolean';
29733    if ($.type(this.settings.selector) !== 'string') throw 'selector must be a string';
29734
29735    if (this.settings.sort !== false && !$.isFunction(this.settings.sort)) {
29736      throw 'sort must be false or a comparison function';
29737    }
29738
29739    if (this.settings.filter !== false && !$.isFunction(this.settings.filter) &&
29740      $.type(this.settings.filter) !== 'string') {
29741      throw 'filter must be false, a string or a filter function';
29742    }
29743  };
29744
29745  /**
29746   * It brings all the indexes from the sizeRangeSuffixes and it orders them. They are then sorted and returned.
29747   * @returns {Array} sorted suffix ranges
29748   */
29749  JustifiedGallery.prototype.retrieveSuffixRanges = function () {
29750    var suffixRanges = [];
29751    for (var rangeIdx in this.settings.sizeRangeSuffixes) {
29752      if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(parseInt(rangeIdx, 10));
29753    }
29754    suffixRanges.sort(function (a, b) { return a > b ? 1 : a < b ? -1 : 0; });
29755    return suffixRanges;
29756  };
29757
29758  /**
29759   * Update the existing settings only changing some of them
29760   *
29761   * @param newSettings the new settings (or a subgroup of them)
29762   */
29763  JustifiedGallery.prototype.updateSettings = function (newSettings) {
29764    // In this case Justified Gallery has been called again changing only some options
29765    this.settings = $.extend({}, this.settings, newSettings);
29766    this.checkSettings();
29767
29768    // As reported in the settings: negative value = same as margins, 0 = disabled
29769    this.border = this.settings.border >= 0 ? this.settings.border : this.settings.margins;
29770
29771    this.maxRowHeight = this.retrieveMaxRowHeight();
29772    this.suffixRanges = this.retrieveSuffixRanges();
29773  };
29774
29775  JustifiedGallery.prototype.defaults = {
29776    sizeRangeSuffixes: {}, /* e.g. Flickr configuration
29777        {
29778          100: '_t',  // used when longest is less than 100px
29779          240: '_m',  // used when longest is between 101px and 240px
29780          320: '_n',  // ...
29781          500: '',
29782          640: '_z',
29783          1024: '_b'  // used as else case because it is the last
29784        }
29785    */
29786    thumbnailPath: undefined, /* If defined, sizeRangeSuffixes is not used, and this function is used to determine the
29787    path relative to a specific thumbnail size. The function should accept respectively three arguments:
29788    current path, width and height */
29789    rowHeight: 120, // required? required to be > 0?
29790    maxRowHeight: false, // false or negative value to deactivate. Positive number to express the value in pixels,
29791    // A string '[0-9]+%' to express in percentage (e.g. 300% means that the row height
29792    // can't exceed 3 * rowHeight)
29793    maxRowsCount: 0, // maximum number of rows to be displayed (0 = disabled)
29794    margins: 1,
29795    border: -1, // negative value = same as margins, 0 = disabled, any other value to set the border
29796
29797    lastRow: 'nojustify', // … which is the same as 'left', or can be 'justify', 'center', 'right' or 'hide'
29798
29799    justifyThreshold: 0.90, /* if row width / available space > 0.90 it will be always justified
29800                             * (i.e. lastRow setting is not considered) */
29801    waitThumbnailsLoad: true,
29802    captions: true,
29803    cssAnimation: true,
29804    imagesAnimationDuration: 500, // ignored with css animations
29805    captionSettings: { // ignored with css animations
29806      animationDuration: 500,
29807      visibleOpacity: 0.7,
29808      nonVisibleOpacity: 0.0
29809    },
29810    rel: null, // rewrite the rel of each analyzed links
29811    target: null, // rewrite the target of all links
29812    extension: /\.[^.\\/]+$/, // regexp to capture the extension of an image
29813    refreshTime: 200, // time interval (in ms) to check if the page changes its width
29814    refreshSensitivity: 0, // change in width allowed (in px) without re-building the gallery
29815    randomize: false,
29816    rtl: false, // right-to-left mode
29817    sort: false, /*
29818      - false: to do not sort
29819      - function: to sort them using the function as comparator (see Array.prototype.sort())
29820    */
29821    filter: false, /*
29822      - false, null or undefined: for a disabled filter
29823      - a string: an entry is kept if entry.is(filter string) returns true
29824                  see jQuery's .is() function for further information
29825      - a function: invoked with arguments (entry, index, array). Return true to keep the entry, false otherwise.
29826                    It follows the specifications of the Array.prototype.filter() function of JavaScript.
29827    */
29828    selector: 'a', // The selector that is used to know what are the entries of the gallery
29829    imgSelector: '> img, > a > img, > svg, > a > svg', // The selector that is used to know what are the images of each entry
29830    triggerEvent: function (event) { // This is called to trigger events, the default behavior is to call $.trigger
29831      this.$gallery.trigger(event);  // Consider that 'this' is this set to the JustifiedGallery object, so it can
29832    }                                // access to fields such as $gallery, useful to trigger events with jQuery.
29833  };
29834
29835
29836  /**
29837   * Justified Gallery plugin for jQuery
29838   *
29839   * Events
29840   *  - jg.complete : called when all the gallery has been created
29841   *  - jg.resize : called when the gallery has been resized
29842   *  - jg.rowflush : when a new row appears
29843   *
29844   * @param arg the action (or the settings) passed when the plugin is called
29845   * @returns {*} the object itself
29846   */
29847  $.fn.justifiedGallery = function (arg) {
29848    return this.each(function (index, gallery) {
29849
29850      var $gallery = $(gallery);
29851      $gallery.addClass('justified-gallery');
29852
29853      var controller = $gallery.data('jg.controller');
29854      if (typeof controller === 'undefined') {
29855        // Create controller and assign it to the object data
29856        if (typeof arg !== 'undefined' && arg !== null && $.type(arg) !== 'object') {
29857          if (arg === 'destroy') return; // Just a call to an unexisting object
29858          throw 'The argument must be an object';
29859        }
29860        controller = new JustifiedGallery($gallery, $.extend({}, JustifiedGallery.prototype.defaults, arg));
29861        $gallery.data('jg.controller', controller);
29862      } else if (arg === 'norewind') {
29863        // In this case we don't rewind: we analyze only the latest images (e.g. to complete the last unfinished row
29864        // ... left to be more readable
29865      } else if (arg === 'destroy') {
29866        controller.destroy();
29867        return;
29868      } else {
29869        // In this case Justified Gallery has been called again changing only some options
29870        controller.updateSettings(arg);
29871        controller.rewind();
29872      }
29873
29874      // Update the entries list
29875      if (!controller.updateEntries(arg === 'norewind')) return;
29876
29877      // Init justified gallery
29878      controller.init();
29879
29880    });
29881  };
29882
29883}));
29884
29885/*!
29886* Customized version of iScroll.js 0.0.1
29887* It fixes bugs affecting its integration with fullpage.js
29888*/
29889/*! iScroll v5.2.0 ~ (c) 2008-2016 Matteo Spinelli ~ http://cubiq.org/license */
29890(function (window, document, Math) {
29891var rAF = window.requestAnimationFrame  ||
29892    window.webkitRequestAnimationFrame  ||
29893    window.mozRequestAnimationFrame     ||
29894    window.oRequestAnimationFrame       ||
29895    window.msRequestAnimationFrame      ||
29896    function (callback) { window.setTimeout(callback, 1000 / 60); };
29897
29898var utils = (function () {
29899    var me = {};
29900
29901    var _elementStyle = document.createElement('div').style;
29902    var _vendor = (function () {
29903        var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'],
29904            transform,
29905            i = 0,
29906            l = vendors.length;
29907
29908        for ( ; i < l; i++ ) {
29909            transform = vendors[i] + 'ransform';
29910            if ( transform in _elementStyle ) return vendors[i].substr(0, vendors[i].length-1);
29911        }
29912
29913        return false;
29914    })();
29915
29916    function _prefixStyle (style) {
29917        if ( _vendor === false ) return false;
29918        if ( _vendor === '' ) return style;
29919        return _vendor + style.charAt(0).toUpperCase() + style.substr(1);
29920    }
29921
29922    me.getTime = Date.now || function getTime () { return new Date().getTime(); };
29923
29924    me.extend = function (target, obj) {
29925        for ( var i in obj ) {
29926            target[i] = obj[i];
29927        }
29928    };
29929
29930    me.addEvent = function (el, type, fn, capture) {
29931        el.addEventListener(type, fn, !!capture);
29932    };
29933
29934    me.removeEvent = function (el, type, fn, capture) {
29935        el.removeEventListener(type, fn, !!capture);
29936    };
29937
29938    me.prefixPointerEvent = function (pointerEvent) {
29939        return window.MSPointerEvent ?
29940            'MSPointer' + pointerEvent.charAt(7).toUpperCase() + pointerEvent.substr(8):
29941            pointerEvent;
29942    };
29943
29944    me.momentum = function (current, start, time, lowerMargin, wrapperSize, deceleration) {
29945        var distance = current - start,
29946            speed = Math.abs(distance) / time,
29947            destination,
29948            duration;
29949
29950        deceleration = deceleration === undefined ? 0.0006 : deceleration;
29951
29952        destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 );
29953        duration = speed / deceleration;
29954
29955        if ( destination < lowerMargin ) {
29956            destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin;
29957            distance = Math.abs(destination - current);
29958            duration = distance / speed;
29959        } else if ( destination > 0 ) {
29960            destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0;
29961            distance = Math.abs(current) + destination;
29962            duration = distance / speed;
29963        }
29964
29965        return {
29966            destination: Math.round(destination),
29967            duration: duration
29968        };
29969    };
29970
29971    var _transform = _prefixStyle('transform');
29972
29973    me.extend(me, {
29974        hasTransform: _transform !== false,
29975        hasPerspective: _prefixStyle('perspective') in _elementStyle,
29976        hasTouch: 'ontouchstart' in window,
29977        hasPointer: !!(window.PointerEvent || window.MSPointerEvent), // IE10 is prefixed
29978        hasTransition: _prefixStyle('transition') in _elementStyle
29979    });
29980
29981    /*
29982    This should find all Android browsers lower than build 535.19 (both stock browser and webview)
29983    - galaxy S2 is ok
29984    - 2.3.6 : `AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1`
29985    - 4.0.4 : `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
29986   - galaxy S3 is badAndroid (stock brower, webview)
29987     `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
29988   - galaxy S4 is badAndroid (stock brower, webview)
29989     `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
29990   - galaxy S5 is OK
29991     `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`
29992   - galaxy S6 is OK
29993     `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`
29994  */
29995    me.isBadAndroid = (function() {
29996        var appVersion = window.navigator.appVersion;
29997        // Android browser is not a chrome browser.
29998        if (/Android/.test(appVersion) && !(/Chrome\/\d/.test(appVersion))) {
29999            var safariVersion = appVersion.match(/Safari\/(\d+.\d)/);
30000            if(safariVersion && typeof safariVersion === "object" && safariVersion.length >= 2) {
30001                return parseFloat(safariVersion[1]) < 535.19;
30002            } else {
30003                return true;
30004            }
30005        } else {
30006            return false;
30007        }
30008    })();
30009
30010    me.extend(me.style = {}, {
30011        transform: _transform,
30012        transitionTimingFunction: _prefixStyle('transitionTimingFunction'),
30013        transitionDuration: _prefixStyle('transitionDuration'),
30014        transitionDelay: _prefixStyle('transitionDelay'),
30015        transformOrigin: _prefixStyle('transformOrigin')
30016    });
30017
30018    me.hasClass = function (e, c) {
30019        var re = new RegExp("(^|\\s)" + c + "(\\s|$)");
30020        return re.test(e.className);
30021    };
30022
30023    me.addClass = function (e, c) {
30024        if ( me.hasClass(e, c) ) {
30025            return;
30026        }
30027
30028        var newclass = e.className.split(' ');
30029        newclass.push(c);
30030        e.className = newclass.join(' ');
30031    };
30032
30033    me.removeClass = function (e, c) {
30034        if ( !me.hasClass(e, c) ) {
30035            return;
30036        }
30037
30038        var re = new RegExp("(^|\\s)" + c + "(\\s|$)", 'g');
30039        e.className = e.className.replace(re, ' ');
30040    };
30041
30042    me.offset = function (el) {
30043        var left = -el.offsetLeft,
30044            top = -el.offsetTop;
30045
30046        // jshint -W084
30047        while (el = el.offsetParent) {
30048            left -= el.offsetLeft;
30049            top -= el.offsetTop;
30050        }
30051        // jshint +W084
30052
30053        return {
30054            left: left,
30055            top: top
30056        };
30057    };
30058
30059    me.preventDefaultException = function (el, exceptions) {
30060        for ( var i in exceptions ) {
30061            if ( exceptions[i].test(el[i]) ) {
30062                return true;
30063            }
30064        }
30065
30066        return false;
30067    };
30068
30069    me.extend(me.eventType = {}, {
30070        touchstart: 1,
30071        touchmove: 1,
30072        touchend: 1,
30073
30074        mousedown: 2,
30075        mousemove: 2,
30076        mouseup: 2,
30077
30078        pointerdown: 3,
30079        pointermove: 3,
30080        pointerup: 3,
30081
30082        MSPointerDown: 3,
30083        MSPointerMove: 3,
30084        MSPointerUp: 3
30085    });
30086
30087    me.extend(me.ease = {}, {
30088        quadratic: {
30089            style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
30090            fn: function (k) {
30091                return k * ( 2 - k );
30092            }
30093        },
30094        circular: {
30095            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)
30096            fn: function (k) {
30097                return Math.sqrt( 1 - ( --k * k ) );
30098            }
30099        },
30100        back: {
30101            style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)',
30102            fn: function (k) {
30103                var b = 4;
30104                return ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1;
30105            }
30106        },
30107        bounce: {
30108            style: '',
30109            fn: function (k) {
30110                if ( ( k /= 1 ) < ( 1 / 2.75 ) ) {
30111                    return 7.5625 * k * k;
30112                } else if ( k < ( 2 / 2.75 ) ) {
30113                    return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75;
30114                } else if ( k < ( 2.5 / 2.75 ) ) {
30115                    return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375;
30116                } else {
30117                    return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375;
30118                }
30119            }
30120        },
30121        elastic: {
30122            style: '',
30123            fn: function (k) {
30124                var f = 0.22,
30125                    e = 0.4;
30126
30127                if ( k === 0 ) { return 0; }
30128                if ( k == 1 ) { return 1; }
30129
30130                return ( e * Math.pow( 2, - 10 * k ) * Math.sin( ( k - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 );
30131            }
30132        }
30133    });
30134
30135    me.tap = function (e, eventName) {
30136        var ev = document.createEvent('Event');
30137        ev.initEvent(eventName, true, true);
30138        ev.pageX = e.pageX;
30139        ev.pageY = e.pageY;
30140        e.target.dispatchEvent(ev);
30141    };
30142
30143    me.click = function (e) {
30144        var target = e.target,
30145            ev;
30146
30147        if ( !(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName) ) {
30148            // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent
30149            // initMouseEvent is deprecated.
30150            ev = document.createEvent(window.MouseEvent ? 'MouseEvents' : 'Event');
30151            ev.initEvent('click', true, true);
30152            ev.view = e.view || window;
30153            ev.detail = 1;
30154            ev.screenX = target.screenX || 0;
30155            ev.screenY = target.screenY || 0;
30156            ev.clientX = target.clientX || 0;
30157            ev.clientY = target.clientY || 0;
30158            ev.ctrlKey = !!e.ctrlKey;
30159            ev.altKey = !!e.altKey;
30160            ev.shiftKey = !!e.shiftKey;
30161            ev.metaKey = !!e.metaKey;
30162            ev.button = 0;
30163            ev.relatedTarget = null;
30164            ev._constructed = true;
30165            target.dispatchEvent(ev);
30166        }
30167    };
30168
30169    return me;
30170})();
30171function IScroll (el, options) {
30172    this.wrapper = typeof el == 'string' ? document.querySelector(el) : el;
30173    this.scroller = this.wrapper.children[0];
30174    this.scrollerStyle = this.scroller.style;       // cache style for better performance
30175
30176    this.options = {
30177
30178        resizeScrollbars: true,
30179
30180        mouseWheelSpeed: 20,
30181
30182        snapThreshold: 0.334,
30183
30184// INSERT POINT: OPTIONS
30185        disablePointer : !utils.hasPointer,
30186        disableTouch : utils.hasPointer || !utils.hasTouch,
30187        disableMouse : utils.hasPointer || utils.hasTouch,
30188        startX: 0,
30189        startY: 0,
30190        scrollY: true,
30191        directionLockThreshold: 5,
30192        momentum: true,
30193
30194        bounce: true,
30195        bounceTime: 600,
30196        bounceEasing: '',
30197
30198        preventDefault: true,
30199        preventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT|LABEL)$/ },
30200
30201        HWCompositing: true,
30202        useTransition: true,
30203        useTransform: true,
30204        bindToWrapper: typeof window.onmousedown === "undefined"
30205    };
30206
30207    for ( var i in options ) {
30208        this.options[i] = options[i];
30209    }
30210
30211    // Normalize options
30212    this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : '';
30213
30214    this.options.useTransition = utils.hasTransition && this.options.useTransition;
30215    this.options.useTransform = utils.hasTransform && this.options.useTransform;
30216
30217    this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough;
30218    this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault;
30219
30220    // If you want eventPassthrough I have to lock one of the axes
30221    this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY;
30222    this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX;
30223
30224    // With eventPassthrough we also need lockDirection mechanism
30225    this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough;
30226    this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold;
30227
30228    this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing;
30229
30230    this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling;
30231
30232    if ( this.options.tap === true ) {
30233        this.options.tap = 'tap';
30234    }
30235
30236    // https://github.com/cubiq/iscroll/issues/1029
30237    if (!this.options.useTransition && !this.options.useTransform) {
30238        if(!(/relative|absolute/i).test(this.scrollerStyle.position)) {
30239            this.scrollerStyle.position = "relative";
30240        }
30241    }
30242
30243    if ( this.options.shrinkScrollbars == 'scale' ) {
30244        this.options.useTransition = false;
30245    }
30246
30247    this.options.invertWheelDirection = this.options.invertWheelDirection ? -1 : 1;
30248
30249// INSERT POINT: NORMALIZATION
30250
30251    // Some defaults
30252    this.x = 0;
30253    this.y = 0;
30254    this.directionX = 0;
30255    this.directionY = 0;
30256    this._events = {};
30257
30258// INSERT POINT: DEFAULTS
30259
30260    this._init();
30261    this.refresh();
30262
30263    this.scrollTo(this.options.startX, this.options.startY);
30264    this.enable();
30265}
30266
30267IScroll.prototype = {
30268    version: '5.2.0',
30269
30270    _init: function () {
30271        this._initEvents();
30272
30273        if ( this.options.scrollbars || this.options.indicators ) {
30274            this._initIndicators();
30275        }
30276
30277        if ( this.options.mouseWheel ) {
30278            this._initWheel();
30279        }
30280
30281        if ( this.options.snap ) {
30282            this._initSnap();
30283        }
30284
30285        if ( this.options.keyBindings ) {
30286            this._initKeys();
30287        }
30288
30289// INSERT POINT: _init
30290
30291    },
30292
30293    destroy: function () {
30294        this._initEvents(true);
30295        clearTimeout(this.resizeTimeout);
30296        this.resizeTimeout = null;
30297        this._execEvent('destroy');
30298    },
30299
30300    _transitionEnd: function (e) {
30301        if ( e.target != this.scroller || !this.isInTransition ) {
30302            return;
30303        }
30304
30305        this._transitionTime();
30306        if ( !this.resetPosition(this.options.bounceTime) ) {
30307            this.isInTransition = false;
30308            this._execEvent('scrollEnd');
30309        }
30310    },
30311
30312    _start: function (e) {
30313        // React to left mouse button only
30314        if ( utils.eventType[e.type] != 1 ) {
30315          // for button property
30316          // http://unixpapa.com/js/mouse.html
30317          var button;
30318        if (!e.which) {
30319          /* IE case */
30320          button = (e.button < 2) ? 0 :
30321                   ((e.button == 4) ? 1 : 2);
30322        } else {
30323          /* All others */
30324          button = e.button;
30325        }
30326            if ( button !== 0 ) {
30327                return;
30328            }
30329        }
30330
30331        if ( !this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated) ) {
30332            return;
30333        }
30334
30335        if ( this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {
30336            e.preventDefault();
30337        }
30338
30339        var point = e.touches ? e.touches[0] : e,
30340            pos;
30341
30342        this.initiated  = utils.eventType[e.type];
30343        this.moved      = false;
30344        this.distX      = 0;
30345        this.distY      = 0;
30346        this.directionX = 0;
30347        this.directionY = 0;
30348        this.directionLocked = 0;
30349
30350        this.startTime = utils.getTime();
30351
30352        if ( this.options.useTransition && this.isInTransition ) {
30353            this._transitionTime();
30354            this.isInTransition = false;
30355            pos = this.getComputedPosition();
30356            this._translate(Math.round(pos.x), Math.round(pos.y));
30357            this._execEvent('scrollEnd');
30358        } else if ( !this.options.useTransition && this.isAnimating ) {
30359            this.isAnimating = false;
30360            this._execEvent('scrollEnd');
30361        }
30362
30363        this.startX    = this.x;
30364        this.startY    = this.y;
30365        this.absStartX = this.x;
30366        this.absStartY = this.y;
30367        this.pointX    = point.pageX;
30368        this.pointY    = point.pageY;
30369
30370        this._execEvent('beforeScrollStart');
30371    },
30372
30373    _move: function (e) {
30374        if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
30375            return;
30376        }
30377
30378        if ( this.options.preventDefault ) {    // increases performance on Android? TODO: check!
30379            e.preventDefault();
30380        }
30381
30382        var point       = e.touches ? e.touches[0] : e,
30383            deltaX      = point.pageX - this.pointX,
30384            deltaY      = point.pageY - this.pointY,
30385            timestamp   = utils.getTime(),
30386            newX, newY,
30387            absDistX, absDistY;
30388
30389        this.pointX     = point.pageX;
30390        this.pointY     = point.pageY;
30391
30392        this.distX      += deltaX;
30393        this.distY      += deltaY;
30394        absDistX        = Math.abs(this.distX);
30395        absDistY        = Math.abs(this.distY);
30396
30397        // We need to move at least 10 pixels for the scrolling to initiate
30398        if ( timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10) ) {
30399            return;
30400        }
30401
30402        // If you are scrolling in one direction lock the other
30403        if ( !this.directionLocked && !this.options.freeScroll ) {
30404            if ( absDistX > absDistY + this.options.directionLockThreshold ) {
30405                this.directionLocked = 'h';     // lock horizontally
30406            } else if ( absDistY >= absDistX + this.options.directionLockThreshold ) {
30407                this.directionLocked = 'v';     // lock vertically
30408            } else {
30409                this.directionLocked = 'n';     // no lock
30410            }
30411        }
30412
30413        if ( this.directionLocked == 'h' ) {
30414            if ( this.options.eventPassthrough == 'vertical' ) {
30415                e.preventDefault();
30416            } else if ( this.options.eventPassthrough == 'horizontal' ) {
30417                this.initiated = false;
30418                return;
30419            }
30420
30421            deltaY = 0;
30422        } else if ( this.directionLocked == 'v' ) {
30423            if ( this.options.eventPassthrough == 'horizontal' ) {
30424                e.preventDefault();
30425            } else if ( this.options.eventPassthrough == 'vertical' ) {
30426                this.initiated = false;
30427                return;
30428            }
30429
30430            deltaX = 0;
30431        }
30432
30433        deltaX = this.hasHorizontalScroll ? deltaX : 0;
30434        deltaY = this.hasVerticalScroll ? deltaY : 0;
30435
30436        newX = this.x + deltaX;
30437        newY = this.y + deltaY;
30438
30439        // Slow down if outside of the boundaries
30440        if ( newX > 0 || newX < this.maxScrollX ) {
30441            newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX;
30442        }
30443        if ( newY > 0 || newY < this.maxScrollY ) {
30444            newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY;
30445        }
30446
30447        this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0;
30448        this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0;
30449
30450        if ( !this.moved ) {
30451            this._execEvent('scrollStart');
30452        }
30453
30454        this.moved = true;
30455
30456        this._translate(newX, newY);
30457
30458/* REPLACE START: _move */
30459
30460        if ( timestamp - this.startTime > 300 ) {
30461            this.startTime = timestamp;
30462            this.startX = this.x;
30463            this.startY = this.y;
30464        }
30465
30466/* REPLACE END: _move */
30467
30468    },
30469
30470    _end: function (e) {
30471        if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
30472            return;
30473        }
30474
30475        if ( this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {
30476            e.preventDefault();
30477        }
30478
30479        var point = e.changedTouches ? e.changedTouches[0] : e,
30480            momentumX,
30481            momentumY,
30482            duration = utils.getTime() - this.startTime,
30483            newX = Math.round(this.x),
30484            newY = Math.round(this.y),
30485            distanceX = Math.abs(newX - this.startX),
30486            distanceY = Math.abs(newY - this.startY),
30487            time = 0,
30488            easing = '';
30489
30490        this.isInTransition = 0;
30491        this.initiated = 0;
30492        this.endTime = utils.getTime();
30493
30494        // reset if we are outside of the boundaries
30495        if ( this.resetPosition(this.options.bounceTime) ) {
30496            return;
30497        }
30498
30499        this.scrollTo(newX, newY);  // ensures that the last position is rounded
30500
30501        // we scrolled less than 10 pixels
30502        if ( !this.moved ) {
30503            if ( this.options.tap ) {
30504                utils.tap(e, this.options.tap);
30505            }
30506
30507            if ( this.options.click ) {
30508                utils.click(e);
30509            }
30510
30511            this._execEvent('scrollCancel');
30512            return;
30513        }
30514
30515        if ( this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100 ) {
30516            this._execEvent('flick');
30517            return;
30518        }
30519
30520        // start momentum animation if needed
30521        if ( this.options.momentum && duration < 300 ) {
30522            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 };
30523            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 };
30524            newX = momentumX.destination;
30525            newY = momentumY.destination;
30526            time = Math.max(momentumX.duration, momentumY.duration);
30527            this.isInTransition = 1;
30528        }
30529
30530
30531        if ( this.options.snap ) {
30532            var snap = this._nearestSnap(newX, newY);
30533            this.currentPage = snap;
30534            time = this.options.snapSpeed || Math.max(
30535                    Math.max(
30536                        Math.min(Math.abs(newX - snap.x), 1000),
30537                        Math.min(Math.abs(newY - snap.y), 1000)
30538                    ), 300);
30539            newX = snap.x;
30540            newY = snap.y;
30541
30542            this.directionX = 0;
30543            this.directionY = 0;
30544            easing = this.options.bounceEasing;
30545        }
30546
30547// INSERT POINT: _end
30548
30549        if ( newX != this.x || newY != this.y ) {
30550            // change easing function when scroller goes out of the boundaries
30551            if ( newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY ) {
30552                easing = utils.ease.quadratic;
30553            }
30554
30555            this.scrollTo(newX, newY, time, easing);
30556            return;
30557        }
30558
30559        this._execEvent('scrollEnd');
30560    },
30561
30562    _resize: function () {
30563        var that = this;
30564
30565        clearTimeout(this.resizeTimeout);
30566
30567        this.resizeTimeout = setTimeout(function () {
30568            that.refresh();
30569        }, this.options.resizePolling);
30570    },
30571
30572    resetPosition: function (time) {
30573        var x = this.x,
30574            y = this.y;
30575
30576        time = time || 0;
30577
30578        if ( !this.hasHorizontalScroll || this.x > 0 ) {
30579            x = 0;
30580        } else if ( this.x < this.maxScrollX ) {
30581            x = this.maxScrollX;
30582        }
30583
30584        if ( !this.hasVerticalScroll || this.y > 0 ) {
30585            y = 0;
30586        } else if ( this.y < this.maxScrollY ) {
30587            y = this.maxScrollY;
30588        }
30589
30590        if ( x == this.x && y == this.y ) {
30591            return false;
30592        }
30593
30594        this.scrollTo(x, y, time, this.options.bounceEasing);
30595
30596        return true;
30597    },
30598
30599    disable: function () {
30600        this.enabled = false;
30601    },
30602
30603    enable: function () {
30604        this.enabled = true;
30605    },
30606
30607    refresh: function () {
30608        var rf = this.wrapper.offsetHeight;     // Force reflow
30609
30610        this.wrapperWidth   = this.wrapper.clientWidth;
30611        this.wrapperHeight  = this.wrapper.clientHeight;
30612
30613/* REPLACE START: refresh */
30614
30615        this.scrollerWidth  = this.scroller.offsetWidth;
30616        this.scrollerHeight = this.scroller.offsetHeight;
30617
30618        this.maxScrollX     = this.wrapperWidth - this.scrollerWidth;
30619        this.maxScrollY     = this.wrapperHeight - this.scrollerHeight;
30620
30621/* REPLACE END: refresh */
30622
30623        this.hasHorizontalScroll    = this.options.scrollX && this.maxScrollX < 0;
30624        this.hasVerticalScroll      = this.options.scrollY && this.maxScrollY < 0;
30625
30626        if ( !this.hasHorizontalScroll ) {
30627            this.maxScrollX = 0;
30628            this.scrollerWidth = this.wrapperWidth;
30629        }
30630
30631        if ( !this.hasVerticalScroll ) {
30632            this.maxScrollY = 0;
30633            this.scrollerHeight = this.wrapperHeight;
30634        }
30635
30636        this.endTime = 0;
30637        this.directionX = 0;
30638        this.directionY = 0;
30639
30640        this.wrapperOffset = utils.offset(this.wrapper);
30641
30642        this._execEvent('refresh');
30643
30644        this.resetPosition();
30645
30646// INSERT POINT: _refresh
30647
30648    },
30649
30650
30651    on: function (type, fn) {
30652        if ( !this._events[type] ) {
30653            this._events[type] = [];
30654        }
30655
30656        this._events[type].push(fn);
30657    },
30658
30659    off: function (type, fn) {
30660        if ( !this._events[type] ) {
30661            return;
30662        }
30663
30664        var index = this._events[type].indexOf(fn);
30665
30666        if ( index > -1 ) {
30667            this._events[type].splice(index, 1);
30668        }
30669    },
30670
30671    _execEvent: function (type) {
30672        if ( !this._events[type] ) {
30673            return;
30674        }
30675
30676        var i = 0,
30677            l = this._events[type].length;
30678
30679        if ( !l ) {
30680            return;
30681        }
30682
30683        for ( ; i < l; i++ ) {
30684            this._events[type][i].apply(this, [].slice.call(arguments, 1));
30685        }
30686    },
30687
30688    scrollBy: function (x, y, time, easing) {
30689        x = this.x + x;
30690        y = this.y + y;
30691        time = time || 0;
30692
30693        this.scrollTo(x, y, time, easing);
30694    },
30695
30696    scrollTo: function (x, y, time, easing) {
30697        easing = easing || utils.ease.circular;
30698
30699        this.isInTransition = this.options.useTransition && time > 0;
30700        var transitionType = this.options.useTransition && easing.style;
30701        if ( !time || transitionType ) {
30702                if(transitionType) {
30703                    this._transitionTimingFunction(easing.style);
30704                    this._transitionTime(time);
30705                }
30706            this._translate(x, y);
30707        } else {
30708            this._animate(x, y, time, easing.fn);
30709        }
30710    },
30711
30712    scrollToElement: function (el, time, offsetX, offsetY, easing) {
30713        el = el.nodeType ? el : this.scroller.querySelector(el);
30714
30715        if ( !el ) {
30716            return;
30717        }
30718
30719        var pos = utils.offset(el);
30720
30721        pos.left -= this.wrapperOffset.left;
30722        pos.top  -= this.wrapperOffset.top;
30723
30724        // if offsetX/Y are true we center the element to the screen
30725        if ( offsetX === true ) {
30726            offsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2);
30727        }
30728        if ( offsetY === true ) {
30729            offsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2);
30730        }
30731
30732        pos.left -= offsetX || 0;
30733        pos.top  -= offsetY || 0;
30734
30735        pos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left;
30736        pos.top  = pos.top  > 0 ? 0 : pos.top  < this.maxScrollY ? this.maxScrollY : pos.top;
30737
30738        time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x-pos.left), Math.abs(this.y-pos.top)) : time;
30739
30740        this.scrollTo(pos.left, pos.top, time, easing);
30741    },
30742
30743    _transitionTime: function (time) {
30744        if (!this.options.useTransition) {
30745            return;
30746        }
30747        time = time || 0;
30748        var durationProp = utils.style.transitionDuration;
30749        if(!durationProp) {
30750            return;
30751        }
30752
30753        this.scrollerStyle[durationProp] = time + 'ms';
30754
30755        if ( !time && utils.isBadAndroid ) {
30756            this.scrollerStyle[durationProp] = '0.0001ms';
30757            // remove 0.0001ms
30758            var self = this;
30759            rAF(function() {
30760                if(self.scrollerStyle[durationProp] === '0.0001ms') {
30761                    self.scrollerStyle[durationProp] = '0s';
30762                }
30763            });
30764        }
30765
30766
30767        if ( this.indicators ) {
30768            for ( var i = this.indicators.length; i--; ) {
30769                this.indicators[i].transitionTime(time);
30770            }
30771        }
30772
30773
30774// INSERT POINT: _transitionTime
30775
30776    },
30777
30778    _transitionTimingFunction: function (easing) {
30779        this.scrollerStyle[utils.style.transitionTimingFunction] = easing;
30780
30781
30782        if ( this.indicators ) {
30783            for ( var i = this.indicators.length; i--; ) {
30784                this.indicators[i].transitionTimingFunction(easing);
30785            }
30786        }
30787
30788
30789// INSERT POINT: _transitionTimingFunction
30790
30791    },
30792
30793    _translate: function (x, y) {
30794        //Uncode addition
30795        if ( (" " + this.wrapper.className + " ").replace(/[\n\t]/g, " ").indexOf(" no-scrolloverflow ") > -1 )
30796            return false;
30797
30798        if ( this.options.useTransform ) {
30799
30800/* REPLACE START: _translate */
30801
30802            this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ;
30803
30804/* REPLACE END: _translate */
30805
30806        } else {
30807            x = Math.round(x);
30808            y = Math.round(y);
30809            this.scrollerStyle.left = x + 'px';
30810            this.scrollerStyle.top = y + 'px';
30811        }
30812
30813        this.x = x;
30814        this.y = y;
30815
30816
30817        if ( this.indicators ) {
30818            for ( var i = this.indicators.length; i--; ) {
30819                this.indicators[i].updatePosition();
30820            }
30821        }
30822
30823        //Uncode addition
30824        var uncodevent = new CustomEvent('fp-slide-scroll');
30825        window.dispatchEvent(uncodevent);
30826
30827// INSERT POINT: _translate
30828
30829    },
30830
30831    _initEvents: function (remove) {
30832        var eventType = remove ? utils.removeEvent : utils.addEvent,
30833            target = this.options.bindToWrapper ? this.wrapper : window;
30834
30835        eventType(window, 'orientationchange', this);
30836        eventType(window, 'resize', this);
30837
30838        if ( this.options.click ) {
30839            eventType(this.wrapper, 'click', this, true);
30840        }
30841
30842        if ( !this.options.disableMouse ) {
30843            eventType(this.wrapper, 'mousedown', this);
30844            eventType(target, 'mousemove', this);
30845            eventType(target, 'mousecancel', this);
30846            eventType(target, 'mouseup', this);
30847        }
30848
30849        if ( utils.hasPointer && !this.options.disablePointer ) {
30850            eventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this);
30851            eventType(target, utils.prefixPointerEvent('pointermove'), this);
30852            eventType(target, utils.prefixPointerEvent('pointercancel'), this);
30853            eventType(target, utils.prefixPointerEvent('pointerup'), this);
30854        }
30855
30856        if ( utils.hasTouch && !this.options.disableTouch ) {
30857            eventType(this.wrapper, 'touchstart', this);
30858            eventType(target, 'touchmove', this);
30859            eventType(target, 'touchcancel', this);
30860            eventType(target, 'touchend', this);
30861        }
30862
30863        eventType(this.scroller, 'transitionend', this);
30864        eventType(this.scroller, 'webkitTransitionEnd', this);
30865        eventType(this.scroller, 'oTransitionEnd', this);
30866        eventType(this.scroller, 'MSTransitionEnd', this);
30867    },
30868
30869    getComputedPosition: function () {
30870        var matrix = window.getComputedStyle(this.scroller, null),
30871            x, y;
30872
30873        if ( this.options.useTransform ) {
30874            matrix = matrix[utils.style.transform].split(')')[0].split(', ');
30875            x = +(matrix[12] || matrix[4]);
30876            y = +(matrix[13] || matrix[5]);
30877        } else {
30878            x = +matrix.left.replace(/[^-\d.]/g, '');
30879            y = +matrix.top.replace(/[^-\d.]/g, '');
30880        }
30881
30882        return { x: x, y: y };
30883    },
30884    _initIndicators: function () {
30885        var interactive = this.options.interactiveScrollbars,
30886            customStyle = typeof this.options.scrollbars != 'string',
30887            indicators = [],
30888            indicator;
30889
30890        var that = this;
30891
30892        this.indicators = [];
30893
30894        if ( this.options.scrollbars ) {
30895            // Vertical scrollbar
30896            if ( this.options.scrollY ) {
30897                indicator = {
30898                    el: createDefaultScrollbar('v', interactive, this.options.scrollbars),
30899                    interactive: interactive,
30900                    defaultScrollbars: true,
30901                    customStyle: customStyle,
30902                    resize: this.options.resizeScrollbars,
30903                    shrink: this.options.shrinkScrollbars,
30904                    fade: this.options.fadeScrollbars,
30905                    listenX: false
30906                };
30907
30908                this.wrapper.appendChild(indicator.el);
30909                indicators.push(indicator);
30910            }
30911
30912            // Horizontal scrollbar
30913            if ( this.options.scrollX ) {
30914                indicator = {
30915                    el: createDefaultScrollbar('h', interactive, this.options.scrollbars),
30916                    interactive: interactive,
30917                    defaultScrollbars: true,
30918                    customStyle: customStyle,
30919                    resize: this.options.resizeScrollbars,
30920                    shrink: this.options.shrinkScrollbars,
30921                    fade: this.options.fadeScrollbars,
30922                    listenY: false
30923                };
30924
30925                this.wrapper.appendChild(indicator.el);
30926                indicators.push(indicator);
30927            }
30928        }
30929
30930        if ( this.options.indicators ) {
30931            // TODO: check concat compatibility
30932            indicators = indicators.concat(this.options.indicators);
30933        }
30934
30935        for ( var i = indicators.length; i--; ) {
30936            this.indicators.push( new Indicator(this, indicators[i]) );
30937        }
30938
30939        // TODO: check if we can use array.map (wide compatibility and performance issues)
30940        function _indicatorsMap (fn) {
30941            if (that.indicators) {
30942                for ( var i = that.indicators.length; i--; ) {
30943                    fn.call(that.indicators[i]);
30944                }
30945            }
30946        }
30947
30948        if ( this.options.fadeScrollbars ) {
30949            this.on('scrollEnd', function () {
30950                _indicatorsMap(function () {
30951                    this.fade();
30952                });
30953            });
30954
30955            this.on('scrollCancel', function () {
30956                _indicatorsMap(function () {
30957                    this.fade();
30958                });
30959            });
30960
30961            this.on('scrollStart', function () {
30962                _indicatorsMap(function () {
30963                    this.fade(1);
30964                });
30965            });
30966
30967            this.on('beforeScrollStart', function () {
30968                _indicatorsMap(function () {
30969                    this.fade(1, true);
30970                });
30971            });
30972        }
30973
30974
30975        this.on('refresh', function () {
30976            _indicatorsMap(function () {
30977                this.refresh();
30978            });
30979        });
30980
30981        this.on('destroy', function () {
30982            _indicatorsMap(function () {
30983                this.destroy();
30984            });
30985
30986            delete this.indicators;
30987        });
30988    },
30989
30990    _initWheel: function () {
30991        utils.addEvent(this.wrapper, 'wheel', this);
30992        utils.addEvent(this.wrapper, 'mousewheel', this);
30993        utils.addEvent(this.wrapper, 'DOMMouseScroll', this);
30994
30995        this.on('destroy', function () {
30996            clearTimeout(this.wheelTimeout);
30997            this.wheelTimeout = null;
30998            utils.removeEvent(this.wrapper, 'wheel', this);
30999            utils.removeEvent(this.wrapper, 'mousewheel', this);
31000            utils.removeEvent(this.wrapper, 'DOMMouseScroll', this);
31001        });
31002    },
31003
31004    _wheel: function (e) {
31005        if ( !this.enabled ) {
31006            return;
31007        }
31008
31009        var wheelDeltaX, wheelDeltaY,
31010            newX, newY,
31011            that = this;
31012
31013        if ( this.wheelTimeout === undefined ) {
31014            that._execEvent('scrollStart');
31015        }
31016
31017        // Execute the scrollEnd event after 400ms the wheel stopped scrolling
31018        clearTimeout(this.wheelTimeout);
31019        this.wheelTimeout = setTimeout(function () {
31020            if(!that.options.snap) {
31021                that._execEvent('scrollEnd');
31022            }
31023            that.wheelTimeout = undefined;
31024        }, 400);
31025
31026        if ( 'deltaX' in e ) {
31027            if (e.deltaMode === 1) {
31028                wheelDeltaX = -e.deltaX * this.options.mouseWheelSpeed;
31029                wheelDeltaY = -e.deltaY * this.options.mouseWheelSpeed;
31030            } else {
31031                wheelDeltaX = -e.deltaX;
31032                wheelDeltaY = -e.deltaY;
31033            }
31034        } else if ( 'wheelDeltaX' in e ) {
31035            wheelDeltaX = e.wheelDeltaX / 120 * this.options.mouseWheelSpeed;
31036            wheelDeltaY = e.wheelDeltaY / 120 * this.options.mouseWheelSpeed;
31037        } else if ( 'wheelDelta' in e ) {
31038            wheelDeltaX = wheelDeltaY = e.wheelDelta / 120 * this.options.mouseWheelSpeed;
31039        } else if ( 'detail' in e ) {
31040            wheelDeltaX = wheelDeltaY = -e.detail / 3 * this.options.mouseWheelSpeed;
31041        } else {
31042            return;
31043        }
31044
31045        wheelDeltaX *= this.options.invertWheelDirection;
31046        wheelDeltaY *= this.options.invertWheelDirection;
31047
31048        if ( !this.hasVerticalScroll ) {
31049            wheelDeltaX = wheelDeltaY;
31050            wheelDeltaY = 0;
31051        }
31052
31053        if ( this.options.snap ) {
31054            newX = this.currentPage.pageX;
31055            newY = this.currentPage.pageY;
31056
31057            if ( wheelDeltaX > 0 ) {
31058                newX--;
31059            } else if ( wheelDeltaX < 0 ) {
31060                newX++;
31061            }
31062
31063            if ( wheelDeltaY > 0 ) {
31064                newY--;
31065            } else if ( wheelDeltaY < 0 ) {
31066                newY++;
31067            }
31068
31069            this.goToPage(newX, newY);
31070
31071            return;
31072        }
31073
31074        newX = this.x + Math.round(this.hasHorizontalScroll ? wheelDeltaX : 0);
31075        newY = this.y + Math.round(this.hasVerticalScroll ? wheelDeltaY : 0);
31076
31077        this.directionX = wheelDeltaX > 0 ? -1 : wheelDeltaX < 0 ? 1 : 0;
31078        this.directionY = wheelDeltaY > 0 ? -1 : wheelDeltaY < 0 ? 1 : 0;
31079
31080        if ( newX > 0 ) {
31081            newX = 0;
31082        } else if ( newX < this.maxScrollX ) {
31083            newX = this.maxScrollX;
31084        }
31085
31086        if ( newY > 0 ) {
31087            newY = 0;
31088        } else if ( newY < this.maxScrollY ) {
31089            newY = this.maxScrollY;
31090        }
31091
31092        this.scrollTo(newX, newY, 0);
31093
31094// INSERT POINT: _wheel
31095    },
31096
31097    _initSnap: function () {
31098        this.currentPage = {};
31099
31100        if ( typeof this.options.snap == 'string' ) {
31101            this.options.snap = this.scroller.querySelectorAll(this.options.snap);
31102        }
31103
31104        this.on('refresh', function () {
31105            var i = 0, l,
31106                m = 0, n,
31107                cx, cy,
31108                x = 0, y,
31109                stepX = this.options.snapStepX || this.wrapperWidth,
31110                stepY = this.options.snapStepY || this.wrapperHeight,
31111                el;
31112
31113            this.pages = [];
31114
31115            if ( !this.wrapperWidth || !this.wrapperHeight || !this.scrollerWidth || !this.scrollerHeight ) {
31116                return;
31117            }
31118
31119            if ( this.options.snap === true ) {
31120                cx = Math.round( stepX / 2 );
31121                cy = Math.round( stepY / 2 );
31122
31123                while ( x > -this.scrollerWidth ) {
31124                    this.pages[i] = [];
31125                    l = 0;
31126                    y = 0;
31127
31128                    while ( y > -this.scrollerHeight ) {
31129                        this.pages[i][l] = {
31130                            x: Math.max(x, this.maxScrollX),
31131                            y: Math.max(y, this.maxScrollY),
31132                            width: stepX,
31133                            height: stepY,
31134                            cx: x - cx,
31135                            cy: y - cy
31136                        };
31137
31138                        y -= stepY;
31139                        l++;
31140                    }
31141
31142                    x -= stepX;
31143                    i++;
31144                }
31145            } else {
31146                el = this.options.snap;
31147                l = el.length;
31148                n = -1;
31149
31150                for ( ; i < l; i++ ) {
31151                    if ( i === 0 || el[i].offsetLeft <= el[i-1].offsetLeft ) {
31152                        m = 0;
31153                        n++;
31154                    }
31155
31156                    if ( !this.pages[m] ) {
31157                        this.pages[m] = [];
31158                    }
31159
31160                    x = Math.max(-el[i].offsetLeft, this.maxScrollX);
31161                    y = Math.max(-el[i].offsetTop, this.maxScrollY);
31162                    cx = x - Math.round(el[i].offsetWidth / 2);
31163                    cy = y - Math.round(el[i].offsetHeight / 2);
31164
31165                    this.pages[m][n] = {
31166                        x: x,
31167                        y: y,
31168                        width: el[i].offsetWidth,
31169                        height: el[i].offsetHeight,
31170                        cx: cx,
31171                        cy: cy
31172                    };
31173
31174                    if ( x > this.maxScrollX ) {
31175                        m++;
31176                    }
31177                }
31178            }
31179
31180            this.goToPage(this.currentPage.pageX || 0, this.currentPage.pageY || 0, 0);
31181
31182            // Update snap threshold if needed
31183            if ( this.options.snapThreshold % 1 === 0 ) {
31184                this.snapThresholdX = this.options.snapThreshold;
31185                this.snapThresholdY = this.options.snapThreshold;
31186            } else {
31187                this.snapThresholdX = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].width * this.options.snapThreshold);
31188                this.snapThresholdY = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].height * this.options.snapThreshold);
31189            }
31190        });
31191
31192        this.on('flick', function () {
31193            var time = this.options.snapSpeed || Math.max(
31194                    Math.max(
31195                        Math.min(Math.abs(this.x - this.startX), 1000),
31196                        Math.min(Math.abs(this.y - this.startY), 1000)
31197                    ), 300);
31198
31199            this.goToPage(
31200                this.currentPage.pageX + this.directionX,
31201                this.currentPage.pageY + this.directionY,
31202                time
31203            );
31204        });
31205    },
31206
31207    _nearestSnap: function (x, y) {
31208        if ( !this.pages.length ) {
31209            return { x: 0, y: 0, pageX: 0, pageY: 0 };
31210        }
31211
31212        var i = 0,
31213            l = this.pages.length,
31214            m = 0;
31215
31216        // Check if we exceeded the snap threshold
31217        if ( Math.abs(x - this.absStartX) < this.snapThresholdX &&
31218            Math.abs(y - this.absStartY) < this.snapThresholdY ) {
31219            return this.currentPage;
31220        }
31221
31222        if ( x > 0 ) {
31223            x = 0;
31224        } else if ( x < this.maxScrollX ) {
31225            x = this.maxScrollX;
31226        }
31227
31228        if ( y > 0 ) {
31229            y = 0;
31230        } else if ( y < this.maxScrollY ) {
31231            y = this.maxScrollY;
31232        }
31233
31234        for ( ; i < l; i++ ) {
31235            if ( x >= this.pages[i][0].cx ) {
31236                x = this.pages[i][0].x;
31237                break;
31238            }
31239        }
31240
31241        l = this.pages[i].length;
31242
31243        for ( ; m < l; m++ ) {
31244            if ( y >= this.pages[0][m].cy ) {
31245                y = this.pages[0][m].y;
31246                break;
31247            }
31248        }
31249
31250        if ( i == this.currentPage.pageX ) {
31251            i += this.directionX;
31252
31253            if ( i < 0 ) {
31254                i = 0;
31255            } else if ( i >= this.pages.length ) {
31256                i = this.pages.length - 1;
31257            }
31258
31259            x = this.pages[i][0].x;
31260        }
31261
31262        if ( m == this.currentPage.pageY ) {
31263            m += this.directionY;
31264
31265            if ( m < 0 ) {
31266                m = 0;
31267            } else if ( m >= this.pages[0].length ) {
31268                m = this.pages[0].length - 1;
31269            }
31270
31271            y = this.pages[0][m].y;
31272        }
31273
31274        return {
31275            x: x,
31276            y: y,
31277            pageX: i,
31278            pageY: m
31279        };
31280    },
31281
31282    goToPage: function (x, y, time, easing) {
31283        easing = easing || this.options.bounceEasing;
31284
31285        if ( x >= this.pages.length ) {
31286            x = this.pages.length - 1;
31287        } else if ( x < 0 ) {
31288            x = 0;
31289        }
31290
31291        if ( y >= this.pages[x].length ) {
31292            y = this.pages[x].length - 1;
31293        } else if ( y < 0 ) {
31294            y = 0;
31295        }
31296
31297        var posX = this.pages[x][y].x,
31298            posY = this.pages[x][y].y;
31299
31300        time = time === undefined ? this.options.snapSpeed || Math.max(
31301            Math.max(
31302                Math.min(Math.abs(posX - this.x), 1000),
31303                Math.min(Math.abs(posY - this.y), 1000)
31304            ), 300) : time;
31305
31306        this.currentPage = {
31307            x: posX,
31308            y: posY,
31309            pageX: x,
31310            pageY: y
31311        };
31312
31313        this.scrollTo(posX, posY, time, easing);
31314    },
31315
31316    next: function (time, easing) {
31317        var x = this.currentPage.pageX,
31318            y = this.currentPage.pageY;
31319
31320        x++;
31321
31322        if ( x >= this.pages.length && this.hasVerticalScroll ) {
31323            x = 0;
31324            y++;
31325        }
31326
31327        this.goToPage(x, y, time, easing);
31328    },
31329
31330    prev: function (time, easing) {
31331        var x = this.currentPage.pageX,
31332            y = this.currentPage.pageY;
31333
31334        x--;
31335
31336        if ( x < 0 && this.hasVerticalScroll ) {
31337            x = 0;
31338            y--;
31339        }
31340
31341        this.goToPage(x, y, time, easing);
31342    },
31343
31344    _initKeys: function (e) {
31345        // default key bindings
31346        var keys = {
31347            pageUp: 33,
31348            pageDown: 34,
31349            end: 35,
31350            home: 36,
31351            left: 37,
31352            up: 38,
31353            right: 39,
31354            down: 40
31355        };
31356        var i;
31357
31358        // if you give me characters I give you keycode
31359        if ( typeof this.options.keyBindings == 'object' ) {
31360            for ( i in this.options.keyBindings ) {
31361                if ( typeof this.options.keyBindings[i] == 'string' ) {
31362                    this.options.keyBindings[i] = this.options.keyBindings[i].toUpperCase().charCo
31362deAt(0);
31363                }
31364            }
31365        } else {
31366            this.options.keyBindings = {};
31367        }
31368
31369        for ( i in keys ) {
31370            this.options.keyBindings[i] = this.options.keyBindings[i] || keys[i];
31371        }
31372
31373        utils.addEvent(window, 'keydown', this);
31374
31375        this.on('destroy', function () {
31376            utils.removeEvent(window, 'keydown', this);
31377        });
31378    },
31379
31380    _key: function (e) {
31381        if ( !this.enabled ) {
31382            return;
31383        }
31384
31385        var snap = this.options.snap,   // we are using this alot, better to cache it
31386            newX = snap ? this.currentPage.pageX : this.x,
31387            newY = snap ? this.currentPage.pageY : this.y,
31388            now = utils.getTime(),
31389            prevTime = this.keyTime || 0,
31390            acceleration = 0.250,
31391            pos;
31392
31393        if ( this.options.useTransition && this.isInTransition ) {
31394            pos = this.getComputedPosition();
31395
31396            this._translate(Math.round(pos.x), Math.round(pos.y));
31397            this.isInTransition = false;
31398        }
31399
31400        this.keyAcceleration = now - prevTime < 200 ? Math.min(this.keyAcceleration + acceleration, 50) : 0;
31401
31402        switch ( e.keyCode ) {
31403            case this.options.keyBindings.pageUp:
31404                if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {
31405                    newX += snap ? 1 : this.wrapperWidth;
31406                } else {
31407                    newY += snap ? 1 : this.wrapperHeight;
31408                }
31409                break;
31410            case this.options.keyBindings.pageDown:
31411                if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {
31412                    newX -= snap ? 1 : this.wrapperWidth;
31413                } else {
31414                    newY -= snap ? 1 : this.wrapperHeight;
31415                }
31416                break;
31417            case this.options.keyBindings.end:
31418                newX = snap ? this.pages.length-1 : this.maxScrollX;
31419                newY = snap ? this.pages[0].length-1 : this.maxScrollY;
31420                break;
31421            case this.options.keyBindings.home:
31422                newX = 0;
31423                newY = 0;
31424                break;
31425            case this.options.keyBindings.left:
31426                newX += snap ? -1 : 5 + this.keyAcceleration>>0;
31427                break;
31428            case this.options.keyBindings.up:
31429                newY += snap ? 1 : 5 + this.keyAcceleration>>0;
31430                break;
31431            case this.options.keyBindings.right:
31432                newX -= snap ? -1 : 5 + this.keyAcceleration>>0;
31433                break;
31434            case this.options.keyBindings.down:
31435                newY -= snap ? 1 : 5 + this.keyAcceleration>>0;
31436                break;
31437            default:
31438                return;
31439        }
31440
31441        if ( snap ) {
31442            this.goToPage(newX, newY);
31443            return;
31444        }
31445
31446        if ( newX > 0 ) {
31447            newX = 0;
31448            this.keyAcceleration = 0;
31449        } else if ( newX < this.maxScrollX ) {
31450            newX = this.maxScrollX;
31451            this.keyAcceleration = 0;
31452        }
31453
31454        if ( newY > 0 ) {
31455            newY = 0;
31456            this.keyAcceleration = 0;
31457        } else if ( newY < this.maxScrollY ) {
31458            newY = this.maxScrollY;
31459            this.keyAcceleration = 0;
31460        }
31461
31462        this.scrollTo(newX, newY, 0);
31463
31464        this.keyTime = now;
31465    },
31466
31467    _animate: function (destX, destY, duration, easingFn) {
31468        var that = this,
31469            startX = this.x,
31470            startY = this.y,
31471            startTime = utils.getTime(),
31472            destTime = startTime + duration;
31473
31474        function step () {
31475            var now = utils.getTime(),
31476                newX, newY,
31477                easing;
31478
31479            if ( now >= destTime ) {
31480                that.isAnimating = false;
31481                that._translate(destX, destY);
31482
31483                if ( !that.resetPosition(that.options.bounceTime) ) {
31484                    that._execEvent('scrollEnd');
31485                }
31486
31487                return;
31488            }
31489
31490            now = ( now - startTime ) / duration;
31491            easing = easingFn(now);
31492            newX = ( destX - startX ) * easing + startX;
31493            newY = ( destY - startY ) * easing + startY;
31494            that._translate(newX, newY);
31495
31496            if ( that.isAnimating ) {
31497                rAF(step);
31498            }
31499        }
31500
31501        this.isAnimating = true;
31502        step();
31503    },
31504    handleEvent: function (e) {
31505        switch ( e.type ) {
31506            case 'touchstart':
31507            case 'pointerdown':
31508            case 'MSPointerDown':
31509            case 'mousedown':
31510                this._start(e);
31511                break;
31512            case 'touchmove':
31513            case 'pointermove':
31514            case 'MSPointerMove':
31515            case 'mousemove':
31516                this._move(e);
31517                break;
31518            case 'touchend':
31519            case 'pointerup':
31520            case 'MSPointerUp':
31521            case 'mouseup':
31522            case 'touchcancel':
31523            case 'pointercancel':
31524            case 'MSPointerCancel':
31525            case 'mousecancel':
31526                this._end(e);
31527                break;
31528            case 'orientationchange':
31529            case 'resize':
31530                this._resize();
31531                break;
31532            case 'transitionend':
31533            case 'webkitTransitionEnd':
31534            case 'oTransitionEnd':
31535            case 'MSTransitionEnd':
31536                this._transitionEnd(e);
31537                break;
31538            case 'wheel':
31539            case 'DOMMouseScroll':
31540            case 'mousewheel':
31541                this._wheel(e);
31542                break;
31543            case 'keydown':
31544                this._key(e);
31545                break;
31546            case 'click':
31547                if ( this.enabled && !e._constructed ) {
31548                    e.preventDefault();
31549                    e.stopPropagation();
31550                }
31551                break;
31552        }
31553    }
31554};
31555function createDefaultScrollbar (direction, interactive, type) {
31556    var scrollbar = document.createElement('div'),
31557        indicator = document.createElement('div');
31558
31559    if ( type === true ) {
31560        scrollbar.style.cssText = 'position:absolute;z-index:9999';
31561        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';
31562    }
31563
31564    indicator.className = 'iScrollIndicator';
31565
31566    if ( direction == 'h' ) {
31567        if ( type === true ) {
31568            scrollbar.style.cssText += ';height:7px;left:2px;right:2px;bottom:0';
31569            indicator.style.height = '100%';
31570        }
31571        scrollbar.className = 'iScrollHorizontalScrollbar';
31572    } else {
31573        if ( type === true ) {
31574            scrollbar.style.cssText += ';width:7px;bottom:2px;top:2px;right:1px';
31575            indicator.style.width = '100%';
31576        }
31577        scrollbar.className = 'iScrollVerticalScrollbar';
31578    }
31579
31580    scrollbar.style.cssText += ';overflow:hidden';
31581
31582    if ( !interactive ) {
31583        scrollbar.style.pointerEvents = 'none';
31584    }
31585
31586    scrollbar.appendChild(indicator);
31587
31588    return scrollbar;
31589}
31590
31591function Indicator (scroller, options) {
31592    this.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el;
31593    this.wrapperStyle = this.wrapper.style;
31594    this.indicator = this.wrapper.children[0];
31595    this.indicatorStyle = this.indicator.style;
31596    this.scroller = scroller;
31597
31598    this.options = {
31599        listenX: true,
31600        listenY: true,
31601        interactive: false,
31602        resize: true,
31603        defaultScrollbars: false,
31604        shrink: false,
31605        fade: false,
31606        speedRatioX: 0,
31607        speedRatioY: 0
31608    };
31609
31610    for ( var i in options ) {
31611        this.options[i] = options[i];
31612    }
31613
31614    this.sizeRatioX = 1;
31615    this.sizeRatioY = 1;
31616    this.maxPosX = 0;
31617    this.maxPosY = 0;
31618
31619    if ( this.options.interactive ) {
31620        if ( !this.options.disableTouch ) {
31621            utils.addEvent(this.indicator, 'touchstart', this);
31622            utils.addEvent(window, 'touchend', this);
31623        }
31624        if ( !this.options.disablePointer ) {
31625            utils.addEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);
31626            utils.addEvent(window, utils.prefixPointerEvent('pointerup'), this);
31627        }
31628        if ( !this.options.disableMouse ) {
31629            utils.addEvent(this.indicator, 'mousedown', this);
31630            utils.addEvent(window, 'mouseup', this);
31631        }
31632    }
31633
31634    if ( this.options.fade ) {
31635        this.wrapperStyle[utils.style.transform] = this.scroller.translateZ;
31636        var durationProp = utils.style.transitionDuration;
31637        if(!durationProp) {
31638            return;
31639        }
31640        this.wrapperStyle[durationProp] = utils.isBadAndroid ? '0.0001ms' : '0ms';
31641        // remove 0.0001ms
31642        var self = this;
31643        if(utils.isBadAndroid) {
31644            rAF(function() {
31645                if(self.wrapperStyle[durationProp] === '0.0001ms') {
31646                    self.wrapperStyle[durationProp] = '0s';
31647                }
31648            });
31649        }
31650        this.wrapperStyle.opacity = '0';
31651    }
31652}
31653
31654Indicator.prototype = {
31655    handleEvent: function (e) {
31656        switch ( e.type ) {
31657            case 'touchstart':
31658            case 'pointerdown':
31659            case 'MSPointerDown':
31660            case 'mousedown':
31661                this._start(e);
31662                break;
31663            case 'touchmove':
31664            case 'pointermove':
31665            case 'MSPointerMove':
31666            case 'mousemove':
31667                this._move(e);
31668                break;
31669            case 'touchend':
31670            case 'pointerup':
31671            case 'MSPointerUp':
31672            case 'mouseup':
31673            case 'touchcancel':
31674            case 'pointercancel':
31675            case 'MSPointerCancel':
31676            case 'mousecancel':
31677                this._end(e);
31678                break;
31679        }
31680    },
31681
31682    destroy: function () {
31683        if ( this.options.fadeScrollbars ) {
31684            clearTimeout(this.fadeTimeout);
31685            this.fadeTimeout = null;
31686        }
31687        if ( this.options.interactive ) {
31688            utils.removeEvent(this.indicator, 'touchstart', this);
31689            utils.removeEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);
31690            utils.removeEvent(this.indicator, 'mousedown', this);
31691
31692            utils.removeEvent(window, 'touchmove', this);
31693            utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);
31694            utils.removeEvent(window, 'mousemove', this);
31695
31696            utils.removeEvent(window, 'touchend', this);
31697            utils.removeEvent(window, utils.prefixPointerEvent('pointerup'), this);
31698            utils.removeEvent(window, 'mouseup', this);
31699        }
31700
31701        if ( this.options.defaultScrollbars ) {
31702            this.wrapper.parentNode.removeChild(this.wrapper);
31703        }
31704    },
31705
31706    _start: function (e) {
31707        var point = e.touches ? e.touches[0] : e;
31708
31709        e.preventDefault();
31710        e.stopPropagation();
31711
31712        this.transitionTime();
31713
31714        this.initiated = true;
31715        this.moved = false;
31716        this.lastPointX = point.pageX;
31717        this.lastPointY = point.pageY;
31718
31719        this.startTime  = utils.getTime();
31720
31721        if ( !this.options.disableTouch ) {
31722            utils.addEvent(window, 'touchmove', this);
31723        }
31724        if ( !this.options.disablePointer ) {
31725            utils.addEvent(window, utils.prefixPointerEvent('pointermove'), this);
31726        }
31727        if ( !this.options.disableMouse ) {
31728            utils.addEvent(window, 'mousemove', this);
31729        }
31730
31731        this.scroller._execEvent('beforeScrollStart');
31732    },
31733
31734    _move: function (e) {
31735        var point = e.touches ? e.touches[0] : e,
31736            deltaX, deltaY,
31737            newX, newY,
31738            timestamp = utils.getTime();
31739
31740        if ( !this.moved ) {
31741            this.scroller._execEvent('scrollStart');
31742        }
31743
31744        this.moved = true;
31745
31746        deltaX = point.pageX - this.lastPointX;
31747        this.lastPointX = point.pageX;
31748
31749        deltaY = point.pageY - this.lastPointY;
31750        this.lastPointY = point.pageY;
31751
31752        newX = this.x + deltaX;
31753        newY = this.y + deltaY;
31754
31755        this._pos(newX, newY);
31756
31757// INSERT POINT: indicator._move
31758
31759        e.preventDefault();
31760        e.stopPropagation();
31761    },
31762
31763    _end: function (e) {
31764        if ( !this.initiated ) {
31765            return;
31766        }
31767
31768        this.initiated = false;
31769
31770        e.preventDefault();
31771        e.stopPropagation();
31772
31773        utils.removeEvent(window, 'touchmove', this);
31774        utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);
31775        utils.removeEvent(window, 'mousemove', this);
31776
31777        if ( this.scroller.options.snap ) {
31778            var snap = this.scroller._nearestSnap(this.scroller.x, this.scroller.y);
31779
31780            var time = this.options.snapSpeed || Math.max(
31781                    Math.max(
31782                        Math.min(Math.abs(this.scroller.x - snap.x), 1000),
31783                        Math.min(Math.abs(this.scroller.y - snap.y), 1000)
31784                    ), 300);
31785
31786            if ( this.scroller.x != snap.x || this.scroller.y != snap.y ) {
31787                this.scroller.directionX = 0;
31788                this.scroller.directionY = 0;
31789                this.scroller.currentPage = snap;
31790                this.scroller.scrollTo(snap.x, snap.y, time, this.scroller.options.bounceEasing);
31791            }
31792        }
31793
31794        if ( this.moved ) {
31795            this.scroller._execEvent('scrollEnd');
31796        }
31797    },
31798
31799    transitionTime: function (time) {
31800        time = time || 0;
31801        var durationProp = utils.style.transitionDuration;
31802        if(!durationProp) {
31803            return;
31804        }
31805
31806        this.indicatorStyle[durationProp] = time + 'ms';
31807
31808        if ( !time && utils.isBadAndroid ) {
31809            this.indicatorStyle[durationProp] = '0.0001ms';
31810            // remove 0.0001ms
31811            var self = this;
31812            rAF(function() {
31813                if(self.indicatorStyle[durationProp] === '0.0001ms') {
31814                    self.indicatorStyle[durationProp] = '0s';
31815                }
31816            });
31817        }
31818    },
31819
31820    transitionTimingFunction: function (easing) {
31821        this.indicatorStyle[utils.style.transitionTimingFunction] = easing;
31822    },
31823
31824    refresh: function () {
31825        this.transitionTime();
31826
31827        if ( this.options.listenX && !this.options.listenY ) {
31828            this.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none';
31829        } else if ( this.options.listenY && !this.options.listenX ) {
31830            this.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none';
31831        } else {
31832            this.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none';
31833        }
31834
31835        if ( this.scroller.hasHorizontalScroll && this.scroller.hasVerticalScroll ) {
31836            utils.addClass(this.wrapper, 'iScrollBothScrollbars');
31837            utils.removeClass(this.wrapper, 'iScrollLoneScrollbar');
31838
31839            if ( this.options.defaultScrollbars && this.options.customStyle ) {
31840                if ( this.options.listenX ) {
31841                    this.wrapper.style.right = '8px';
31842                } else {
31843                    this.wrapper.style.bottom = '8px';
31844                }
31845            }
31846        } else {
31847            utils.removeClass(this.wrapper, 'iScrollBothScrollbars');
31848            utils.addClass(this.wrapper, 'iScrollLoneScrollbar');
31849
31850            if ( this.options.defaultScrollbars && this.options.customStyle ) {
31851                if ( this.options.listenX ) {
31852                    this.wrapper.style.right = '2px';
31853                } else {
31854                    this.wrapper.style.bottom = '2px';
31855                }
31856            }
31857        }
31858
31859        var r = this.wrapper.offsetHeight;  // force refresh
31860
31861        if ( this.options.listenX ) {
31862            this.wrapperWidth = this.wrapper.clientWidth;
31863            if ( this.options.resize ) {
31864                this.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / (this.scroller.scrollerWidth || this.wrapperWidth || 1)), 8);
31865                this.indicatorStyle.width = this.indicatorWidth + 'px';
31866            } else {
31867                this.indicatorWidth = this.indicator.clientWidth;
31868            }
31869
31870            this.maxPosX = this.wrapperWidth - this.indicatorWidth;
31871
31872            if ( this.options.shrink == 'clip' ) {
31873                this.minBoundaryX = -this.indicatorWidth + 8;
31874                this.maxBoundaryX = this.wrapperWidth - 8;
31875            } else {
31876                this.minBoundaryX = 0;
31877                this.maxBoundaryX = this.maxPosX;
31878            }
31879
31880            this.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX));
31881        }
31882
31883        if ( this.options.listenY ) {
31884            this.wrapperHeight = this.wrapper.clientHeight;
31885            if ( this.options.resize ) {
31886                this.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / (this.scroller.scrollerHeight || this.wrapperHeight || 1)), 8);
31887                this.indicatorStyle.height = this.indicatorHeight + 'px';
31888            } else {
31889                this.indicatorHeight = this.indicator.clientHeight;
31890            }
31891
31892            this.maxPosY = this.wrapperHeight - this.indicatorHeight;
31893
31894            if ( this.options.shrink == 'clip' ) {
31895                this.minBoundaryY = -this.indicatorHeight + 8;
31896                this.maxBoundaryY = this.wrapperHeight - 8;
31897            } else {
31898                this.minBoundaryY = 0;
31899                this.maxBoundaryY = this.maxPosY;
31900            }
31901
31902            this.maxPosY = this.wrapperHeight - this.indicatorHeight;
31903            this.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY));
31904        }
31905
31906        this.updatePosition();
31907    },
31908
31909    updatePosition: function () {
31910        var x = this.options.listenX && Math.round(this.sizeRatioX * this.scroller.x) || 0,
31911            y = this.options.listenY && Math.round(this.sizeRatioY * this.scroller.y) || 0;
31912
31913        if ( !this.options.ignoreBoundaries ) {
31914            if ( x < this.minBoundaryX ) {
31915                if ( this.options.shrink == 'scale' ) {
31916                    this.width = Math.max(this.indicatorWidth + x, 8);
31917                    this.indicatorStyle.width = this.width + 'px';
31918                }
31919                x = this.minBoundaryX;
31920            } else if ( x > this.maxBoundaryX ) {
31921                if ( this.options.shrink == 'scale' ) {
31922                    this.width = Math.max(this.indicatorWidth - (x - this.maxPosX), 8);
31923                    this.indicatorStyle.width = this.width + 'px';
31924                    x = this.maxPosX + this.indicatorWidth - this.width;
31925                } else {
31926                    x = this.maxBoundaryX;
31927                }
31928            } else if ( this.options.shrink == 'scale' && this.width != this.indicatorWidth ) {
31929                this.width = this.indicatorWidth;
31930                this.indicatorStyle.width = this.width + 'px';
31931            }
31932
31933            if ( y < this.minBoundaryY ) {
31934                if ( this.options.shrink == 'scale' ) {
31935                    this.height = Math.max(this.indicatorHeight + y * 3, 8);
31936                    this.indicatorStyle.height = this.height + 'px';
31937                }
31938                y = this.minBoundaryY;
31939            } else if ( y > this.maxBoundaryY ) {
31940                if ( this.options.shrink == 'scale' ) {
31941                    this.height = Math.max(this.indicatorHeight - (y - this.maxPosY) * 3, 8);
31942                    this.indicatorStyle.height = this.height + 'px';
31943                    y = this.maxPosY + this.indicatorHeight - this.height;
31944                } else {
31945                    y = this.maxBoundaryY;
31946                }
31947            } else if ( this.options.shrink == 'scale' && this.height != this.indicatorHeight ) {
31948                this.height = this.indicatorHeight;
31949                this.indicatorStyle.height = this.height + 'px';
31950            }
31951        }
31952
31953        this.x = x;
31954        this.y = y;
31955
31956        if ( this.scroller.options.useTransform ) {
31957            this.indicatorStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.scroller.translateZ;
31958        } else {
31959            this.indicatorStyle.left = x + 'px';
31960            this.indicatorStyle.top = y + 'px';
31961        }
31962    },
31963
31964    _pos: function (x, y) {
31965        if ( x < 0 ) {
31966            x = 0;
31967        } else if ( x > this.maxPosX ) {
31968            x = this.maxPosX;
31969        }
31970
31971        if ( y < 0 ) {
31972            y = 0;
31973        } else if ( y > this.maxPosY ) {
31974            y = this.maxPosY;
31975        }
31976
31977        x = this.options.listenX ? Math.round(x / this.sizeRatioX) : this.scroller.x;
31978        y = this.options.listenY ? Math.round(y / this.sizeRatioY) : this.scroller.y;
31979
31980        this.scroller.scrollTo(x, y);
31981    },
31982
31983    fade: function (val, hold) {
31984        if ( hold && !this.visible ) {
31985            return;
31986        }
31987
31988        clearTimeout(this.fadeTimeout);
31989        this.fadeTimeout = null;
31990
31991        var time = val ? 250 : 500,
31992            delay = val ? 0 : 300;
31993
31994        val = val ? '1' : '0';
31995
31996        this.wrapperStyle[utils.style.transitionDuration] = time + 'ms';
31997
31998        this.fadeTimeout = setTimeout((function (val) {
31999            this.wrapperStyle.opacity = val;
32000            this.visible = +val;
32001        }).bind(this, val), delay);
32002    }
32003};
32004
32005IScroll.utils = utils;
32006
32007if ( typeof module != 'undefined' && module.exports ) {
32008    module.exports = IScroll;
32009} else if ( typeof define == 'function' && define.amd ) {
32010        define( function () { return IScroll; } );
32011} else {
32012    window.IScroll = IScroll;
32013}
32014
32015})(window, document, Math);
32016/*!
32017 * fullPage 2.9.4
32018 * https://github.com/alvarotrigo/fullPage.js
32019 * @license MIT licensed
32020 *
32021 * Copyright (C) 2015 alvarotrigo.com - A project by Alvaro Trigo
32022 */
32023(function(global, factory) {
32024    'use strict';
32025    if (typeof define === 'function' && define.amd) {
32026        define(['jquery'], function($) {
32027          return factory($, global, global.document, global.Math);
32028        });
32029    } else if (typeof exports === "object" && exports) {
32030        module.exports = factory(require('jquery'), global, global.document, global.Math);
32031    } else {
32032        factory(jQuery, global, global.document, global.Math);
32033    }
32034})(typeof window !== 'undefined' ? window : this, function($, window, document, Math, undefined) {
32035    'use strict';
32036
32037    // keeping central set of classnames and selectors
32038    var WRAPPER =               'fullpage-wrapper';
32039    var WRAPPER_SEL =           '.' + WRAPPER;
32040
32041    // slimscroll
32042    var SCROLLABLE =            'fp-scrollable';
32043    var SCROLLABLE_SEL =        '.' + SCROLLABLE;
32044
32045    // util
32046    var RESPONSIVE =            'fp-responsive';
32047    var NO_TRANSITION =         'fp-notransition';
32048    var DESTROYED =             'fp-destroyed';
32049    var ENABLED =               'fp-enabled';
32050    var VIEWING_PREFIX =        'fp-viewing';
32051    var ACTIVE =                'active';
32052    var ACTIVE_SEL =            '.' + ACTIVE;
32053    var COMPLETELY =            'fp-completely';
32054    var COMPLETELY_SEL =        '.' + COMPLETELY;
32055
32056    // section
32057    var SECTION_DEFAULT_SEL =   '.section';
32058    var SECTION =               'fp-section';
32059    var SECTION_SEL =           '.' + SECTION;
32060    var SECTION_ACTIVE_SEL =    SECTION_SEL + ACTIVE_SEL;
32061    var SECTION_FIRST_SEL =     SECTION_SEL + ':first';
32062    var SECTION_LAST_SEL =      SECTION_SEL + ':last';
32063    var TABLE_CELL =            'fp-tableCell';
32064    var TABLE_CELL_SEL =        '.' + TABLE_CELL;
32065    var AUTO_HEIGHT =           'fp-auto-height';
32066    var AUTO_HEIGHT_SEL =       '.fp-auto-height';
32067    var NORMAL_SCROLL =         'fp-normal-scroll';
32068    var NORMAL_SCROLL_SEL =     '.fp-normal-scroll';
32069
32070    // section nav
32071    var SECTION_NAV =           'fp-nav';
32072    var SECTION_NAV_SEL =       '#' + SECTION_NAV;
32073    var SECTION_NAV_TOOLTIP =   'fp-tooltip';
32074    var SECTION_NAV_TOOLTIP_SEL='.'+SECTION_NAV_TOOLTIP;
32075    var SHOW_ACTIVE_TOOLTIP =   'fp-show-active';
32076
32077    // slide
32078    var SLIDE_DEFAULT_SEL =     '.slide';
32079    var SLIDE =                 'fp-slide';
32080    var SLIDE_SEL =             '.' + SLIDE;
32081    var SLIDE_ACTIVE_SEL =      SLIDE_SEL + ACTIVE_SEL;
32082    var SLIDES_WRAPPER =        'fp-slides';
32083    var SLIDES_WRAPPER_SEL =    '.' + SLIDES_WRAPPER;
32084    var SLIDES_CONTAINER =      'fp-slidesContainer';
32085    var SLIDES_CONTAINER_SEL =  '.' + SLIDES_CONTAINER;
32086    var TABLE =                 'fp-table';
32087
32088    // slide nav
32089    var SLIDES_NAV =            'fp-slidesNav';
32090    var SLIDES_NAV_SEL =        '.' + SLIDES_NAV;
32091    var SLIDES_NAV_LINK_SEL =   SLIDES_NAV_SEL + ' a';
32092    var SLIDES_ARROW =          'fp-controlArrow';
32093    var SLIDES_ARROW_SEL =      '.' + SLIDES_ARROW;
32094    var SLIDES_PREV =           'fp-prev';
32095    var SLIDES_PREV_SEL =       '.' + SLIDES_PREV;
32096    var SLIDES_ARROW_PREV =     SLIDES_ARROW + ' ' + SLIDES_PREV;
32097    var SLIDES_ARROW_PREV_SEL = SLIDES_ARROW_SEL + SLIDES_PREV_SEL;
32098    var SLIDES_NEXT =           'fp-next';
32099    var SLIDES_NEXT_SEL =       '.' + SLIDES_NEXT;
32100    var SLIDES_ARROW_NEXT =     SLIDES_ARROW + ' ' + SLIDES_NEXT;
32101    var SLIDES_ARROW_NEXT_SEL = SLIDES_ARROW_SEL + SLIDES_NEXT_SEL;
32102
32103    var $window = $(window);
32104    var $document = $(document);
32105
32106    // Default options for iScroll.js used when using scrollOverflow
32107    var iscrollOptions = {
32108        scrollbars: true,
32109        mouseWheel: true,
32110        hideScrollbars: false,
32111        fadeScrollbars: false,
32112        disableMouse: true,
32113        interactiveScrollbars: true,
32114        bounce: false,
32115    };
32116
32117    $.fn.fullpage = function(options) {
32118        //only once my friend!
32119        if($('html').hasClass(ENABLED)){ displayWarnings(); return; }
32120
32121        // common jQuery objects
32122        var $htmlBody = $('html, body');
32123        var $body = $('body');
32124
32125        var FP = $.fn.fullpage;
32126
32127        // Creating some defaults, extending them with any options that were provided
32128        options = $.extend({
32129            //navigation
32130            menu: false,
32131            anchors:[],
32132            lockAnchors: false,
32133            navigation: false,
32134            navigationPosition: 'right',
32135            navigationTooltips: [],
32136            showActiveTooltip: false,
32137            slidesNavigation: false,
32138            slidesNavPosition: 'bottom',
32139            scrollBar: false,
32140            hybrid: false,
32141
32142            //scrolling
32143            css3: true,
32144            scrollingSpeed: 700,
32145            autoScrolling: true,
32146            fitToSection: true,
32147            fitToSectionDelay: 1000,
32148            easing: 'easeInOutCubic',
32149            easingcss3: 'ease',
32150            loopBottom: false,
32151            loopTop: false,
32152            loopHorizontal: true,
32153            continuousVertical: false,
32154            continuousHorizontal: false,
32155            scrollHorizontally: false,
32156            interlockedSlides: false,
32157            dragAndMove: false,
32158            offsetSections: false,
32159            resetSliders: false,
32160            fadingEffect: false,
32161            normalScrollElements: null,
32162            scrollOverflow: false,
32163            scrollOverflowReset: false,
32164            scrollOverflowHandler: iscrollHandler,
32165            scrollOverflowOptions: null,
32166            touchSensitivity: 5,
32167            normalScrollElementTouchThreshold: 5,
32168            bigSectionsDestination: null,
32169
32170            //Accessibility
32171            keyboardScrolling: true,
32172            animateAnchor: true,
32173            recordHistory: true,
32174
32175            //design
32176            controlArrows: true,
32177            controlArrowColor: '#fff',
32178            verticalCentered: true,
32179            sectionsColor : [],
32180            paddingTop: 0,
32181            paddingBottom: 0,
32182            fixedElements: null,
32183            responsive: 0, //backwards compabitility with responsiveWiddth
32184            responsiveWidth: 0,
32185            responsiveHeight: 0,
32186            responsiveSlides: false,
32187            parallax: false,
32188            parallaxOptions: {
32189                type: 'reveal',
32190                percentage: 62,
32191                property: 'translate'
32192            },
32193
32194            //Custom selectors
32195            sectionSelector: SECTION_DEFAULT_SEL,
32196            slideSelector: SLIDE_DEFAULT_SEL,
32197
32198            //events
32199            afterLoad: null,
32200            onLeave: null,
32201            afterRender: null,
32202            afterResize: null,
32203            afterReBuild: null,
32204            afterSlideLoad: null,
32205            onSlideLeave: null,
32206            afterResponsive: null,
32207
32208            lazyLoading: true
32209        }, options);
32210
32211        //flag to avoid very fast sliding for landscape sliders
32212        var slideMoving = false;
32213
32214        var isTouchDevice = navigator.userAgent.match(/(iPhone|iPod|iPad|Android|playbook|silk|BlackBerry|BB10|Windows Phone|Tizen|Bada|webOS|IEMobile|Opera Mini)/);
32215        var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0) || (navigator.maxTouchPoints));
32216        var container = $(this);
32217        var windowsHeight = $window.height();
32218        var isResizing = false;
32219        var isWindowFocused = true;
32220        var lastScrolledDestiny;
32221        var lastScrolledSlide;
32222        var canScroll = true;
32223        var scrollings = [];
32224        var controlPressed;
32225        var startingSection;
32226        var isScrollAllowed = {};
32227        isScrollAllowed.m = {  'up':true, 'down':true, 'left':true, 'right':true };
32228        isScrollAllowed.k = $.extend(true,{}, isScrollAllowed.m);
32229        var MSPointer = getMSPointer();
32230        var events = {
32231            touchmove: 'ontouchmove' in window ? 'touchmove' :  MSPointer.move,
32232            touchstart: 'ontouchstart' in window ? 'touchstart' :  MSPointer.down
32233        };
32234
32235        //cheks for passive event support
32236        //added by Uncode from new fullPage updates
32237        var g_supportsPassive = false;
32238        try {
32239          var opts = Object.defineProperty({}, 'passive', {
32240            get: function() {
32241              g_supportsPassive = true;
32242            }
32243          });
32244          window.addEventListener("testPassive", null, opts);
32245          window.removeEventListener("testPassive", null, opts);
32246        } catch (e) {}
32247
32248        //timeouts
32249        var resizeId;
32250        var afterSectionLoadsId;
32251        var afterSlideLoadsId;
32252        var scrollId;
32253        var scrollId2;
32254        var keydownId;
32255        var originals = $.extend(true, {}, options); //deep copy
32256
32257        //Uncode addition
32258        var $masthead = $('#masthead');
32259        var hideMenu = !$('body').hasClass('vmenu') && $('body').hasClass('uncode-fp-menu-hide') ? true : false;
32260        var menuHeight = $masthead.hasClass('menu-transparent') || hideMenu ? 0 : UNCODE.menuHeight;
32261        var bodyBorder = UNCODE.bodyBorder;
32262        var adminBarHeight = UNCODE.adminBarHeight;
32263
32264        displayWarnings();
32265
32266        //fixing bug in iScroll with links: https://github.com/cubiq/iscroll/issues/783
32267        iscrollOptions.click = isTouch; // see #2035
32268
32269        //extending iScroll options with the user custom ones
32270        iscrollOptions = $.extend(iscrollOptions, options.scrollOverflowOptions);
32271
32272        //easeInOutCubic animation included in the plugin
32273        $.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;}});
32274
32275        /**
32276        * Sets the autoScroll option.
32277        * It changes the scroll bar visibility and the history of the site as a result.
32278        */
32279        function setAutoScrolling(value, type){
32280            //removing the transformation
32281            if(!value){
32282                silentScroll(0);
32283            }
32284
32285            setVariableState('autoScrolling', value, type);
32286
32287            var element = $(SECTION_ACTIVE_SEL);
32288
32289            if(options.autoScrolling && !options.scrollBar){
32290                $htmlBody.css({
32291                    'overflow' : 'hidden !important',
32292                    'height' : '100%'
32293                });
32294
32295                //Uncode addition
32296                //setRecordHistory(originals.recordHistory, 'internal');
32297
32298                //for IE touch devices
32299                container.css({
32300                    '-ms-touch-action': 'none',
32301                    'touch-action': 'none'
32302                });
32303
32304                if(element.length){
32305                    //moving the container up
32306                    silentScroll(element.position().top);
32307                }
32308
32309            }else{
32310                $htmlBody.css({
32311                    'overflow' : 'visible !important',
32312                    'height' : 'initial'
32313                });
32314
32315                //Uncode addition
32316                //setRecordHistory(false, 'internal');
32317
32318                //for IE touch devices
32319                container.css({
32320                    '-ms-touch-action': '',
32321                    'touch-action': ''
32322                });
32323
32324                //scrolling the page to the section with no animation
32325                if (element.length) {
32326                    $htmlBody.scrollTop(element.position().top);
32327                }
32328            }
32329        }
32330
32331        /**
32332        * Defines wheter to record the history for each hash change in the URL.
32333        */
32334        function setRecordHistory(value, type){
32335            setVariableState('recordHistory', value, type);
32336        }
32337
32338        /**
32339        * Defines the scrolling speed
32340        */
32341        function setScrollingSpeed(value, type){
32342            setVariableState('scrollingSpeed', value, type);
32343        }
32344
32345        /**
32346        * Sets fitToSection
32347        */
32348        function setFitToSection(value, type){
32349            setVariableState('fitToSection', value, type);
32350        }
32351
32352        /**
32353        * Sets lockAnchors
32354        */
32355        function setLockAnchors(value){
32356            options.lockAnchors = value;
32357        }
32358
32359        /**
32360        * Adds or remove the possiblity of scrolling through sections by using the mouse wheel or the trackpad.
32361        */
32362        function setMouseWheelScrolling(value){
32363            if(value){
32364                addMouseWheelHandler();
32365                addMiddleWheelHandler();
32366            }else{
32367                removeMouseWheelHandler();
32368                removeMiddleWheelHandler();
32369            }
32370        }
32371
32372        /**
32373        * Adds or remove the possibility of scrolling through sections by using the mouse wheel/trackpad or touch gestures.
32374        * Optionally a second parameter can be used to specify the direction for which the action will be applied.
32375        *
32376        * @param directions string containing the direction or directions separated by comma.
32377        */
32378        function setAllowScrolling(value, directions){
32379            if(typeof directions !== 'undefined'){
32380                directions = directions.replace(/ /g,'').split(',');
32381
32382                $.each(directions, function (index, direction){
32383                    setIsScrollAllowed(value, direction, 'm');
32384                });
32385            }
32386            else if(value){
32387                setMouseWheelScrolling(true);
32388                addTouchHandler();
32389            }else{
32390                setMouseWheelScrolling(false);
32391                removeTouchHandler();
32392            }
32393        }
32394
32395        /**
32396        * Adds or remove the possibility of scrolling through sections by using the keyboard arrow keys
32397        */
32398        function setKeyboardScrolling(value, directions){
32399            if(typeof directions !== 'undefined'){
32400                directions = directions.replace(/ /g,'').split(',');
32401
32402                $.each(directions, function (index, direction){
32403                    setIsScrollAllowed(value, direction, 'k');
32404                });
32405            }else{
32406                options.keyboardScrolling = value;
32407            }
32408        }
32409
32410        /**
32411        * Moves the page up one section.
32412        */
32413        function moveSectionUp(){
32414            var prev = $(SECTION_ACTIVE_SEL).prev(SECTION_SEL);
32415
32416            //looping to the bottom if there's no more sections above
32417            if (!prev.length && (options.loopTop || options.continuousVertical)) {
32418                prev = $(SECTION_SEL).last();
32419            }
32420
32421            if (prev.length) {
32422                scrollPage(prev, null, true);
32423            }
32424        }
32425
32426        /**
32427        * Moves the page down one section.
32428        */
32429        function moveSectionDown(){
32430            var next = $(SECTION_ACTIVE_SEL).next(SECTION_SEL);
32431
32432            //looping to the top if there's no more sections below
32433            if(!next.length &&
32434                (options.loopBottom || options.continuousVertical)){
32435                next = $(SECTION_SEL).first();
32436            }
32437
32438            if(next.length){
32439                scrollPage(next, null, false);
32440            }
32441        }
32442
32443        /**
32444        * Moves the page to the given section and slide with no animation.
32445        * Anchors or index positions can be used as params.
32446        */
32447        function silentMoveTo(sectionAnchor, slideAnchor){
32448            setScrollingSpeed (0, 'internal');
32449            moveTo(sectionAnchor, slideAnchor);
32450            setScrollingSpeed (originals.scrollingSpeed, 'internal');
32451        }
32452
32453        /**
32454        * Moves the page to the given section and slide.
32455        * Anchors or index positions can be used as params.
32456        */
32457        function moveTo(sectionAnchor, slideAnchor){
32458            var destiny = getSectionByAnchor(sectionAnchor);
32459
32460            if (typeof slideAnchor !== 'undefined'){
32461                scrollPageAndSlide(sectionAnchor, slideAnchor);
32462            }else if(destiny.length > 0){
32463                scrollPage(destiny);
32464            }
32465        }
32466
32467        /**
32468        * Slides right the slider of the active section.
32469        * Optional `section` param.
32470        */
32471        function moveSlideRight(section){
32472            moveSlide('right', section);
32473        }
32474
32475        /**
32476        * Slides left the slider of the active section.
32477        * Optional `section` param.
32478        */
32479        function moveSlideLeft(section){
32480            moveSlide('left', section);
32481        }
32482
32483        /**
32484         * When resizing is finished, we adjust the slides sizes and positions
32485         */
32486        function reBuild(resizing){
32487            if(container.hasClass(DESTROYED)){ return; }  //nothing to do if the plugin was destroyed
32488
32489            isResizing = true;
32490
32491            windowsHeight = $window.height();  //updating global var
32492
32493            $(SECTION_SEL).each(function(){
32494                var slidesWrap = $(this).find(SLIDES_WRAPPER_SEL);
32495                var slides = $(this).find(SLIDE_SEL);
32496
32497                //adjusting the height of the table-cell for IE and Firefox
32498                if(options.verticalCentered){
32499                    $(this).find(TABLE_CELL_SEL).css('height', getTableHeight($(this)) + 'px');
32500                }
32501
32502                $(this).css('height', windowsHeight + 'px');
32503
32504                //resizing the scrolling divs
32505                if(options.scrollOverflow){
32506                    if(slides.length){
32507                        slides.each(function(){
32508                            createScrollBar($(this));
32509                        });
32510                    }else{
32511                        createScrollBar($(this));
32512                    }
32513                }
32514
32515                //adjusting the position fo the FULL WIDTH slides...
32516                if (slides.length > 1) {
32517                    landscapeScroll(slidesWrap, slidesWrap.find(SLIDE_ACTIVE_SEL));
32518                }
32519            });
32520
32521            var activeSection = $(SECTION_ACTIVE_SEL);
32522            var sectionIndex = activeSection.index(SECTION_SEL);
32523
32524            //isn't it the first section?
32525            if(sectionIndex){
32526                //adjusting the position for the current section
32527                silentMoveTo(sectionIndex + 1);
32528            }
32529
32530            isResizing = false;
32531            // Uncode change
32532            // $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container);
32533            $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container, getTableHeight());
32534            $.isFunction( options.afterReBuild ) && !resizing && options.afterReBuild.call(container);
32535        }
32536
32537        /**
32538        * Turns fullPage.js to normal scrolling mode when the viewport `width` or `height`
32539        * are smaller than the set limit values.
32540        */
32541        function setResponsive(active){
32542            var isResponsive = $body.hasClass(RESPONSIVE);
32543
32544            if(active){
32545                if(!isResponsive){
32546                    setAutoScrolling(false, 'internal');
32547                    setFitToSection(false, 'internal');
32548                    $(SECTION_NAV_SEL).hide();
32549                    $body.addClass(RESPONSIVE);
32550                    $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active);
32551                }
32552            }
32553            else if(isResponsive){
32554                setAutoScrolling(originals.autoScrolling, 'internal');
32555                setFitToSection(originals.autoScrolling, 'internal');
32556                $(SECTION_NAV_SEL).show();
32557                $body.removeClass(RESPONSIVE);
32558                $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active);
32559            }
32560        }
32561
32562        if($(this).length){
32563            //public functions
32564            FP.setAutoScrolling = setAutoScrolling;
32565            FP.setRecordHistory = setRecordHistory;
32566            FP.setScrollingSpeed = setScrollingSpeed;
32567            FP.setFitToSection = setFitToSection;
32568            FP.setLockAnchors = setLockAnchors;
32569            FP.setMouseWheelScrolling = setMouseWheelScrolling;
32570            FP.setAllowScrolling = setAllowScrolling;
32571            FP.setKeyboardScrolling = setKeyboardScrolling;
32572            FP.moveSectionUp = moveSectionUp;
32573            FP.moveSectionDown = moveSectionDown;
32574            FP.silentMoveTo = silentMoveTo;
32575            FP.moveTo = moveTo;
32576            FP.moveSlideRight = moveSlideRight;
32577            FP.moveSlideLeft = moveSlideLeft;
32578            FP.fitToSection = fitToSection;
32579            FP.reBuild = reBuild;
32580            FP.setResponsive = setResponsive;
32581            FP.destroy = destroy;
32582
32583            init();
32584
32585            bindEvents();
32586        }
32587
32588        function init(){
32589            //if css3 is not supported, it will use jQuery animations
32590            if(options.css3){
32591                options.css3 = support3d();
32592            }
32593
32594            options.scrollBar = options.scrollBar || options.hybrid;
32595
32596            setOptionsFromDOM();
32597            prepareDom();
32598            setAllowScrolling(true);
32599            setAutoScrolling(options.autoScrolling, 'internal');
32600            responsive();
32601
32602            //setting the class for the body element
32603            setBodyClass();
32604
32605            //Uncode addition
32606            // if(document.readyState === 'complete'){
32607            //     scrollToAnchor();
32608            // }
32609            // $window.on('load', scrollToAnchor);
32610        }
32611
32612        function bindEvents(){
32613            $window
32614                //when scrolling...
32615                //.on('scroll', scrollHandler)
32616
32617                //detecting any change on the URL to scroll to the given anchor link
32618                //(a way to detect back history button as we play with the hashes on the URL)
32619                .on('hashchange', hashChangeHandler)
32620
32621                //when opening a new tab (ctrl + t), `control` won't be pressed when coming back.
32622                .blur(blurHandler)
32623
32624                //when resizing the site, we adjust the heights of the sections, slimScroll...
32625                .resize(resizeHandler);
32626
32627            $document
32628                //Sliding with arrow keys, both, vertical and horizontal
32629                .keydown(keydownHandler)
32630
32631                //to prevent scrolling while zooming
32632                .keyup(keyUpHandler)
32633
32634                //Scrolls to the section when clicking the navigation bullet
32635                .on('click touchstart', SECTION_NAV_SEL + ' a', sectionBulletHandler)
32636
32637                //Scrolls the slider to the given slide destination for the given section
32638                .on('click touchstart', SLIDES_NAV_LINK_SEL, slideBulletHandler)
32639
32640                .on('click', SECTION_NAV_TOOLTIP_SEL, tooltipTextHandler);
32641
32642            //Scrolling horizontally when clicking on the slider controls.
32643            $(SECTION_SEL).on('click touchstart', SLIDES_ARROW_SEL, slideArrowHandler);
32644
32645            /**
32646            * Applying normalScroll elements.
32647            * Ignoring the scrolls over the specified selectors.
32648            */
32649            if(options.normalScrollElements){
32650                $document.on('mouseenter', options.normalScrollElements, function () {
32651                    setMouseWheelScrolling(false);
32652                });
32653
32654                $document.on('mouseleave', options.normalScrollElements, function(){
32655                    setMouseWheelScrolling(true);
32656                });
32657            }
32658        }
32659
32660        /**
32661        * Setting options from DOM elements if they are not provided.
32662        */
32663        function setOptionsFromDOM(){
32664            var sections = container.find(options.sectionSelector);
32665
32666            //no anchors option? Checking for them in the DOM attributes
32667            if(!options.anchors.length){
32668                options.anchors = sections.filter('[data-anchor]').map(function(){
32669                    return $(this).data('anchor').toString();
32670                }).get();
32671            }
32672
32673            //no tooltips option? Checking for them in the DOM attributes
32674            if(!options.navigationTooltips.length){
32675                options.navigationTooltips = sections.filter('[data-tooltip]').map(function(){
32676                    return $(this).data('tooltip').toString();
32677                }).get();
32678            }
32679        }
32680
32681        /**
32682        * Works over the DOM structure to set it up for the current fullpage options.
32683        */
32684        function prepareDom(){
32685            container.css({
32686                'height': '100%',
32687                'position': 'relative'
32688            });
32689
32690            //adding a class to recognize the container internally in the code
32691            container.addClass(WRAPPER);
32692            $('html').addClass(ENABLED);
32693
32694            windowsHeight = $window.height();
32695
32696            container.removeClass(DESTROYED); //in case it was destroyed before initializing it again
32697
32698            addInternalSelectors();
32699
32700             //styling the sections / slides / menu
32701            $(SECTION_SEL).each(function(index){
32702                var section = $(this);
32703                var slides = section.find(SLIDE_SEL);
32704                var numSlides = slides.length;
32705
32706                styleSection(section, index);
32707                styleMenu(section, index);
32708
32709                // if there's any slide
32710                if (numSlides > 0) {
32711                    styleSlides(section, slides, numSlides);
32712                }else{
32713                    if(options.verticalCentered){
32714                        addTableClass(section);
32715                    }
32716                }
32717            });
32718
32719            //fixed elements need to be moved out of the plugin container due to problems with CSS3.
32720            if(options.fixedElements && options.css3){
32721                $(options.fixedElements).appendTo($body);
32722            }
32723
32724            //vertical centered of the navigation + active bullet
32725            if(options.navigation){
32726                addVerticalNavigation();
32727            }
32728
32729            enableYoutubeAPI();
32730
32731            if(options.scrollOverflow){
32732                if(document.readyState === 'complete'){
32733                    createScrollBarHandler();
32734                }
32735                //after DOM and images are loaded
32736                $window.on('load', createScrollBarHandler);
32737            }else{
32738                afterRenderActions();
32739            }
32740        }
32741
32742        /**
32743        * Styles the horizontal slides for a section.
32744        */
32745        function styleSlides(section, slides, numSlides){
32746            var sliderWidth = numSlides * 100;
32747            var slideWidth = 100 / numSlides;
32748
32749            slides.wrapAll('<div class="' + SLIDES_CONTAINER + '" />');
32750            slides.parent().wrap('<div class="' + SLIDES_WRAPPER + '" />');
32751
32752            section.find(SLIDES_CONTAINER_SEL).css('width', sliderWidth + '%');
32753
32754            if(numSlides > 1){
32755                if(options.controlArrows){
32756                    createSlideArrows(section);
32757                }
32758
32759                if(options.slidesNavigation){
32760                    addSlidesNavigation(section, numSlides);
32761                }
32762            }
32763
32764            slides.each(function(index) {
32765                $(this).css('width', slideWidth + '%');
32766
32767                if(options.verticalCentered){
32768                    addTableClass($(this));
32769                }
32770            });
32771
32772            var startingSlide = section.find(SLIDE_ACTIVE_SEL);
32773
32774            //if the slide won't be an starting point, the default will be the first one
32775            //the active section isn't the first one? Is not the first slide of the first section? Then we load that section/sl
32775ide by default.
32776            if( startingSlide.length &&  ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) !== 0 || ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) === 0 && startingSlide.index() !== 0))){
32777                silentLandscapeScroll(startingSlide, 'internal');
32778            }else{
32779                slides.eq(0).addClass(ACTIVE);
32780            }
32781        }
32782
32783        /**
32784        * Styling vertical sections
32785        */
32786        function styleSection(section, index){
32787            //if no active section is defined, the 1st one will be the default one
32788            if(!index && $(SECTION_ACTIVE_SEL).length === 0) {
32789                section.addClass(ACTIVE);
32790            }
32791            startingSection = $(SECTION_ACTIVE_SEL);
32792
32793            section.css('height', windowsHeight + 'px');
32794
32795            if(options.paddingTop){
32796                section.css('padding-top', options.paddingTop);
32797            }
32798
32799            if(options.paddingBottom){
32800                section.css('padding-bottom', options.paddingBottom);
32801            }
32802
32803            if (typeof options.sectionsColor[index] !==  'undefined') {
32804                section.css('background-color', options.sectionsColor[index]);
32805            }
32806
32807            if (typeof options.anchors[index] !== 'undefined') {
32808                section.attr('data-anchor', options.anchors[index]);
32809            }
32810        }
32811
32812        /**
32813        * Sets the data-anchor attributes to the menu elements and activates the current one.
32814        */
32815        function styleMenu(section, index){
32816            if (typeof options.anchors[index] !== 'undefined') {
32817                //activating the menu / nav element on load
32818                if(section.hasClass(ACTIVE)){
32819                    activateMenuAndNav(options.anchors[index], index);
32820                }
32821            }
32822
32823            //moving the menu outside the main container if it is inside (avoid problems with fixed positions when using CSS3 tranforms)
32824            if(options.menu && options.css3 && $(options.menu).closest(WRAPPER_SEL).length){
32825                $(options.menu).appendTo($body);
32826            }
32827        }
32828
32829        /**
32830        * Adds internal classes to be able to provide customizable selectors
32831        * keeping the link with the style sheet.
32832        */
32833        function addInternalSelectors(){
32834            container.find(options.sectionSelector).addClass(SECTION);
32835            container.find(options.slideSelector).addClass(SLIDE);
32836        }
32837
32838        /**
32839        * Creates the control arrows for the given section
32840        */
32841        function createSlideArrows(section){
32842            section.find(SLIDES_WRAPPER_SEL).after('<div class="' + SLIDES_ARROW_PREV + '"></div><div class="' + SLIDES_ARROW_NEXT + '"></div>');
32843
32844            if(options.controlArrowColor!='#fff'){
32845                section.find(SLIDES_ARROW_NEXT_SEL).css('border-color', 'transparent transparent transparent '+options.controlArrowColor);
32846                section.find(SLIDES_ARROW_PREV_SEL).css('border-color', 'transparent '+ options.controlArrowColor + ' transparent transparent');
32847            }
32848
32849            if(!options.loopHorizontal){
32850                section.find(SLIDES_ARROW_PREV_SEL).hide();
32851            }
32852        }
32853
32854        /**
32855        * Creates a vertical navigation bar.
32856        */
32857        function addVerticalNavigation(){
32858            $body.append('<div id="' + SECTION_NAV + '"><ul></ul></div>');
32859            var nav = $(SECTION_NAV_SEL);
32860
32861            nav.addClass(function() {
32862                return options.showActiveTooltip ? SHOW_ACTIVE_TOOLTIP + ' ' + options.navigationPosition : options.navigationPosition;
32863            });
32864
32865            for (var i = 0; i < $(SECTION_SEL).length; i++) {
32866                var link = '';
32867                if (options.anchors.length) {
32868                    link = options.anchors[i];
32869                }
32870
32871                var li = '<li><a href="#' + link + '"><span></span></a>';
32872
32873                // Only add tooltip if needed (defined by user)
32874                var tooltip = options.navigationTooltips[i];
32875
32876                if (typeof tooltip !== 'undefined' && tooltip !== '') {
32877                    li += '<div class="' + SECTION_NAV_TOOLTIP + ' ' + options.navigationPosition + '">' + tooltip + '</div>';
32878                }
32879
32880                li += '</li>';
32881
32882                nav.find('ul').append(li);
32883            }
32884
32885            //centering it vertically
32886            $(SECTION_NAV_SEL).css('margin-top', '-' + ($(SECTION_NAV_SEL).height()/2) + 'px');
32887
32888            //activating the current active section
32889            $(SECTION_NAV_SEL).find('li').eq($(SECTION_ACTIVE_SEL).index(SECTION_SEL)).find('a').addClass(ACTIVE);
32890        }
32891
32892        /**
32893        * Creates the slim scroll scrollbar for the sections and slides inside them.
32894        */
32895        function createScrollBarHandler(){
32896            $(SECTION_SEL).each(function(){
32897                var slides = $(this).find(SLIDE_SEL);
32898
32899                if(slides.length){
32900                    slides.each(function(){
32901                        createScrollBar($(this));
32902                    });
32903                }else{
32904                    createScrollBar($(this));
32905                }
32906
32907            });
32908            afterRenderActions();
32909        }
32910
32911        /*
32912        * Enables the Youtube videos API so we can control their flow if necessary.
32913        */
32914        function enableYoutubeAPI(){
32915            container.find('iframe[src*="youtube.com/embed/"]').each(function(){
32916                addURLParam($(this), 'enablejsapi=1');
32917            });
32918        }
32919
32920        /**
32921        * Adds a new parameter and its value to the `src` of a given element
32922        */
32923        function addURLParam(element, newParam){
32924            var originalSrc = element.attr('src');
32925            element.attr('src', originalSrc + getUrlParamSign(originalSrc) + newParam);
32926        }
32927
32928        /*
32929        * Returns the prefix sign to use for a new parameter in an existen URL.
32930        *
32931        * @return {String}  ? | &
32932        */
32933        function getUrlParamSign(url){
32934            return ( !/\?/.test( url ) ) ? '?' : '&';
32935        }
32936
32937        /**
32938        * Actions and callbacks to fire afterRender
32939        */
32940        function afterRenderActions(){
32941            var section = $(SECTION_ACTIVE_SEL);
32942
32943            section.addClass(COMPLETELY);
32944
32945            if(options.scrollOverflowHandler.afterRender){
32946                options.scrollOverflowHandler.afterRender(section);
32947            }
32948            lazyLoad(section);
32949            playMedia(section);
32950            options.scrollOverflowHandler.afterLoad();
32951
32952            if(isDestinyTheStartingSection()){
32953                $.isFunction( options.afterLoad ) && options.afterLoad.call(section, section.data('anchor'), (section.index(SECTION_SEL) + 1));
32954            }
32955
32956            // Uncode change
32957            // $.isFunction( options.afterRender ) && options.afterRender.call(container);
32958            $.isFunction( options.afterRender ) && options.afterRender.call(container, getTableHeight());
32959        }
32960
32961        /**
32962        * Determines if the URL anchor destiny is the starting section (the one using 'active' class before initialization)
32963        */
32964        function isDestinyTheStartingSection(){
32965            var anchors =  window.location.hash.replace('#', '').split('/');
32966            var destinationSection = getSectionByAnchor(decodeURIComponent(anchors[0]));
32967
32968            return !destinationSection.length || destinationSection.length && destinationSection.index() === startingSection.index();
32969        }
32970
32971
32972        var isScrolling = false;
32973        var lastScroll = 0;
32974
32975        //when scrolling...
32976        function scrollHandler(){
32977            var currentSection;
32978
32979            if(!options.autoScrolling || options.scrollBar){
32980                var currentScroll = $window.scrollTop();
32981                var scrollDirection = getScrollDirection(currentScroll);
32982                var visibleSectionIndex = 0;
32983                var screen_mid = currentScroll + ($window.height() / 2.0);
32984                var isAtBottom = $body.height() - $window.height() === currentScroll;
32985                var sections =  document.querySelectorAll(SECTION_SEL);
32986
32987                //when using `auto-height` for a small last section it won't be centered in the viewport
32988                if(isAtBottom){
32989                    visibleSectionIndex = sections.length - 1;
32990                }
32991                //is at top? when using `auto-height` for a small first section it won't be centered in the viewport
32992                else if(!currentScroll){
32993                    visibleSectionIndex = 0;
32994                }
32995
32996                //taking the section which is showing more content in the viewport
32997                else{
32998                    for (var i = 0; i < sections.length; ++i) {
32999                        var section = sections[i];
33000
33001                        // Pick the the last section which passes the middle line of the screen.
33002                        if (section.offsetTop <= screen_mid)
33003                        {
33004                            visibleSectionIndex = i;
33005                        }
33006                    }
33007                }
33008
33009                if(isCompletelyInViewPort(scrollDirection)){
33010                    if(!$(SECTION_ACTIVE_SEL).hasClass(COMPLETELY)){
33011                        $(SECTION_ACTIVE_SEL).addClass(COMPLETELY).siblings().removeClass(COMPLETELY);
33012                    }
33013                }
33014
33015                //geting the last one, the current one on the screen
33016                currentSection = $(sections).eq(visibleSectionIndex);
33017
33018                //setting the visible section as active when manually scrolling
33019                //executing only once the first time we reach the section
33020                if(!currentSection.hasClass(ACTIVE)){
33021                    isScrolling = true;
33022                    var leavingSection = $(SECTION_ACTIVE_SEL);
33023                    var leavingSectionIndex = leavingSection.index(SECTION_SEL) + 1;
33024                    var yMovement = getYmovement(currentSection);
33025                    var anchorLink  = currentSection.data('anchor');
33026                    var sectionIndex = currentSection.index(SECTION_SEL) + 1;
33027                    var activeSlide = currentSection.find(SLIDE_ACTIVE_SEL);
33028                    var slideIndex;
33029                    var slideAnchorLink;
33030
33031                    if(activeSlide.length){
33032                        slideAnchorLink = activeSlide.data('anchor');
33033                        slideIndex = activeSlide.index();
33034                    }
33035
33036                    if(canScroll){
33037                        currentSection.addClass(ACTIVE).siblings().removeClass(ACTIVE);
33038
33039                        $.isFunction( options.onLeave ) && options.onLeave.call( leavingSection, leavingSectionIndex, sectionIndex, yMovement);
33040                        $.isFunction( options.afterLoad ) && options.afterLoad.call( currentSection, anchorLink, sectionIndex);
33041
33042                        stopMedia(leavingSection);
33043                        lazyLoad(currentSection);
33044                        playMedia(currentSection);
33045
33046                        activateMenuAndNav(anchorLink, sectionIndex - 1);
33047
33048                        if(options.anchors.length){
33049                            //needed to enter in hashChange event when using the menu with anchor links
33050                            lastScrolledDestiny = anchorLink;
33051                        }
33052                        setState(slideIndex, slideAnchorLink, anchorLink, sectionIndex);
33053                    }
33054
33055                    //small timeout in order to avoid entering in hashChange event when scrolling is not finished yet
33056                    clearTimeout(scrollId);
33057                    scrollId = setTimeout(function(){
33058                        isScrolling = false;
33059                    }, 100);
33060                }
33061
33062                if(options.fitToSection){
33063                    //for the auto adjust of the viewport to fit a whole section
33064                    clearTimeout(scrollId2);
33065
33066                    scrollId2 = setTimeout(function(){
33067                        //checking it again in case it changed during the delay
33068                        if(options.fitToSection){
33069                            fitToSection();
33070                        }
33071                    }, options.fitToSectionDelay);
33072                }
33073            }
33074        }
33075
33076        /**
33077        * Fits the site to the nearest active section
33078        */
33079        function fitToSection(){
33080            //checking fitToSection again in case it was set to false before the timeout delay
33081            if(canScroll){
33082                //allows to scroll to an active section and
33083                //if the section is already active, we prevent firing callbacks
33084                isResizing = true;
33085
33086                scrollPage($(SECTION_ACTIVE_SEL));
33087                isResizing = false;
33088            }
33089        }
33090
33091        /**
33092        * Determines whether the active section has seen in its whole or not.
33093        */
33094        function isCompletelyInViewPort(movement){
33095            var top = $(SECTION_ACTIVE_SEL).position().top;
33096            var bottom = top + $window.height();
33097
33098            if(movement == 'up'){
33099                return bottom >= ($window.scrollTop() + $window.height());
33100            }
33101            return top <= $window.scrollTop();
33102        }
33103
33104        /**
33105        * Gets the directon of the the scrolling fired by the scroll event.
33106        */
33107        function getScrollDirection(currentScroll){
33108            var direction = currentScroll > lastScroll ? 'down' : 'up';
33109
33110            lastScroll = currentScroll;
33111
33112            //needed for auto-height sections to determine if we want to scroll to the top or bottom of the destination
33113            previousDestTop = currentScroll;
33114
33115            return direction;
33116        }
33117
33118        /**
33119        * Determines the way of scrolling up or down:
33120        * by 'automatically' scrolling a section or by using the default and normal scrolling.
33121        */
33122        function scrolling(type, scrollable){
33123            if (!isScrollAllowed.m[type]){
33124                return;
33125            }
33126            var check = (type === 'down') ? 'bottom' : 'top';
33127            var scrollSection = (type === 'down') ? moveSectionDown : moveSectionUp;
33128
33129            if(scrollable.length > 0 ){
33130                //is the scrollbar at the start/end of the scroll?
33131                if(options.scrollOverflowHandler.isScrolled(check, scrollable)){
33132                    scrollSection();
33133                }else{
33134                    return true;
33135                }
33136            }else{
33137                // moved up/down
33138                scrollSection();
33139            }
33140        }
33141
33142        /*
33143        * Preventing bouncing in iOS #2285
33144        */
33145        function preventBouncing(event){
33146            var e = event.originalEvent;
33147            if(!checkParentForNormalScrollElement(event.target) && options.autoScrolling && isReallyTouch(e) && isScrollAllowed.m.up){
33148                //preventing the easing on iOS devices
33149                event.preventDefault();
33150            }
33151        }
33152
33153        var touchStartY = 0;
33154        var touchStartX = 0;
33155        var touchEndY = 0;
33156        var touchEndX = 0;
33157
33158        /* Detecting touch events
33159
33160        * As we are changing the top property of the page on scrolling, we can not use the traditional way to detect it.
33161        * This way, the touchstart and the touch moves shows an small difference between them which is the
33162        * used one to determine the direction.
33163        */
33164        function touchMoveHandler(event){
33165            var e = event.originalEvent;
33166            var activeSection = $(e.target).closest(SECTION_SEL);
33167
33168            // additional: if one of the normalScrollElements isn't within options.normalScrollElementTouchThreshold hops up the DOM chain
33169            if (!checkParentForNormalScrollElement(event.target) && isReallyTouch(e) ) {
33170
33171                if(options.autoScrolling){
33172                    //preventing the easing on iOS devices
33173                    event.preventDefault();
33174                }
33175
33176                var scrollable = options.scrollOverflowHandler.scrollable(activeSection);
33177                var touchEvents = getEventsPage(e);
33178
33179                touchEndY = touchEvents.y;
33180                touchEndX = touchEvents.x;
33181
33182                //if movement in the X axys is greater than in the Y and the currect section has slides...
33183                if (activeSection.find(SLIDES_WRAPPER_SEL).length && Math.abs(touchStartX - touchEndX) > (Math.abs(touchStartY - touchEndY))) {
33184
33185                    //is the movement greater than the minimum resistance to scroll?
33186                    if (!slideMoving && Math.abs(touchStartX - touchEndX) > ($window.outerWidth() / 100 * options.touchSensitivity)) {
33187                        if (touchStartX > touchEndX) {
33188                            if(isScrollAllowed.m.right){
33189                                moveSlideRight(activeSection); //next
33190                            }
33191                        } else {
33192                            if(isScrollAllowed.m.left){
33193                                moveSlideLeft(activeSection); //prev
33194                            }
33195                        }
33196                    }
33197                }
33198
33199                //vertical scrolling (only when autoScrolling is enabled)
33200                else if(options.autoScrolling && canScroll){
33201
33202                    //is the movement greater than the minimum resistance to scroll?
33203                    if (Math.abs(touchStartY - touchEndY) > ($window.height() / 100 * options.touchSensitivity)) {
33204                        if (touchStartY > touchEndY) {
33205                            scrolling('down', scrollable);
33206                        } else if (touchEndY > touchStartY) {
33207                            scrolling('up', scrollable);
33208                        }
33209                    }
33210                }
33211            }
33212        }
33213
33214        /**
33215         * recursive function to loop up the parent nodes to check if one of them exists in options.normalScrollElements
33216         * Currently works well for iOS - Android might need some testing
33217         * @param  {Element} el  target element / jquery selector (in subsequent nodes)
33218         * @param  {int}     hop current hop compared to options.normalScrollElementTouchThreshold
33219         * @return {boolean} true if there is a match to options.normalScrollElements
33220         */
33221        function checkParentForNormalScrollElement (el, hop) {
33222            hop = hop || 0;
33223            var parent = $(el).parent();
33224
33225            if (hop < options.normalScrollElementTouchThreshold &&
33226                parent.is(options.normalScrollElements) ) {
33227                return true;
33228            } else if (hop == options.normalScrollElementTouchThreshold) {
33229                return false;
33230            } else {
33231                return checkParentForNormalScrollElement(parent, ++hop);
33232            }
33233        }
33234
33235        /**
33236        * As IE >= 10 fires both touch and mouse events when using a mouse in a touchscreen
33237        * this way we make sure that is really a touch event what IE is detecting.
33238        */
33239        function isReallyTouch(e){
33240            //if is not IE   ||  IE is detecting `touch` or `pen`
33241            return typeof e.pointerType === 'undefined' || e.pointerType != 'mouse';
33242        }
33243
33244        /**
33245        * Handler for the touch start event.
33246        */
33247        function touchStartHandler(event){
33248            var e = event.originalEvent;
33249
33250            //stopping the auto scroll to adjust to a section
33251            if(options.fitToSection){
33252                $htmlBody.stop();
33253            }
33254
33255            if(isReallyTouch(e)){
33256                var touchEvents = getEventsPage(e);
33257                touchStartY = touchEvents.y;
33258                touchStartX = touchEvents.x;
33259            }
33260        }
33261
33262        /**
33263        * Gets the average of the last `number` elements of the given array.
33264        */
33265        function getAverage(elements, number){
33266            var sum = 0;
33267
33268            //taking `number` elements from the end to make the average, if there are not enought, 1
33269            var lastElements = elements.slice(Math.max(elements.length - number, 1));
33270
33271            for(var i = 0; i < lastElements.length; i++){
33272                sum = sum + lastElements[i];
33273            }
33274
33275            return Math.ceil(sum/number);
33276        }
33277
33278        /**
33279         * Detecting mousewheel scrolling
33280         *
33281         * http://blogs.sitepointstatic.com/examples/tech/mouse-wheel/index.html
33282         * http://www.sitepoint.com/html5-javascript-mouse-wheel/
33283         */
33284        var prevTime = new Date().getTime();
33285
33286        function MouseWheelHandler(e) {
33287            var curTime = new Date().getTime();
33288            var isNormalScroll = $(COMPLETELY_SEL).hasClass(NORMAL_SCROLL);
33289
33290            //autoscrolling and not zooming?
33291            if(options.autoScrolling && !controlPressed && !isNormalScroll){
33292                // cross-browser wheel delta
33293                e = e || window.event;
33294                var value = e.wheelDelta || -e.deltaY || -e.detail;
33295                var delta = Math.max(-1, Math.min(1, value));
33296
33297                var horizontalDetection = typeof e.wheelDeltaX !== 'undefined' || typeof e.deltaX !== 'undefined';
33298                var isScrollingVertically = (Math.abs(e.wheelDeltaX) < Math.abs(e.wheelDelta)) || (Math.abs(e.deltaX ) < Math.abs(e.deltaY) || !horizontalDetection);
33299
33300                //Limiting the array to 150 (lets not waste memory!)
33301                if(scrollings.length > 149){
33302                    scrollings.shift();
33303                }
33304
33305                //keeping record of the previous scrollings
33306                scrollings.push(Math.abs(value));
33307
33308                //preventing to scroll the site on mouse wheel when scrollbar is present
33309                if(options.scrollBar){
33310                    e.preventDefault ? e.preventDefault() : e.returnValue = false;
33311                }
33312
33313                var activeSection = $(SECTION_ACTIVE_SEL);
33314                var scrollable = options.scrollOverflowHandler.scrollable(activeSection);
33315
33316                //time difference between the last scroll and the current one
33317                var timeDiff = curTime-prevTime;
33318                prevTime = curTime;
33319
33320                //haven't they scrolled in a while?
33321                //(enough to be consider a different scrolling action to scroll another section)
33322                if(timeDiff > 200){
33323                    //emptying the array, we dont care about old scrollings for our averages
33324                    scrollings = [];
33325                }
33326
33327                if(canScroll){
33328                    var averageEnd = getAverage(scrollings, 10);
33329                    var averageMiddle = getAverage(scrollings, 70);
33330                    var isAccelerating = averageEnd >= averageMiddle;
33331
33332                    //to avoid double swipes...
33333                    if(isAccelerating && isScrollingVertically){
33334                        //scrolling down?
33335                        if (delta < 0) {
33336                            scrolling('down', scrollable);
33337
33338                        //scrolling up?
33339                        }else {
33340                            scrolling('up', scrollable);
33341                        }
33342                    }
33343                }
33344
33345                return false;
33346            }
33347
33348            if(options.fitToSection){
33349                //stopping the auto scroll to adjust to a section
33350                $htmlBody.stop();
33351            }
33352        }
33353
33354        /**
33355        * Slides a slider to the given direction.
33356        * Optional `section` param.
33357        */
33358        function moveSlide(direction, section){
33359            var activeSection = typeof section === 'undefined' ? $(SECTION_ACTIVE_SEL) : section;
33360            var slides = activeSection.find(SLIDES_WRAPPER_SEL);
33361            var numSlides = slides.find(SLIDE_SEL).length;
33362
33363            // more than one slide needed and nothing should be sliding
33364            if (!slides.length || slideMoving || numSlides < 2) {
33365                return;
33366            }
33367
33368            var currentSlide = slides.find(SLIDE_ACTIVE_SEL);
33369            var destiny = null;
33370
33371            if(direction === 'left'){
33372                destiny = currentSlide.prev(SLIDE_SEL);
33373            }else{
33374                destiny = currentSlide.next(SLIDE_SEL);
33375            }
33376
33377            //isn't there a next slide in the secuence?
33378            if(!destiny.length){
33379                //respect loopHorizontal settin
33380                if (!options.loopHorizontal) return;
33381
33382                if(direction === 'left'){
33383                    destiny = currentSlide.siblings(':last');
33384                }else{
33385                    destiny = currentSlide.siblings(':first');
33386                }
33387            }
33388
33389            slideMoving = true;
33390
33391            landscapeScroll(slides, destiny, direction);
33392        }
33393
33394        /**
33395        * Maintains the active slides in the viewport
33396        * (Because the `scroll` animation might get lost with some actions, such as when using continuousVertical)
33397        */
33398        function keepSlidesPosition(){
33399            $(SLIDE_ACTIVE_SEL).each(function(){
33400                silentLandscapeScroll($(this), 'internal');
33401            });
33402        }
33403
33404        var previousDestTop = 0;
33405        /**
33406        * Returns the destination Y position based on the scrolling direction and
33407        * the height of the section.
33408        */
33409        function getDestinationPosition(element){
33410            var elemPosition = element.position();
33411
33412            //top of the desination will be at the top of the viewport
33413            var position = elemPosition.top;
33414            var isScrollingDown =  elemPosition.top > previousDestTop;
33415            var sectionBottom = position - windowsHeight + element.outerHeight();
33416            var bigSectionsDestination = options.bigSectionsDestination;
33417
33418            //Uncode addition
33419            var containerH = container.outerHeight();
33420            var containerPosition = container.offset();
33421
33422            //########### Commented by Uncode - START ###########
33423            //is the destination element bigger than the viewport?
33424            // if(element.outerHeight() > windowsHeight){
33425            //     //scrolling up?
33426            //     if(!isScrollingDown && !bigSectionsDestination || bigSectionsDestination === 'bottom' ){
33427            //         position = sectionBottom;
33428            //     }
33429            // }
33430
33431            // //sections equal or smaller than the viewport height && scrolling down? ||  is resizing and its in the last section
33432            // else if(isScrollingDown || (isResizing && element.is(':last-child')) ){
33433            //     //The bottom of the destination will be at the bottom of the viewport
33434            //     position = sectionBottom;
33435            // }
33436            //########### Commented by Uncode - END ###########
33437
33438            //Uncode addition
33439            if ( !$masthead.hasClass('menu-transparent') && $('body').hasClass('uncode-fp-menu-shrink') && !element.is(':first-child') )
33440                position += 18;
33441            if ( ( containerH + menuHeight + bodyBorder + adminBarHeight - windowsHeight ) < position || ( isResizing && element.is(':last-child') ) ) {
33442                position = sectionBottom + menuHeight + bodyBorder*2 + adminBarHeight;
33443            }
33444
33445            /*
33446            Keeping record of the last scrolled position to determine the scrolling direction.
33447            No conventional methods can be used as the scroll bar might not be present
33448            AND the section might not be active if it is auto-height and didnt reach the middle
33449            of the viewport.
33450            */
33451            previousDestTop = position;
33452            return position;
33453        }
33454
33455        /**
33456        * Scrolls the site to the given element and scrolls to the slide if a callback is given.
33457        */
33458        function scrollPage(element, callback, isMovementUp){
33459            if(typeof element === 'undefined'){ return; } //there's no element to scroll, leaving the function
33460
33461            var dtop = getDestinationPosition(element);
33462            var slideAnchorLink;
33463            var slideIndex;
33464
33465            //local variables
33466            var v = {
33467                element: element,
33468                callback: callback,
33469                isMovementUp: isMovementUp,
33470                dtop: dtop,
33471                yMovement: getYmovement(element),
33472                anchorLink: element.data('anchor'),
33473                sectionIndex: element.index(SECTION_SEL),
33474                activeSlide: element.find(SLIDE_ACTIVE_SEL),
33475                activeSection: $(SECTION_ACTIVE_SEL),
33476                leavingSection: $(SECTION_ACTIVE_SEL).index(SECTION_SEL) + 1,
33477
33478                //caching the value of isResizing at the momment the function is called
33479                //because it will be checked later inside a setTimeout and the value might change
33480                localIsResizing: isResizing
33481            };
33482
33483            //quiting when destination scroll is the same as the current one
33484            if((v.activeSection.is(element) && !isResizing) || (options.scrollBar && $window.scrollTop() === v.dtop && !element.hasClass(AUTO_HEIGHT) )){ return; }
33485
33486            if(v.activeSlide.length){
33487                slideAnchorLink = v.activeSlide.data('anchor');
33488                slideIndex = v.activeSlide.index();
33489            }
33490
33491            // If continuousVertical && we need to wrap around
33492            if (options.autoScrolling && options.continuousVertical && typeof (v.isMovementUp) !== "undefined" &&
33493                ((!v.isMovementUp && v.yMovement == 'up') || // Intending to scroll down but about to go up or
33494                (v.isMovementUp && v.yMovement == 'down'))) { // intending to scroll up but about to go down
33495
33496                v = createInfiniteSections(v);
33497            }
33498
33499            //callback (onLeave) if the site is not just resizing and readjusting the slides
33500            if($.isFunction(options.onLeave) && !v.localIsResizing){
33501                if(options.onLeave.call(v.activeSection, v.leavingSection, (v.sectionIndex + 1), v.yMovement) === false){
33502                    return;
33503                }
33504            }
33505
33506            //pausing media of the leaving section (if we are not just resizing, as destinatino will be the same one)
33507            if(!v.localIsResizing){
33508                stopMedia(v.activeSection);
33509            }
33510
33511            options.scrollOverflowHandler.beforeLeave();
33512            element.addClass(ACTIVE).siblings().removeClass(ACTIVE);
33513            lazyLoad(element);
33514            options.scrollOverflowHandler.onLeave();
33515
33516
33517            //preventing from activating the MouseWheelHandler event
33518            //more than once if the page is scrolling
33519            canScroll = false;
33520
33521            setState(slideIndex, slideAnchorLink, v.anchorLink, v.sectionIndex);
33522
33523            performMovement(v);
33524
33525            //flag to avoid callingn `scrollPage()` twice in case of using anchor links
33526            lastScrolledDestiny = v.anchorLink;
33527
33528            //avoid firing it twice (as it does also on scroll)
33529            activateMenuAndNav(v.anchorLink, v.sectionIndex);
33530        }
33531
33532        /**
33533        * Performs the vertical movement (by CSS3 or by jQuery)
33534        */
33535        function performMovement(v){
33536            // using CSS3 translate functionality
33537            if (options.css3 && options.autoScrolling && !options.scrollBar) {
33538
33539                // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625
33540                // that's why we round it to 0.
33541                var translate3d = 'translate3d(0px, -' + Math.round(v.dtop) + 'px, 0px)';
33542                transformContainer(translate3d, true);
33543
33544                //even when the scrollingSpeed is 0 there's a little delay, which might cause the
33545                //scrollingSpeed to change in case of using silentMoveTo();
33546                if(options.scrollingSpeed){
33547                    clearTimeout(afterSectionLoadsId);
33548                    afterSectionLoadsId = setTimeout(function () {
33549                        afterSectionLoads(v);
33550                    }, options.scrollingSpeed);
33551                }else{
33552                    afterSectionLoads(v);
33553                }
33554            }
33555
33556            // using jQuery animate
33557            else{
33558                var scrollSettings = getScrollSettings(v);
33559
33560                $(scrollSettings.element).animate(
33561                    scrollSettings.options,
33562                options.scrollingSpeed, options.easing).promise().done(function () { //only one single callback in case of animating  `html, body`
33563                    if(options.scrollBar){
33564
33565                        /* Hack!
33566                        The timeout prevents setting the most dominant section in the viewport as "active" when the user
33567                        scrolled to a smaller section by using the mousewheel (auto scrolling) rather than draging the scroll bar.
33568
33569                        When using scrollBar:true It seems like the scroll events still getting propagated even after the scrolling animation has finished.
33570                        */
33571                        setTimeout(function(){
33572                            afterSectionLoads(v);
33573                        },30);
33574                    }else{
33575                        afterSectionLoads(v);
33576                    }
33577                });
33578            }
33579        }
33580
33581        /**
33582        * Gets the scrolling settings depending on the plugin autoScrolling option
33583        */
33584        function getScrollSettings(v){
33585            var scroll = {};
33586
33587            if(options.autoScrolling && !options.scrollBar){
33588                scroll.options = { 'top': -v.dtop};
33589                scroll.element = WRAPPER_SEL;
33590            }else{
33591                scroll.options = { 'scrollTop': v.dtop};
33592                scroll.element = 'html, body';
33593            }
33594
33595            return scroll;
33596        }
33597
33598        /**
33599        * Adds sections before or after the current one to create the infinite effect.
33600        */
33601        function createInfiniteSections(v){
33602            // Scrolling down
33603            if (!v.isMovementUp) {
33604                // Move all previous sections to after the active section
33605                $(SECTION_ACTIVE_SEL).after(v.activeSection.prevAll(SECTION_SEL).get().reverse());
33606            }
33607            else { // Scrolling up
33608                // Move all next sections to before the active section
33609                $(SECTION_ACTIVE_SEL).before(v.activeSection.nextAll(SECTION_SEL));
33610            }
33611
33612            // Maintain the displayed position (now that we changed the element order)
33613            silentScroll($(SECTION_ACTIVE_SEL).position().top);
33614
33615            // Maintain the active slides visible in the viewport
33616            keepSlidesPosition();
33617
33618            // save for later the elements that still need to be reordered
33619            v.wrapAroundElements = v.activeSection;
33620
33621            // Recalculate animation variables
33622            v.dtop = v.element.position().top;
33623            v.yMovement = getYmovement(v.element);
33624
33625            return v;
33626        }
33627
33628        /**
33629        * Fix section order after continuousVertical changes have been animated
33630        */
33631        function continuousVerticalFixSectionOrder (v) {
33632            // If continuousVertical is in effect (and autoScrolling would also be in effect then),
33633            // finish moving the elements around so the direct navigation will function more simply
33634            if (!v.wrapAroundElements || !v.wrapAroundElements.length) {
33635                return;
33636            }
33637
33638            if (v.isMovementUp) {
33639                $(SECTION_FIRST_SEL).before(v.wrapAroundElements);
33640            }
33641            else {
33642                $(SECTION_LAST_SEL).after(v.wrapAroundElements);
33643            }
33644
33645            silentScroll($(SECTION_ACTIVE_SEL).position().top);
33646
33647            // Maintain the active slides visible in the viewport
33648            keepSlidesPosition();
33649        }
33650
33651
33652        /**
33653        * Actions to do once the section is loaded.
33654        */
33655        function afterSectionLoads (v){
33656            continuousVerticalFixSectionOrder(v);
33657
33658            //callback (afterLoad) if the site is not just resizing and readjusting the slides
33659            $.isFunction(options.afterLoad) && !v.localIsResizing && options.afterLoad.call(v.element, v.anchorLink, (v.sectionIndex + 1));
33660            options.scrollOverflowHandler.afterLoad();
33661
33662            if(!v.localIsResizing){
33663                playMedia(v.element);
33664            }
33665
33666            v.element.addClass(COMPLETELY).siblings().removeClass(COMPLETELY);
33667
33668            canScroll = true;
33669
33670            $.isFunction(v.callback) && v.callback.call(this);
33671        }
33672
33673        /**
33674        * Sets the value for the given attribute from the `data-` attribute with the same suffix
33675        * ie: data-srcset ==> srcset  |  data-src ==> src
33676        */
33677        function setSrc(element, attribute){
33678            element
33679                .attr(attribute, element.data(attribute))
33680                .removeAttr('data-' + attribute);
33681        }
33682
33683        /**
33684        * Lazy loads image, video and audio elements.
33685        */
33686        function lazyLoad(destiny){
33687            if (!options.lazyLoading){
33688                return;
33689            }
33690
33691            var panel = getSlideOrSection(destiny);
33692            var element;
33693
33694            panel.find('img[data-src], img[data-srcset], source[data-src], audio[data-src], iframe[data-src]').each(function(){
33695                element = $(this);
33696
33697                $.each(['src', 'srcset'], function(index, type){
33698                    var attribute = element.attr('data-' + type);
33699                    if(typeof attribute !== 'undefined' && attribute){
33700                        setSrc(element, type);
33701                    }
33702                });
33703
33704                if(element.is('source')){
33705                    element.closest('video').get(0).load();
33706                }
33707            });
33708        }
33709
33710        /**
33711        * Plays video and audio elements.
33712        */
33713        function playMedia(destiny){
33714            var panel = getSlideOrSection(destiny);
33715
33716            //playing HTML5 media elements
33717            panel.find('video, audio').each(function(){
33718                var element = $(this).get(0);
33719
33720                if( element.hasAttribute('data-autoplay') && typeof element.play === 'function' ) {
33721                    element.play();
33722                }
33723            });
33724
33725            //youtube videos
33726            panel.find('iframe[src*="youtube.com/embed/"]').each(function(){
33727                var element = $(this).get(0);
33728
33729                if ( element.hasAttribute('data-autoplay') ){
33730                    playYoutube(element);
33731                }
33732
33733                //in case the URL was not loaded yet. On page load we need time for the new URL (with the API string) to load.
33734                element.onload = function() {
33735                    if ( element.hasAttribute('data-autoplay') ){
33736                        playYoutube(element);
33737                    }
33738                };
33739            });
33740        }
33741
33742        /**
33743        * Plays a youtube video
33744        */
33745        function playYoutube(element){
33746            element.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*');
33747        }
33748
33749        /**
33750        * Stops video and audio elements.
33751        */
33752        function stopMedia(destiny){
33753            var panel = getSlideOrSection(destiny);
33754
33755            //stopping HTML5 media elements
33756            panel.find('video, audio').each(function(){
33757                var element = $(this).get(0);
33758
33759                if( !element.hasAttribute('data-keepplaying') && typeof element.pause === 'function' ) {
33760                    element.pause();
33761                }
33762            });
33763
33764            //youtube videos
33765            panel.find('iframe[src*="youtube.com/embed/"]').each(function(){
33766                var element = $(this).get(0);
33767
33768                if( /youtube\.com\/embed\//.test($(this).attr('src')) && !element.hasAttribute('data-keepplaying')){
33769                    $(this).get(0).contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}','*');
33770                }
33771            });
33772        }
33773
33774        /**
33775        * Gets the active slide (or section) for the given section
33776        */
33777        function getSlideOrSection(destiny){
33778            var slide = destiny.find(SLIDE_ACTIVE_SEL);
33779            if( slide.length ) {
33780                destiny = $(slide);
33781            }
33782
33783            return destiny;
33784        }
33785
33786        /**
33787        * Scrolls to the anchor in the URL when loading the site
33788        */
33789        function scrollToAnchor(){
33790            //getting the anchor link in the URL and deleting the `#`
33791            var value =  window.location.hash.replace('#', '').split('/');
33792            var sectionAnchor = decodeURIComponent(value[0]);
33793            var slideAnchor = decodeURIComponent(value[1]);
33794
33795            if(sectionAnchor){  //if theres any #
33796                if(options.animateAnchor){
33797                    scrollPageAndSlide(sectionAnchor, slideAnchor);
33798                }else{
33799                    silentMoveTo(sectionAnchor, slideAnchor);
33800                }
33801            }
33802        }
33803
33804        /**
33805        * Detecting any change on the URL to scroll to the given anchor link
33806        * (a way to detect back history button as we play with the hashes on the URL)
33807        */
33808        function hashChangeHandler(){
33809            if(!isScrolling && !options.lockAnchors){
33810                var value =  window.location.hash.replace('#', '').split('/');
33811                var sectionAnchor = decodeURIComponent(value[0]);
33812                var slideAnchor = decodeURIComponent(value[1]);
33813
33814                    //when moving to a slide in the first section for the first time (first time to add an anchor to the URL)
33815                    var isFirstSlideMove =  (typeof lastScrolledDestiny === 'undefined');
33816                    var isFirstScrollMove = (typeof lastScrolledDestiny === 'undefined' && typeof slideAnchor === 'undefined' && !slideMoving);
33817
33818
33819                if(sectionAnchor.length){
33820                    /*in order to call scrollpage() only once for each destination at a time
33821                    It is called twice for each scroll otherwise, as in case of using anchorlinks `hashChange`
33822                    event is fired on every scroll too.*/
33823                    if ((sectionAnchor && sectionAnchor !== lastScrolledDestiny) && !isFirstSlideMove || isFirstScrollMove || (!slideMoving && lastScrolledSlide != slideAnchor ))  {
33824                        scrollPageAndSlide(sectionAnchor, slideAnchor);
33825                    }
33826                }
33827            }
33828        }
33829
33830        //Sliding with arrow keys, both, vertical and horizontal
33831        function keydownHandler(e) {
33832
33833            clearTimeout(keydownId);
33834
33835            var activeElement = $(':focus');
33836
33837            if(!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select') &&
33838                activeElement.attr('contentEditable') !== "true" && activeElement.attr('contentEditable') !== '' &&
33839                options.keyboardScrolling && options.autoScrolling){
33840                var keyCode = e.which;
33841
33842                //preventing the scroll with arrow keys & spacebar & Page Up & Down keys
33843                var keyControls = [40, 38, 32, 33, 34];
33844                if($.inArray(keyCode, keyControls) > -1){
33845                    e.preventDefault();
33846                }
33847
33848                controlPressed = e.ctrlKey;
33849
33850                keydownId = setTimeout(function(){
33851                    onkeydown(e);
33852                },150);
33853            }
33854        }
33855
33856        function tooltipTextHandler(){
33857            $(this).prev().trigger('click');
33858        }
33859
33860        //to prevent scrolling while zooming
33861        function keyUpHandler(e){
33862            if(isWindowFocused){ //the keyup gets fired on new tab ctrl + t in Firefox
33863                controlPressed = e.ctrlKey;
33864            }
33865        }
33866
33867        //binding the mousemove when the mouse's middle button is released
33868        function mouseDownHandler(e){
33869            //middle button
33870            if (e.which == 2){
33871                oldPageY = e.pageY;
33872                container.on('mousemove', mouseMoveHandler);
33873            }
33874        }
33875
33876        //unbinding the mousemove when the mouse's middle button is released
33877        function mouseUpHandler(e){
33878            //middle button
33879            if (e.which == 2){
33880                container.off('mousemove');
33881            }
33882        }
33883
33884        //Scrolling horizontally when clicking on the slider controls.
33885        function slideArrowHandler(){
33886            var section = $(this).closest(SECTION_SEL);
33887
33888            if ($(this).hasClass(SLIDES_PREV)) {
33889                if(isScrollAllowed.m.left){
33890                    moveSlideLeft(section);
33891                }
33892            } else {
33893                if(isScrollAllowed.m.right){
33894                    moveSlideRight(section);
33895                }
33896            }
33897        }
33898
33899        //when opening a new tab (ctrl + t), `control` won't be pressed when coming back.
33900        function blurHandler(){
33901            isWindowFocused = false;
33902            controlPressed = false;
33903        }
33904
33905        //Scrolls to the section when clicking the navigation bullet
33906        function sectionBulletHandler(e){
33907            e.preventDefault();
33908            var index = $(this).parent().index();
33909            scrollPage($(SECTION_SEL).eq(index));
33910        }
33911
33912        //Scrolls the slider to the given slide destination for the given section
33913        function slideBulletHandler(e){
33914            e.preventDefault();
33915            var slides = $(this).closest(SECTION_SEL).find(SLIDES_WRAPPER_SEL);
33916            var destiny = slides.find(SLIDE_SEL).eq($(this).closest('li').index());
33917
33918            landscapeScroll(slides, destiny);
33919        }
33920
33921        /**
33922        * Keydown event
33923        */
33924        function onkeydown(e){
33925            var shiftPressed = e.shiftKey;
33926
33927            //do nothing if we can not scroll or we are not using horizotnal key arrows.
33928            if(!canScroll && [37,39].indexOf(e.which) < 0){
33929                return;
33930            }
33931
33932            switch (e.which) {
33933                //up
33934                case 38:
33935                case 33:
33936                    if(isScrollAllowed.k.up){
33937                        moveSectionUp();
33938                    }
33939                    break;
33940
33941                //down
33942                case 32: //spacebar
33943                    if(shiftPressed && isScrollAllowed.k.up){
33944                        moveSectionUp();
33945                        break;
33946                    }
33947                /* falls through */
33948                case 40:
33949                case 34:
33950                    if(isScrollAllowed.k.down){
33951                        moveSectionDown();
33952                    }
33953                    break;
33954
33955                //Home
33956                case 36:
33957                    if(isScrollAllowed.k.up){
33958                        moveTo(1);
33959                    }
33960                    break;
33961
33962                //End
33963                case 35:
33964                     if(isScrollAllowed.k.down){
33965                        moveTo( $(SECTION_SEL).length );
33966                    }
33967                    break;
33968
33969                //left
33970                case 37:
33971                    if(isScrollAllowed.k.left){
33972                        moveSlideLeft();
33973                    }
33974                    break;
33975
33976                //right
33977                case 39:
33978                    if(isScrollAllowed.k.right){
33979                        moveSlideRight();
33980                    }
33981                    break;
33982
33983                default:
33984                    return; // exit this handler for other keys
33985            }
33986        }
33987
33988        /**
33989        * Detecting the direction of the mouse movement.
33990        * Used only for the middle button of the mouse.
33991        */
33992        var oldPageY = 0;
33993        function mouseMoveHandler(e){
33994            if(canScroll){
33995                // moving up
33996                if (e.pageY < oldPageY && isScrollAllowed.m.up){
33997                    moveSectionUp();
33998                }
33999
34000                // moving down
34001                else if(e.pageY > oldPageY && isScrollAllowed.m.down){
34002                    moveSectionDown();
34003                }
34004            }
34005            oldPageY = e.pageY;
34006        }
34007
34008        /**
34009        * Scrolls horizontal sliders.
34010        */
34011        function landscapeScroll(slides, destiny, direction){
34012            var section = slides.closest(SECTION_SEL);
34013            var v = {
34014                slides: slides,
34015                destiny: destiny,
34016                direction: direction,
34017                destinyPos: destiny.position(),
34018                slideIndex: destiny.index(),
34019                section: section,
34020                sectionIndex: section.index(SECTION_SEL),
34021                anchorLink: section.data('anchor'),
34022                slidesNav: section.find(SLIDES_NAV_SEL),
34023                slideAnchor:  getAnchor(destiny),
34024                prevSlide: section.find(SLIDE_ACTIVE_SEL),
34025                prevSlideIndex: section.find(SLIDE_ACTIVE_SEL).index(),
34026
34027                //caching the value of isResizing at the momment the function is called
34028                //because it will be checked later inside a setTimeout and the value might change
34029                localIsResizing: isResizing
34030            };
34031            v.xMovement = getXmovement(v.prevSlideIndex, v.slideIndex);
34032            v.direction = v.direction ? v.direction : v.xMovement;
34033
34034            //important!! Only do it when not resizing
34035            if(!v.localIsResizing){
34036                //preventing from scrolling to the next/prev section when using scrollHorizontally
34037                canScroll = false;
34038            }
34039
34040            if(options.onSlideLeave){
34041
34042                //if the site is not just resizing and readjusting the slides
34043                if(!v.localIsResizing && v.xMovement!=='none'){
34044                    if($.isFunction( options.onSlideLeave )){
34045                        if(options.onSlideLeave.call( v.prevSlide, v.anchorLink, (v.sectionIndex + 1), v.prevSlideIndex, v.xMovement, v.slideIndex ) === false){
34046                            slideMoving = false;
34047                            return;
34048                        }
34049                    }
34050                }
34051            }
34052
34053            destiny.addClass(ACTIVE).siblings().removeClass(ACTIVE);
34054
34055            if(!v.localIsResizing){
34056                stopMedia(v.prevSlide);
34057                lazyLoad(destiny);
34058            }
34059
34060            if(!options.loopHorizontal && options.controlArrows){
34061                //hidding it for the fist slide, showing for the rest
34062                section.find(SLIDES_ARROW_PREV_SEL).toggle(v.slideIndex!==0);
34063
34064                //hidding it for the last slide, showing for the rest
34065                section.find(SLIDES_ARROW_NEXT_SEL).toggle(!destiny.is(':last-child'));
34066            }
34067
34068            //only changing the URL if the slides are in the current section (not for resize re-adjusting)
34069            if(section.hasClass(ACTIVE) && !v.localIsResizing){
34070                setState(v.slideIndex, v.slideAnchor, v.anchorLink, v.sectionIndex);
34071            }
34072
34073            performHorizontalMove(slides, v, true);
34074        }
34075
34076
34077        function afterSlideLoads(v){
34078            activeSlidesNavigation(v.slidesNav, v.slideIndex);
34079
34080            //if the site is not just resizing and readjusting the slides
34081            if(!v.localIsResizing){
34082                $.isFunction( options.afterSlideLoad ) && options.afterSlideLoad.call( v.destiny, v.anchorLink, (v.sectionIndex + 1), v.slideAnchor, v.slideIndex);
34083
34084                //needs to be inside the condition to prevent problems with continuousVertical and scrollHorizontally
34085                //and to prevent double scroll right after a windows resize
34086                canScroll = true;
34087
34088                playMedia(v.destiny);
34089            }
34090
34091            //letting them slide again
34092            slideMoving = false;
34093        }
34094
34095        /**
34096        * Performs the horizontal movement. (CSS3 or jQuery)
34097        *
34098        * @param fireCallback {Bool} - determines whether or not to fire the callback
34099        */
34100        function performHorizontalMove(slides, v, fireCallback){
34101            var destinyPos = v.destinyPos;
34102
34103            if(options.css3){
34104                var translate3d = 'translate3d(-' + Math.round(destinyPos.left) + 'px, 0px, 0px)';
34105
34106                addAnimation(slides.find(SLIDES_CONTAINER_SEL)).css(getTransforms(translate3d), v);
34107
34108                afterSlideLoadsId = setTimeout(function(){
34109                    fireCallback && afterSlideLoads(v);
34110                }, options.scrollingSpeed, options.easing);
34111            }else{
34112                slides.animate({
34113                    scrollLeft : Math.round(destinyPos.left)
34114                }, options.scrollingSpeed, options.easing, function() {
34115
34116                    fireCallback && afterSlideLoads(v);
34117                });
34118            }
34119        }
34120
34121        /**
34122        * Sets the state for the horizontal bullet navigations.
34123        */
34124        function activeSlidesNavigation(slidesNav, slideIndex){
34125            slidesNav.find(ACTIVE_SEL).removeClass(ACTIVE);
34126            slidesNav.find('li').eq(slideIndex).find('a').addClass(ACTIVE);
34127        }
34128
34129        var previousHeight = windowsHeight;
34130
34131        //when resizing the site, we adjust the heights of the sections, slimScroll...
34132        function resizeHandler(){
34133            //checking if it needs to get responsive
34134            responsive();
34135
34136            // rebuild immediately on touch devices
34137            if (isTouchDevice) {
34138                var activeElement = $(document.activeElement);
34139
34140                //if the keyboard is NOT visible
34141                if (!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select')) {
34142                    var currentHeight = $window.height();
34143
34144                    //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)
34145                    if( Math.abs(currentHeight - previousHeight) > (20 * Math.max(previousHeight, currentHeight) / 100) ){
34146                        reBuild(true);
34147                        previousHeight = currentHeight;
34148                    }
34149                }
34150            }else{
34151                //in order to call the functions only when the resize is finished
34152                //http://stackoverflow.com/questions/4298612/jquery-how-to-call-resize-event-only-once-its-finished-resizing
34153                clearTimeout(resizeId);
34154
34155                resizeId = setTimeout(function(){
34156                    reBuild(true);
34157                }, 350);
34158            }
34159        }
34160
34161        /**
34162        * Checks if the site needs to get responsive and disables autoScrolling if so.
34163        * A class `fp-responsive` is added to the plugin's container in case the user wants to use it for his own responsive CSS.
34164        */
34165        function responsive(){
34166            var widthLimit = options.responsive || options.responsiveWidth; //backwards compatiblity
34167            var heightLimit = options.responsiveHeight;
34168
34169            //only calculating what we need. Remember its called on the resize event.
34170            var isBreakingPointWidth = widthLimit && $window.outerWidth() < widthLimit;
34171            var isBreakingPointHeight = heightLimit && $window.height() < heightLimit;
34172
34173            if(widthLimit && heightLimit){
34174                setResponsive(isBreakingPointWidth || isBreakingPointHeight);
34175            }
34176            else if(widthLimit){
34177                setResponsive(isBreakingPointWidth);
34178            }
34179            else if(heightLimit){
34180                setResponsive(isBreakingPointHeight);
34181            }
34182        }
34183
34184        /**
34185        * Adds transition animations for the given element
34186        */
34187        function addAnimation(container, element){
34188            var transition = 'all ' + options.scrollingSpeed + 'ms ' + options.easingcss3;
34189
34190            container.removeClass(NO_TRANSITION);
34191            return container.css({
34192                '-webkit-transition': transition,
34193                'transition': transition
34194            });
34195        }
34196
34197        /**
34198        * Remove transition animations for the given element
34199        */
34200        function removeAnimation(element){
34201            return element.addClass(NO_TRANSITION);
34202        }
34203
34204        /**
34205        * Activating the vertical navigation bullets according to the given slide name.
34206        */
34207        function activateNavDots(name, sectionIndex){
34208            if(options.navigation){
34209                $(SECTION_NAV_SEL).find(ACTIVE_SEL).removeClass(ACTIVE);
34210                if(name){
34211                    $(SECTION_NAV_SEL).find('a[href="#' + name + '"]').addClass(ACTIVE);
34212                }else{
34213                    $(SECTION_NAV_SEL).find('li').eq(sectionIndex).find('a').addClass(ACTIVE);
34214                }
34215            }
34216        }
34217
34218        /**
34219        * Activating the website main menu elements according to the given slide name.
34220        */
34221        function activateMenuElement(name){
34222            if(options.menu){
34223                $(options.menu).find(ACTIVE_SEL).removeClass(ACTIVE);
34224                $(options.menu).find('[data-menuanchor="'+name+'"]').addClass(ACTIVE);
34225            }
34226        }
34227
34228        /**
34229        * Sets to active the current menu and vertical nav items.
34230        */
34231        function activateMenuAndNav(anchor, index){
34232            activateMenuElement(anchor);
34233            activateNavDots(anchor, index);
34234        }
34235
34236        /**
34237        * Retuns `up` or `down` depending on the scrolling movement to reach its destination
34238        * from the current section.
34239        */
34240        function getYmovement(destiny){
34241            var fromIndex = $(SECTION_ACTIVE_SEL).index(SECTION_SEL);
34242            var toIndex = destiny.index(SECTION_SEL);
34243            if( fromIndex == toIndex){
34244                return 'none';
34245            }
34246            if(fromIndex > toIndex){
34247                return 'up';
34248            }
34249            return 'down';
34250        }
34251
34252        /**
34253        * Retuns `right` or `left` depending on the scrolling movement to reach its destination
34254        * from the current slide.
34255        */
34256        function getXmovement(fromIndex, toIndex){
34257            if( fromIndex == toIndex){
34258                return 'none';
34259            }
34260            if(fromIndex > toIndex){
34261                return 'left';
34262            }
34263            return 'right';
34264        }
34265
34266        /**
34267        * Checks if the element needs scrollbar and if the user wants to apply it.
34268        * If so it creates it.
34269        *
34270        * @param {Object} element   jQuery object of the section or slide
34271        */
34272        function createScrollBar(element){
34273            //User doesn't want scrollbar here? Sayonara baby!
34274            if(element.hasClass('fp-noscroll')) return;
34275
34276            //needed to make `scrollHeight` work under Opera 12
34277            element.css('overflow', 'hidden');
34278
34279            var scrollOverflowHandler = options.scrollOverflowHandler;
34280            var wrap = scrollOverflowHandler.wrapContent();
34281            //in case element is a slide
34282            var section = element.closest(SECTION_SEL);
34283            var scrollable = scrollOverflowHandler.scrollable(element);
34284            var contentHeight;
34285
34286            //if there was scroll, the contentHeight will be the one in the scrollable section
34287            if(scrollable.length){
34288                contentHeight = scrollOverflowHandler.scrollHeight(element);
34289            }else{
34290                contentHeight = element.get(0).scrollHeight;
34291                if(options.verticalCentered){
34292                    contentHeight = element.find(TABLE_CELL_SEL).get(0).scrollHeight;
34293                }
34294            }
34295
34296            var scrollHeight = windowsHeight - parseInt(section.css('padding-bottom')) - parseInt(section.css('padding-top'));
34297
34298            //needs scroll?
34299            if ( contentHeight > scrollHeight) {
34300                //did we already have an scrollbar ? Updating it
34301                if(scrollable.length){
34302                    scrollOverflowHandler.update(element, scrollHeight);
34303                }
34304                //creating the scrolling
34305                else{
34306                    if(options.verticalCentered){
34307                        element.find(TABLE_CELL_SEL).wrapInner(wrap);
34308                    }else{
34309                        element.wrapInner(wrap);
34310                    }
34311                    scrollOverflowHandler.create(element, scrollHeight);
34312                }
34313            }
34314            //removing the scrolling when it is not necessary anymore
34315            else{
34316                scrollOverflowHandler.remove(element);
34317            }
34318
34319            //undo
34320            element.css('overflow', '');
34321        }
34322
34323        function addTableClass(element){
34324            //In case we are styling for the 2nd time as in with reponsiveSlides
34325            if(!element.hasClass(TABLE)){
34326                element.addClass(TABLE).wrapInner('<div class="' + TABLE_CELL + '" style="height:' + getTableHeight(element) + 'px;" />');
34327            }
34328        }
34329
34330        function getTableHeight(element){
34331            var sectionHeight = windowsHeight;
34332
34333            if(options.paddingTop || options.paddingBottom){
34334                var section = element;
34335                if(!section.hasClass(SECTION)){
34336                    section = element.closest(SECTION_SEL);
34337                }
34338
34339                var paddings = parseInt(section.css('padding-top')) + parseInt(section.css('padding-bottom'));
34340                sectionHeight = (windowsHeight - paddings);
34341            }
34342
34343            return sectionHeight;
34344        }
34345
34346        /**
34347        * Adds a css3 transform property to the container class with or without animation depending on the animated param.
34348        */
34349        function transformContainer(translate3d, animated){
34350            if(animated){
34351                addAnimation(container);
34352            }else{
34353                removeAnimation(container);
34354            }
34355
34356            container.css(getTransforms(translate3d));
34357
34358            //syncronously removing the class after the animation has been applied.
34359            setTimeout(function(){
34360                container.removeClass(NO_TRANSITION);
34361            },10);
34362        }
34363
34364        /**
34365        * Gets a section by its anchor / index
34366        */
34367        function getSectionByAnchor(sectionAnchor){
34368            if(!sectionAnchor) return [];
34369
34370            var section = container.find(SECTION_SEL + '[data-anchor="'+sectionAnchor+'"]');
34371            if(!section.length){
34372                section = $(SECTION_SEL).eq( sectionAnchor -1);
34373            }
34374
34375            return section;
34376        }
34377
34378        /**
34379        * Gets a slide inside a given section by its anchor / index
34380        */
34381        function getSlideByAnchor(slideAnchor, section){
34382            var slides = section.find(SLIDES_WRAPPER_SEL);
34383            var slide =  slides.find(SLIDE_SEL + '[data-anchor="'+slideAnchor+'"]');
34384
34385            if(!slide.length){
34386                slide = slides.find(SLIDE_SEL).eq(slideAnchor);
34387            }
34388
34389            return slide;
34390        }
34391
34392        /**
34393        * Scrolls to the given section and slide anchors
34394        */
34395        function scrollPageAndSlide(destiny, slide){
34396            var section = getSectionByAnchor(destiny);
34397
34398            //do nothing if there's no section with the given anchor name
34399            if(!section.length) return;
34400
34401            //default slide
34402            if (typeof slide === 'undefined') {
34403                slide = 0;
34404            }
34405
34406            //we need to scroll to the section and then to the slide
34407            if (destiny !== lastScrolledDestiny && !section.hasClass(ACTIVE)){
34408                scrollPage(section, function(){
34409                    scrollSlider(section, slide);
34410                });
34411            }
34412            //if we were already in the section
34413            else{
34414                scrollSlider(section, slide);
34415            }
34416        }
34417
34418        /**
34419        * Scrolls the slider to the given slide destination for the given section
34420        */
34421        function scrollSlider(section, slideAnchor){
34422            if(typeof slideAnchor !== 'undefined'){
34423                var slides = section.find(SLIDES_WRAPPER_SEL);
34424                var destiny =  getSlideByAnchor(slideAnchor, section);
34425
34426                if(destiny.length){
34427                    landscapeScroll(slides, destiny);
34428                }
34429            }
34430        }
34431
34432        /**
34433        * Creates a landscape navigation bar with dots for horizontal sliders.
34434        */
34435        function addSlidesNavigation(section, numSlides){
34436            section.append('<div class="' + SLIDES_NAV + '"><ul></ul></div>');
34437            var nav = section.find(SLIDES_NAV_SEL);
34438
34439            //top or bottom
34440            nav.addClass(options.slidesNavPosition);
34441
34442            for(var i=0; i< numSlides; i++){
34443                nav.find('ul').append('<li><a href="#"><span></span></a></li>');
34444            }
34445
34446            //centering it
34447            nav.css('margin-left', '-' + (nav.width()/2) + 'px');
34448
34449            nav.find('li').first().find('a').addClass(ACTIVE);
34450        }
34451
34452
34453        /**
34454        * Sets the state of the website depending on the active section/slide.
34455        * It changes the URL hash when needed and updates the body class.
34456        */
34457        function setState(slideIndex, slideAnchor, anchorLink, sectionIndex){
34458            var sectionHash = '';
34459
34460            if(options.anchors.length && !options.lockAnchors){
34461
34462                //isn't it the first slide?
34463                if(slideIndex){
34464                    if(typeof anchorLink !== 'undefined'){
34465                        sectionHash = anchorLink;
34466                    }
34467
34468                    //slide without anchor link? We take the index instead.
34469                    if(typeof slideAnchor === 'undefined'){
34470                        slideAnchor = slideIndex;
34471                    }
34472
34473                    lastScrolledSlide = slideAnchor;
34474                    setUrlHash(sectionHash + '/' + slideAnchor);
34475
34476                //first slide won't have slide anchor, just the section one
34477                }else if(typeof slideIndex !== 'undefined'){
34478                    lastScrolledSlide = slideAnchor;
34479                    setUrlHash(anchorLink);
34480                }
34481
34482                //section without slides
34483                else{
34484                    setUrlHash(anchorLink);
34485                }
34486            }
34487
34488            setBodyClass();
34489        }
34490
34491        /**
34492        * Sets the URL hash.
34493        */
34494        function setUrlHash(url){
34495            //Uncode addition
34496            if ( typeof SiteParameters.slide_footer != 'undefined' && url == SiteParameters.slide_footer )
34497                return false;
34498
34499            if(options.recordHistory){
34500                location.hash = url;
34501            }else{
34502                //Uncode addition
34503                //Mobile Chrome doesn't work the normal way, so... lets use HTML5 for phones :)
34504                // if(isTouchDevice || isTouch){
34505                //     window.history.replaceState(undefined, undefined, '#' + url);
34506                // }else{
34507                //     var baseUrl = window.location.href.split('#')[0];
34508                //     window.location.replace( baseUrl + '#' + url );
34509                // }
34510                return false;
34511            }
34512        }
34513
34514        /**
34515        * Gets the anchor for the given slide / section. Its index will be used if there's none.
34516        */
34517        function getAnchor(element){
34518            var anchor = element.data('anchor');
34519            var index = element.index();
34520
34521            //Slide without anchor link? We take the index instead.
34522            if(typeof anchor === 'undefined'){
34523                anchor = index;
34524            }
34525
34526            return anchor;
34527        }
34528
34529        /**
34530        * Sets a class for the body of the page depending on the active section / slide
34531        */
34532        function setBodyClass(){
34533            var section = $(SECTION_ACTIVE_SEL);
34534            var slide = section.find(SLIDE_ACTIVE_SEL);
34535
34536            var sectionAnchor = getAnchor(section);
34537            var slideAnchor = getAnchor(slide);
34538
34539            var text = String(sectionAnchor);
34540
34541            if(slide.length){
34542                text = text + '-' + slideAnchor;
34543            }
34544
34545            //changing slash for dash to make it a valid CSS style
34546            text = text.replace('/', '-').replace('#','');
34547
34548            //removing previous anchor classes
34549            var classRe = new RegExp('\\b\\s?' + VIEWING_PREFIX + '-[^\\s]+\\b', "g");
34550            $body[0].className = $body[0].className.replace(classRe, '');
34551
34552            //adding the current anchor
34553            $body.addClass(VIEWING_PREFIX + '-' + text);
34554        }
34555
34556        /**
34557        * Checks for translate3d support
34558        * @return boolean
34559        * http://stackoverflow.com/questions/5661671/detecting-transform-translate3d-support
34560        */
34561        function support3d() {
34562            var el = document.createElement('p'),
34563                has3d,
34564                transforms = {
34565                    'webkitTransform':'-webkit-transform',
34566                    'OTransform':'-o-transform',
34567                    'msTransform':'-ms-transform',
34568                    'MozTransform':'-moz-transform',
34569                    'transform':'transform'
34570                };
34571
34572            // Add it to the body to get the computed style.
34573            document.body.insertBefore(el, null);
34574
34575            for (var t in transforms) {
34576                if (el.style[t] !== undefined) {
34577                    el.style[t] = 'translate3d(1px,1px,1px)';
34578                    has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]);
34579                }
34580            }
34581
34582            document.body.removeChild(el);
34583
34584            return (has3d !== undefined && has3d.length > 0 && has3d !== 'none');
34585        }
34586
34587        /**
34588        * Removes the auto scrolling action fired by the mouse wheel and trackpad.
34589        * After this function is called, the mousewheel and trackpad movements won't scroll through sections.
34590        */
34591        function removeMouseWheelHandler(){
34592            if (document.addEventListener) {
34593                document.removeEventListener('mousewheel', MouseWheelHandler, false); //IE9, Chrome, Safari, Oper
34594                document.removeEventListener('wheel', MouseWheelHandler, false); //Firefox
34595                document.removeEventListener('MozMousePixelScroll', MouseWheelHandler, false); //old Firefox
34596            } else {
34597                document.detachEvent('onmousewheel', MouseWheelHandler); //IE 6/7/8
34598            }
34599        }
34600
34601        /**
34602        * Adds the auto scrolling action for the mouse wheel and trackpad.
34603        * After this function is called, the mousewheel and trackpad movements will scroll through sections
34604        * https://developer.mozilla.org/en-US/docs/Web/Events/wheel
34605        */
34606        function addMouseWheelHandler(){
34607            var prefix = '';
34608            var _addEventListener;
34609
34610            if (window.addEventListener){
34611                _addEventListener = "addEventListener";
34612            }else{
34613                _addEventListener = "attachEvent";
34614                prefix = 'on';
34615            }
34616
34617             // detect available wheel event
34618            var support = 'onwheel' in document.createElement('div') ? 'wheel' : // Modern browsers support "wheel"
34619                      document.onmousewheel !== undefined ? 'mousewheel' : // Webkit and IE support at least "mousewheel"
34620                      'DOMMouseScroll'; // let's assume that remaining browsers are older Firefox
34621            var passiveEvent = g_supportsPassive ? {passive: false }
34621: false;
34622
34623
34624            if(support == 'DOMMouseScroll'){
34625                document[ _addEventListener ](prefix + 'MozMousePixelScroll', MouseWheelHandler, passiveEvent);
34626            }
34627
34628            //handle MozMousePixelScroll in older Firefox
34629            else{
34630                document[ _addEventListener ](prefix + support, MouseWheelHandler, passiveEvent);
34631            }
34632        }
34633
34634        /**
34635        * Binding the mousemove when the mouse's middle button is pressed
34636        */
34637        function addMiddleWheelHandler(){
34638            container
34639                .on('mousedown', mouseDownHandler)
34640                .on('mouseup', mouseUpHandler);
34641        }
34642
34643        /**
34644        * Unbinding the mousemove when the mouse's middle button is released
34645        */
34646        function removeMiddleWheelHandler(){
34647            container
34648                .off('mousedown', mouseDownHandler)
34649                .off('mouseup', mouseUpHandler);
34650        }
34651
34652        /**
34653        * Adds the possibility to auto scroll through sections on touch devices.
34654        */
34655        function addTouchHandler(){
34656            if(isTouchDevice || isTouch){
34657                if(options.autoScrolling){
34658                    $body.off(events.touchmove).on(events.touchmove, preventBouncing);
34659                }
34660
34661                $(WRAPPER_SEL)
34662                    .off(events.touchstart).on(events.touchstart, touchStartHandler)
34663                    .off(events.touchmove).on(events.touchmove, touchMoveHandler);
34664            }
34665        }
34666
34667        /**
34668        * Removes the auto scrolling for touch devices.
34669        */
34670        function removeTouchHandler(){
34671            if(isTouchDevice || isTouch){
34672                $(WRAPPER_SEL)
34673                    .off(events.touchstart)
34674                    .off(events.touchmove);
34675            }
34676        }
34677
34678        /*
34679        * Returns and object with Microsoft pointers (for IE<11 and for IE >= 11)
34680        * http://msdn.microsoft.com/en-us/library/ie/dn304886(v=vs.85).aspx
34681        */
34682        function getMSPointer(){
34683            var pointer;
34684
34685            //IE >= 11 & rest of browsers
34686            if(window.PointerEvent){
34687                pointer = { down: 'pointerdown', move: 'pointermove'};
34688            }
34689
34690            //IE < 11
34691            else{
34692                pointer = { down: 'MSPointerDown', move: 'MSPointerMove'};
34693            }
34694
34695            return pointer;
34696        }
34697
34698        /**
34699        * Gets the pageX and pageY properties depending on the browser.
34700        * https://github.com/alvarotrigo/fullPage.js/issues/194#issuecomment-34069854
34701        */
34702        function getEventsPage(e){
34703            var events = [];
34704
34705            events.y = (typeof e.pageY !== 'undefined' && (e.pageY || e.pageX) ? e.pageY : e.touches[0].pageY);
34706            events.x = (typeof e.pageX !== 'undefined' && (e.pageY || e.pageX) ? e.pageX : e.touches[0].pageX);
34707
34708            //in touch devices with scrollBar:true, e.pageY is detected, but we have to deal with touch events. #1008
34709            if(isTouch && isReallyTouch(e) && options.scrollBar){
34710                events.y = e.touches[0].pageY;
34711                events.x = e.touches[0].pageX;
34712            }
34713
34714            return events;
34715        }
34716
34717        /**
34718        * Slides silently (with no animation) the active slider to the given slide.
34719        * @param noCallback {bool} true or defined -> no callbacks
34720        */
34721        function silentLandscapeScroll(activeSlide, noCallbacks){
34722            setScrollingSpeed (0, 'internal');
34723
34724            if(typeof noCallbacks !== 'undefined'){
34725                //preventing firing callbacks afterSlideLoad etc.
34726                isResizing = true;
34727            }
34728
34729            landscapeScroll(activeSlide.closest(SLIDES_WRAPPER_SEL), activeSlide);
34730
34731            if(typeof noCallbacks !== 'undefined'){
34732                isResizing = false;
34733            }
34734
34735            setScrollingSpeed(originals.scrollingSpeed, 'internal');
34736        }
34737
34738        /**
34739        * Scrolls silently (with no animation) the page to the given Y position.
34740        */
34741        function silentScroll(top){
34742            // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625
34743            // that's why we round it to 0.
34744            var roundedTop = Math.round(top);
34745
34746            if (options.css3 && options.autoScrolling && !options.scrollBar){
34747                var translate3d = 'translate3d(0px, -' + roundedTop + 'px, 0px)';
34748                transformContainer(translate3d, false);
34749            }
34750            else if(options.autoScrolling && !options.scrollBar){
34751                container.css('top', -roundedTop);
34752            }
34753            else{
34754                $htmlBody.scrollTop(roundedTop);
34755            }
34756        }
34757
34758        /**
34759        * Returns the cross-browser transform string.
34760        */
34761        function getTransforms(translate3d){
34762            return {
34763                '-webkit-transform': translate3d,
34764                '-moz-transform': translate3d,
34765                '-ms-transform':translate3d,
34766                'transform': translate3d
34767            };
34768        }
34769
34770        /**
34771        * Allowing or disallowing the mouse/swipe scroll in a given direction. (not for keyboard)
34772        * @type  m (mouse) or k (keyboard)
34773        */
34774        function setIsScrollAllowed(value, direction, type){
34775            switch (direction){
34776                case 'up': isScrollAllowed[type].up = value; break;
34777                case 'down': isScrollAllowed[type].down = value; break;
34778                case 'left': isScrollAllowed[type].left = value; break;
34779                case 'right': isScrollAllowed[type].right = value; break;
34780                case 'all':
34781                    if(type == 'm'){
34782                        setAllowScrolling(value);
34783                    }else{
34784                        setKeyboardScrolling(value);
34785                    }
34786            }
34787        }
34788
34789        /*
34790        * Destroys fullpage.js plugin events and optinally its html markup and styles
34791        */
34792        function destroy(all){
34793            setAutoScrolling(false, 'internal');
34794            setAllowScrolling(false);
34795            setKeyboardScrolling(false);
34796            container.addClass(DESTROYED);
34797
34798            clearTimeout(afterSlideLoadsId);
34799            clearTimeout(afterSectionLoadsId);
34800            clearTimeout(resizeId);
34801            clearTimeout(scrollId);
34802            clearTimeout(scrollId2);
34803
34804            $window
34805                .off('scroll', scrollHandler)
34806                .off('hashchange', hashChangeHandler)
34807                .off('resize', resizeHandler);
34808
34809            $document
34810                .off('click touchstart', SECTION_NAV_SEL + ' a')
34811                .off('mouseenter', SECTION_NAV_SEL + ' li')
34812                .off('mouseleave', SECTION_NAV_SEL + ' li')
34813                .off('click touchstart', SLIDES_NAV_LINK_SEL)
34814                .off('mouseover', options.normalScrollElements)
34815                .off('mouseout', options.normalScrollElements);
34816
34817            $(SECTION_SEL)
34818                .off('click touchstart', SLIDES_ARROW_SEL);
34819
34820            clearTimeout(afterSlideLoadsId);
34821            clearTimeout(afterSectionLoadsId);
34822
34823            //lets make a mess!
34824            if(all){
34825                destroyStructure();
34826            }
34827        }
34828
34829        /*
34830        * Removes inline styles added by fullpage.js
34831        */
34832        function destroyStructure(){
34833            //reseting the `top` or `translate` properties to 0
34834            silentScroll(0);
34835
34836            //loading all the lazy load content
34837            container.find('img[data-src], source[data-src], audio[data-src], iframe[data-src]').each(function(){
34838                setSrc($(this), 'src');
34839            });
34840
34841            container.find('img[data-srcset]').each(function(){
34842                setSrc($(this), 'srcset');
34843            });
34844
34845            $(SECTION_NAV_SEL + ', ' + SLIDES_NAV_SEL +  ', ' + SLIDES_ARROW_SEL).remove();
34846
34847            //removing inline styles
34848            $(SECTION_SEL).css( {
34849                'height': '',
34850                'background-color' : '',
34851                'padding': ''
34852            });
34853
34854            $(SLIDE_SEL).css( {
34855                'width': ''
34856            });
34857
34858            container.css({
34859                'height': '',
34860                'position': '',
34861                '-ms-touch-action': '',
34862                'touch-action': ''
34863            });
34864
34865            $htmlBody.css({
34866                'overflow': '',
34867                'height': ''
34868            });
34869
34870            // remove .fp-enabled class
34871            $('html').removeClass(ENABLED);
34872
34873            // remove .fp-responsive class
34874            $body.removeClass(RESPONSIVE);
34875
34876            // remove all of the .fp-viewing- classes
34877            $.each($body.get(0).className.split(/\s+/), function (index, className) {
34878                if (className.indexOf(VIEWING_PREFIX) === 0) {
34879                    $body.removeClass(className);
34880                }
34881            });
34882
34883            //removing added classes
34884            $(SECTION_SEL + ', ' + SLIDE_SEL).each(function(){
34885                options.scrollOverflowHandler.remove($(this));
34886                $(this).removeClass(TABLE + ' ' + ACTIVE);
34887            });
34888
34889            removeAnimation(container);
34890
34891            //Unwrapping content
34892            container.find(TABLE_CELL_SEL + ', ' + SLIDES_CONTAINER_SEL + ', ' + SLIDES_WRAPPER_SEL).each(function(){
34893                //unwrap not being use in case there's no child element inside and its just text
34894                $(this).replaceWith(this.childNodes);
34895            });
34896
34897            //removing the applied transition from the fullpage wrapper
34898            container.css({
34899                '-webkit-transition': 'none',
34900                'transition': 'none'
34901            });
34902
34903            //scrolling the page to the top with no animation
34904            $htmlBody.scrollTop(0);
34905
34906            //removing selectors
34907            var usedSelectors = [SECTION, SLIDE, SLIDES_CONTAINER];
34908            $.each(usedSelectors, function(index, value){
34909                $('.' + value).removeClass(value);
34910            });
34911        }
34912
34913        /*
34914        * Sets the state for a variable with multiple states (original, and temporal)
34915        * Some variables such as `autoScrolling` or `recordHistory` might change automatically its state when using `responsive` or `autoScrolling:false`.
34916        * This function is used to keep track of both states, the original and the temporal one.
34917        * If type is not 'internal', then we assume the user is globally changing the variable.
34918        */
34919        function setVariableState(variable, value, type){
34920            options[variable] = value;
34921            if(type !== 'internal'){
34922                originals[variable] = value;
34923            }
34924        }
34925
34926        /**
34927        * Displays warnings
34928        */
34929        function displayWarnings(){
34930            var extensions = ['fadingEffect', 'continuousHorizontal', 'scrollHorizontally', 'interlockedSlides', 'resetSliders', 'responsiveSlides', 'offsetSections', 'dragAndMove', 'scrollOverflowReset', 'parallax'];
34931            //UNCODE.addition
34932            // if($('html').hasClass(ENABLED)){
34933            //     showError('error', 'Fullpage.js can only be initialized once and you are doing it multiple times!');
34934            //     return;
34935            // }
34936
34937            // Disable mutually exclusive settings
34938            //UNCODE.addition
34939            // if (options.continuousVertical &&
34940            //     (options.loopTop || options.loopBottom)) {
34941            //     options.continuousVertical = false;
34942            //     showError('warn', 'Option `loopTop/loopBottom` is mutually exclusive with `continuousVertical`; `continuousVertical` disabled');
34943            // }
34944
34945            // if(options.scrollBar && options.scrollOverflow){
34946            //     showError('warn', 'Option `scrollBar` is mutually exclusive with `scrollOverflow`. Sections with scrollOverflow might not work well in Firefox');
34947            // }
34948
34949            // if(options.continuousVertical && (options.scrollBar || !options.autoScrolling)){
34950            //     options.continuousVertical = false;
34951            //     showError('warn', 'Scroll bars (`scrollBar:true` or `autoScrolling:false`) are mutually exclusive with `continuousVertical`; `continuousVertical` disabled');
34952            // }
34953
34954            //using extensions? Wrong file!
34955            $.each(extensions, function(index, extension){
34956                //is the option set to true?
34957                if(options[extension]){
34958                    showError('warn', 'fullpage.js extensions require jquery.fullpage.extensions.min.js file instead of the usual jquery.fullpage.js. Requested: '+ extension);
34959                }
34960            });
34961
34962            //anchors can not have the same value as any element ID or NAME
34963            $.each(options.anchors, function(index, name){
34964
34965                //case insensitive selectors (http://stackoverflow.com/a/19465187/1081396)
34966                var nameAttr = $document.find('[name]').filter(function() {
34967                    return $(this).attr('name') && $(this).attr('name').toLowerCase() == name.toLowerCase();
34968                });
34969
34970                var idAttr = $document.find('[id]').filter(function() {
34971                    return $(this).attr('id') && $(this).attr('id').toLowerCase() == name.toLowerCase();
34972                });
34973
34974                if(idAttr.length || nameAttr.length ){
34975                    showError('error', 'data-anchor tags can not have the same value as any `id` element on the site (or `name` element for IE).');
34976                    idAttr.length && showError('error', '"' + name + '" is is being used by another element `id` property');
34977                    nameAttr.length && showError('error', '"' + name + '" is is being used by another element `name` property');
34978                }
34979            });
34980        }
34981
34982        /**
34983        * Shows a message in the console of the given type.
34984        */
34985        function showError(type, text){
34986            console && console[type] && console[type]('fullPage: ' + text);
34987        }
34988
34989    }; //end of $.fn.fullpage
34990
34991    if(typeof IScroll !== 'undefined'){
34992        /*
34993        * Turns iScroll `mousewheel` option off dynamically
34994        * https://github.com/cubiq/iscroll/issues/1036
34995        */
34996        IScroll.prototype.wheelOn = function () {
34997            this.wrapper.addEventListener('wheel', this);
34998            this.wrapper.addEventListener('mousewheel', this);
34999            this.wrapper.addEventListener('DOMMouseScroll', this);
35000        };
35001
35002        /*
35003        * Turns iScroll `mousewheel` option on dynamically
35004        * https://github.com/cubiq/iscroll/issues/1036
35005        */
35006        IScroll.prototype.wheelOff = function () {
35007            this.wrapper.removeEventListener('wheel', this);
35008            this.wrapper.removeEventListener('mousewheel', this);
35009            this.wrapper.removeEventListener('DOMMouseScroll', this);
35010        };
35011    }
35012
35013    /**
35014     * An object to handle overflow scrolling.
35015     * This uses jquery.slimScroll to accomplish overflow scrolling.
35016     * It is possible to pass in an alternate scrollOverflowHandler
35017     * to the fullpage.js option that implements the same functions
35018     * as this handler.
35019     *
35020     * @type {Object}
35021     */
35022    var iscrollHandler = {
35023        refreshId: null,
35024        iScrollInstances: [],
35025
35026        // Enables or disables the mouse wheel for the active section or all slides in it
35027        toggleWheel: function(value){
35028            var scrollable = $(SECTION_ACTIVE_SEL).find(SCROLLABLE_SEL);
35029            scrollable.each(function(){
35030                var iScrollInstance = $(this).data('iscrollInstance');
35031                if(typeof iScrollInstance !== 'undefined' && iScrollInstance){
35032                    if(value){
35033                        iScrollInstance.wheelOn();
35034                    }
35035                    else{
35036                        iScrollInstance.wheelOff();
35037                    }
35038                }
35039            });
35040        },
35041
35042        /**
35043        * Turns off iScroll for the destination section.
35044        * When scrolling very fast on some trackpads (and Apple laptops) the inertial scrolling would
35045        * scroll the destination section/slide before the sections animations ends.
35046        */
35047        onLeave: function(){
35048            iscrollHandler.toggleWheel(false);
35049        },
35050
35051        // Turns off iScroll for the leaving section
35052        beforeLeave: function(){
35053            iscrollHandler.onLeave()
35054        },
35055
35056        // Turns on iScroll on section load
35057        afterLoad: function(){
35058            iscrollHandler.toggleWheel(true);
35059        },
35060
35061        /**
35062         * Called when overflow scrolling is needed for a section.
35063         *
35064         * @param  {Object} element      jQuery object containing current section
35065         * @param  {Number} scrollHeight Current window height in pixels
35066         */
35067        create: function(element, scrollHeight) {
35068            var scrollable = element.find(SCROLLABLE_SEL);
35069
35070            scrollable.height(scrollHeight);
35071            scrollable.each(function() {
35072                var $this = $(this);
35073                var iScrollInstance = $this.data('iscrollInstance');
35074                if (iScrollInstance) {
35075                    $.each(iscrollHandler.iScrollInstances, function(){
35076                        $(this).destroy();
35077                    });
35078                }
35079
35080                iScrollInstance = new IScroll($this.get(0), iscrollOptions);
35081                iscrollHandler.iScrollInstances.push(iScrollInstance);
35082
35083                //off by default until the section gets active
35084                iScrollInstance.wheelOff();
35085
35086                $this.data('iscrollInstance', iScrollInstance);
35087            });
35088        },
35089
35090        /**
35091         * Return a boolean depending on whether the scrollable element is a
35092         * the end or at the start of the scrolling depending on the given type.
35093         *
35094         * @param  {String}  type       Either 'top' or 'bottom'
35095         * @param  {Object}  scrollable jQuery object for the scrollable element
35096         * @return {Boolean}
35097         */
35098        isScrolled: function(type, scrollable) {
35099            var scroller = scrollable.data('iscrollInstance');
35100
35101            //no scroller?
35102            if (!scroller) {
35103                return true;
35104            }
35105
35106            //Uncode addition
35107            var uncode_body_borders = parseFloat($('.body-borders').attr('data-border')) || 0;
35108            //End Uncode addition
35109
35110            if (type === 'top') {
35111                return scroller.y >= 0 && !scrollable.scrollTop();
35112            } else if (type === 'bottom') {
35113                //Uncode change
35114                // return (0 - scroller.y) + scrollable.scrollTop() + 1 + scrollable.innerHeight() >= scrollable[0].scrollHeight;
35115                return (0 - scroller.y) + scrollable.scrollTop() + 1 + ( uncode_body_borders * 2 ) + scrollable.innerHeight() >= scrollable[0].scrollHeight;
35116                //End Uncode change
35117            }
35118        },
35119
35120        /**
35121         * Returns the scrollable element for the given section.
35122         * If there are landscape slides, will only return a scrollable element
35123         * if it is in the active slide.
35124         *
35125         * @param  {Object}  activeSection jQuery object containing current section
35126         * @return {Boolean}
35127         */
35128        scrollable: function(activeSection){
35129            // if there are landscape slides, we check if the scrolling bar is in the current one or not
35130            if (activeSection.find(SLIDES_WRAPPER_SEL).length) {
35131                return activeSection.find(SLIDE_ACTIVE_SEL).find(SCROLLABLE_SEL);
35132            }
35133            return activeSection.find(SCROLLABLE_SEL);
35134        },
35135
35136        /**
35137         * Returns the scroll height of the wrapped content.
35138         * If this is larger than the window height minus section padding,
35139         * overflow scrolling is needed.
35140         *
35141         * @param  {Object} element jQuery object containing current section
35142         * @return {Number}
35143         */
35144        scrollHeight: function(element) {
35145            return element.find(SCROLLABLE_SEL).children().first().get(0).scrollHeight;
35146        },
35147
35148        /**
35149         * Called when overflow scrolling is no longer needed for a section.
35150         *
35151         * @param  {Object}
vendor: 5,435 bytes, lines 35151-35302
35151 element      jQuery object containing current section
35152         */
35153        remove: function(element) {
35154            var scrollable = element.find(SCROLLABLE_SEL);
35155            if (scrollable.length) {
35156                var iScrollInstance = scrollable.data('iscrollInstance');
35157                iScrollInstance.destroy();
35158
35159                scrollable.data('iscrollInstance', null);
35160            }
35161            element.find(SCROLLABLE_SEL).children().first().children().first().unwrap().unwrap();
35162        },
35163
35164        /**
35165         * Called when overflow scrolling has already been setup but the
35166         * window height has potentially changed.
35167         *
35168         * @param  {Object} element      jQuery object containing current section
35169         * @param  {Number} scrollHeight Current window height in pixels
35170         */
35171        update: function(element, scrollHeight) {
35172            //using a timeout in order to execute the refresh function only once when `update` is called multiple times in a
35173            //short period of time.
35174            //it also comes on handy because iScroll requires the use of timeout when using `refresh`.
35175            clearTimeout(iscrollHandler.refreshId);
35176            iscrollHandler.refreshId = setTimeout(function(){
35177                $.each(iscrollHandler.iScrollInstances, function(){
35178                    $(this).get(0).refresh();
35179                });
35180            }, 150);
35181
35182            //updating the wrappers height
35183            element.find(SCROLLABLE_SEL).css('height', scrollHeight + 'px').parent().css('height', scrollHeight + 'px');
35184        },
35185
35186        /**
35187         * Called to get any additional elements needed to wrap the section
35188         * content in order to facilitate overflow scrolling.
35189         *
35190         * @return {String|Object} Can be a string containing HTML,
35191         *                         a DOM element, or jQuery object.
35192         */
35193        wrapContent: function() {
35194            return '<div class="' + SCROLLABLE + '"><div class="fp-scroller"></div></div>';
35195        }
35196    };
35197});
35198
35199(function (global, factory) {
35200	typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
35201	typeof define === 'function' && define.amd ? define(['exports'], factory) :
35202	(global = global || self, factory(global.window = global.window || {}));
35203  }(this, (function (exports) { 'use strict';
35204  
35205	function _defineProperties(target, props) {
35206	  for (var i = 0; i < props.length; i++) {
35207		var descriptor = props[i];
35208		descriptor.enumerable = descriptor.enumerable || false;
35209		descriptor.configurable = true;
35210		if ("value" in descriptor) descriptor.writable = true;
35211		Object.defineProperty(target, descriptor.key, descriptor);
35212	  }
35213	}
35214  
35215	function _createClass(Constructor, protoProps, staticProps) {
35216	  if (protoProps) _defineProperties(Constructor.prototype, protoProps);
35217	  if (staticProps) _defineProperties(Constructor, staticProps);
35218	  return Constructor;
35219	}
35220  
35221	/*!
35222	 * Observer 3.12.5
35223	 * https://gsap.com
35224	 *
35225	 * @license Copyright 2008-2024, GreenSock. All rights reserved.
35226	 * Subject to the terms at https://gsap.com/standard-license or for
35227	 * Club GSAP members, the agreement issued with that membership.
35228	 * @author: Jack Doyle, [email protected]
35229	*/
35230	var gsap,
35231		_coreInitted,
35232		_clamp,
35233		_win,
35234		_doc,
35235		_docEl,
35236		_body,
35237		_isTouch,
35238		_pointerType,
35239		ScrollTrigger,
35240		_root,
35241		_normalizer,
35242		_eventTypes,
35243		_context,
35244		_getGSAP = function _getGSAP() {
35245	  return gsap || typeof window !== "undefined" && (gsap = window.gsap) && gsap.registerPlugin && gsap;
35246	},
35247		_startup = 1,
35248		_observers = [],
35249		_scrollers = [],
35250		_proxies = [],
35251		_getTime = Date.now,
35252		_bridge = function _bridge(name, value) {
35253	  return value;
35254	},
35255		_integrate = function _integrate() {
35256	  var core = ScrollTrigger.core,
35257		  data = core.bridge || {},
35258		  scrollers = core._scrollers,
35259		  proxies = core._proxies;
35260	  scrollers.push.apply(scrollers, _scrollers);
35261	  proxies.push.apply(proxies, _proxies);
35262	  _scrollers = scrollers;
35263	  _proxies = proxies;
35264  
35265	  _bridge = function _bridge(name, value) {
35266		return data[name](value);
35267	  };
35268	},
35269		_getProxyProp = function _getProxyProp(element, property) {
35270	  return ~_proxies.indexOf(element) && _proxies[_proxies.indexOf(element) + 1][property];
35271	},
35272		_isViewport = function _isViewport(el) {
35273	  return !!~_root.indexOf(el);
35274	},
35275		_addListener = function _addListener(element, type, func, passive, capture) {
35276	  return element.addEventListener(type, func, {
35277		passive: passive !== false,
35278		capture: !!capture
35279	  });
35280	},
35281		_removeListener = function _removeListener(element, type, func, capture) {
35282	  return element.removeEventListener(type, func, !!capture);
35283	},
35284		_scrollLeft = "scrollLeft",
35285		_scrollTop = "scrollTop",
35286		_onScroll = function _onScroll() {
35287	  return _normalizer && _normalizer.isPressed || _scrollers.cache++;
35288	},
35289		_scrollCacheFunc = function _scrollCacheFunc(f, doNotCache) {
35290	  var cachingFunc = function cachingFunc(value) {
35291		if (value || value === 0) {
35292		  _startup && (_win.history.scrollRestoration = "manual");
35293		  var isNormalizing = _normalizer && _normalizer.isPressed;
35294		  value = cachingFunc.v = Math.round(value) || (_normalizer && _normalizer.iOS ? 1 : 0);
35295		  f(value);
35296		  cachingFunc.cacheID = _scrollers.cache;
35297		  isNormalizing && _bridge("ss", value);
35298		} else if (doNotCache || _scrollers.cache !== cachingFunc.cacheID || _bridge("ref")) {
35299		  cachingFunc.cacheID = _scrollers.cache;
35300		  cachingFunc.v = f();
35301		}
35302  
vendor: 13,754 bytes, lines 35303-35756
35303		return cachingFunc.v + cachingFunc.offset;
35304	  };
35305  
35306	  cachingFunc.offset = 0;
35307	  return f && cachingFunc;
35308	},
35309		_horizontal = {
35310	  s: _scrollLeft,
35311	  p: "left",
35312	  p2: "Left",
35313	  os: "right",
35314	  os2: "Right",
35315	  d: "width",
35316	  d2: "Width",
35317	  a: "x",
35318	  sc: _scrollCacheFunc(function (value) {
35319		return arguments.length ? _win.scrollTo(value, _vertical.sc()) : _win.pageXOffset || _doc[_scrollLeft] || _docEl[_scrollLeft] || _body[_scrollLeft] || 0;
35320	  })
35321	},
35322		_vertical = {
35323	  s: _scrollTop,
35324	  p: "top",
35325	  p2: "Top",
35326	  os: "bottom",
35327	  os2: "Bottom",
35328	  d: "height",
35329	  d2: "Height",
35330	  a: "y",
35331	  op: _horizontal,
35332	  sc: _scrollCacheFunc(function (value) {
35333		return arguments.length ? _win.scrollTo(_horizontal.sc(), value) : _win.pageYOffset || _doc[_scrollTop] || _docEl[_scrollTop] || _body[_scrollTop] || 0;
35334	  })
35335	},
35336		_getTarget = function _getTarget(t, self) {
35337	  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);
35338	},
35339		_getScrollFunc = function _getScrollFunc(element, _ref) {
35340	  var s = _ref.s,
35341		  sc = _ref.sc;
35342	  _isViewport(element) && (element = _doc.scrollingElement || _docEl);
35343  
35344	  var i = _scrollers.indexOf(element),
35345		  offset = sc === _vertical.sc ? 1 : 2;
35346  
35347	  !~i && (i = _scrollers.push(element) - 1);
35348	  _scrollers[i + offset] || _addListener(element, "scroll", _onScroll);
35349	  var prev = _scrollers[i + offset],
35350		  func = prev || (_scrollers[i + offset] = _scrollCacheFunc(_getProxyProp(element, s), true) || (_isViewport(element) ? sc : _scrollCacheFunc(function (value) {
35351		return arguments.length ? element[s] = value : element[s];
35352	  })));
35353	  func.target = element;
35354	  prev || (func.smooth = gsap.getProperty(element, "scrollBehavior") === "smooth");
35355	  return func;
35356	},
35357		_getVelocityProp = function _getVelocityProp(value, minTimeRefresh, useDelta) {
35358	  var v1 = value,
35359		  v2 = value,
35360		  t1 = _getTime(),
35361		  t2 = t1,
35362		  min = minTimeRefresh || 50,
35363		  dropToZeroTime = Math.max(500, min * 3),
35364		  update = function update(value, force) {
35365		var t = _getTime();
35366  
35367		if (force || t - t1 > min) {
35368		  v2 = v1;
35369		  v1 = value;
35370		  t2 = t1;
35371		  t1 = t;
35372		} else if (useDelta) {
35373		  v1 += value;
35374		} else {
35375		  v1 = v2 + (value - v2) / (t - t2) * (t1 - t2);
35376		}
35377	  },
35378		  reset = function reset() {
35379		v2 = v1 = useDelta ? 0 : v1;
35380		t2 = t1 = 0;
35381	  },
35382		  getVelocity = function getVelocity(latestValue) {
35383		var tOld = t2,
35384			vOld = v2,
35385			t = _getTime();
35386  
35387		(latestValue || latestValue === 0) && latestValue !== v1 && update(latestValue);
35388		return t1 === t2 || t - t2 > dropToZeroTime ? 0 : (v1 + (useDelta ? vOld : -vOld)) / ((useDelta ? t : t1) - tOld) * 1000;
35389	  };
35390  
35391	  return {
35392		update: update,
35393		reset: reset,
35394		getVelocity: getVelocity
35395	  };
35396	},
35397		_getEvent = function _getEvent(e, preventDefault) {
35398	  preventDefault && !e._gsapAllow && e.preventDefault();
35399	  return e.changedTouches ? e.changedTouches[0] : e;
35400	},
35401		_getAbsoluteMax = function _getAbsoluteMax(a) {
35402	  var max = Math.max.apply(Math, a),
35403		  min = Math.min.apply(Math, a);
35404	  return Math.abs(max) >= Math.abs(min) ? max : min;
35405	},
35406		_setScrollTrigger = function _setScrollTrigger() {
35407	  ScrollTrigger = gsap.core.globals().ScrollTrigger;
35408	  ScrollTrigger && ScrollTrigger.core && _integrate();
35409	},
35410		_initCore = function _initCore(core) {
35411	  gsap = core || _getGSAP();
35412  
35413	  if (!_coreInitted && gsap && typeof document !== "undefined" && document.body) {
35414		_win = window;
35415		_doc = document;
35416		_docEl = _doc.documentElement;
35417		_body = _doc.body;
35418		_root = [_win, _doc, _docEl, _body];
35419		_clamp = gsap.utils.clamp;
35420  
35421		_context = gsap.core.context || function () {};
35422  
35423		_pointerType = "onpointerenter" in _body ? "pointer" : "mouse";
35424		_isTouch = Observer.isTouch = _win.matchMedia && _win.matchMedia("(hover: none), (pointer: coarse)").matches ? 1 : "ontouchstart" in _win || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0 ? 2 : 0;
35425		_eventTypes = Observer.eventTypes = ("ontouchstart" in _docEl ? "touchstart,touchmove,touchcancel,touchend" : !("onpointerdown" in _docEl) ? "mousedown,mousemove,mouseup,mouseup" : "pointerdown,pointermove,pointercancel,pointerup").split(",");
35426		setTimeout(function () {
35427		  return _startup = 0;
35428		}, 500);
35429  
35430		_setScrollTrigger();
35431  
35432		_coreInitted = 1;
35433	  }
35434  
35435	  return _coreInitted;
35436	};
35437  
35438	_horizontal.op = _vertical;
35439	_scrollers.cache = 0;
35440	var Observer = function () {
35441	  function Observer(vars) {
35442		this.init(vars);
35443	  }
35444  
35445	  var _proto = Observer.prototype;
35446  
35447	  _proto.init = function init(vars) {
35448		_coreInitted || _initCore(gsap) || console.warn("Please gsap.registerPlugin(Observer)");
35449		ScrollTrigger || _setScrollTrigger();
35450		var tolerance = vars.tolerance,
35451			dragMinimum = vars.dragMinimum,
35452			type = vars.type,
35453			target = vars.target,
35454			lineHeight = vars.lineHeight,
35455			debounce = vars.debounce,
35456			preventDefault = vars.preventDefault,
35457			onStop = vars.onStop,
35458			onStopDelay = vars.onStopDelay,
35459			ignore = vars.ignore,
35460			wheelSpeed = vars.wheelSpeed,
35461			event = vars.event,
35462			onDragStart = vars.onDragStart,
35463			onDragEnd = vars.onDragEnd,
35464			onDrag = vars.onDrag,
35465			onPress = vars.onPress,
35466			onRelease = vars.onRelease,
35467			onRight = vars.onRight,
35468			onLeft = vars.onLeft,
35469			onUp = vars.onUp,
35470			onDown = vars.onDown,
35471			onChangeX = vars.onChangeX,
35472			onChangeY = vars.onChangeY,
35473			onChange = vars.onChange,
35474			onToggleX = vars.onToggleX,
35475			onToggleY = vars.onToggleY,
35476			onHover = vars.onHover,
35477			onHoverEnd = vars.onHoverEnd,
35478			onMove = vars.onMove,
35479			ignoreCheck = vars.ignoreCheck,
35480			isNormalizer = vars.isNormalizer,
35481			onGestureStart = vars.onGestureStart,
35482			onGestureEnd = vars.onGestureEnd,
35483			onWheel = vars.onWheel,
35484			onEnable = vars.onEnable,
35485			onDisable = vars.onDisable,
35486			onClick = vars.onClick,
35487			scrollSpeed = vars.scrollSpeed,
35488			capture = vars.capture,
35489			allowClicks = vars.allowClicks,
35490			lockAxis = vars.lockAxis,
35491			onLockAxis = vars.onLockAxis;
35492		this.target = target = _getTarget(target) || _docEl;
35493		this.vars = vars;
35494		ignore && (ignore = gsap.utils.toArray(ignore));
35495		tolerance = tolerance || 1e-9;
35496		dragMinimum = dragMinimum || 0;
35497		wheelSpeed = wheelSpeed || 1;
35498		scrollSpeed = scrollSpeed || 1;
35499		type = type || "wheel,touch,pointer";
35500		debounce = debounce !== false;
35501		lineHeight || (lineHeight = parseFloat(_win.getComputedStyle(_body).lineHeight) || 22);
35502  
35503		var id,
35504			onStopDelayedCall,
35505			dragged,
35506			moved,
35507			wheeled,
35508			locked,
35509			axis,
35510			self = this,
35511			prevDeltaX = 0,
35512			prevDeltaY = 0,
35513			passive = vars.passive || !preventDefault,
35514			scrollFuncX = _getScrollFunc(target, _horizontal),
35515			scrollFuncY = _getScrollFunc(target, _vertical),
35516			scrollX = scrollFuncX(),
35517			scrollY = scrollFuncY(),
35518			limitToTouch = ~type.indexOf("touch") && !~type.indexOf("pointer") && _eventTypes[0] === "pointerdown",
35519			isViewport = _isViewport(target),
35520			ownerDoc = target.ownerDocument || _doc,
35521			deltaX = [0, 0, 0],
35522			deltaY = [0, 0, 0],
35523			onClickTime = 0,
35524			clickCapture = function clickCapture() {
35525		  return onClickTime = _getTime();
35526		},
35527			_ignoreCheck = function _ignoreCheck(e, isPointerOrTouch) {
35528		  return (self.event = e) && ignore && ~ignore.indexOf(e.target) || isPointerOrTouch && limitToTouch && e.pointerType !== "touch" || ignoreCheck && ignoreCheck(e, isPointerOrTouch);
35529		},
35530			onStopFunc = function onStopFunc() {
35531		  self._vx.reset();
35532  
35533		  self._vy.reset();
35534  
35535		  onStopDelayedCall.pause();
35536		  onStop && onStop(self);
35537		},
35538			update = function update() {
35539		  var dx = self.deltaX = _getAbsoluteMax(deltaX),
35540			  dy = self.deltaY = _getAbsoluteMax(deltaY),
35541			  changedX = Math.abs(dx) >= tolerance,
35542			  changedY = Math.abs(dy) >= tolerance;
35543  
35544		  onChange && (changedX || changedY) && onChange(self, dx, dy, deltaX, deltaY);
35545  
35546		  if (changedX) {
35547			onRight && self.deltaX > 0 && onRight(self);
35548			onLeft && self.deltaX < 0 && onLeft(self);
35549			onChangeX && onChangeX(self);
35550			onToggleX && self.deltaX < 0 !== prevDeltaX < 0 && onToggleX(self);
35551			prevDeltaX = self.deltaX;
35552			deltaX[0] = deltaX[1] = deltaX[2] = 0;
35553		  }
35554  
35555		  if (changedY) {
35556			onDown && self.deltaY > 0 && onDown(self);
35557			onUp && self.deltaY < 0 && onUp(self);
35558			onChangeY && onChangeY(self);
35559			onToggleY && self.deltaY < 0 !== prevDeltaY < 0 && onToggleY(self);
35560			prevDeltaY = self.deltaY;
35561			deltaY[0] = deltaY[1] = deltaY[2] = 0;
35562		  }
35563  
35564		  if (moved || dragged) {
35565			onMove && onMove(self);
35566  
35567			if (dragged) {
35568			  onDrag(self);
35569			  dragged = false;
35570			}
35571  
35572			moved = false;
35573		  }
35574  
35575		  locked && !(locked = false) && onLockAxis && onLockAxis(self);
35576  
35577		  if (wheeled) {
35578			onWheel(self);
35579			wheeled = false;
35580		  }
35581  
35582		  id = 0;
35583		},
35584			onDelta = function onDelta(x, y, index) {
35585		  deltaX[index] += x;
35586		  deltaY[index] += y;
35587  
35588		  self._vx.update(x);
35589  
35590		  self._vy.update(y);
35591  
35592		  debounce ? id || (id = requestAnimationFrame(update)) : update();
35593		},
35594			onTouchOrPointerDelta = function onTouchOrPointerDelta(x, y) {
35595		  if (lockAxis && !axis) {
35596			self.axis = axis = Math.abs(x) > Math.abs(y) ? "x" : "y";
35597			locked = true;
35598		  }
35599  
35600		  if (axis !== "y") {
35601			deltaX[2] += x;
35602  
35603			self._vx.update(x, true);
35604		  }
35605  
35606		  if (axis !== "x") {
35607			deltaY[2] += y;
35608  
35609			self._vy.update(y, true);
35610		  }
35611  
35612		  debounce ? id || (id = requestAnimationFrame(update)) : update();
35613		},
35614			_onDrag = function _onDrag(e) {
35615		  if (_ignoreCheck(e, 1)) {
35616			return;
35617		  }
35618  
35619		  e = _getEvent(e, preventDefault);
35620		  var x = e.clientX,
35621			  y = e.clientY,
35622			  dx = x - self.x,
35623			  dy = y - self.y,
35624			  isDragging = self.isDragging;
35625		  self.x = x;
35626		  self.y = y;
35627  
35628		  if (isDragging || Math.abs(self.startX - x) >= dragMinimum || Math.abs(self.startY - y) >= dragMinimum) {
35629			onDrag && (dragged = true);
35630			isDragging || (self.isDragging = true);
35631			onTouchOrPointerDelta(dx, dy);
35632			isDragging || onDragStart && onDragStart(self);
35633		  }
35634		},
35635			_onPress = self.onPress = function (e) {
35636		  if (_ignoreCheck(e, 1) || e && e.button) {
35637			return;
35638		  }
35639  
35640		  self.axis = axis = null;
35641		  onStopDelayedCall.pause();
35642		  self.isPressed = true;
35643		  e = _getEvent(e);
35644		  prevDeltaX = prevDeltaY = 0;
35645		  self.startX = self.x = e.clientX;
35646		  self.startY = self.y = e.clientY;
35647  
35648		  self._vx.reset();
35649  
35650		  self._vy.reset();
35651  
35652		  _addListener(isNormalizer ? target : ownerDoc, _eventTypes[1], _onDrag, passive, true);
35653  
35654		  self.deltaX = self.deltaY = 0;
35655		  onPress && onPress(self);
35656		},
35657			_onRelease = self.onRelease = function (e) {
35658		  if (_ignoreCheck(e, 1)) {
35659			return;
35660		  }
35661  
35662		  _removeListener(isNormalizer ? target : ownerDoc, _eventTypes[1], _onDrag, true);
35663  
35664		  var isTrackingDrag = !isNaN(self.y - self.startY),
35665			  wasDragging = self.isDragging,
35666			  isDragNotClick = wasDragging && (Math.abs(self.x - self.startX) > 3 || Math.abs(self.y - self.startY) > 3),
35667			  eventData = _getEvent(e);
35668  
35669		  if (!isDragNotClick && isTrackingDrag) {
35670			self._vx.reset();
35671  
35672			self._vy.reset();
35673  
35674			if (preventDefault && allowClicks) {
35675			  gsap.delayedCall(0.08, function () {
35676				if (_getTime() - onClickTime > 300 && !e.defaultPrevented) {
35677				  if (e.target.click) {
35678					e.target.click();
35679				  } else if (ownerDoc.createEvent) {
35680					var syntheticEvent = ownerDoc.createEvent("MouseEvents");
35681					syntheticEvent.initMouseEvent("click", true, true, _win, 1, eventData.screenX, eventData.screenY, eventData.clientX, eventData.clientY, false, false, false, false, 0, null);
35682					e.target.dispatchEvent(syntheticEvent);
35683				  }
35684				}
35685			  });
35686			}
35687		  }
35688  
35689		  self.isDragging = self.isGesturing = self.isPressed = false;
35690		  onStop && wasDragging && !isNormalizer && onStopDelayedCall.restart(true);
35691		  onDragEnd && wasDragging && onDragEnd(self);
35692		  onRelease && onRelease(self, isDragNotClick);
35693		},
35694			_onGestureStart = function _onGestureStart(e) {
35695		  return e.touches && e.touches.length > 1 && (self.isGesturing = true) && onGestureStart(e, self.isDragging);
35696		},
35697			_onGestureEnd = function _onGestureEnd() {
35698		  return (self.isGesturing = false) || onGestureEnd(self);
35699		},
35700			onScroll = function onScroll(e) {
35701		  if (_ignoreCheck(e)) {
35702			return;
35703		  }
35704  
35705		  var x = scrollFuncX(),
35706			  y = scrollFuncY();
35707		  onDelta((x - scrollX) * scrollSpeed, (y - scrollY) * scrollSpeed, 1);
35708		  scrollX = x;
35709		  scrollY = y;
35710		  onStop && onStopDelayedCall.restart(true);
35711		},
35712			_onWheel = function _onWheel(e) {
35713		  if (_ignoreCheck(e)) {
35714			return;
35715		  }
35716  
35717		  e = _getEvent(e, preventDefault);
35718		  onWheel && (wheeled = true);
35719		  var multiplier = (e.deltaMode === 1 ? lineHeight : e.deltaMode === 2 ? _win.innerHeight : 1) * wheelSpeed;
35720		  onDelta(e.deltaX * multiplier, e.deltaY * multiplier, 0);
35721		  onStop && !isNormalizer && onStopDelayedCall.restart(true);
35722		},
35723			_onMove = function _onMove(e) {
35724		  if (_ignoreCheck(e)) {
35725			return;
35726		  }
35727  
35728		  var x = e.clientX,
35729			  y = e.clientY,
35730			  dx = x - self.x,
35731			  dy = y - self.y;
35732		  self.x = x;
35733		  self.y = y;
35734		  moved = true;
35735		  onStop && onStopDelayedCall.restart(true);
35736		  (dx || dy) && onTouchOrPointerDelta(dx, dy);
35737		},
35738			_onHover = function _onHover(e) {
35739		  self.event = e;
35740		  onHover(self);
35741		},
35742			_onHoverEnd = function _onHoverEnd(e) {
35743		  self.event = e;
35744		  onHoverEnd(self);
35745		},
35746			_onClick = function _onClick(e) {
35747		  return _ignoreCheck(e) || _getEvent(e, preventDefault) && onClick(self);
35748		};
35749  
35750		onStopDelayedCall = self._dc = gsap.delayedCall(onStopDelay || 0.25, onStopFunc).pause();
35751		self.deltaX = self.deltaY = 0;
35752		self._vx = _getVelocityProp(0, 50, true);
35753		self._vy = _getVelocityProp(0, 50, true);
35754		self.scrollX = scrollFuncX;
35755		self.scrollY = scrollFuncY;
35756		self.isDragging = self.isGesturing = self.isPressed = false;
vendor: 7,173 bytes, lines 35757-35999
35757  
35758		_context(this);
35759  
35760		self.enable = function (e) {
35761		  if (!self.isEnabled) {
35762			_addListener(isViewport ? ownerDoc : target, "scroll", _onScroll);
35763  
35764			type.indexOf("scroll") >= 0 && _addListener(isViewport ? ownerDoc : target, "scroll", onScroll, passive, capture);
35765			type.indexOf("wheel") >= 0 && _addListener(target, "wheel", _onWheel, passive, capture);
35766  
35767			if (type.indexOf("touch") >= 0 && _isTouch || type.indexOf("pointer") >= 0) {
35768			  _addListener(target, _eventTypes[0], _onPress, passive, capture);
35769  
35770			  _addListener(ownerDoc, _eventTypes[2], _onRelease);
35771  
35772			  _addListener(ownerDoc, _eventTypes[3], _onRelease);
35773  
35774			  allowClicks && _addListener(target, "click", clickCapture, true, true);
35775			  onClick && _addListener(target, "click", _onClick);
35776			  onGestureStart && _addListener(ownerDoc, "gesturestart", _onGestureStart);
35777			  onGestureEnd && _addListener(ownerDoc, "gestureend", _onGestureEnd);
35778			  onHover && _addListener(target, _pointerType + "enter", _onHover);
35779			  onHoverEnd && _addListener(target, _pointerType + "leave", _onHoverEnd);
35780			  onMove && _addListener(target, _pointerType + "move", _onMove);
35781			}
35782  
35783			self.isEnabled = true;
35784			e && e.type && _onPress(e);
35785			onEnable && onEnable(self);
35786		  }
35787  
35788		  return self;
35789		};
35790  
35791		self.disable = function () {
35792		  if (self.isEnabled) {
35793			_observers.filter(function (o) {
35794			  return o !== self && _isViewport(o.target);
35795			}).length || _removeListener(isViewport ? ownerDoc : target, "scroll", _onScroll);
35796  
35797			if (self.isPressed) {
35798			  self._vx.reset();
35799  
35800			  self._vy.reset();
35801  
35802			  _removeListener(isNormalizer ? target : ownerDoc, _eventTypes[1], _onDrag, true);
35803			}
35804  
35805			_removeListener(isViewport ? ownerDoc : target, "scroll", onScroll, capture);
35806  
35807			_removeListener(target, "wheel", _onWheel, capture);
35808  
35809			_removeListener(target, _eventTypes[0], _onPress, capture);
35810  
35811			_removeListener(ownerDoc, _eventTypes[2], _onRelease);
35812  
35813			_removeListener(ownerDoc, _eventTypes[3], _onRelease);
35814  
35815			_removeListener(target, "click", clickCapture, true);
35816  
35817			_removeListener(target, "click", _onClick);
35818  
35819			_removeListener(ownerDoc, "gesturestart", _onGestureStart);
35820  
35821			_removeListener(ownerDoc, "gestureend", _onGestureEnd);
35822  
35823			_removeListener(target, _pointerType + "enter", _onHover);
35824  
35825			_removeListener(target, _pointerType + "leave", _onHoverEnd);
35826  
35827			_removeListener(target, _pointerType + "move", _onMove);
35828  
35829			self.isEnabled = self.isPressed = self.isDragging = false;
35830			onDisable && onDisable(self);
35831		  }
35832		};
35833  
35834		self.kill = self.revert = function () {
35835		  self.disable();
35836  
35837		  var i = _observers.indexOf(self);
35838  
35839		  i >= 0 && _observers.splice(i, 1);
35840		  _normalizer === self && (_normalizer = 0);
35841		};
35842  
35843		_observers.push(self);
35844  
35845		isNormalizer && _isViewport(target) && (_normalizer = self);
35846		self.enable(event);
35847	  };
35848  
35849	  _createClass(Observer, [{
35850		key: "velocityX",
35851		get: function get() {
35852		  return this._vx.getVelocity();
35853		}
35854	  }, {
35855		key: "velocityY",
35856		get: function get() {
35857		  return this._vy.getVelocity();
35858		}
35859	  }]);
35860  
35861	  return Observer;
35862	}();
35863	Observer.version = "3.12.5";
35864  
35865	Observer.create = function (vars) {
35866	  return new Observer(vars);
35867	};
35868  
35869	Observer.register = _initCore;
35870  
35871	Observer.getAll = function () {
35872	  return _observers.slice();
35873	};
35874  
35875	Observer.getById = function (id) {
35876	  return _observers.filter(function (o) {
35877		return o.vars.id === id;
35878	  })[0];
35879	};
35880  
35881	_getGSAP() && gsap.registerPlugin(Observer);
35882  
35883	/*!
35884	 * ScrollTrigger 3.12.5
35885	 * https://gsap.com
35886	 *
35887	 * @license Copyright 2008-2024, GreenSock. All rights reserved.
35888	 * Subject to the terms at https://gsap.com/standard-license or for
35889	 * Club GSAP members, the agreement issued with that membership.
35890	 * @author: Jack Doyle, [email protected]
35891	*/
35892  
35893	var gsap$1,
35894		_coreInitted$1,
35895		_win$1,
35896		_doc$1,
35897		_docEl$1,
35898		_body$1,
35899		_root$1,
35900		_resizeDelay,
35901		_toArray,
35902		_clamp$1,
35903		_time2,
35904		_syncInterval,
35905		_refreshing,
35906		_pointerIsDown,
35907		_transformProp,
35908		_i,
35909		_prevWidth,
35910		_prevHeight,
35911		_autoRefresh,
35912		_sort,
35913		_suppressOverwrites,
35914		_ignoreResize,
35915		_normalizer$1,
35916		_ignoreMobileResize,
35917		_baseScreenHeight,
35918		_baseScreenWidth,
35919		_fixIOSBug,
35920		_context$1,
35921		_scrollRestoration,
35922		_div100vh,
35923		_100vh,
35924		_isReverted,
35925		_clampingMax,
35926		_limitCallbacks,
35927		_startup$1 = 1,
35928		_getTime$1 = Date.now,
35929		_time1 = _getTime$1(),
35930		_lastScrollTime = 0,
35931		_enabled = 0,
35932		_parseClamp = function _parseClamp(value, type, self) {
35933	  var clamp = _isString(value) && (value.substr(0, 6) === "clamp(" || value.indexOf("max") > -1);
35934	  self["_" + type + "Clamp"] = clamp;
35935	  return clamp ? value.substr(6, value.length - 7) : value;
35936	},
35937		_keepClamp = function _keepClamp(value, clamp) {
35938	  return clamp && (!_isString(value) || value.substr(0, 6) !== "clamp(") ? "clamp(" + value + ")" : value;
35939	},
35940		_rafBugFix = function _rafBugFix() {
35941	  return _enabled && requestAnimationFrame(_rafBugFix);
35942	},
35943		_pointerDownHandler = function _pointerDownHandler() {
35944	  return _pointerIsDown = 1;
35945	},
35946		_pointerUpHandler = function _pointerUpHandler() {
35947	  return _pointerIsDown = 0;
35948	},
35949		_passThrough = function _passThrough(v) {
35950	  return v;
35951	},
35952		_round = function _round(value) {
35953	  return Math.round(value * 100000) / 100000 || 0;
35954	},
35955		_windowExists = function _windowExists() {
35956	  return typeof window !== "undefined";
35957	},
35958		_getGSAP$1 = function _getGSAP() {
35959	  return gsap$1 || _windowExists() && (gsap$1 = window.gsap) && gsap$1.registerPlugin && gsap$1;
35960	},
35961		_isViewport$1 = function _isViewport(e) {
35962	  return !!~_root$1.indexOf(e);
35963	},
35964		_getViewportDimension = function _getViewportDimension(dimensionProperty) {
35965	  return (dimensionProperty === "Height" ? _100vh : _win$1["inner" + dimensionProperty]) || _docEl$1["client" + dimensionProperty] || _body$1["client" + dimensionProperty];
35966	},
35967		_getBoundsFunc = function _getBoundsFunc(element) {
35968	  return _getProxyProp(element, "getBoundingClientRect") || (_isViewport$1(element) ? function () {
35969		_winOffsets.width = _win$1.innerWidth;
35970		_winOffsets.height = _100vh;
35971		return _winOffsets;
35972	  } : function () {
35973		return _getBounds(element);
35974	  });
35975	},
35976		_getSizeFunc = function _getSizeFunc(scroller, isViewport, _ref) {
35977	  var d = _ref.d,
35978		  d2 = _ref.d2,
35979		  a = _ref.a;
35980	  return (a = _getProxyProp(scroller, "getBoundingClientRect")) ? function () {
35981		return a()[d];
35982	  } : function () {
35983		return (isViewport ? _getViewportDimension(d2) : scroller["client" + d2]) || 0;
35984	  };
35985	},
35986		_getOffsetsFunc = function _getOffsetsFunc(element, isViewport) {
35987	  return !isViewport || ~_proxies.indexOf(element) ? _getBoundsFunc(element) : function () {
35988		return _winOffsets;
35989	  };
35990	},
35991		_maxScroll = function _maxScroll(element, _ref2) {
35992	  var s = _ref2.s,
35993		  d2 = _ref2.d2,
35994		  d = _ref2.d,
35995		  a = _ref2.a;
35996	  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]);
35997	},
35998		_iterateAutoRefresh = function _iterateAutoRefresh(func, events) {
35999	  for (var i = 0; i < _autoRefresh.length; i += 3) {
vendor: 4,900 bytes, lines 36000-36181
36000		(!events || ~events.indexOf(_autoRefresh[i + 1])) && func(_autoRefresh[i], _autoRefresh[i + 1], _autoRefresh[i + 2]);
36001	  }
36002	},
36003		_isString = function _isString(value) {
36004	  return typeof value === "string";
36005	},
36006		_isFunction = function _isFunction(value) {
36007	  return typeof value === "function";
36008	},
36009		_isNumber = function _isNumber(value) {
36010	  return typeof value === "number";
36011	},
36012		_isObject = function _isObject(value) {
36013	  return typeof value === "object";
36014	},
36015		_endAnimation = function _endAnimation(animation, reversed, pause) {
36016	  return animation && animation.progress(reversed ? 0 : 1) && pause && animation.pause();
36017	},
36018		_callback = function _callback(self, func) {
36019	  if (self.enabled) {
36020		var result = self._ctx ? self._ctx.add(function () {
36021		  return func(self);
36022		}) : func(self);
36023		result && result.totalTime && (self.callbackAnimation = result);
36024	  }
36025	},
36026		_abs = Math.abs,
36027		_left = "left",
36028		_top = "top",
36029		_right = "right",
36030		_bottom = "bottom",
36031		_width = "width",
36032		_height = "height",
36033		_Right = "Right",
36034		_Left = "Left",
36035		_Top = "Top",
36036		_Bottom = "Bottom",
36037		_padding = "padding",
36038		_margin = "margin",
36039		_Width = "Width",
36040		_Height = "Height",
36041		_px = "px",
36042		_getComputedStyle = function _getComputedStyle(element) {
36043	  return _win$1.getComputedStyle(element);
36044	},
36045		_makePositionable = function _makePositionable(element) {
36046	  var position = _getComputedStyle(element).position;
36047  
36048	  element.style.position = position === "absolute" || position === "fixed" ? position : "relative";
36049	},
36050		_setDefaults = function _setDefaults(obj, defaults) {
36051	  for (var p in defaults) {
36052		p in obj || (obj[p] = defaults[p]);
36053	  }
36054  
36055	  return obj;
36056	},
36057		_getBounds = function _getBounds(element, withoutTransforms) {
36058	  var tween = withoutTransforms && _getComputedStyle(element)[_transformProp] !== "matrix(1, 0, 0, 1, 0, 0)" && gsap$1.to(element, {
36059		x: 0,
36060		y: 0,
36061		xPercent: 0,
36062		yPercent: 0,
36063		rotation: 0,
36064		rotationX: 0,
36065		rotationY: 0,
36066		scale: 1,
36067		skewX: 0,
36068		skewY: 0
36069	  }).progress(1),
36070		  bounds = element.getBoundingClientRect();
36071	  tween && tween.progress(0).kill();
36072	  return bounds;
36073	},
36074		_getSize = function _getSize(element, _ref3) {
36075	  var d2 = _ref3.d2;
36076	  return element["offset" + d2] || element["client" + d2] || 0;
36077	},
36078		_getLabelRatioArray = function _getLabelRatioArray(timeline) {
36079	  var a = [],
36080		  labels = timeline.labels,
36081		  duration = timeline.duration(),
36082		  p;
36083  
36084	  for (p in labels) {
36085		a.push(labels[p] / duration);
36086	  }
36087  
36088	  return a;
36089	},
36090		_getClosestLabel = function _getClosestLabel(animation) {
36091	  return function (value) {
36092		return gsap$1.utils.snap(_getLabelRatioArray(animation), value);
36093	  };
36094	},
36095		_snapDirectional = function _snapDirectional(snapIncrementOrArray) {
36096	  var snap = gsap$1.utils.snap(snapIncrementOrArray),
36097		  a = Array.isArray(snapIncrementOrArray) && snapIncrementOrArray.slice(0).sort(function (a, b) {
36098		return a - b;
36099	  });
36100	  return a ? function (value, direction, threshold) {
36101		if (threshold === void 0) {
36102		  threshold = 1e-3;
36103		}
36104  
36105		var i;
36106  
36107		if (!direction) {
36108		  return snap(value);
36109		}
36110  
36111		if (direction > 0) {
36112		  value -= threshold;
36113  
36114		  for (i = 0; i < a.length; i++) {
36115			if (a[i] >= value) {
36116			  return a[i];
36117			}
36118		  }
36119  
36120		  return a[i - 1];
36121		} else {
36122		  i = a.length;
36123		  value += threshold;
36124  
36125		  while (i--) {
36126			if (a[i] <= value) {
36127			  return a[i];
36128			}
36129		  }
36130		}
36131  
36132		return a[0];
36133	  } : function (value, direction, threshold) {
36134		if (threshold === void 0) {
36135		  threshold = 1e-3;
36136		}
36137  
36138		var snapped = snap(value);
36139		return !direction || Math.abs(snapped - value) < threshold || snapped - value < 0 === direction < 0 ? snapped : snap(direction < 0 ? value - snapIncrementOrArray : value + snapIncrementOrArray);
36140	  };
36141	},
36142		_getLabelAtDirection = function _getLabelAtDirection(timeline) {
36143	  return function (value, st) {
36144		return _snapDirectional(_getLabelRatioArray(timeline))(value, st.direction);
36145	  };
36146	},
36147		_multiListener = function _multiListener(func, element, types, callback) {
36148	  return types.split(",").forEach(function (type) {
36149		return func(element, type, callback);
36150	  });
36151	},
36152		_addListener$1 = function _addListener(element, type, func, nonPassive, capture) {
36153	  return element.addEventListener(type, func, {
36154		passive: !nonPassive,
36155		capture: !!capture
36156	  });
36157	},
36158		_removeListener$1 = function _removeListener(element, type, func, capture) {
36159	  return element.removeEventListener(type, func, !!capture);
36160	},
36161		_wheelListener = function _wheelListener(func, el, scrollFunc) {
36162	  scrollFunc = scrollFunc && scrollFunc.wheelHandler;
36163  
36164	  if (scrollFunc) {
36165		func(el, "wheel", scrollFunc);
36166		func(el, "touchmove", scrollFunc);
36167	  }
36168	},
36169		_markerDefaults = {
36170	  startColor: "green",
36171	  endColor: "red",
36172	  indent: 0,
36173	  fontSize: "16px",
36174	  fontWeight: "normal"
36175	},
36176		_defaults = {
36177	  toggleActions: "play",
36178	  anticipatePin: 0
36179	},
36180		_keywords = {
36181	  top: 0,
vendor: 14,119 bytes, lines 36182-36622
36182	  left: 0,
36183	  center: 0.5,
36184	  bottom: 1,
36185	  right: 1
36186	},
36187		_offsetToPx = function _offsetToPx(value, size) {
36188	  if (_isString(value)) {
36189		var eqIndex = value.indexOf("="),
36190			relative = ~eqIndex ? +(value.charAt(eqIndex - 1) + 1) * parseFloat(value.substr(eqIndex + 1)) : 0;
36191  
36192		if (~eqIndex) {
36193		  value.indexOf("%") > eqIndex && (relative *= size / 100);
36194		  value = value.substr(0, eqIndex - 1);
36195		}
36196  
36197		value = relative + (value in _keywords ? _keywords[value] * size : ~value.indexOf("%") ? parseFloat(value) * size / 100 : parseFloat(value) || 0);
36198	  }
36199  
36200	  return value;
36201	},
36202		_createMarker = function _createMarker(type, name, container, direction, _ref4, offset, matchWidthEl, containerAnimation) {
36203	  var startColor = _ref4.startColor,
36204		  endColor = _ref4.endColor,
36205		  fontSize = _ref4.fontSize,
36206		  indent = _ref4.indent,
36207		  fontWeight = _ref4.fontWeight;
36208  
36209	  var e = _doc$1.createElement("div"),
36210		  useFixedPosition = _isViewport$1(container) || _getProxyProp(container, "pinType") === "fixed",
36211		  isScroller = type.indexOf("scroller") !== -1,
36212		  parent = useFixedPosition ? _body$1 : container,
36213		  isStart = type.indexOf("start") !== -1,
36214		  color = isStart ? startColor : endColor,
36215		  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;";
36216  
36217	  css += "position:" + ((isScroller || containerAnimation) && useFixedPosition ? "fixed;" : "absolute;");
36218	  (isScroller || containerAnimation || !useFixedPosition) && (css += (direction === _vertical ? _right : _bottom) + ":" + (offset + parseFloat(indent)) + "px;");
36219	  matchWidthEl && (css += "box-sizing:border-box;text-align:left;width:" + matchWidthEl.offsetWidth + "px;");
36220	  e._isStart = isStart;
36221	  e.setAttribute("class", "gsap-marker-" + type + (name ? " marker-" + name : ""));
36222	  e.style.cssText = css;
36223	  e.innerText = name || name === 0 ? type + "-" + name : type;
36224	  parent.children[0] ? parent.insertBefore(e, parent.children[0]) : parent.appendChild(e);
36225	  e._offset = e["offset" + direction.op.d2];
36226  
36227	  _positionMarker(e, 0, direction, isStart);
36228  
36229	  return e;
36230	},
36231		_positionMarker = function _positionMarker(marker, start, direction, flipped) {
36232	  var vars = {
36233		display: "block"
36234	  },
36235		  side = direction[flipped ? "os2" : "p2"],
36236		  oppositeSide = direction[flipped ? "p2" : "os2"];
36237	  marker._isFlipped = flipped;
36238	  vars[direction.a + "Percent"] = flipped ? -100 : 0;
36239	  vars[direction.a] = flipped ? "1px" : 0;
36240	  vars["border" + side + _Width] = 1;
36241	  vars["border" + oppositeSide + _Width] = 0;
36242	  vars[direction.p] = start + "px";
36243	  gsap$1.set(marker, vars);
36244	},
36245		_triggers = [],
36246		_ids = {},
36247		_rafID,
36248		_sync = function _sync() {
36249	  return _getTime$1() - _lastScrollTime > 34 && (_rafID || (_rafID = requestAnimationFrame(_updateAll)));
36250	},
36251		_onScroll$1 = function _onScroll() {
36252	  if (!_normalizer$1 || !_normalizer$1.isPressed || _normalizer$1.startX > _body$1.clientWidth) {
36253		_scrollers.cache++;
36254  
36255		if (_normalizer$1) {
36256		  _rafID || (_rafID = requestAnimationFrame(_updateAll));
36257		} else {
36258		  _updateAll();
36259		}
36260  
36261		_lastScrollTime || _dispatch("scrollStart");
36262		_lastScrollTime = _getTime$1();
36263	  }
36264	},
36265		_setBaseDimensions = function _setBaseDimensions() {
36266	  _baseScreenWidth = _win$1.innerWidth;
36267	  _baseScreenHeight = _win$1.innerHeight;
36268	},
36269		_onResize = function _onResize() {
36270	  _scrollers.cache++;
36271	  !_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);
36272	},
36273		_listeners = {},
36274		_emptyArray = [],
36275		_softRefresh = function _softRefresh() {
36276	  return _removeListener$1(ScrollTrigger$1, "scrollEnd", _softRefresh) || _refreshAll(true);
36277	},
36278		_dispatch = function _dispatch(type) {
36279	  return _listeners[type] && _listeners[type].map(function (f) {
36280		return f();
36281	  }) || _emptyArray;
36282	},
36283		_savedStyles = [],
36284		_revertRecorded = function _revertRecorded(media) {
36285	  for (var i = 0; i < _savedStyles.length; i += 5) {
36286		if (!media || _savedStyles[i + 4] && _savedStyles[i + 4].query === media) {
36287		  _savedStyles[i].style.cssText = _savedStyles[i + 1];
36288		  _savedStyles[i].getBBox && _savedStyles[i].setAttribute("transform", _savedStyles[i + 2] || "");
36289		  _savedStyles[i + 3].uncache = 1;
36290		}
36291	  }
36292	},
36293		_revertAll = function _revertAll(kill, media) {
36294	  var trigger;
36295  
36296	  for (_i = 0; _i < _triggers.length; _i++) {
36297		trigger = _triggers[_i];
36298  
36299		if (trigger && (!media || trigger._ctx === media)) {
36300		  if (kill) {
36301			trigger.kill(1);
36302		  } else {
36303			trigger.revert(true, true);
36304		  }
36305		}
36306	  }
36307  
36308	  _isReverted = true;
36309	  media && _revertRecorded(media);
36310	  media || _dispatch("revert");
36311	},
36312		_clearScrollMemory = function _clearScrollMemory(scrollRestoration, force) {
36313	  _scrollers.cache++;
36314	  (force || !_refreshingAll) && _scrollers.forEach(function (obj) {
36315		return _isFunction(obj) && obj.cacheID++ && (obj.rec = 0);
36316	  });
36317	  _isString(scrollRestoration) && (_win$1.history.scrollRestoration = _scrollRestoration = scrollRestoration);
36318	},
36319		_refreshingAll,
36320		_refreshID = 0,
36321		_queueRefreshID,
36322		_queueRefreshAll = function _queueRefreshAll() {
36323	  if (_queueRefreshID !== _refreshID) {
36324		var id = _queueRefreshID = _refreshID;
36325		requestAnimationFrame(function () {
36326		  return id === _refreshID && _refreshAll(true);
36327		});
36328	  }
36329	},
36330		_refresh100vh = function _refresh100vh() {
36331	  _body$1.appendChild(_div100vh);
36332  
36333	  _100vh = !_normalizer$1 && _div100vh.offsetHeight || _win$1.innerHeight;
36334  
36335	  _body$1.removeChild(_div100vh);
36336	},
36337		_hideAllMarkers = function _hideAllMarkers(hide) {
36338	  return _toArray(".gsap-marker-start, .gsap-marker-end, .gsap-marker-scroller-start, .gsap-marker-scroller-end").forEach(function (el) {
36339		return el.style.display = hide ? "none" : "block";
36340	  });
36341	},
36342		_refreshAll = function _refreshAll(force, skipRevert) {
36343	  if (_lastScrollTime && !force && !_isReverted) {
36344		_addListener$1(ScrollTrigger$1, "scrollEnd", _softRefresh);
36345  
36346		return;
36347	  }
36348  
36349	  _refresh100vh();
36350  
36351	  _refreshingAll = ScrollTrigger$1.isRefreshing = true;
36352  
36353	  _scrollers.forEach(function (obj) {
36354		return _isFunction(obj) && ++obj.cacheID && (obj.rec = obj());
36355	  });
36356  
36357	  var refreshInits = _dispatch("refreshInit");
36358  
36359	  _sort && ScrollTrigger$1.sort();
36360	  skipRevert || _revertAll();
36361  
36362	  _scrollers.forEach(function (obj) {
36363		if (_isFunction(obj)) {
36364		  obj.smooth && (obj.target.style.scrollBehavior = "auto");
36365		  obj(0);
36366		}
36367	  });
36368  
36369	  _triggers.slice(0).forEach(function (t) {
36370		return t.refresh();
36371	  });
36372  
36373	  _isReverted = false;
36374  
36375	  _triggers.forEach(function (t) {
36376		if (t._subPinOffset && t.pin) {
36377		  var prop = t.vars.horizontal ? "offsetWidth" : "offsetHeight",
36378			  original = t.pin[prop];
36379		  t.revert(true, 1);
36380		  t.adjustPinSpacing(t.pin[prop] - original);
36381		  t.refresh();
36382		}
36383	  });
36384  
36385	  _clampingMax = 1;
36386  
36387	  _hideAllMarkers(true);
36388  
36389	  _triggers.forEach(function (t) {
36390		var max = _maxScroll(t.scroller, t._dir),
36391			endClamp = t.vars.end === "max" || t._endClamp && t.end > max,
36392			startClamp = t._startClamp && t.start >= max;
36393  
36394		(endClamp || startClamp) && t.setPositions(startClamp ? max - 1 : t.start, endClamp ? Math.max(startClamp ? max : t.start + 1, max) : t.end, true);
36395	  });
36396  
36397	  _hideAllMarkers(false);
36398  
36399	  _clampingMax = 0;
36400	  refreshInits.forEach(function (result) {
36401		return result && result.render && result.render(-1);
36402	  });
36403  
36404	  _scrollers.forEach(function (obj) {
36405		if (_isFunction(obj)) {
36406		  obj.smooth && requestAnimationFrame(function () {
36407			return obj.target.style.scrollBehavior = "smooth";
36408		  });
36409		  obj.rec && obj(obj.rec);
36410		}
36411	  });
36412  
36413	  _clearScrollMemory(_scrollRestoration, 1);
36414  
36415	  _resizeDelay.pause();
36416  
36417	  _refreshID++;
36418	  _refreshingAll = 2;
36419  
36420	  _updateAll(2);
36421  
36422	  _triggers.forEach(function (t) {
36423		return _isFunction(t.vars.onRefresh) && t.vars.onRefresh(t);
36424	  });
36425  
36426	  _refreshingAll = ScrollTrigger$1.isRefreshing = false;
36427  
36428	  _dispatch("refresh");
36429	},
36430		_lastScroll = 0,
36431		_direction = 1,
36432		_primary,
36433		_updateAll = function _updateAll(force) {
36434	  if (force === 2 || !_refreshingAll && !_isReverted) {
36435		ScrollTrigger$1.isUpdating = true;
36436		_primary && _primary.update(0);
36437  
36438		var l = _triggers.length,
36439			time = _getTime$1(),
36440			recordVelocity = time - _time1 >= 50,
36441			scroll = l && _triggers[0].scroll();
36442  
36443		_direction = _lastScroll > scroll ? -1 : 1;
36444		_refreshingAll || (_lastScroll = scroll);
36445  
36446		if (recordVelocity) {
36447		  if (_lastScrollTime && !_pointerIsDown && time - _lastScrollTime > 200) {
36448			_lastScrollTime = 0;
36449  
36450			_dispatch("scrollEnd");
36451		  }
36452  
36453		  _time2 = _time1;
36454		  _time1 = time;
36455		}
36456  
36457		if (_direction < 0) {
36458		  _i = l;
36459  
36460		  while (_i-- > 0) {
36461			_triggers[_i] && _triggers[_i].update(0, recordVelocity);
36462		  }
36463  
36464		  _direction = 1;
36465		} else {
36466		  for (_i = 0; _i < l; _i++) {
36467			_triggers[_i] && _triggers[_i].update(0, recordVelocity);
36468		  }
36469		}
36470  
36471		ScrollTrigger$1.isUpdating = false;
36472	  }
36473  
36474	  _rafID = 0;
36475	},
36476		_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"],
36477		_stateProps = _propNamesToCopy.concat([_width, _height, "boxSizing", "max" + _Width, "max" + _Height, "position", _margin, _padding, _padding + _Top, _padding + _Right, _padding + _Bottom, _padding + _Left]),
36478		_swapPinOut = function _swapPinOut(pin, spacer, state) {
36479	  _setState(state);
36480  
36481	  var cache = pin._gsap;
36482  
36483	  if (cache.spacerIsNative) {
36484		_setState(cache.spacerState);
36485	  } else if (pin._gsap.swappedIn) {
36486		var parent = spacer.parentNode;
36487  
36488		if (parent) {
36489		  parent.insertBefore(pin, spacer);
36490		  parent.removeChild(spacer);
36491		}
36492	  }
36493  
36494	  pin._gsap.swappedIn = false;
36495	},
36496		_swapPinIn = function _swapPinIn(pin, spacer, cs, spacerState) {
36497	  if (!pin._gsap.swappedIn) {
36498		var i = _propNamesToCopy.length,
36499			spacerStyle = spacer.style,
36500			pinStyle = pin.style,
36501			p;
36502  
36503		while (i--) {
36504		  p = _propNamesToCopy[i];
36505		  spacerStyle[p] = cs[p];
36506		}
36507  
36508		spacerStyle.position = cs.position === "absolute" ? "absolute" : "relative";
36509		cs.display === "inline" && (spacerStyle.display = "inline-block");
36510		pinStyle[_bottom] = pinStyle[_right] = "auto";
36511		spacerStyle.flexBasis = cs.flexBasis || "auto";
36512		spacerStyle.overflow = "visible";
36513		spacerStyle.boxSizing = "border-box";
36514		spacerStyle[_width] = _getSize(pin, _horizontal) + _px;
36515		spacerStyle[_height] = _getSize(pin, _vertical) + _px;
36516		spacerStyle[_padding] = pinStyle[_margin] = pinStyle[_top] = pinStyle[_left] = "0";
36517  
36518		_setState(spacerState);
36519  
36520		pinStyle[_width] = pinStyle["max" + _Width] = cs[_width];
36521		pinStyle[_height] = pinStyle["max" + _Height] = cs[_height];
36522		pinStyle[_padding] = cs[_padding];
36523  
36524		if (pin.parentNode !== spacer) {
36525		  pin.parentNode.insertBefore(spacer, pin);
36526		  spacer.appendChild(pin);
36527		}
36528  
36529		pin._gsap.swappedIn = true;
36530	  }
36531	},
36532		_capsExp = /([A-Z])/g,
36533		_setState = function _setState(state) {
36534	  if (state) {
36535		var style = state.t.style,
36536			l = state.length,
36537			i = 0,
36538			p,
36539			value;
36540		(state.t._gsap || gsap$1.core.getCache(state.t)).uncache = 1;
36541  
36542		for (; i < l; i += 2) {
36543		  value = state[i + 1];
36544		  p = state[i];
36545  
36546		  if (value) {
36547			style[p] = value;
36548		  } else if (style[p]) {
36549			style.removeProperty(p.replace(_capsExp, "-$1").toLowerCase());
36550		  }
36551		}
36552	  }
36553	},
36554		_getState = function _getState(element) {
36555	  var l = _stateProps.length,
36556		  style = element.style,
36557		  state = [],
36558		  i = 0;
36559  
36560	  for (; i < l; i++) {
36561		state.push(_stateProps[i], style[_stateProps[i]]);
36562	  }
36563  
36564	  state.t = element;
36565	  return state;
36566	},
36567		_copyState = function _copyState(state, override, omitOffsets) {
36568	  var result = [],
36569		  l = state.length,
36570		  i = omitOffsets ? 8 : 0,
36571		  p;
36572  
36573	  for (; i < l; i += 2) {
36574		p = state[i];
36575		result.push(p, p in override ? override[p] : state[i + 1]);
36576	  }
36577  
36578	  result.t = state.t;
36579	  return result;
36580	},
36581		_winOffsets = {
36582	  left: 0,
36583	  top: 0
36584	},
36585		_parsePosition = function _parsePosition(value, trigger, scrollerSize, direction, scroll, marker, markerScroller, self, scrollerBounds, borderWidth, useFixedPosition, scrollerMax, containerAnimation, clampZeroProp) {
36586	  _isFunction(value) && (value = value(self));
36587  
36588	  if (_isString(value) && value.substr(0, 3) === "max") {
36589		value = scrollerMax + (value.charAt(4) === "=" ? _offsetToPx("0" + value.substr(3), scrollerSize) : 0);
36590	  }
36591  
36592	  var time = containerAnimation ? containerAnimation.time() : 0,
36593		  p1,
36594		  p2,
36595		  element;
36596	  containerAnimation && containerAnimation.seek(0);
36597	  isNaN(value) || (value = +value);
36598  
36599	  if (!_isNumber(value)) {
36600		_isFunction(trigger) && (trigger = trigger(self));
36601		var offsets = (value || "0").split(" "),
36602			bounds,
36603			localOffset,
36604			globalOffset,
36605			display;
36606		element = _getTarget(trigger, self) || _body$1;
36607		bounds = _getBounds(element) || {};
36608  
36609		if ((!bounds || !bounds.left && !bounds.top) && _getComputedStyle(element).display === "none") {
36610		  display = element.style.display;
36611		  element.style.display = "block";
36612		  bounds = _getBounds(element);
36613		  display ? element.style.display = display : element.style.removeProperty("display");
36614		}
36615  
36616		localOffset = _offsetToPx(offsets[0], bounds[direction.d]);
36617		globalOffset = _offsetToPx(offsets[1] || "0", scrollerSize);
36618		value = bounds[direction.p] - scrollerBounds[direction.p] - borderWidth + localOffset + scroll - globalOffset;
36619		markerScroller && _positionMarker(markerScroller, globalOffset, direction, scrollerSize - globalOffset < 20 || markerScroller._isStart && globalOffset > 20);
36620		scrollerSize -= scrollerSize - globalOffset;
36621	  } else {
36622		containerAnimation && (value = gsap$1.utils.mapRange(containerAnimation.scrollTrigger.start, containerAnimation.scrollTrigger.end, 0, scrollerMa
vendor: 4,541 bytes, lines 36622-36778
36622x, value));
36623		markerScroller && _positionMarker(markerScroller, scrollerSize, direction, true);
36624	  }
36625  
36626	  if (clampZeroProp) {
36627		self[clampZeroProp] = value || -0.001;
36628		value < 0 && (value = 0);
36629	  }
36630  
36631	  if (marker) {
36632		var position = value + scrollerSize,
36633			isStart = marker._isStart;
36634		p1 = "scroll" + direction.d2;
36635  
36636		_positionMarker(marker, position, direction, isStart && position > 20 || !isStart && (useFixedPosition ? Math.max(_body$1[p1], _docEl$1[p1]) : marker.parentNode[p1]) <= position + 1);
36637  
36638		if (useFixedPosition) {
36639		  scrollerBounds = _getBounds(markerScroller);
36640		  useFixedPosition && (marker.style[direction.op.p] = scrollerBounds[direction.op.p] - direction.op.m - marker._offset + _px);
36641		}
36642	  }
36643  
36644	  if (containerAnimation && element) {
36645		p1 = _getBounds(element);
36646		containerAnimation.seek(scrollerMax);
36647		p2 = _getBounds(element);
36648		containerAnimation._caScrollDist = p1[direction.p] - p2[direction.p];
36649		value = value / containerAnimation._caScrollDist * scrollerMax;
36650	  }
36651  
36652	  containerAnimation && containerAnimation.seek(time);
36653	  return containerAnimation ? value : Math.round(value);
36654	},
36655		_prefixExp = /(webkit|moz|length|cssText|inset)/i,
36656		_reparent = function _reparent(element, parent, top, left) {
36657	  if (element.parentNode !== parent) {
36658		var style = element.style,
36659			p,
36660			cs;
36661  
36662		if (parent === _body$1) {
36663		  element._stOrig = style.cssText;
36664		  cs = _getComputedStyle(element);
36665  
36666		  for (p in cs) {
36667			if (!+p && !_prefixExp.test(p) && cs[p] && typeof style[p] === "string" && p !== "0") {
36668			  style[p] = cs[p];
36669			}
36670		  }
36671  
36672		  style.top = top;
36673		  style.left = left;
36674		} else {
36675		  style.cssText = element._stOrig;
36676		}
36677  
36678		gsap$1.core.getCache(element).uncache = 1;
36679		parent.appendChild(element);
36680	  }
36681	},
36682		_interruptionTracker = function _interruptionTracker(getValueFunc, initialValue, onInterrupt) {
36683	  var last1 = initialValue,
36684		  last2 = last1;
36685	  return function (value) {
36686		var current = Math.round(getValueFunc());
36687  
36688		if (current !== last1 && current !== last2 && Math.abs(current - last1) > 3 && Math.abs(current - last2) > 3) {
36689		  value = current;
36690		  onInterrupt && onInterrupt();
36691		}
36692  
36693		last2 = last1;
36694		last1 = value;
36695		return value;
36696	  };
36697	},
36698		_shiftMarker = function _shiftMarker(marker, direction, value) {
36699	  var vars = {};
36700	  vars[direction.p] = "+=" + value;
36701	  gsap$1.set(marker, vars);
36702	},
36703		_getTweenCreator = function _getTweenCreator(scroller, direction) {
36704	  var getScroll = _getScrollFunc(scroller, direction),
36705		  prop = "_scroll" + direction.p2,
36706		  getTween = function getTween(scrollTo, vars, initialValue, change1, change2) {
36707		var tween = getTween.tween,
36708			onComplete = vars.onComplete,
36709			modifiers = {};
36710		initialValue = initialValue || getScroll();
36711  
36712		var checkForInterruption = _interruptionTracker(getScroll, initialValue, function () {
36713		  tween.kill();
36714		  getTween.tween = 0;
36715		});
36716  
36717		change2 = change1 && change2 || 0;
36718		change1 = change1 || scrollTo - initialValue;
36719		tween && tween.kill();
36720		vars[prop] = scrollTo;
36721		vars.inherit = false;
36722		vars.modifiers = modifiers;
36723  
36724		modifiers[prop] = function () {
36725		  return checkForInterruption(initialValue + change1 * tween.ratio + change2 * tween.ratio * tween.ratio);
36726		};
36727  
36728		vars.onUpdate = function () {
36729		  _scrollers.cache++;
36730		  getTween.tween && _updateAll();
36731		};
36732  
36733		vars.onComplete = function () {
36734		  getTween.tween = 0;
36735		  onComplete && onComplete.call(tween);
36736		};
36737  
36738		tween = getTween.tween = gsap$1.to(scroller, vars);
36739		return tween;
36740	  };
36741  
36742	  scroller[prop] = getScroll;
36743  
36744	  getScroll.wheelHandler = function () {
36745		return getTween.tween && getTween.tween.kill() && (getTween.tween = 0);
36746	  };
36747  
36748	  _addListener$1(scroller, "wheel", getScroll.wheelHandler);
36749  
36750	  ScrollTrigger$1.isTouch && _addListener$1(scroller, "touchmove", getScroll.wheelHandler);
36751	  return getTween;
36752	};
36753  
36754	var ScrollTrigger$1 = function () {
36755	  function ScrollTrigger(vars, animation) {
36756		_coreInitted$1 || ScrollTrigger.register(gsap$1) || console.warn("Please gsap.registerPlugin(ScrollTrigger)");
36757  
36758		_context$1(this);
36759  
36760		this.init(vars, animation);
36761	  }
36762  
36763	  var _proto = ScrollTrigger.prototype;
36764  
36765	  _proto.init = function init(vars, animation) {
36766		this.progress = this.start = 0;
36767		this.vars && this.kill(true, true);
36768  
36769		if (!_enabled) {
36770		  this.update = this.refresh = this.kill = _passThrough;
36771		  return;
36772		}
36773  
36774		vars = _setDefaults(_isString(vars) || _isNumber(vars) || vars.nodeType ? {
36775		  trigger: vars
36776		} : vars, _defaults);
36777  
36778		var _vars = vars,
vendor: 4,184 bytes, lines 36779-36919
36779			onUpdate = _vars.onUpdate,
36780			toggleClass = _vars.toggleClass,
36781			id = _vars.id,
36782			onToggle = _vars.onToggle,
36783			onRefresh = _vars.onRefresh,
36784			scrub = _vars.scrub,
36785			trigger = _vars.trigger,
36786			pin = _vars.pin,
36787			pinSpacing = _vars.pinSpacing,
36788			invalidateOnRefresh = _vars.invalidateOnRefresh,
36789			anticipatePin = _vars.anticipatePin,
36790			onScrubComplete = _vars.onScrubComplete,
36791			onSnapComplete = _vars.onSnapComplete,
36792			once = _vars.once,
36793			snap = _vars.snap,
36794			pinReparent = _vars.pinReparent,
36795			pinSpacer = _vars.pinSpacer,
36796			containerAnimation = _vars.containerAnimation,
36797			fastScrollEnd = _vars.fastScrollEnd,
36798			preventOverlaps = _vars.preventOverlaps,
36799			direction = vars.horizontal || vars.containerAnimation && vars.horizontal !== false ? _horizontal : _vertical,
36800			isToggle = !scrub && scrub !== 0,
36801			scroller = _getTarget(vars.scroller || _win$1),
36802			scrollerCache = gsap$1.core.getCache(scroller),
36803			isViewport = _isViewport$1(scroller),
36804			useFixedPosition = ("pinType" in vars ? vars.pinType : _getProxyProp(scroller, "pinType") || isViewport && "fixed") === "fixed",
36805			callbacks = [vars.onEnter, vars.onLeave, vars.onEnterBack, vars.onLeaveBack],
36806			toggleActions = isToggle && vars.toggleActions.split(" "),
36807			markers = "markers" in vars ? vars.markers : _defaults.markers,
36808			borderWidth = isViewport ? 0 : parseFloat(_getComputedStyle(scroller)["border" + direction.p2 + _Width]) || 0,
36809			self = this,
36810			onRefreshInit = vars.onRefreshInit && function () {
36811		  return vars.onRefreshInit(self);
36812		},
36813			getScrollerSize = _getSizeFunc(scroller, isViewport, direction),
36814			getScrollerOffsets = _getOffsetsFunc(scroller, isViewport),
36815			lastSnap = 0,
36816			lastRefresh = 0,
36817			prevProgress = 0,
36818			scrollFunc = _getScrollFunc(scroller, direction),
36819			tweenTo,
36820			pinCache,
36821			snapFunc,
36822			scroll1,
36823			scroll2,
36824			start,
36825			end,
36826			markerStart,
36827			markerEnd,
36828			markerStartTrigger,
36829			markerEndTrigger,
36830			markerVars,
36831			executingOnRefresh,
36832			change,
36833			pinOriginalState,
36834			pinActiveState,
36835			pinState,
36836			spacer,
36837			offset,
36838			pinGetter,
36839			pinSetter,
36840			pinStart,
36841			pinChange,
36842			spacingStart,
36843			spacerState,
36844			markerStartSetter,
36845			pinMoves,
36846			markerEndSetter,
36847			cs,
36848			snap1,
36849			snap2,
36850			scrubTween,
36851			scrubSmooth,
36852			snapDurClamp,
36853			snapDelayedCall,
36854			prevScroll,
36855			prevAnimProgress,
36856			caMarkerSetter,
36857			customRevertReturn;
36858  
36859		self._startClamp = self._endClamp = false;
36860		self._dir = direction;
36861		anticipatePin *= 45;
36862		self.scroller = scroller;
36863		self.scroll = containerAnimation ? containerAnimation.time.bind(containerAnimation) : scrollFunc;
36864		scroll1 = scrollFunc();
36865		self.vars = vars;
36866		animation = animation || vars.animation;
36867  
36868		if ("refreshPriority" in vars) {
36869		  _sort = 1;
36870		  vars.refreshPriority === -9999 && (_primary = self);
36871		}
36872  
36873		scrollerCache.tweenScroll = scrollerCache.tweenScroll || {
36874		  top: _getTweenCreator(scroller, _vertical),
36875		  left: _getTweenCreator(scroller, _horizontal)
36876		};
36877		self.tweenTo = tweenTo = scrollerCache.tweenScroll[direction.p];
36878  
36879		self.scrubDuration = function (value) {
36880		  scrubSmooth = _isNumber(value) && value;
36881  
36882		  if (!scrubSmooth) {
36883			scrubTween && scrubTween.progress(1).kill();
36884			scrubTween = 0;
36885		  } else {
36886			scrubTween ? scrubTween.duration(value) : scrubTween = gsap$1.to(animation, {
36887			  ease: "expo",
36888			  totalProgress: "+=0",
36889			  inherit: false,
36890			  duration: scrubSmooth,
36891			  paused: true,
36892			  onComplete: function onComplete() {
36893				return onScrubComplete && onScrubComplete(self);
36894			  }
36895			});
36896		  }
36897		};
36898  
36899		if (animation) {
36900		  animation.vars.lazy = false;
36901		  animation._initted && !self.isReverted || animation.vars.immediateRender !== false && vars.immediateRender !== false && animation.duration() && animation.render(0, true, true);
36902		  self.animation = animation.pause();
36903		  animation.scrollTrigger = self;
36904		  self.scrubDuration(scrub);
36905		  snap1 = 0;
36906		  id || (id = animation.vars.id);
36907		}
36908  
36909		if (snap) {
36910		  if (!_isObject(snap) || snap.push) {
36911			snap = {
36912			  snapTo: snap
36913			};
36914		  }
36915  
36916		  "scrollBehavior" in _body$1.style && gsap$1.set(isViewport ? [_body$1, _docEl$1] : scroller, {
36917			scrollBehavior: "auto"
36918		  });
36919  
vendor: 4,259 bytes, lines 36920-37015
36920		  _scrollers.forEach(function (o) {
36921			return _isFunction(o) && o.target === (isViewport ? _doc$1.scrollingElement || _docEl$1 : scroller) && (o.smooth = false);
36922		  });
36923  
36924		  snapFunc = _isFunction(snap.snapTo) ? snap.snapTo : snap.snapTo === "labels" ? _getClosestLabel(animation) : snap.snapTo === "labelsDirectional" ? _getLabelAtDirection(animation) : snap.directional !== false ? function (value, st) {
36925			return _snapDirectional(snap.snapTo)(value, _getTime$1() - lastRefresh < 500 ? 0 : st.direction);
36926		  } : gsap$1.utils.snap(snap.snapTo);
36927		  snapDurClamp = snap.duration || {
36928			min: 0.1,
36929			max: 2
36930		  };
36931		  snapDurClamp = _isObject(snapDurClamp) ? _clamp$1(snapDurClamp.min, snapDurClamp.max) : _clamp$1(snapDurClamp, snapDurClamp);
36932		  snapDelayedCall = gsap$1.delayedCall(snap.delay || scrubSmooth / 2 || 0.1, function () {
36933			var scroll = scrollFunc(),
36934				refreshedRecently = _getTime$1() - lastRefresh < 500,
36935				tween = tweenTo.tween;
36936  
36937			if ((refreshedRecently || Math.abs(self.getVelocity()) < 10) && !tween && !_pointerIsDown && lastSnap !== scroll) {
36938			  var progress = (scroll - start) / change,
36939				  totalProgress = animation && !isToggle ? animation.totalProgress() : progress,
36940				  velocity = refreshedRecently ? 0 : (totalProgress - snap2) / (_getTime$1() - _time2) * 1000 || 0,
36941				  change1 = gsap$1.utils.clamp(-progress, 1 - progress, _abs(velocity / 2) * velocity / 0.185),
36942				  naturalEnd = progress + (snap.inertia === false ? 0 : change1),
36943				  endValue,
36944				  endScroll,
36945				  _snap = snap,
36946				  onStart = _snap.onStart,
36947				  _onInterrupt = _snap.onInterrupt,
36948				  _onComplete = _snap.onComplete;
36949			  endValue = snapFunc(naturalEnd, self);
36950			  _isNumber(endValue) || (endValue = naturalEnd);
36951			  endScroll = Math.round(start + endValue * change);
36952  
36953			  if (scroll <= end && scroll >= start && endScroll !== scroll) {
36954				if (tween && !tween._initted && tween.data <= _abs(endScroll - scroll)) {
36955				  return;
36956				}
36957  
36958				if (snap.inertia === false) {
36959				  change1 = endValue - progress;
36960				}
36961  
36962				tweenTo(endScroll, {
36963				  duration: snapDurClamp(_abs(Math.max(_abs(naturalEnd - totalProgress), _abs(endValue - totalProgress)) * 0.185 / velocity / 0.05 || 0)),
36964				  ease: snap.ease || "power3",
36965				  data: _abs(endScroll - scroll),
36966				  onInterrupt: function onInterrupt() {
36967					return snapDelayedCall.restart(true) && _onInterrupt && _onInterrupt(self);
36968				  },
36969				  onComplete: function onComplete() {
36970					self.update();
36971					lastSnap = scrollFunc();
36972  
36973					if (animation) {
36974					  scrubTween ? scrubTween.resetTo("totalProgress", endValue, animation._tTime / animation._tDur) : animation.progress(endValue);
36975					}
36976  
36977					snap1 = snap2 = animation && !isToggle ? animation.totalProgress() : self.progress;
36978					onSnapComplete && onSnapComplete(self);
36979					_onComplete && _onComplete(self);
36980				  }
36981				}, scroll, change1 * change, endScroll - scroll - change1 * change);
36982				onStart && onStart(self, tweenTo.tween);
36983			  }
36984			} else if (self.isActive && lastSnap !== scroll) {
36985			  snapDelayedCall.restart(true);
36986			}
36987		  }).pause();
36988		}
36989  
36990		id && (_ids[id] = self);
36991		trigger = self.trigger = _getTarget(trigger || pin !== true && pin);
36992		customRevertReturn = trigger && trigger._gsap && trigger._gsap.stRevert;
36993		customRevertReturn && (customRevertReturn = customRevertReturn(self));
36994		pin = pin === true ? trigger : _getTarget(pin);
36995		_isString(toggleClass) && (toggleClass = {
36996		  targets: trigger,
36997		  className: toggleClass
36998		});
36999  
37000		if (pin) {
37001		  pinSpacing === false || pinSpacing === _margin || (pinSpacing = !pinSpacing && pin.parentNode && pin.parentNode.style && _getComputedStyle(pin.parentNode).display === "flex" ? false : _padding);
37002		  self.pin = pin;
37003		  pinCache = gsap$1.core.getCache(pin);
37004  
37005		  if (!pinCache.spacer) {
37006			if (pinSpacer) {
37007			  pinSpacer = _getTarget(pinSpacer);
37008			  pinSpacer && !pinSpacer.nodeType && (pinSpacer = pinSpacer.current || pinSpacer.nativeElement);
37009			  pinCache.spacerIsNative = !!pinSpacer;
37010			  pinSpacer && (pinCache.spacerState = _getState(pinSpacer));
37011			}
37012  
37013			pinCache.spacer = spacer = pinSpacer || _doc$1.createElement("div");
37014			spacer.classList.add("pin-spacer");
37015			id && spacer.classList.add("pin-spacer-" + id);
vendor: 4,987 bytes, lines 37016-37170
37016			pinCache.pinState = pinOriginalState = _getState(pin);
37017		  } else {
37018			pinOriginalState = pinCache.pinState;
37019		  }
37020  
37021		  vars.force3D !== false && gsap$1.set(pin, {
37022			force3D: true
37023		  });
37024		  self.spacer = spacer = pinCache.spacer;
37025		  cs = _getComputedStyle(pin);
37026		  spacingStart = cs[pinSpacing + direction.os2];
37027		  pinGetter = gsap$1.getProperty(pin);
37028		  pinSetter = gsap$1.quickSetter(pin, direction.a, _px);
37029  
37030		  _swapPinIn(pin, spacer, cs);
37031  
37032		  pinState = _getState(pin);
37033		}
37034  
37035		if (markers) {
37036		  markerVars = _isObject(markers) ? _setDefaults(markers, _markerDefaults) : _markerDefaults;
37037		  markerStartTrigger = _createMarker("scroller-start", id, scroller, direction, markerVars, 0);
37038		  markerEndTrigger = _createMarker("scroller-end", id, scroller, direction, markerVars, 0, markerStartTrigger);
37039		  offset = markerStartTrigger["offset" + direction.op.d2];
37040  
37041		  var content = _getTarget(_getProxyProp(scroller, "content") || scroller);
37042  
37043		  markerStart = this.markerStart = _createMarker("start", id, content, direction, markerVars, offset, 0, containerAnimation);
37044		  markerEnd = this.markerEnd = _createMarker("end", id, content, direction, markerVars, offset, 0, containerAnimation);
37045		  containerAnimation && (caMarkerSetter = gsap$1.quickSetter([markerStart, markerEnd], direction.a, _px));
37046  
37047		  if (!useFixedPosition && !(_proxies.length && _getProxyProp(scroller, "fixedMarkers") === true)) {
37048			_makePositionable(isViewport ? _body$1 : scroller);
37049  
37050			gsap$1.set([markerStartTrigger, markerEndTrigger], {
37051			  force3D: true
37052			});
37053			markerStartSetter = gsap$1.quickSetter(markerStartTrigger, direction.a, _px);
37054			markerEndSetter = gsap$1.quickSetter(markerEndTrigger, direction.a, _px);
37055		  }
37056		}
37057  
37058		if (containerAnimation) {
37059		  var oldOnUpdate = containerAnimation.vars.onUpdate,
37060			  oldParams = containerAnimation.vars.onUpdateParams;
37061		  containerAnimation.eventCallback("onUpdate", function () {
37062			self.update(0, 0, 1);
37063			oldOnUpdate && oldOnUpdate.apply(containerAnimation, oldParams || []);
37064		  });
37065		}
37066  
37067		self.previous = function () {
37068		  return _triggers[_triggers.indexOf(self) - 1];
37069		};
37070  
37071		self.next = function () {
37072		  return _triggers[_triggers.indexOf(self) + 1];
37073		};
37074  
37075		self.revert = function (revert, temp) {
37076		  if (!temp) {
37077			return self.kill(true);
37078		  }
37079  
37080		  var r = revert !== false || !self.enabled,
37081			  prevRefreshing = _refreshing;
37082  
37083		  if (r !== self.isReverted) {
37084			if (r) {
37085			  prevScroll = Math.max(scrollFunc(), self.scroll.rec || 0);
37086			  prevProgress = self.progress;
37087			  prevAnimProgress = animation && animation.progress();
37088			}
37089  
37090			markerStart && [markerStart, markerEnd, markerStartTrigger, markerEndTrigger].forEach(function (m) {
37091			  return m.style.display = r ? "none" : "block";
37092			});
37093  
37094			if (r) {
37095			  _refreshing = self;
37096			  self.update(r);
37097			}
37098  
37099			if (pin && (!pinReparent || !self.isActive)) {
37100			  if (r) {
37101				_swapPinOut(pin, spacer, pinOriginalState);
37102			  } else {
37103				_swapPinIn(pin, spacer, _getComputedStyle(pin), spacerState);
37104			  }
37105			}
37106  
37107			r || self.update(r);
37108			_refreshing = prevRefreshing;
37109			self.isReverted = r;
37110		  }
37111		};
37112  
37113		self.refresh = function (soft, force, position, pinOffset) {
37114		  if ((_refreshing || !self.enabled) && !force) {
37115			return;
37116		  }
37117  
37118		  if (pin && soft && _lastScrollTime) {
37119			_addListener$1(ScrollTrigger, "scrollEnd", _softRefresh);
37120  
37121			return;
37122		  }
37123  
37124		  !_refreshingAll && onRefreshInit && onRefreshInit(self);
37125		  _refreshing = self;
37126  
37127		  if (tweenTo.tween && !position) {
37128			tweenTo.tween.kill();
37129			tweenTo.tween = 0;
37130		  }
37131  
37132		  scrubTween && scrubTween.pause();
37133		  invalidateOnRefresh && animation && animation.revert({
37134			kill: false
37135		  }).invalidate();
37136		  self.isReverted || self.revert(true, true);
37137		  self._subPinOffset = false;
37138  
37139		  var size = getScrollerSize(),
37140			  scrollerBounds = getScrollerOffsets(),
37141			  max = containerAnimation ? containerAnimation.duration() : _maxScroll(scroller, direction),
37142			  isFirstRefresh = change <= 0.01,
37143			  offset = 0,
37144			  otherPinOffset = pinOffset || 0,
37145			  parsedEnd = _isObject(position) ? position.end : vars.end,
37146			  parsedEndTrigger = vars.endTrigger || trigger,
37147			  parsedStart = _isObject(position) ? position.start : vars.start || (vars.start === 0 || !trigger ? 0 : pin ? "0 0" : "0 100%"),
37148			  pinnedContainer = self.pinnedContainer = vars.pinnedContainer && _getTarget(vars.pinnedContainer, self),
37149			  triggerIndex = trigger && Math.max(0, _triggers.indexOf(self)) || 0,
37150			  i = triggerIndex,
37151			  cs,
37152			  bounds,
37153			  scroll,
37154			  isVertical,
37155			  override,
37156			  curTrigger,
37157			  curPin,
37158			  oppositeScroll,
37159			  initted,
37160			  revertedPins,
37161			  forcedOverflow,
37162			  markerStartOffset,
37163			  markerEndOffset;
37164  
37165		  if (markers && _isObject(position)) {
37166			markerStartOffset = gsap$1.getProperty(markerStartTrigger, direction.p);
37167			markerEndOffset = gsap$1.getProperty(markerEndTrigger, direction.p);
37168		  }
37169  
37170		  while (i--) {
vendor: 4,360 bytes, lines 37171-37282
37171			curTrigger = _triggers[i];
37172			curTrigger.end || curTrigger.refresh(0, 1) || (_refreshing = self);
37173			curPin = curTrigger.pin;
37174  
37175			if (curPin && (curPin === trigger || curPin === pin || curPin === pinnedContainer) && !curTrigger.isReverted) {
37176			  revertedPins || (revertedPins = []);
37177			  revertedPins.unshift(curTrigger);
37178			  curTrigger.revert(true, true);
37179			}
37180  
37181			if (curTrigger !== _triggers[i]) {
37182			  triggerIndex--;
37183			  i--;
37184			}
37185		  }
37186  
37187		  _isFunction(parsedStart) && (parsedStart = parsedStart(self));
37188		  parsedStart = _parseClamp(parsedStart, "start", self);
37189		  start = _parsePosition(parsedStart, trigger, size, direction, scrollFunc(), markerStart, markerStartTrigger, self, scrollerBounds, borderWidth, useFixedPosition, max, containerAnimation, self._startClamp && "_startClamp") || (pin ? -0.001 : 0);
37190		  _isFunction(parsedEnd) && (parsedEnd = parsedEnd(self));
37191  
37192		  if (_isString(parsedEnd) && !parsedEnd.indexOf("+=")) {
37193			if (~parsedEnd.indexOf(" ")) {
37194			  parsedEnd = (_isString(parsedStart) ? parsedStart.split(" ")[0] : "") + parsedEnd;
37195			} else {
37196			  offset = _offsetToPx(parsedEnd.substr(2), size);
37197			  parsedEnd = _isString(parsedStart) ? parsedStart : (containerAnimation ? gsap$1.utils.mapRange(0, containerAnimation.duration(), containerAnimation.scrollTrigger.start, containerAnimation.scrollTrigger.end, start) : start) + offset;
37198			  parsedEndTrigger = trigger;
37199			}
37200		  }
37201  
37202		  parsedEnd = _parseClamp(parsedEnd, "end", self);
37203		  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;
37204		  offset = 0;
37205		  i = triggerIndex;
37206  
37207		  while (i--) {
37208			curTrigger = _triggers[i];
37209			curPin = curTrigger.pin;
37210  
37211			if (curPin && curTrigger.start - curTrigger._pinPush <= start && !containerAnimation && curTrigger.end > 0) {
37212			  cs = curTrigger.end - (self._startClamp ? Math.max(0, curTrigger.start) : curTrigger.start);
37213  
37214			  if ((curPin === trigger && curTrigger.start - curTrigger._pinPush < start || curPin === pinnedContainer) && isNaN(parsedStart)) {
37215				offset += cs * (1 - curTrigger.progress);
37216			  }
37217  
37218			  curPin === pin && (otherPinOffset += cs);
37219			}
37220		  }
37221  
37222		  start += offset;
37223		  end += offset;
37224		  self._startClamp && (self._startClamp += offset);
37225  
37226		  if (self._endClamp && !_refreshingAll) {
37227			self._endClamp = end || -0.001;
37228			end = Math.min(end, _maxScroll(scroller, direction));
37229		  }
37230  
37231		  change = end - start || (start -= 0.01) && 0.001;
37232  
37233		  if (isFirstRefresh) {
37234			prevProgress = gsap$1.utils.clamp(0, 1, gsap$1.utils.normalize(start, end, prevScroll));
37235		  }
37236  
37237		  self._pinPush = otherPinOffset;
37238  
37239		  if (markerStart && offset) {
37240			cs = {};
37241			cs[direction.a] = "+=" + offset;
37242			pinnedContainer && (cs[direction.p] = "-=" + scrollFunc());
37243			gsap$1.set([markerStart, markerEnd], cs);
37244		  }
37245  
37246		  if (pin && !(_clampingMax && self.end >= _maxScroll(scroller, direction))) {
37247			cs = _getComputedStyle(pin);
37248			isVertical = direction === _vertical;
37249			scroll = scrollFunc();
37250			pinStart = parseFloat(pinGetter(direction.a)) + otherPinOffset;
37251  
37252			if (!max && end > 1) {
37253			  forcedOverflow = (isViewport ? _doc$1.scrollingElement || _docEl$1 : scroller).style;
37254			  forcedOverflow = {
37255				style: forcedOverflow,
37256				value: forcedOverflow["overflow" + direction.a.toUpperCase()]
37257			  };
37258  
37259			  if (isViewport && _getComputedStyle(_body$1)["overflow" + direction.a.toUpperCase()] !== "scroll") {
37260				forcedOverflow.style["overflow" + direction.a.toUpperCase()] = "scroll";
37261			  }
37262			}
37263  
37264			_swapPinIn(pin, spacer, cs);
37265  
37266			pinState = _getState(pin);
37267			bounds = _getBounds(pin, true);
37268			oppositeScroll = useFixedPosition && _getScrollFunc(scroller, isVertical ? _horizontal : _vertical)();
37269  
37270			if (pinSpacing) {
37271			  spacerState = [pinSpacing + direction.os2, change + otherPinOffset + _px];
37272			  spacerState.t = spacer;
37273			  i = pinSpacing === _padding ? _getSize(pin, direction) + change + otherPinOffset : 0;
37274  
37275			  if (i) {
37276				spacerState.push(direction.d, i + _px);
37277				spacer.style.flexBasis !== "auto" && (spacer.style.flexBasis = i + _px);
37278			  }
37279  
37280			  _setState(spacerState);
37281  
37282			  if (pinnedContainer) {
vendor: 28,838 bytes, lines 37283-38173
37283				_triggers.forEach(function (t) {
37284				  if (t.pin === pinnedContainer && t.vars.pinSpacing !== false) {
37285					t._subPinOffset = true;
37286				  }
37287				});
37288			  }
37289  
37290			  useFixedPosition && scrollFunc(prevScroll);
37291			} else {
37292			  i = _getSize(pin, direction);
37293			  i && spacer.style.flexBasis !== "auto" && (spacer.style.flexBasis = i + _px);
37294			}
37295  
37296			if (useFixedPosition) {
37297			  override = {
37298				top: bounds.top + (isVertical ? scroll - start : oppositeScroll) + _px,
37299				left: bounds.left + (isVertical ? oppositeScroll : scroll - start) + _px,
37300				boxSizing: "border-box",
37301				position: "fixed"
37302			  };
37303			  override[_width] = override["max" + _Width] = Math.ceil(bounds.width) + _px;
37304			  override[_height] = override["max" + _Height] = Math.ceil(bounds.height) + _px;
37305			  override[_margin] = override[_margin + _Top] = override[_margin + _Right] = override[_margin + _Bottom] = override[_margin + _Left] = "0";
37306			  override[_padding] = cs[_padding];
37307			  override[_padding + _Top] = cs[_padding + _Top];
37308			  override[_padding + _Right] = cs[_padding + _Right];
37309			  override[_padding + _Bottom] = cs[_padding + _Bottom];
37310			  override[_padding + _Left] = cs[_padding + _Left];
37311			  pinActiveState = _copyState(pinOriginalState, override, pinReparent);
37312			  _refreshingAll && scrollFunc(0);
37313			}
37314  
37315			if (animation) {
37316			  initted = animation._initted;
37317  
37318			  _suppressOverwrites(1);
37319  
37320			  animation.render(animation.duration(), true, true);
37321			  pinChange = pinGetter(direction.a) - pinStart + change + otherPinOffset;
37322			  pinMoves = Math.abs(change - pinChange) > 1;
37323			  useFixedPosition && pinMoves && pinActiveState.splice(pinActiveState.length - 2, 2);
37324			  animation.render(0, true, true);
37325			  initted || animation.invalidate(true);
37326			  animation.parent || animation.totalTime(animation.totalTime());
37327  
37328			  _suppressOverwrites(0);
37329			} else {
37330			  pinChange = change;
37331			}
37332  
37333			forcedOverflow && (forcedOverflow.value ? forcedOverflow.style["overflow" + direction.a.toUpperCase()] = forcedOverflow.value : forcedOverflow.style.removeProperty("overflow-" + direction.a));
37334		  } else if (trigger && scrollFunc() && !containerAnimation) {
37335			bounds = trigger.parentNode;
37336  
37337			while (bounds && bounds !== _body$1) {
37338			  if (bounds._pinOffset) {
37339				start -= bounds._pinOffset;
37340				end -= bounds._pinOffset;
37341			  }
37342  
37343			  bounds = bounds.parentNode;
37344			}
37345		  }
37346  
37347		  revertedPins && revertedPins.forEach(function (t) {
37348			return t.revert(false, true);
37349		  });
37350		  self.start = start;
37351		  self.end = end;
37352		  scroll1 = scroll2 = _refreshingAll ? prevScroll : scrollFunc();
37353  
37354		  if (!containerAnimation && !_refreshingAll) {
37355			scroll1 < prevScroll && scrollFunc(prevScroll);
37356			self.scroll.rec = 0;
37357		  }
37358  
37359		  self.revert(false, true);
37360		  lastRefresh = _getTime$1();
37361  
37362		  if (snapDelayedCall) {
37363			lastSnap = -1;
37364			snapDelayedCall.restart(true);
37365		  }
37366  
37367		  _refreshing = 0;
37368		  animation && isToggle && (animation._initted || prevAnimProgress) && animation.progress() !== prevAnimProgress && animation.progress(prevAnimProgress || 0, true).render(animation.time(), true, true);
37369  
37370		  if (isFirstRefresh || prevProgress !== self.progress || containerAnimation || invalidateOnRefresh) {
37371			animation && !isToggle && animation.totalProgress(containerAnimation && start < -0.001 && !prevProgress ? gsap$1.utils.normalize(start, end, 0) : prevProgress, true);
37372			self.progress = isFirstRefresh || (scroll1 - start) / change === prevProgress ? 0 : prevProgress;
37373		  }
37374  
37375		  pin && pinSpacing && (spacer._pinOffset = Math.round(self.progress * pinChange));
37376		  scrubTween && scrubTween.invalidate();
37377  
37378		  if (!isNaN(markerStartOffset)) {
37379			markerStartOffset -= gsap$1.getProperty(markerStartTrigger, direction.p);
37380			markerEndOffset -= gsap$1.getProperty(markerEndTrigger, direction.p);
37381  
37382			_shiftMarker(markerStartTrigger, direction, markerStartOffset);
37383  
37384			_shiftMarker(markerStart, direction, markerStartOffset - (pinOffset || 0));
37385  
37386			_shiftMarker(markerEndTrigger, direction, markerEndOffset);
37387  
37388			_shiftMarker(markerEnd, direction, markerEndOffset - (pinOffset || 0));
37389		  }
37390  
37391		  isFirstRefresh && !_refreshingAll && self.update();
37392  
37393		  if (onRefresh && !_refreshingAll && !executingOnRefresh) {
37394			executingOnRefresh = true;
37395			onRefresh(self);
37396			executingOnRefresh = false;
37397		  }
37398		};
37399  
37400		self.getVelocity = function () {
37401		  return (scrollFunc() - scroll2) / (_getTime$1() - _time2) * 1000 || 0;
37402		};
37403  
37404		self.endAnimation = function () {
37405		  _endAnimation(self.callbackAnimation);
37406  
37407		  if (animation) {
37408			scrubTween ? scrubTween.progress(1) : !animation.paused() ? _endAnimation(animation, animation.reversed()) : isToggle || _endAnimation(animation, self.direction < 0, 1);
37409		  }
37410		};
37411  
37412		self.labelToScroll = function (label) {
37413		  return animation && animation.labels && (start || self.refresh() || start) + animation.labels[label] / animation.duration() * change || 0;
37414		};
37415  
37416		self.getTrailing = function (name) {
37417		  var i = _triggers.indexOf(self),
37418			  a = self.direction > 0 ? _triggers.slice(0, i).reverse() : _triggers.slice(i + 1);
37419  
37420		  return (_isString(name) ? a.filter(function (t) {
37421			return t.vars.preventOverlaps === name;
37422		  }) : a).filter(function (t) {
37423			return self.direction > 0 ? t.end <= start : t.start >= end;
37424		  });
37425		};
37426  
37427		self.update = function (reset, recordVelocity, forceFake) {
37428		  if (containerAnimation && !forceFake && !reset) {
37429			return;
37430		  }
37431  
37432		  var scroll = _refreshingAll === true ? prevScroll : self.scroll(),
37433			  p = reset ? 0 : (scroll - start) / change,
37434			  clipped = p < 0 ? 0 : p > 1 ? 1 : p || 0,
37435			  prevProgress = self.progress,
37436			  isActive,
37437			  wasActive,
37438			  toggleState,
37439			  action,
37440			  stateChanged,
37441			  toggled,
37442			  isAtMax,
37443			  isTakingAction;
37444  
37445		  if (recordVelocity) {
37446			scroll2 = scroll1;
37447			scroll1 = containerAnimation ? scrollFunc() : scroll;
37448  
37449			if (snap) {
37450			  snap2 = snap1;
37451			  snap1 = animation && !isToggle ? animation.totalProgress() : clipped;
37452			}
37453		  }
37454  
37455		  if (anticipatePin && pin && !_refreshing && !_startup$1 && _lastScrollTime) {
37456			if (!clipped && start < scroll + (scroll - scroll2) / (_getTime$1() - _time2) * anticipatePin) {
37457			  clipped = 0.0001;
37458			} else if (clipped === 1 && end > scroll + (scroll - scroll2) / (_getTime$1() - _time2) * anticipatePin) {
37459			  clipped = 0.9999;
37460			}
37461		  }
37462  
37463		  if (clipped !== prevProgress && self.enabled) {
37464			isActive = self.isActive = !!clipped && clipped < 1;
37465			wasActive = !!prevProgress && prevProgress < 1;
37466			toggled = isActive !== wasActive;
37467			stateChanged = toggled || !!clipped !== !!prevProgress;
37468			self.direction = clipped > prevProgress ? 1 : -1;
37469			self.progress = clipped;
37470  
37471			if (stateChanged && !_refreshing) {
37472			  toggleState = clipped && !prevProgress ? 0 : clipped === 1 ? 1 : prevProgress === 1 ? 2 : 3;
37473  
37474			  if (isToggle) {
37475				action = !toggled && toggleActions[toggleState + 1] !== "none" && toggleActions[toggleState + 1] || toggleActions[toggleState];
37476				isTakingAction = animation && (action === "complete" || action === "reset" || action in animation);
37477			  }
37478			}
37479  
37480			preventOverlaps && (toggled || isTakingAction) && (isTakingAction || scrub || !animation) && (_isFunction(preventOverlaps) ? preventOverlaps(self) : self.getTrailing(preventOverlaps).forEach(function (t) {
37481			  return t.endAnimation();
37482			}));
37483  
37484			if (!isToggle) {
37485			  if (scrubTween && !_refreshing && !_startup$1) {
37486				scrubTween._dp._time - scrubTween._start !== scrubTween._time && scrubTween.render(scrubTween._dp._time - scrubTween._start);
37487  
37488				if (scrubTween.resetTo) {
37489				  scrubTween.resetTo("totalProgress", clipped, animation._tTime / animation._tDur);
37490				} else {
37491				  scrubTween.vars.totalProgress = clipped;
37492				  scrubTween.invalidate().restart();
37493				}
37494			  } else if (animation) {
37495				animation.totalProgress(clipped, !!(_refreshing && (lastRefresh || reset)));
37496			  }
37497			}
37498  
37499			if (pin) {
37500			  reset && pinSpacing && (spacer.style[pinSpacing + direction.os2] = spacingStart);
37501  
37502			  if (!useFixedPosition) {
37503				pinSetter(_round(pinStart + pinChange * clipped));
37504			  } else if (stateChanged) {
37505				isAtMax = !reset && clipped > prevProgress && end + 1 > scroll && scroll + 1 >= _maxScroll(scroller, direction);
37506  
37507				if (pinReparent) {
37508				  if (!reset && (isActive || isAtMax)) {
37509					var bounds = _getBounds(pin, true),
37510						_offset = scroll - start;
37511  
37512					_reparent(pin, _body$1, bounds.top + (direction === _vertical ? _offset : 0) + _px, bounds.left + (direction === _vertical ? 0 : _offset) + _px);
37513				  } else {
37514					_reparent(pin, spacer);
37515				  }
37516				}
37517  
37518				_setState(isActive || isAtMax ? pinActiveState : pinState);
37519  
37520				pinMoves && clipped < 1 && isActive || pinSetter(pinStart + (clipped === 1 && !isAtMax ? pinChange : 0));
37521			  }
37522			}
37523  
37524			snap && !tweenTo.tween && !_refreshing && !_startup$1 && snapDelayedCall.restart(true);
37525			toggleClass && (toggled || once && clipped && (clipped < 1 || !_limitCallbacks)) && _toArray(toggleClass.targets).forEach(function (el) {
37526			  return el.classList[isActive || once ? "add" : "remove"](toggleClass.className);
37527			});
37528			onUpdate && !isToggle && !reset && onUpdate(self);
37529  
37530			if (stateChanged && !_refreshing) {
37531			  if (isToggle) {
37532				if (isTakingAction) {
37533				  if (action === "complete") {
37534					animation.pause().totalProgress(1);
37535				  } else if (action === "reset") {
37536					animation.restart(true).pause();
37537				  } else if (action === "restart") {
37538					animation.restart(true);
37539				  } else {
37540					animation[action]();
37541				  }
37542				}
37543  
37544				onUpdate && onUpdate(self);
37545			  }
37546  
37547			  if (toggled || !_limitCallbacks) {
37548				onToggle && toggled && _callback(self, onToggle);
37549				callbacks[toggleState] && _callback(self, callbacks[toggleState]);
37550				once && (clipped === 1 ? self.kill(false, 1) : callbacks[toggleState] = 0);
37551  
37552				if (!toggled) {
37553				  toggleState = clipped === 1 ? 1 : 3;
37554				  callbacks[toggleState] && _callback(self, callbacks[toggleState]);
37555				}
37556			  }
37557  
37558			  if (fastScrollEnd && !isActive && Math.abs(self.getVelocity()) > (_isNumber(fastScrollEnd) ? fastScrollEnd : 2500)) {
37559				_endAnimation(self.callbackAnimation);
37560  
37561				scrubTween ? scrubTween.progress(1) : _endAnimation(animation, action === "reverse" ? 1 : !clipped, 1);
37562			  }
37563			} else if (isToggle && onUpdate && !_refreshing) {
37564			  onUpdate(self);
37565			}
37566		  }
37567  
37568		  if (markerEndSetter) {
37569			var n = containerAnimation ? scroll / containerAnimation.duration() * (containerAnimation._caScrollDist || 0) : scroll;
37570			markerStartSetter(n + (markerStartTrigger._isFlipped ? 1 : 0));
37571			markerEndSetter(n);
37572		  }
37573  
37574		  caMarkerSetter && caMarkerSetter(-scroll / containerAnimation.duration() * (containerAnimation._caScrollDist || 0));
37575		};
37576  
37577		self.enable = function (reset, refresh) {
37578		  if (!self.enabled) {
37579			self.enabled = true;
37580  
37581			_addListener$1(scroller, "resize", _onResize);
37582  
37583			isViewport || _addListener$1(scroller, "scroll", _onScroll$1);
37584			onRefreshInit && _addListener$1(ScrollTrigger, "refreshInit", onRefreshInit);
37585  
37586			if (reset !== false) {
37587			  self.progress = prevProgress = 0;
37588			  scroll1 = scroll2 = lastSnap = scrollFunc();
37589			}
37590  
37591			refresh !== false && self.refresh();
37592		  }
37593		};
37594  
37595		self.getTween = function (snap) {
37596		  return snap && tweenTo ? tweenTo.tween : scrubTween;
37597		};
37598  
37599		self.setPositions = function (newStart, newEnd, keepClamp, pinOffset) {
37600		  if (containerAnimation) {
37601			var st = containerAnimation.scrollTrigger,
37602				duration = containerAnimation.duration(),
37603				_change = st.end - st.start;
37604  
37605			newStart = st.start + _change * newStart / duration;
37606			newEnd = st.start + _change * newEnd / duration;
37607		  }
37608  
37609		  self.refresh(false, false, {
37610			start: _keepClamp(newStart, keepClamp && !!self._startClamp),
37611			end: _keepClamp(newEnd, keepClamp && !!self._endClamp)
37612		  }, pinOffset);
37613		  self.update();
37614		};
37615  
37616		self.adjustPinSpacing = function (amount) {
37617		  if (spacerState && amount) {
37618			var i = spacerState.indexOf(direction.d) + 1;
37619			spacerState[i] = parseFloat(spacerState[i]) + amount + _px;
37620			spacerState[1] = parseFloat(spacerState[1]) + amount + _px;
37621  
37622			_setState(spacerState);
37623		  }
37624		};
37625  
37626		self.disable = function (reset, allowAnimation) {
37627		  if (self.enabled) {
37628			reset !== false && self.revert(true, true);
37629			self.enabled = self.isActive = false;
37630			allowAnimation || scrubTween && scrubTween.pause();
37631			prevScroll = 0;
37632			pinCache && (pinCache.uncache = 1);
37633			onRefreshInit && _removeListener$1(ScrollTrigger, "refreshInit", onRefreshInit);
37634  
37635			if (snapDelayedCall) {
37636			  snapDelayedCall.pause();
37637			  tweenTo.tween && tweenTo.tween.kill() && (tweenTo.tween = 0);
37638			}
37639  
37640			if (!isViewport) {
37641			  var i = _triggers.length;
37642  
37643			  while (i--) {
37644				if (_triggers[i].scroller === scroller && _triggers[i] !== self) {
37645				  return;
37646				}
37647			  }
37648  
37649			  _removeListener$1(scroller, "resize", _onResize);
37650  
37651			  isViewport || _removeListener$1(scroller, "scroll", _onScroll$1);
37652			}
37653		  }
37654		};
37655  
37656		self.kill = function (revert, allowAnimation) {
37657		  self.disable(revert, allowAnimation);
37658		  scrubTween && !allowAnimation && scrubTween.kill();
37659		  id && delete _ids[id];
37660  
37661		  var i = _triggers.indexOf(self);
37662  
37663		  i >= 0 && _triggers.splice(i, 1);
37664		  i === _i && _direction > 0 && _i--;
37665		  i = 0;
37666  
37667		  _triggers.forEach(function (t) {
37668			return t.scroller === self.scroller && (i = 1);
37669		  });
37670  
37671		  i || _refreshingAll || (self.scroll.rec = 0);
37672  
37673		  if (animation) {
37674			animation.scrollTrigger = null;
37675			revert && animation.revert({
37676			  kill: false
37677			});
37678			allowAnimation || animation.kill();
37679		  }
37680  
37681		  markerStart && [markerStart, markerEnd, markerStartTrigger, markerEndTrigger].forEach(function (m) {
37682			return m.parentNode && m.parentNode.removeChild(m);
37683		  });
37684		  _primary === self && (_primary = 0);
37685  
37686		  if (pin) {
37687			pinCache && (pinCache.uncache = 1);
37688			i = 0;
37689  
37690			_triggers.forEach(function (t) {
37691			  return t.pin === pin && i++;
37692			});
37693  
37694			i || (pinCache.spacer = 0);
37695		  }
37696  
37697		  vars.onKill && vars.onKill(self);
37698		};
37699  
37700		_triggers.push(self);
37701  
37702		self.enable(false, false);
37703		customRevertReturn && customRevertReturn(self);
37704  
37705		if (animation && animation.add && !change) {
37706		  var updateFunc = self.update;
37707  
37708		  self.update = function () {
37709			self.update = updateFunc;
37710			start || end || self.refresh();
37711		  };
37712  
37713		  gsap$1.delayedCall(0.01, self.update);
37714		  change = 0.01;
37715		  start = end = 0;
37716		} else {
37717		  self.refresh();
37718		}
37719  
37720		pin && _queueRefreshAll();
37721	  };
37722  
37723	  ScrollTrigger.register = function register(core) {
37724		if (!_coreInitted$1) {
37725		  gsap$1 = core || _getGSAP$1();
37726		  _windowExists() && window.document && ScrollTrigger.enable();
37727		  _coreInitted$1 = _enabled;
37728		}
37729  
37730		return _coreInitted$1;
37731	  };
37732  
37733	  ScrollTrigger.defaults = function defaults(config) {
37734		if (config) {
37735		  for (var p in config) {
37736			_defaults[p] = config[p];
37737		  }
37738		}
37739  
37740		return _defaults;
37741	  };
37742  
37743	  ScrollTrigger.disable = function disable(reset, kill) {
37744		_enabled = 0;
37745  
37746		_triggers.forEach(function (trigger) {
37747		  return trigger[kill ? "kill" : "disable"](reset);
37748		});
37749  
37750		_removeListener$1(_win$1, "wheel", _onScroll$1);
37751  
37752		_removeListener$1(_doc$1, "scroll", _onScroll$1);
37753  
37754		clearInterval(_syncInterval);
37755  
37756		_removeListener$1(_doc$1, "touchcancel", _passThrough);
37757  
37758		_removeListener$1(_body$1, "touchstart", _passThrough);
37759  
37760		_multiListener(_removeListener$1, _doc$1, "pointerdown,touchstart,mousedown", _pointerDownHandler);
37761  
37762		_multiListener(_removeListener$1, _doc$1, "pointerup,touchend,mouseup", _pointerUpHandler);
37763  
37764		_resizeDelay.kill();
37765  
37766		_iterateAutoRefresh(_removeListener$1);
37767  
37768		for (var i = 0; i < _scrollers.length; i += 3) {
37769		  _wheelListener(_removeListener$1, _scrollers[i], _scrollers[i + 1]);
37770  
37771		  _wheelListener(_removeListener$1, _scrollers[i], _scrollers[i + 2]);
37772		}
37773	  };
37774  
37775	  ScrollTrigger.enable = function enable() {
37776		_win$1 = window;
37777		_doc$1 = document;
37778		_docEl$1 = _doc$1.documentElement;
37779		_body$1 = _doc$1.body;
37780  
37781		if (gsap$1) {
37782		  _toArray = gsap$1.utils.toArray;
37783		  _clamp$1 = gsap$1.utils.clamp;
37784		  _context$1 = gsap$1.core.context || _passThrough;
37785		  _suppressOverwrites = gsap$1.core.suppressOverwrites || _passThrough;
37786		  _scrollRestoration = _win$1.history.scrollRestoration || "auto";
37787		  _lastScroll = _win$1.pageYOffset;
37788		  gsap$1.core.globals("ScrollTrigger", ScrollTrigger);
37789  
37790		  if (_body$1) {
37791			_enabled = 1;
37792			_div100vh = document.createElement("div");
37793			_div100vh.style.height = "100vh";
37794			_div100vh.style.position = "absolute";
37795  
37796			_refresh100vh();
37797  
37798			_rafBugFix();
37799  
37800			Observer.register(gsap$1);
37801			ScrollTrigger.isTouch = Observer.isTouch;
37802			_fixIOSBug = Observer.isTouch && /(iPad|iPhone|iPod|Mac)/g.test(navigator.userAgent);
37803			_ignoreMobileResize = Observer.isTouch === 1;
37804  
37805			_addListener$1(_win$1, "wheel", _onScroll$1);
37806  
37807			_root$1 = [_win$1, _doc$1, _docEl$1, _body$1];
37808  
37809			if (gsap$1.matchMedia) {
37810			  ScrollTrigger.matchMedia = function (vars) {
37811				var mm = gsap$1.matchMedia(),
37812					p;
37813  
37814				for (p in vars) {
37815				  mm.add(p, vars[p]);
37816				}
37817  
37818				return mm;
37819			  };
37820  
37821			  gsap$1.addEventListener("matchMediaInit", function () {
37822				return _revertAll();
37823			  });
37824			  gsap$1.addEventListener("matchMediaRevert", function () {
37825				return _revertRecorded();
37826			  });
37827			  gsap$1.addEventListener("matchMedia", function () {
37828				_refreshAll(0, 1);
37829  
37830				_dispatch("matchMedia");
37831			  });
37832			  gsap$1.matchMedia("(orientation: portrait)", function () {
37833				_setBaseDimensions();
37834  
37835				return _setBaseDimensions;
37836			  });
37837			} else {
37838			  console.warn("Requires GSAP 3.11.0 or later");
37839			}
37840  
37841			_setBaseDimensions();
37842  
37843			_addListener$1(_doc$1, "scroll", _onScroll$1);
37844  
37845			var bodyStyle = _body$1.style,
37846				border = bodyStyle.borderTopStyle,
37847				AnimationProto = gsap$1.core.Animation.prototype,
37848				bounds,
37849				i;
37850			AnimationProto.revert || Object.defineProperty(AnimationProto, "revert", {
37851			  value: function value() {
37852				return this.time(-0.01, true);
37853			  }
37854			});
37855			bodyStyle.borderTopStyle = "solid";
37856			bounds = _getBounds(_body$1);
37857			_vertical.m = Math.round(bounds.top + _vertical.sc()) || 0;
37858			_horizontal.m = Math.round(bounds.left + _horizontal.sc()) || 0;
37859			border ? bodyStyle.borderTopStyle = border : bodyStyle.removeProperty("border-top-style");
37860			_syncInterval = setInterval(_sync, 250);
37861			gsap$1.delayedCall(0.5, function () {
37862			  return _startup$1 = 0;
37863			});
37864  
37865			_addListener$1(_doc$1, "touchcancel", _passThrough);
37866  
37867			_addListener$1(_body$1, "touchstart", _passThrough);
37868  
37869			_multiListener(_addListener$1, _doc$1, "pointerdown,touchstart,mousedown", _pointerDownHandler);
37870  
37871			_multiListener(_addListener$1, _doc$1, "pointerup,touchend,mouseup", _pointerUpHandler);
37872  
37873			_transformProp = gsap$1.utils.checkPrefix("transform");
37874  
37875			_stateProps.push(_transformProp);
37876  
37877			_coreInitted$1 = _getTime$1();
37878			_resizeDelay = gsap$1.delayedCall(0.2, _refreshAll).pause();
37879			_autoRefresh = [_doc$1, "visibilitychange", function () {
37880			  var w = _win$1.innerWidth,
37881				  h = _win$1.innerHeight;
37882  
37883			  if (_doc$1.hidden) {
37884				_prevWidth = w;
37885				_prevHeight = h;
37886			  } else if (_prevWidth !== w || _prevHeight !== h) {
37887				_onResize();
37888			  }
37889			}, _doc$1, "DOMContentLoaded", _refreshAll, _win$1, "load", _refreshAll, _win$1, "resize", _onResize];
37890  
37891			_iterateAutoRefresh(_addListener$1);
37892  
37893			_triggers.forEach(function (trigger) {
37894			  return trigger.enable(0, 1);
37895			});
37896  
37897			for (i = 0; i < _scrollers.length; i += 3) {
37898			  _wheelListener(_removeListener$1, _scrollers[i], _scrollers[i + 1]);
37899  
37900			  _wheelListener(_removeListener$1, _scrollers[i], _scrollers[i + 2]);
37901			}
37902		  }
37903		}
37904	  };
37905  
37906	  ScrollTrigger.config = function config(vars) {
37907		"limitCallbacks" in vars && (_limitCallbacks = !!vars.limitCallbacks);
37908		var ms = vars.syncInterval;
37909		ms && clearInterval(_syncInterval) || (_syncInterval = ms) && setInterval(_sync, ms);
37910		"ignoreMobileResize" in vars && (_ignoreMobileResize = ScrollTrigger.isTouch === 1 && vars.ignoreMobileResize);
37911  
37912		if ("autoRefreshEvents" in vars) {
37913		  _iterateAutoRefresh(_removeListener$1) || _iterateAutoRefresh(_addListener$1, vars.autoRefreshEvents || "none");
37914		  _ignoreResize = (vars.autoRefreshEvents + "").indexOf("resize") === -1;
37915		}
37916	  };
37917  
37918	  ScrollTrigger.scrollerProxy = function scrollerProxy(target, vars) {
37919		var t = _getTarget(target),
37920			i = _scrollers.indexOf(t),
37921			isViewport = _isViewport$1(t);
37922  
37923		if (~i) {
37924		  _scrollers.splice(i, isViewport ? 6 : 2);
37925		}
37926  
37927		if (vars) {
37928		  isViewport ? _proxies.unshift(_win$1, vars, _body$1, vars, _docEl$1, vars) : _proxies.unshift(t, vars);
37929		}
37930	  };
37931  
37932	  ScrollTrigger.clearMatchMedia = function clearMatchMedia(query) {
37933		_triggers.forEach(function (t) {
37934		  return t._ctx && t._ctx.query === query && t._ctx.kill(true, true);
37935		});
37936	  };
37937  
37938	  ScrollTrigger.isInViewport = function isInViewport(element, ratio, horizontal) {
37939		var bounds = (_isString(element) ? _getTarget(element) : element).getBoundingClientRect(),
37940			offset = bounds[horizontal ? _width : _height] * ratio || 0;
37941		return horizontal ? bounds.right - offset > 0 && bounds.left + offset < _win$1.innerWidth : bounds.bottom - offset > 0 && bounds.top + offset < _win$1.innerHeight;
37942	  };
37943  
37944	  ScrollTrigger.positionInViewport = function positionInViewport(element, referencePoint, horizontal) {
37945		_isString(element) && (element = _getTarget(element));
37946		var bounds = element.getBoundingClientRect(),
37947			size = bounds[horizontal ? _width : _height],
37948			offset = referencePoint == null ? size / 2 : referencePoint in _keywords ? _keywords[referencePoint] * size : ~referencePoint.indexOf("%") ? parseFloat(referencePoint) * size / 100 : parseFloat(referencePoint) || 0;
37949		return horizontal ? (bounds.left + offset) / _win$1.innerWidth : (bounds.top + offset) / _win$1.innerHeight;
37950	  };
37951  
37952	  ScrollTrigger.killAll = function killAll(allowListeners) {
37953		_triggers.slice(0).forEach(function (t) {
37954		  return t.vars.id !== "ScrollSmoother" && t.kill();
37955		});
37956  
37957		if (allowListeners !== true) {
37958		  var listeners = _listeners.killAll || [];
37959		  _listeners = {};
37960		  listeners.forEach(function (f) {
37961			return f();
37962		  });
37963		}
37964	  };
37965  
37966	  return ScrollTrigger;
37967	}();
37968	ScrollTrigger$1.version = "3.12.5";
37969  
37970	ScrollTrigger$1.saveStyles = function (targets) {
37971	  return targets ? _toArray(targets).forEach(function (target) {
37972		if (target && target.style) {
37973		  var i = _savedStyles.indexOf(target);
37974  
37975		  i >= 0 && _savedStyles.splice(i, 5);
37976  
37977		  _savedStyles.push(target, target.style.cssText, target.getBBox && target.getAttribute("transform"), gsap$1.core.getCache(target), _context$1());
37978		}
37979	  }) : _savedStyles;
37980	};
37981  
37982	ScrollTrigger$1.revert = function (soft, media) {
37983	  return _revertAll(!soft, media);
37984	};
37985  
37986	ScrollTrigger$1.create = function (vars, animation) {
37987	  return new ScrollTrigger$1(vars, animation);
37988	};
37989  
37990	ScrollTrigger$1.refresh = function (safe) {
37991	  return safe ? _onResize() : (_coreInitted$1 || ScrollTrigger$1.register()) && _refreshAll(true);
37992	};
37993  
37994	ScrollTrigger$1.update = function (force) {
37995	  return ++_scrollers.cache && _updateAll(force === true ? 2 : 0);
37996	};
37997  
37998	ScrollTrigger$1.clearScrollMemory = _clearScrollMemory;
37999  
38000	ScrollTrigger$1.maxScroll = function (element, horizontal) {
38001	  return _maxScroll(element, horizontal ? _horizontal : _vertical);
38002	};
38003  
38004	ScrollTrigger$1.getScrollFunc = function (element, horizontal) {
38005	  return _getScrollFunc(_getTarget(element), horizontal ? _horizontal : _vertical);
38006	};
38007  
38008	ScrollTrigger$1.getById = function (id) {
38009	  return _ids[id];
38010	};
38011  
38012	ScrollTrigger$1.getAll = function () {
38013	  return _triggers.filter(function (t) {
38014		return t.vars.id !== "ScrollSmoother";
38015	  });
38016	};
38017  
38018	ScrollTrigger$1.isScrolling = function () {
38019	  return !!_lastScrollTime;
38020	};
38021  
38022	ScrollTrigger$1.snapDirectional = _snapDirectional;
38023  
38024	ScrollTrigger$1.addEventListener = function (type, callback) {
38025	  var a = _listeners[type] || (_listeners[type] = []);
38026	  ~a.indexOf(callback) || a.push(callback);
38027	};
38028  
38029	ScrollTrigger$1.removeEventListener = function (type, callback) {
38030	  var a = _listeners[type],
38031		  i = a && a.indexOf(callback);
38032	  i >= 0 && a.splice(i, 1);
38033	};
38034  
38035	ScrollTrigger$1.batch = function (targets, vars) {
38036	  var result = [],
38037		  varsCopy = {},
38038		  interval = vars.interval || 0.016,
38039		  batchMax = vars.batchMax || 1e9,
38040		  proxyCallback = function proxyCallback(type, callback) {
38041		var elements = [],
38042			triggers = [],
38043			delay = gsap$1.delayedCall(interval, function () {
38044		  callback(elements, triggers);
38045		  elements = [];
38046		  triggers = [];
38047		}).pause();
38048		return function (self) {
38049		  elements.length || delay.restart(true);
38050		  elements.push(self.trigger);
38051		  triggers.push(self);
38052		  batchMax <= elements.length && delay.progress(1);
38053		};
38054	  },
38055		  p;
38056  
38057	  for (p in vars) {
38058		varsCopy[p] = p.substr(0, 2) === "on" && _isFunction(vars[p]) && p !== "onRefreshInit" ? proxyCallback(p, vars[p]) : vars[p];
38059	  }
38060  
38061	  if (_isFunction(batchMax)) {
38062		batchMax = batchMax();
38063  
38064		_addListener$1(ScrollTrigger$1, "refresh", function () {
38065		  return batchMax = vars.batchMax();
38066		});
38067	  }
38068  
38069	  _toArray(targets).forEach(function (target) {
38070		var config = {};
38071  
38072		for (p in varsCopy) {
38073		  config[p] = varsCopy[p];
38074		}
38075  
38076		config.trigger = target;
38077		result.push(ScrollTrigger$1.create(config));
38078	  });
38079  
38080	  return result;
38081	};
38082  
38083	var _clampScrollAndGetDurationMultiplier = function _clampScrollAndGetDurationMultiplier(scrollFunc, current, end, max) {
38084	  current > max ? scrollFunc(max) : current < 0 && scrollFunc(0);
38085	  return end > max ? (max - current) / (end - current) : end < 0 ? current / (current - end) : 1;
38086	},
38087		_allowNativePanning = function _allowNativePanning(target, direction) {
38088	  if (direction === true) {
38089		target.style.removeProperty("touch-action");
38090	  } else {
38091		target.style.touchAction = direction === true ? "auto" : direction ? "pan-" + direction + (Observer.isTouch ? " pinch-zoom" : "") : "none";
38092	  }
38093  
38094	  target === _docEl$1 && _allowNativePanning(_body$1, direction);
38095	},
38096		_overflow = {
38097	  auto: 1,
38098	  scroll: 1
38099	},
38100		_nestedScroll = function _nestedScroll(_ref5) {
38101	  var event = _ref5.event,
38102		  target = _ref5.target,
38103		  axis = _ref5.axis;
38104  
38105	  var node = (event.changedTouches ? event.changedTouches[0] : event).target,
38106		  cache = node._gsap || gsap$1.core.getCache(node),
38107		  time = _getTime$1(),
38108		  cs;
38109  
38110	  if (!cache._isScrollT || time - cache._isScrollT > 2000) {
38111		while (node && node !== _body$1 && (node.scrollHeight <= node.clientHeight && node.scrollWidth <= node.clientWidth || !(_overflow[(cs = _getComputedStyle(node)).overflowY] || _overflow[cs.overflowX]))) {
38112		  node = node.parentNode;
38113		}
38114  
38115		cache._isScroll = node && node !== target && !_isViewport$1(node) && (_overflow[(cs = _getComputedStyle(node)).overflowY] || _overflow[cs.overflowX]);
38116		cache._isScrollT = time;
38117	  }
38118  
38119	  if (cache._isScroll || axis === "x") {
38120		event.stopPropagation();
38121		event._gsapAllow = true;
38122	  }
38123	},
38124		_inputObserver = function _inputObserver(target, type, inputs, nested) {
38125	  return Observer.create({
38126		target: target,
38127		capture: true,
38128		debounce: false,
38129		lockAxis: true,
38130		type: type,
38131		onWheel: nested = nested && _nestedScroll,
38132		onPress: nested,
38133		onDrag: nested,
38134		onScroll: nested,
38135		onEnable: function onEnable() {
38136		  return inputs && _addListener$1(_doc$1, Observer.eventTypes[0], _captureInputs, false, true);
38137		},
38138		onDisable: function onDisable() {
38139		  return _removeListener$1(_doc$1, Observer.eventTypes[0], _captureInputs, true);
38140		}
38141	  });
38142	},
38143		_inputExp = /(input|label|select|textarea)/i,
38144		_inputIsFocused,
38145		_captureInputs = function _captureInputs(e) {
38146	  var isInput = _inputExp.test(e.target.tagName);
38147  
38148	  if (isInput || _inputIsFocused) {
38149		e._gsapAllow = true;
38150		_inputIsFocused = isInput;
38151	  }
38152	},
38153		_getScrollNormalizer = function _getScrollNormalizer(vars) {
38154	  _isObject(vars) || (vars = {});
38155	  vars.preventDefault = vars.isNormalizer = vars.allowClicks = true;
38156	  vars.type || (vars.type = "wheel,touch");
38157	  vars.debounce = !!vars.debounce;
38158	  vars.id = vars.id || "normalizer";
38159  
38160	  var _vars2 = vars,
38161		  normalizeScrollX = _vars2.normalizeScrollX,
38162		  momentum = _vars2.momentum,
38163		  allowNestedScroll = _vars2.allowNestedScroll,
38164		  onRelease = _vars2.onRelease,
38165		  self,
38166		  maxY,
38167		  target = _getTarget(vars.target) || _docEl$1,
38168		  smoother = gsap$1.core.globals().ScrollSmoother,
38169		  smootherInstance = smoother && smoother.get(),
38170		  content = _fixIOSBug && (vars.content && _getTarget(vars.content) || smootherInstance && vars.content !== false && !smootherInstance.smooth() && smootherInstance.content()),
38171		  scrollFuncY = _getScrollFunc(target, _vertical),
38172		  scrollFuncX = _getScrollFunc(target, _horizontal),
38173		  scale = 1,
vendor: 4,132 bytes, lines 38174-38295
38174		  initialScale = (Observer.isTouch && _win$1.visualViewport ? _win$1.visualViewport.scale * _win$1.visualViewport.width : _win$1.outerWidth) / _win$1.innerWidth,
38175		  wheelRefresh = 0,
38176		  resolveMomentumDuration = _isFunction(momentum) ? function () {
38177		return momentum(self);
38178	  } : function () {
38179		return momentum || 2.8;
38180	  },
38181		  lastRefreshID,
38182		  skipTouchMove,
38183		  inputObserver = _inputObserver(target, vars.type, true, allowNestedScroll),
38184		  resumeTouchMove = function resumeTouchMove() {
38185		return skipTouchMove = false;
38186	  },
38187		  scrollClampX = _passThrough,
38188		  scrollClampY = _passThrough,
38189		  updateClamps = function updateClamps() {
38190		maxY = _maxScroll(target, _vertical);
38191		scrollClampY = _clamp$1(_fixIOSBug ? 1 : 0, maxY);
38192		normalizeScrollX && (scrollClampX = _clamp$1(0, _maxScroll(target, _horizontal)));
38193		lastRefreshID = _refreshID;
38194	  },
38195		  removeContentOffset = function removeContentOffset() {
38196		content._gsap.y = _round(parseFloat(content._gsap.y) + scrollFuncY.offset) + "px";
38197		content.style.transform = "matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, " + parseFloat(content._gsap.y) + ", 0, 1)";
38198		scrollFuncY.offset = scrollFuncY.cacheID = 0;
38199	  },
38200		  ignoreDrag = function ignoreDrag() {
38201		if (skipTouchMove) {
38202		  requestAnimationFrame(resumeTouchMove);
38203  
38204		  var offset = _round(self.deltaY / 2),
38205			  scroll = scrollClampY(scrollFuncY.v - offset);
38206  
38207		  if (content && scroll !== scrollFuncY.v + scrollFuncY.offset) {
38208			scrollFuncY.offset = scroll - scrollFuncY.v;
38209  
38210			var y = _round((parseFloat(content && content._gsap.y) || 0) - scrollFuncY.offset);
38211  
38212			content.style.transform = "matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, " + y + ", 0, 1)";
38213			content._gsap.y = y + "px";
38214			scrollFuncY.cacheID = _scrollers.cache;
38215  
38216			_updateAll();
38217		  }
38218  
38219		  return true;
38220		}
38221  
38222		scrollFuncY.offset && removeContentOffset();
38223		skipTouchMove = true;
38224	  },
38225		  tween,
38226		  startScrollX,
38227		  startScrollY,
38228		  onStopDelayedCall,
38229		  onResize = function onResize() {
38230		updateClamps();
38231  
38232		if (tween.isActive() && tween.vars.scrollY > maxY) {
38233		  scrollFuncY() > maxY ? tween.progress(1) && scrollFuncY(maxY) : tween.resetTo("scrollY", maxY);
38234		}
38235	  };
38236  
38237	  content && gsap$1.set(content, {
38238		y: "+=0"
38239	  });
38240  
38241	  vars.ignoreCheck = function (e) {
38242		return _fixIOSBug && e.type === "touchmove" && ignoreDrag() || scale > 1.05 && e.type !== "touchstart" || self.isGesturing || e.touches && e.touches.length > 1;
38243	  };
38244  
38245	  vars.onPress = function () {
38246		skipTouchMove = false;
38247		var prevScale = scale;
38248		scale = _round((_win$1.visualViewport && _win$1.visualViewport.scale || 1) / initialScale);
38249		tween.pause();
38250		prevScale !== scale && _allowNativePanning(target, scale > 1.01 ? true : normalizeScrollX ? false : "x");
38251		startScrollX = scrollFuncX();
38252		startScrollY = scrollFuncY();
38253		updateClamps();
38254		lastRefreshID = _refreshID;
38255	  };
38256  
38257	  vars.onRelease = vars.onGestureStart = function (self, wasDragging) {
38258		scrollFuncY.offset && removeContentOffset();
38259  
38260		if (!wasDragging) {
38261		  onStopDelayedCall.restart(true);
38262		} else {
38263		  _scrollers.cache++;
38264		  var dur = resolveMomentumDuration(),
38265			  currentScroll,
38266			  endScroll;
38267  
38268		  if (normalizeScrollX) {
38269			currentScroll = scrollFuncX();
38270			endScroll = currentScroll + dur * 0.05 * -self.velocityX / 0.227;
38271			dur *= _clampScrollAndGetDurationMultiplier(scrollFuncX, currentScroll, endScroll, _maxScroll(target, _horizontal));
38272			tween.vars.scrollX = scrollClampX(endScroll);
38273		  }
38274  
38275		  currentScroll = scrollFuncY();
38276		  endScroll = currentScroll + dur * 0.05 * -self.velocityY / 0.227;
38277		  dur *= _clampScrollAndGetDurationMultiplier(scrollFuncY, currentScroll, endScroll, _maxScroll(target, _vertical));
38278		  tween.vars.scrollY = scrollClampY(endScroll);
38279		  tween.invalidate().duration(dur).play(0.01);
38280  
38281		  if (_fixIOSBug && tween.vars.scrollY >= maxY || currentScroll >= maxY - 1) {
38282			gsap$1.to({}, {
38283			  onUpdate: onResize,
38284			  duration: dur
38285			});
38286		  }
38287		}
38288  
38289		onRelease && onRelease(self);
38290	  };
38291  
38292	  vars.onWheel = function () {
38293		tween._ts && tween.pause();
38294  
38295		if (_getTime$1() - wheelRefresh > 1000) {
vendor: 9,792 bytes, lines 38296-38623
38296		  lastRefreshID = 0;
38297		  wheelRefresh = _getTime$1();
38298		}
38299	  };
38300  
38301	  vars.onChange = function (self, dx, dy, xArray, yArray) {
38302		_refreshID !== lastRefreshID && updateClamps();
38303		dx && normalizeScrollX && scrollFuncX(scrollClampX(xArray[2] === dx ? startScrollX + (self.startX - self.x) : scrollFuncX() + dx - xArray[1]));
38304  
38305		if (dy) {
38306		  scrollFuncY.offset && removeContentOffset();
38307		  var isTouch = yArray[2] === dy,
38308			  y = isTouch ? startScrollY + self.startY - self.y : scrollFuncY() + dy - yArray[1],
38309			  yClamped = scrollClampY(y);
38310		  isTouch && y !== yClamped && (startScrollY += yClamped - y);
38311		  scrollFuncY(yClamped);
38312		}
38313  
38314		(dy || dx) && _updateAll();
38315	  };
38316  
38317	  vars.onEnable = function () {
38318		_allowNativePanning(target, normalizeScrollX ? false : "x");
38319  
38320		ScrollTrigger$1.addEventListener("refresh", onResize);
38321  
38322		_addListener$1(_win$1, "resize", onResize);
38323  
38324		if (scrollFuncY.smooth) {
38325		  scrollFuncY.target.style.scrollBehavior = "auto";
38326		  scrollFuncY.smooth = scrollFuncX.smooth = false;
38327		}
38328  
38329		inputObserver.enable();
38330	  };
38331  
38332	  vars.onDisable = function () {
38333		_allowNativePanning(target, true);
38334  
38335		_removeListener$1(_win$1, "resize", onResize);
38336  
38337		ScrollTrigger$1.removeEventListener("refresh", onResize);
38338		inputObserver.kill();
38339	  };
38340  
38341	  vars.lockAxis = vars.lockAxis !== false;
38342	  self = new Observer(vars);
38343	  self.iOS = _fixIOSBug;
38344	  _fixIOSBug && !scrollFuncY() && scrollFuncY(1);
38345	  _fixIOSBug && gsap$1.ticker.add(_passThrough);
38346	  onStopDelayedCall = self._dc;
38347	  tween = gsap$1.to(self, {
38348		ease: "power4",
38349		paused: true,
38350		inherit: false,
38351		scrollX: normalizeScrollX ? "+=0.1" : "+=0",
38352		scrollY: "+=0.1",
38353		modifiers: {
38354		  scrollY: _interruptionTracker(scrollFuncY, scrollFuncY(), function () {
38355			return tween.pause();
38356		  })
38357		},
38358		onUpdate: _updateAll,
38359		onComplete: onStopDelayedCall.vars.onComplete
38360	  });
38361	  return self;
38362	};
38363  
38364	ScrollTrigger$1.sort = function (func) {
38365	  return _triggers.sort(func || function (a, b) {
38366		return (a.vars.refreshPriority || 0) * -1e6 + a.start - (b.start + (b.vars.refreshPriority || 0) * -1e6);
38367	  });
38368	};
38369  
38370	ScrollTrigger$1.observe = function (vars) {
38371	  return new Observer(vars);
38372	};
38373  
38374	ScrollTrigger$1.normalizeScroll = function (vars) {
38375	  if (typeof vars === "undefined") {
38376		return _normalizer$1;
38377	  }
38378  
38379	  if (vars === true && _normalizer$1) {
38380		return _normalizer$1.enable();
38381	  }
38382  
38383	  if (vars === false) {
38384		_normalizer$1 && _normalizer$1.kill();
38385		_normalizer$1 = vars;
38386		return;
38387	  }
38388  
38389	  var normalizer = vars instanceof Observer ? vars : _getScrollNormalizer(vars);
38390	  _normalizer$1 && _normalizer$1.target === normalizer.target && _normalizer$1.kill();
38391	  _isViewport$1(normalizer.target) && (_normalizer$1 = normalizer);
38392	  return normalizer;
38393	};
38394  
38395	ScrollTrigger$1.core = {
38396	  _getVelocityProp: _getVelocityProp,
38397	  _inputObserver: _inputObserver,
38398	  _scrollers: _scrollers,
38399	  _proxies: _proxies,
38400	  bridge: {
38401		ss: function ss() {
38402		  _lastScrollTime || _dispatch("scrollStart");
38403		  _lastScrollTime = _getTime$1();
38404		},
38405		ref: function ref() {
38406		  return _refreshing;
38407		}
38408	  }
38409	};
38410	_getGSAP$1() && gsap$1.registerPlugin(ScrollTrigger$1);
38411  
38412	exports.ScrollTrigger = ScrollTrigger$1;
38413	exports.default = ScrollTrigger$1;
38414  
38415	if (typeof(window) === 'undefined' || window !== exports) {Object.defineProperty(exports, '__esModule', { value: true });} else {delete window.default;}
38416  
38417  })));
38418(function (global, factory) {
38419  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
38420  typeof define === 'function' && define.amd ? define(['exports'], factory) :
38421  (global = global || self, factory(global.window = global.window || {}));
38422}(this, (function (exports) { 'use strict';
38423
38424  function _inheritsLoose(subClass, superClass) {
38425    subClass.prototype = Object.create(superClass.prototype);
38426    subClass.prototype.constructor = subClass;
38427    subClass.__proto__ = superClass;
38428  }
38429
38430  function _assertThisInitialized(self) {
38431    if (self === void 0) {
38432      throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
38433    }
38434
38435    return self;
38436  }
38437
38438  var _doc,
38439      _win,
38440      _docElement,
38441      _body,
38442      _divContainer,
38443      _svgContainer,
38444      _identityMatrix,
38445      _gEl,
38446      _transformProp = "transform",
38447      _transformOriginProp = _transformProp + "Origin",
38448      _hasOffsetBug,
38449      _setDoc = function _setDoc(element) {
38450    var doc = element.ownerDocument || element;
38451
38452    if (!(_transformProp in element.style) && "msTransform" in element.style) {
38453      _transformProp = "msTransform";
38454      _transformOriginProp = _transformProp + "Origin";
38455    }
38456
38457    while (doc.parentNode && (doc = doc.parentNode)) {}
38458
38459    _win = window;
38460    _identityMatrix = new Matrix2D();
38461
38462    if (doc) {
38463      _doc = doc;
38464      _docElement = doc.documentElement;
38465      _body = doc.body;
38466      _gEl = _doc.createElementNS("http://www.w3.org/2000/svg", "g");
38467      _gEl.style.transform = "none";
38468      var d1 = doc.createElement("div"),
38469          d2 = doc.createElement("div"),
38470          root = doc && (doc.body || doc.firstElementChild);
38471
38472      if (root && root.appendChild) {
38473        root.appendChild(d1);
38474        d1.appendChild(d2);
38475        d1.setAttribute("style", "position:static;transform:translate3d(0,0,1px)");
38476        _hasOffsetBug = d2.offsetParent !== d1;
38477        root.removeChild(d1);
38478      }
38479    }
38480
38481    return doc;
38482  },
38483      _forceNonZeroScale = function _forceNonZeroScale(e) {
38484    var a, cache;
38485
38486    while (e && e !== _body) {
38487      cache = e._gsap;
38488      cache && cache.uncache && cache.get(e, "x");
38489
38490      if (cache && !cache.scaleX && !cache.scaleY && cache.renderTransform) {
38491        cache.scaleX = cache.scaleY = 1e-4;
38492        cache.renderTransform(1, cache);
38493        a ? a.push(cache) : a = [cache];
38494      }
38495
38496      e = e.parentNode;
38497    }
38498
38499    return a;
38500  },
38501      _svgTemps = [],
38502      _divTemps = [],
38503      _getDocScrollTop = function _getDocScrollTop() {
38504    return _win.pageYOffset || _doc.scrollTop || _docElement.scrollTop || _body.scrollTop || 0;
38505  },
38506      _getDocScrollLeft = function _getDocScrollLeft() {
38507    return _win.pageXOffset || _doc.scrollLeft || _docElement.scrollLeft || _body.scrollLeft || 0;
38508  },
38509      _svgOwner = function _svgOwner(element) {
38510    return element.ownerSVGElement || ((element.tagName + "").toLowerCase() === "svg" ? element : null);
38511  },
38512      _isFixed = function _isFixed(element) {
38513    if (_win.getComputedStyle(element).position === "fixed") {
38514      return true;
38515    }
38516
38517    element = element.parentNode;
38518
38519    if (element && element.nodeType === 1) {
38520      return _isFixed(element);
38521    }
38522  },
38523      _createSibling = function _createSibling(element, i) {
38524    if (element.parentNode && (_doc || _setDoc(element))) {
38525      var svg = _svgOwner(element),
38526          ns = svg ? svg.getAttribute("xmlns") || "http://www.w3.org/2000/svg" : "http://www.w3.org/1999/xhtml",
38527          type = svg ? i ? "rect" : "g" : "div",
38528          x = i !== 2 ? 0 : 100,
38529          y = i === 3 ? 100 : 0,
38530          css = "position:absolute;display:block;pointer-events:none;margin:0;padding:0;",
38531          e = _doc.createElementNS ? _doc.createElementNS(ns.replace(/^https/, "http"), type) : _doc.createElement(type);
38532
38533      if (i) {
38534        if (!svg) {
38535          if (!_divContainer) {
38536            _divContainer = _createSibling(element);
38537            _divContainer.style.cssText = css;
38538          }
38539
38540          e.style.cssText = css + "width:0.1px;height:0.1px;top:" + y + "px;left:" + x + "px";
38541
38542          _divContainer.appendChild(e);
38543        } else {
38544          _svgContainer || (_svgContainer = _createSibling(element));
38545          e.setAttribute("width", 0.01);
38546          e.setAttribute("height", 0.01);
38547          e.setAttribute("transform", "translate(" + x + "," + y + ")");
38548
38549          _svgContainer.appendChild(e);
38550        }
38551      }
38552
38553      return e;
38554    }
38555
38556    throw "Need document and parent.";
38557  },
38558      _consolidate = function _consolidate(m) {
38559    var c = new Matrix2D(),
38560        i = 0;
38561
38562    for (; i < m.numberOfItems; i++) {
38563      c.multiply(m.getItem(i).matrix);
38564    }
38565
38566    return c;
38567  },
38568      _getCTM = function _getCTM(svg) {
38569    var m = svg.getCTM(),
38570        transform;
38571
38572    if (!m) {
38573      transform = svg.style[_transformProp];
38574      svg.style[_transformProp] = "none";
38575      svg.appendChild(_gEl);
38576      m = _gEl.getCTM();
38577      svg.removeChild(_gEl);
38578      transform ? svg.style[_transformProp] = transform : svg.style.removeProperty(_transformProp.replace(/([A-Z])/g, "-$1").toLowerCase());
38579    }
38580
38581    return m || _identityMatrix.clone();
38582  },
38583      _placeSiblings = function _placeSiblings(element, adjustGOffset) {
38584    var svg = _svgOwner(element),
38585        isRootSVG = element === svg,
38586        siblings = svg ? _svgTemps : _divTemps,
38587        parent = element.parentNode,
38588        container,
38589        m,
38590        b,
38591        x,
38592        y,
38593        cs;
38594
38595    if (element === _win) {
38596      return element;
38597    }
38598
38599    siblings.length || siblings.push(_createSibling(element, 1), _createSibling(element, 2), _createSibling(element, 3));
38600    container = svg ? _svgContainer : _divContainer;
38601
38602    if (svg) {
38603      if (isRootSVG) {
38604        b = _getCTM(element);
38605        x = -b.e / b.a;
38606        y = -b.f / b.d;
38607        m = _identityMatrix;
38608      } else if (element.getBBox) {
38609        b = element.getBBox();
38610        m = element.transform ? element.transform.baseVal : {};
38611        m = !m.numberOfItems ? _identityMatrix : m.numberOfItems > 1 ? _consolidate(m) : m.getItem(0).matrix;
38612        x = m.a * b.x + m.c * b.y;
38613        y = m.b * b.x + m.d * b.y;
38614      } else {
38615        m = new Matrix2D();
38616        x = y = 0;
38617      }
38618
38619      if (adjustGOffset && element.tagName.toLowerCase() === "g") {
38620        x = y = 0;
38621      }
38622
38623      (isRootSVG ? svg : parent).appendChild(container);
vendor: 1,139 bytes, lines 38624-38659
38624      container.setAttribute("transform", "matrix(" + m.a + "," + m.b + "," + m.c + "," + m.d + "," + (m.e + x) + "," + (m.f + y) + ")");
38625    } else {
38626      x = y = 0;
38627
38628      if (_hasOffsetBug) {
38629        m = element.offsetParent;
38630        b = element;
38631
38632        while (b && (b = b.parentNode) && b !== m && b.parentNode) {
38633          if ((_win.getComputedStyle(b)[_transformProp] + "").length > 4) {
38634            x = b.offsetLeft;
38635            y = b.offsetTop;
38636            b = 0;
38637          }
38638        }
38639      }
38640
38641      cs = _win.getComputedStyle(element);
38642
38643      if (cs.position !== "absolute" && cs.position !== "fixed") {
38644        m = element.offsetParent;
38645
38646        while (parent && parent !== m) {
38647          x += parent.scrollLeft || 0;
38648          y += parent.scrollTop || 0;
38649          parent = parent.parentNode;
38650        }
38651      }
38652
38653      b = container.style;
38654      b.top = element.offsetTop - y + "px";
38655      b.left = element.offsetLeft - x + "px";
38656      b[_transformProp] = cs[_transformProp];
38657      b[_transformOriginProp] = cs[_transformOriginProp];
38658      b.position = cs.position === "fixed" ? "fixed" : "absolute";
38659      element.parentNode
vendor: 37,456 bytes, lines 38659-39914
38659.appendChild(container);
38660    }
38661
38662    return container;
38663  },
38664      _setMatrix = function _setMatrix(m, a, b, c, d, e, f) {
38665    m.a = a;
38666    m.b = b;
38667    m.c = c;
38668    m.d = d;
38669    m.e = e;
38670    m.f = f;
38671    return m;
38672  };
38673
38674  var Matrix2D = function () {
38675    function Matrix2D(a, b, c, d, e, f) {
38676      if (a === void 0) {
38677        a = 1;
38678      }
38679
38680      if (b === void 0) {
38681        b = 0;
38682      }
38683
38684      if (c === void 0) {
38685        c = 0;
38686      }
38687
38688      if (d === void 0) {
38689        d = 1;
38690      }
38691
38692      if (e === void 0) {
38693        e = 0;
38694      }
38695
38696      if (f === void 0) {
38697        f = 0;
38698      }
38699
38700      _setMatrix(this, a, b, c, d, e, f);
38701    }
38702
38703    var _proto = Matrix2D.prototype;
38704
38705    _proto.inverse = function inverse() {
38706      var a = this.a,
38707          b = this.b,
38708          c = this.c,
38709          d = this.d,
38710          e = this.e,
38711          f = this.f,
38712          determinant = a * d - b * c || 1e-10;
38713      return _setMatrix(this, d / determinant, -b / determinant, -c / determinant, a / determinant, (c * f - d * e) / determinant, -(a * f - b * e) / determinant);
38714    };
38715
38716    _proto.multiply = function multiply(matrix) {
38717      var a = this.a,
38718          b = this.b,
38719          c = this.c,
38720          d = this.d,
38721          e = this.e,
38722          f = this.f,
38723          a2 = matrix.a,
38724          b2 = matrix.c,
38725          c2 = matrix.b,
38726          d2 = matrix.d,
38727          e2 = matrix.e,
38728          f2 = matrix.f;
38729      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);
38730    };
38731
38732    _proto.clone = function clone() {
38733      return new Matrix2D(this.a, this.b, this.c, this.d, this.e, this.f);
38734    };
38735
38736    _proto.equals = function equals(matrix) {
38737      var a = this.a,
38738          b = this.b,
38739          c = this.c,
38740          d = this.d,
38741          e = this.e,
38742          f = this.f;
38743      return a === matrix.a && b === matrix.b && c === matrix.c && d === matrix.d && e === matrix.e && f === matrix.f;
38744    };
38745
38746    _proto.apply = function apply(point, decoratee) {
38747      if (decoratee === void 0) {
38748        decoratee = {};
38749      }
38750
38751      var x = point.x,
38752          y = point.y,
38753          a = this.a,
38754          b = this.b,
38755          c = this.c,
38756          d = this.d,
38757          e = this.e,
38758          f = this.f;
38759      decoratee.x = x * a + y * c + e || 0;
38760      decoratee.y = x * b + y * d + f || 0;
38761      return decoratee;
38762    };
38763
38764    return Matrix2D;
38765  }();
38766  function getGlobalMatrix(element, inverse, adjustGOffset, includeScrollInFixed) {
38767    if (!element || !element.parentNode || (_doc || _setDoc(element)).documentElement === element) {
38768      return new Matrix2D();
38769    }
38770
38771    var zeroScales = _forceNonZeroScale(element),
38772        svg = _svgOwner(element),
38773        temps = svg ? _svgTemps : _divTemps,
38774        container = _placeSiblings(element, adjustGOffset),
38775        b1 = temps[0].getBoundingClientRect(),
38776        b2 = temps[1].getBoundingClientRect(),
38777        b3 = temps[2].getBoundingClientRect(),
38778        parent = container.parentNode,
38779        isFixed = !includeScrollInFixed && _isFixed(element),
38780        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()));
38781
38782    parent.removeChild(container);
38783
38784    if (zeroScales) {
38785      b1 = zeroScales.length;
38786
38787      while (b1--) {
38788        b2 = zeroScales[b1];
38789        b2.scaleX = b2.scaleY = 0;
38790        b2.renderTransform(1, b2);
38791      }
38792    }
38793
38794    return inverse ? m.inverse() : m;
38795  }
38796
38797  var gsap,
38798      _win$1,
38799      _doc$1,
38800      _docElement$1,
38801      _body$1,
38802      _tempDiv,
38803      _placeholderDiv,
38804      _coreInitted,
38805      _checkPrefix,
38806      _toArray,
38807      _supportsPassive,
38808      _isTouchDevice,
38809      _touchEventLookup,
38810      _isMultiTouching,
38811      _isAndroid,
38812      InertiaPlugin,
38813      _defaultCursor,
38814      _supportsPointer,
38815      _context,
38816      _getStyleSaver,
38817      _dragCount = 0,
38818      _windowExists = function _windowExists() {
38819    return typeof window !== "undefined";
38820  },
38821      _getGSAP = function _getGSAP() {
38822    return gsap || _windowExists() && (gsap = window.gsap) && gsap.registerPlugin && gsap;
38823  },
38824      _isFunction = function _isFunction(value) {
38825    return typeof value === "function";
38826  },
38827      _isObject = function _isObject(value) {
38828    return typeof value === "object";
38829  },
38830      _isUndefined = function _isUndefined(value) {
38831    return typeof value === "undefined";
38832  },
38833      _emptyFunc = function _emptyFunc() {
38834    return false;
38835  },
38836      _transformProp$1 = "transform",
38837      _transformOriginProp$1 = "transformOrigin",
38838      _round = function _round(value) {
38839    return Math.round(value * 10000) / 10000;
38840  },
38841      _isArray = Array.isArray,
38842      _createElement = function _createElement(type, ns) {
38843    var e = _doc$1.createElementNS ? _doc$1.createElementNS((ns || "http://www.w3.org/1999/xhtml").replace(/^https/, "http"), type) : _doc$1.createElement(type);
38844    return e.style ? e : _doc$1.createElement(type);
38845  },
38846      _RAD2DEG = 180 / Math.PI,
38847      _bigNum = 1e20,
38848      _identityMatrix$1 = new Matrix2D(),
38849      _getTime = Date.now || function () {
38850    return new Date().getTime();
38851  },
38852      _renderQueue = [],
38853      _lookup = {},
38854      _lookupCount = 0,
38855      _clickableTagExp = /^(?:a|input|textarea|button|select)$/i,
38856      _lastDragTime = 0,
38857      _temp1 = {},
38858      _windowProxy = {},
38859      _copy = function _copy(obj, factor) {
38860    var copy = {},
38861        p;
38862
38863    for (p in obj) {
38864      copy[p] = factor ? obj[p] * factor : obj[p];
38865    }
38866
38867    return copy;
38868  },
38869      _extend = function _extend(obj, defaults) {
38870    for (var p in defaults) {
38871      if (!(p in obj)) {
38872        obj[p] = defaults[p];
38873      }
38874    }
38875
38876    return obj;
38877  },
38878      _setTouchActionForAllDescendants = function _setTouchActionForAllDescendants(elements, value) {
38879    var i = elements.length,
38880        children;
38881
38882    while (i--) {
38883      value ? elements[i].style.touchAction = value : elements[i].style.removeProperty("touch-action");
38884      children = elements[i].children;
38885      children && children.length && _setTouchActionForAllDescendants(children, value);
38886    }
38887  },
38888      _renderQueueTick = function _renderQueueTick() {
38889    return _renderQueue.forEach(function (func) {
38890      return func();
38891    });
38892  },
38893      _addToRenderQueue = function _addToRenderQueue(func) {
38894    _renderQueue.push(func);
38895
38896    if (_renderQueue.length === 1) {
38897      gsap.ticker.add(_renderQueueTick);
38898    }
38899  },
38900      _renderQueueTimeout = function _renderQueueTimeout() {
38901    return !_renderQueue.length && gsap.ticker.remove(_renderQueueTick);
38902  },
38903      _removeFromRenderQueue = function _removeFromRenderQueue(func) {
38904    var i = _renderQueue.length;
38905
38906    while (i--) {
38907      if (_renderQueue[i] === func) {
38908        _renderQueue.splice(i, 1);
38909      }
38910    }
38911
38912    gsap.to(_renderQueueTimeout, {
38913      overwrite: true,
38914      delay: 15,
38915      duration: 0,
38916      onComplete: _renderQueueTimeout,
38917      data: "_draggable"
38918    });
38919  },
38920      _setDefaults = function _setDefaults(obj, defaults) {
38921    for (var p in defaults) {
38922      if (!(p in obj)) {
38923        obj[p] = defaults[p];
38924      }
38925    }
38926
38927    return obj;
38928  },
38929      _addListener = function _addListener(element, type, func, capture) {
38930    if (element.addEventListener) {
38931      var touchType = _touchEventLookup[type];
38932      capture = capture || (_supportsPassive ? {
38933        passive: false
38934      } : null);
38935      element.addEventListener(touchType || type, func, capture);
38936      touchType && type !== touchType && element.addEventListener(type, func, capture);
38937    }
38938  },
38939      _removeListener = function _removeListener(element, type, func, capture) {
38940    if (element.removeEventListener) {
38941      var touchType = _touchEventLookup[type];
38942      element.removeEventListener(touchType || type, func, capture);
38943      touchType && type !== touchType && element.removeEventListener(type, func, capture);
38944    }
38945  },
38946      _preventDefault = function _preventDefault(event) {
38947    event.preventDefault && event.preventDefault();
38948    event.preventManipulation && event.preventManipulation();
38949  },
38950      _hasTouchID = function _hasTouchID(list, ID) {
38951    var i = list.length;
38952
38953    while (i--) {
38954      if (list[i].identifier === ID) {
38955        return true;
38956      }
38957    }
38958  },
38959      _onMultiTouchDocumentEnd = function _onMultiTouchDocumentEnd(event) {
38960    _isMultiTouching = event.touches && _dragCount < event.touches.length;
38961
38962    _removeListener(event.target, "touchend", _onMultiTouchDocumentEnd);
38963  },
38964      _onMultiTouchDocument = function _onMultiTouchDocument(event) {
38965    _isMultiTouching = event.touches && _dragCount < event.touches.length;
38966
38967    _addListener(event.target, "touchend", _onMultiTouchDocumentEnd);
38968  },
38969      _getDocScrollTop$1 = function _getDocScrollTop(doc) {
38970    return _win$1.pageYOffset || doc.scrollTop || doc.documentElement.scrollTop || doc.body.scrollTop || 0;
38971  },
38972      _getDocScrollLeft$1 = function _getDocScrollLeft(doc) {
38973    return _win$1.pageXOffset || doc.scrollLeft || doc.documentElement.scrollLeft || doc.body.scrollLeft || 0;
38974  },
38975      _addScrollListener = function _addScrollListener(e, callback) {
38976    _addListener(e, "scroll", callback);
38977
38978    if (!_isRoot(e.parentNode)) {
38979      _addScrollListener(e.parentNode, callback);
38980    }
38981  },
38982      _removeScrollListener = function _removeScrollListener(e, callback) {
38983    _removeListener(e, "scroll", callback);
38984
38985    if (!_isRoot(e.parentNode)) {
38986      _removeScrollListener(e.parentNode, callback);
38987    }
38988  },
38989      _isRoot = function _isRoot(e) {
38990    return !!(!e || e === _docElement$1 || e.nodeType === 9 || e === _doc$1.body || e === _win$1 || !e.nodeType || !e.parentNode);
38991  },
38992      _getMaxScroll = function _getMaxScroll(element, axis) {
38993    var dim = axis === "x" ? "Width" : "Height",
38994        scroll = "scroll" + dim,
38995        client = "client" + dim;
38996    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]);
38997  },
38998      _recordMaxScrolls = function _recordMaxScrolls(e, skipCurrent) {
38999    var x = _getMaxScroll(e, "x"),
39000        y = _getMaxScroll(e, "y");
39001
39002    if (_isRoot(e)) {
39003      e = _windowProxy;
39004    } else {
39005      _recordMaxScrolls(e.parentNode, skipCurrent);
39006    }
39007
39008    e._gsMaxScrollX = x;
39009    e._gsMaxScrollY = y;
39010
39011    if (!skipCurrent) {
39012      e._gsScrollX = e.scrollLeft || 0;
39013      e._gsScrollY = e.scrollTop || 0;
39014    }
39015  },
39016      _setStyle = function _setStyle(element, property, value) {
39017    var style = element.style;
39018
39019    if (!style) {
39020      return;
39021    }
39022
39023    if (_isUndefined(style[property])) {
39024      property = _checkPrefix(property, element) || property;
39025    }
39026
39027    if (value == null) {
39028      style.removeProperty && style.removeProperty(property.replace(/([A-Z])/g, "-$1").toLowerCase());
39029    } else {
39030      style[property] = value;
39031    }
39032  },
39033      _getComputedStyle = function _getComputedStyle(element) {
39034    return _win$1.getComputedStyle(element instanceof Element ? element : element.host || (element.parentNode || {}).host || element);
39035  },
39036      _tempRect = {},
39037      _parseRect = function _parseRect(e) {
39038    if (e === _win$1) {
39039      _tempRect.left = _tempRect.top = 0;
39040      _tempRect.width = _tempRect.right = _docElement$1.clientWidth || e.innerWidth || _body$1.clientWidth || 0;
39041      _tempRect.height = _tempRect.bottom = (e.innerHeight || 0) - 20 < _docElement$1.clientHeight ? _docElement$1.clientHeight : e.innerHeight || _body$1.clientHeight || 0;
39042      return _tempRect;
39043    }
39044
39045    var doc = e.ownerDocument || _doc$1,
39046        r = !_isUndefined(e.pageX) ? {
39047      left: e.pageX - _getDocScrollLeft$1(doc),
39048      top: e.pageY - _getDocScrollTop$1(doc),
39049      right: e.pageX - _getDocScrollLeft$1(doc) + 1,
39050      bottom: e.pageY - _getDocScrollTop$1(doc) + 1
39051    } : !e.nodeType && !_isUndefined(e.left) && !_isUndefined(e.top) ? e : _toArray(e)[0].getBoundingClientRect();
39052
39053    if (_isUndefined(r.right) && !_isUndefined(r.width)) {
39054      r.right = r.left + r.width;
39055      r.bottom = r.top + r.height;
39056    } else if (_isUndefined(r.width)) {
39057      r = {
39058        width: r.right - r.left,
39059        height: r.bottom - r.top,
39060        right: r.right,
39061        left: r.left,
39062        bottom: r.bottom,
39063        top: r.top
39064      };
39065    }
39066
39067    return r;
39068  },
39069      _dispatchEvent = function _dispatchEvent(target, type, callbackName) {
39070    var vars = target.vars,
39071        callback = vars[callbackName],
39072        listeners = target._listeners[type],
39073        result;
39074
39075    if (_isFunction(callback)) {
39076      result = callback.apply(vars.callbackScope || target, vars[callbackName + "Params"] || [target.pointerEvent]);
39077    }
39078
39079    if (listeners && target.dispatchEvent(type) === false) {
39080      result = false;
39081    }
39082
39083    return result;
39084  },
39085      _getBounds = function _getBounds(target, context) {
39086    var e = _toArray(target)[0],
39087        top,
39088        left,
39089        offset;
39090
39091    if (!e.nodeType && e !== _win$1) {
39092      if (!_isUndefined(target.left)) {
39093        offset = {
39094          x: 0,
39095          y: 0
39096        };
39097        return {
39098          left: target.left - offset.x,
39099          top: target.top - offset.y,
39100          width: target.width,
39101          height: target.height
39102        };
39103      }
39104
39105      left = target.min || target.minX || target.minRotation || 0;
39106      top = target.min || target.minY || 0;
39107      return {
39108        left: left,
39109        top: top,
39110        width: (target.max || target.maxX || target.maxRotation || 0) - left,
39111        height: (target.max || target.maxY || 0) - top
39112      };
39113    }
39114
39115    return _getElementBounds(e, context);
39116  },
39117      _point1 = {},
39118      _getElementBounds = function _getElementBounds(element, context) {
39119    context = _toArray(context)[0];
39120    var isSVG = element.getBBox && element.ownerSVGElement,
39121        doc = element.ownerDocument || _doc$1,
39122        left,
39123        right,
39124        top,
39125        bottom,
39126        matrix,
39127        p1,
39128        p2,
39129        p3,
39130        p4,
39131        bbox,
39132        width,
39133        height,
39134        cs;
39135
39136    if (element === _win$1) {
39137      top = _getDocScrollTop$1(doc);
39138      left = _getDocScrollLeft$1(doc);
39139      right = left + (doc.documentElement.clientWidth || element.innerWidth || doc.body.clientWidth || 0);
39140      bottom = top + ((element.innerHeight || 0) - 20 < doc.documentElement.clientHeight ? doc.documentElement.clientHeight : element.innerHeight || doc.body.clientHeight || 0);
39141    } else if (context === _win$1 || _isUndefined(context)) {
39142      return element.getBoundingClientRect();
39143    } else {
39144      left = top = 0;
39145
39146      if (isSVG) {
39147        bbox = element.getBBox();
39148        width = bbox.width;
39149        height = bbox.height;
39150      } else {
39151        if (element.viewBox && (bbox = element.viewBox.baseVal)) {
39152          left = bbox.x || 0;
39153          top = bbox.y || 0;
39154          width = bbox.width;
39155          height = bbox.height;
39156        }
39157
39158        if (!width) {
39159          cs = _getComputedStyle(element);
39160          bbox = cs.boxSizing === "border-box";
39161          width = (parseFloat(cs.width) || element.clientWidth || 0) + (bbox ? 0 : parseFloat(cs.borderLeftWidth) + parseFloat(cs.borderRightWidth));
39162          height = (parseFloat(cs.height) || element.clientHeight || 0) + (bbox ? 0 : parseFloat(cs.borderTopWidth) + parseFloat(cs.borderBottomWidth));
39163        }
39164      }
39165
39166      right = width;
39167      bottom = height;
39168    }
39169
39170    if (element === context) {
39171      return {
39172        left: left,
39173        top: top,
39174        width: right - left,
39175        height: bottom - top
39176      };
39177    }
39178
39179    matrix = getGlobalMatrix(context, true).multiply(getGlobalMatrix(element));
39180    p1 = matrix.apply({
39181      x: left,
39182      y: top
39183    });
39184    p2 = matrix.apply({
39185      x: right,
39186      y: top
39187    });
39188    p3 = matrix.apply({
39189      x: right,
39190      y: bottom
39191    });
39192    p4 = matrix.apply({
39193      x: left,
39194      y: bottom
39195    });
39196    left = Math.min(p1.x, p2.x, p3.x, p4.x);
39197    top = Math.min(p1.y, p2.y, p3.y, p4.y);
39198    return {
39199      left: left,
39200      top: top,
39201      width: Math.max(p1.x, p2.x, p3.x, p4.x) - left,
39202      height: Math.max(p1.y, p2.y, p3.y, p4.y) - top
39203    };
39204  },
39205      _parseInertia = function _parseInertia(draggable, snap, max, min, factor, forceZeroVelocity) {
39206    var vars = {},
39207        a,
39208        i,
39209        l;
39210
39211    if (snap) {
39212      if (factor !== 1 && snap instanceof Array) {
39213        vars.end = a = [];
39214        l = snap.length;
39215
39216        if (_isObject(snap[0])) {
39217          for (i = 0; i < l; i++) {
39218            a[i] = _copy(snap[i], factor);
39219          }
39220        } else {
39221          for (i = 0; i < l; i++) {
39222            a[i] = snap[i] * factor;
39223          }
39224        }
39225
39226        max += 1.1;
39227        min -= 1.1;
39228      } else if (_isFunction(snap)) {
39229        vars.end = function (value) {
39230          var result = snap.call(draggable, value),
39231              copy,
39232              p;
39233
39234          if (factor !== 1) {
39235            if (_isObject(result)) {
39236              copy = {};
39237
39238              for (p in result) {
39239                copy[p] = result[p] * factor;
39240              }
39241
39242              result = copy;
39243            } else {
39244              result *= factor;
39245            }
39246          }
39247
39248          return result;
39249        };
39250      } else {
39251        vars.end = snap;
39252      }
39253    }
39254
39255    if (max || max === 0) {
39256      vars.max = max;
39257    }
39258
39259    if (min || min === 0) {
39260      vars.min = min;
39261    }
39262
39263    if (forceZeroVelocity) {
39264      vars.velocity = 0;
39265    }
39266
39267    return vars;
39268  },
39269      _isClickable = function _isClickable(element) {
39270    var data;
39271    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);
39272  },
39273      _setSelectable = function _setSelectable(elements, selectable) {
39274    var i = elements.length,
39275        e;
39276
39277    while (i--) {
39278      e = elements[i];
39279      e.ondragstart = e.onselectstart = selectable ? null : _emptyFunc;
39280      gsap.set(e, {
39281        lazy: true,
39282        userSelect: selectable ? "text" : "none"
39283      });
39284    }
39285  },
39286      _isFixed$1 = function _isFixed(element) {
39287    if (_getComputedStyle(element).position === "fixed") {
39288      return true;
39289    }
39290
39291    element = element.parentNode;
39292
39293    if (element && element.nodeType === 1) {
39294      return _isFixed(element);
39295    }
39296  },
39297      _supports3D,
39298      _addPaddingBR,
39299      ScrollProxy = function ScrollProxy(element, vars) {
39300    element = gsap.utils.toArray(element)[0];
39301    vars = vars || {};
39302    var content = document.createElement("div"),
39303        style = content.style,
39304        node = element.firstChild,
39305        offsetTop = 0,
39306        offsetLeft = 0,
39307        prevTop = element.scrollTop,
39308        prevLeft = element.scrollLeft,
39309        scrollWidth = element.scrollWidth,
39310        scrollHeight = element.scrollHeight,
39311        extraPadRight = 0,
39312        maxLeft = 0,
39313        maxTop = 0,
39314        elementWidth,
39315        elementHeight,
39316        contentHeight,
39317        nextNode,
39318        transformStart,
39319        transformEnd;
39320
39321    if (_supports3D && vars.force3D !== false) {
39322      transformStart = "translate3d(";
39323      transformEnd = "px,0px)";
39324    } else if (_transformProp$1) {
39325      transformStart = "translate(";
39326      transformEnd = "px)";
39327    }
39328
39329    this.scrollTop = function (value, force) {
39330      if (!arguments.length) {
39331        return -this.top();
39332      }
39333
39334      this.top(-value, force);
39335    };
39336
39337    this.scrollLeft = function (value, force) {
39338      if (!arguments.length) {
39339        return -this.left();
39340      }
39341
39342      this.left(-value, force);
39343    };
39344
39345    this.left = function (value, force) {
39346      if (!arguments.length) {
39347        return -(element.scrollLeft + offsetLeft);
39348      }
39349
39350      var dif = element.scrollLeft - prevLeft,
39351          oldOffset = offsetLeft;
39352
39353      if ((dif > 2 || dif < -2) && !force) {
39354        prevLeft = element.scrollLeft;
39355        gsap.killTweensOf(this, {
39356          left: 1,
39357          scrollLeft: 1
39358        });
39359        this.left(-prevLeft);
39360
39361        if (vars.onKill) {
39362          vars.onKill();
39363        }
39364
39365        return;
39366      }
39367
39368      value = -value;
39369
39370      if (value < 0) {
39371        offsetLeft = value - 0.5 | 0;
39372        value = 0;
39373      } else if (value > maxLeft) {
39374        offsetLeft = value - maxLeft | 0;
39375        value = maxLeft;
39376      } else {
39377        offsetLeft = 0;
39378      }
39379
39380      if (offsetLeft || oldOffset) {
39381        if (!this._skip) {
39382          style[_transformProp$1] = transformStart + -offsetLeft + "px," + -offsetTop + transformEnd;
39383        }
39384
39385        if (offsetLeft + extraPadRight >= 0) {
39386          style.paddingRight = offsetLeft + extraPadRight + "px";
39387        }
39388      }
39389
39390      element.scrollLeft = value | 0;
39391      prevLeft = element.scrollLeft;
39392    };
39393
39394    this.top = function (value, force) {
39395      if (!arguments.length) {
39396        return -(element.scrollTop + offsetTop);
39397      }
39398
39399      var dif = element.scrollTop - prevTop,
39400          oldOffset = offsetTop;
39401
39402      if ((dif > 2 || dif < -2) && !force) {
39403        prevTop = element.scrollTop;
39404        gsap.killTweensOf(this, {
39405          top: 1,
39406          scrollTop: 1
39407        });
39408        this.top(-prevTop);
39409
39410        if (vars.onKill) {
39411          vars.onKill();
39412        }
39413
39414        return;
39415      }
39416
39417      value = -value;
39418
39419      if (value < 0) {
39420        offsetTop = value - 0.5 | 0;
39421        value = 0;
39422      } else if (value > maxTop) {
39423        offsetTop = value - maxTop | 0;
39424        value = maxTop;
39425      } else {
39426        offsetTop = 0;
39427      }
39428
39429      if (offsetTop || oldOffset) {
39430        if (!this._skip) {
39431          style[_transformProp$1] = transformStart + -offsetLeft + "px," + -offsetTop + transformEnd;
39432        }
39433      }
39434
39435      element.scrollTop = value | 0;
39436      prevTop = element.scrollTop;
39437    };
39438
39439    this.maxScrollTop = function () {
39440      return maxTop;
39441    };
39442
39443    this.maxScrollLeft = function () {
39444      return maxLeft;
39445    };
39446
39447    this.disable = function () {
39448      node = content.firstChild;
39449
39450      while (node) {
39451        nextNode = node.nextSibling;
39452        element.appendChild(node);
39453        node = nextNode;
39454      }
39455
39456      if (element === content.parentNode) {
39457        element.removeChild(content);
39458      }
39459    };
39460
39461    this.enable = function () {
39462      node = element.firstChild;
39463
39464      if (node === content) {
39465        return;
39466      }
39467
39468      while (node) {
39469        nextNode = node.nextSibling;
39470        content.appendChild(node);
39471        node = nextNode;
39472      }
39473
39474      element.appendChild(content);
39475      this.calibrate();
39476    };
39477
39478    this.calibrate = function (force) {
39479      var widthMatches = element.clientWidth === elementWidth,
39480          cs,
39481          x,
39482          y;
39483      prevTop = element.scrollTop;
39484      prevLeft = element.scrollLeft;
39485
39486      if (widthMatches && element.clientHeight === elementHeight && content.offsetHeight === contentHeight && scrollWidth === element.scrollWidth && scrollHeight === element.scrollHeight && !force) {
39487        return;
39488      }
39489
39490      if (offsetTop || offsetLeft) {
39491        x = this.left();
39492        y = this.top();
39493        this.left(-element.scrollLeft);
39494        this.top(-element.scrollTop);
39495      }
39496
39497      cs = _getComputedStyle(element);
39498
39499      if (!widthMatches || force) {
39500        style.display = "block";
39501        style.width = "auto";
39502        style.paddingRight = "0px";
39503        extraPadRight = Math.max(0, element.scrollWidth - element.clientWidth);
39504
39505        if (extraPadRight) {
39506          extraPadRight += parseFloat(cs.paddingLeft) + (_addPaddingBR ? parseFloat(cs.paddingRight) : 0);
39507        }
39508      }
39509
39510      style.display = "inline-block";
39511      style.position = "relative";
39512      style.overflow = "visible";
39513      style.verticalAlign = "top";
39514      style.boxSizing = "content-box";
39515      style.width = "100%";
39516      style.paddingRight = extraPadRight + "px";
39517
39518      if (_addPaddingBR) {
39519        style.paddingBottom = cs.paddingBottom;
39520      }
39521
39522      elementWidth = element.clientWidth;
39523      elementHeight = element.clientHeight;
39524      scrollWidth = element.scrollWidth;
39525      scrollHeight = element.scrollHeight;
39526      maxLeft = element.scrollWidth - elementWidth;
39527      maxTop = element.scrollHeight - elementHeight;
39528      contentHeight = content.offsetHeight;
39529      style.display = "block";
39530
39531      if (x || y) {
39532        this.left(x);
39533        this.top(y);
39534      }
39535    };
39536
39537    this.content = content;
39538    this.element = element;
39539    this._skip = false;
39540    this.enable();
39541  },
39542      _initCore = function _initCore(required) {
39543    if (_windowExists() && document.body) {
39544      var nav = window && window.navigator;
39545      _win$1 = window;
39546      _doc$1 = document;
39547      _docElement$1 = _doc$1.documentElement;
39548      _body$1 = _doc$1.body;
39549      _tempDiv = _createElement("div");
39550      _supportsPointer = !!window.PointerEvent;
39551      _placeholderDiv = _createElement("div");
39552      _placeholderDiv.style.cssText = "visibility:hidden;height:1px;top:-1px;pointer-events:none;position:relative;clear:both;cursor:grab";
39553      _defaultCursor = _placeholderDiv.style.cursor === "grab" ? "grab" : "move";
39554      _isAndroid = nav && nav.userAgent.toLowerCase().indexOf("android") !== -1;
39555      _isTouchDevice = "ontouchstart" in _docElement$1 && "orientation" in _win$1 || nav && (nav.MaxTouchPoints > 0 || nav.msMaxTouchPoints > 0);
39556
39557      _addPaddingBR = function () {
39558        var div = _createElement("div"),
39559            child = _createElement("div"),
39560            childStyle = child.style,
39561            parent = _body$1,
39562            val;
39563
39564        childStyle.display = "inline-block";
39565        childStyle.position = "relative";
39566        div.style.cssText = "width:90px;height:40px;padding:10px;overflow:auto;visibility:hidden";
39567        div.appendChild(child);
39568        parent.appendChild(div);
39569        val = child.offsetHeight + 18 > div.scrollHeight;
39570        parent.removeChild(div);
39571        return val;
39572      }();
39573
39574      _touchEventLookup = function (types) {
39575        var standard = types.split(","),
39576            converted = ("onpointerdown" in _tempDiv ? "pointerdown,pointermove,pointerup,pointercancel" : "onmspointerdown" in _tempDiv ? "MSPointerDown,MSPointerMove,MSPointerUp,MSPointerCancel" : types).split(","),
39577            obj = {},
39578            i = 4;
39579
39580        while (--i > -1) {
39581          obj[standard[i]] = converted[i];
39582          obj[converted[i]] = standard[i];
39583        }
39584
39585        try {
39586          _docElement$1.addEventListener("test", null, Object.defineProperty({}, "passive", {
39587            get: function get() {
39588              _supportsPassive = 1;
39589            }
39590          }));
39591        } catch (e) {}
39592
39593        return obj;
39594      }("touchstart,touchmove,touchend,touchcancel");
39595
39596      _addListener(_doc$1, "touchcancel", _emptyFunc);
39597
39598      _addListener(_win$1, "touchmove", _emptyFunc);
39599
39600      _body$1 && _body$1.addEventListener("touchstart", _emptyFunc);
39601
39602      _addListener(_doc$1, "contextmenu", function () {
39603        for (var p in _lookup) {
39604          if (_lookup[p].isPressed) {
39605            _lookup[p].endDrag();
39606          }
39607        }
39608      });
39609
39610      gsap = _coreInitted = _getGSAP();
39611    }
39612
39613    if (gsap) {
39614      InertiaPlugin = gsap.plugins.inertia;
39615
39616      _context = gsap.core.context || function () {};
39617
39618      _checkPrefix = gsap.utils.checkPrefix;
39619      _transformProp$1 = _checkPrefix(_transformProp$1);
39620      _transformOriginProp$1 = _checkPrefix(_transformOriginProp$1);
39621      _toArray = gsap.utils.toArray;
39622      _getStyleSaver = gsap.core.getStyleSaver;
39623      _supports3D = !!_checkPrefix("perspective");
39624    } else if (required) {
39625      console.warn("Please gsap.registerPlugin(Draggable)");
39626    }
39627  };
39628
39629  var EventDispatcher = function () {
39630    function EventDispatcher(target) {
39631      this._listeners = {};
39632      this.target = target || this;
39633    }
39634
39635    var _proto = EventDispatcher.prototype;
39636
39637    _proto.addEventListener = function addEventListener(type, callback) {
39638      var list = this._listeners[type] || (this._listeners[type] = []);
39639
39640      if (!~list.indexOf(callback)) {
39641        list.push(callback);
39642      }
39643    };
39644
39645    _proto.removeEventListener = function removeEventListener(type, callback) {
39646      var list = this._listeners[type],
39647          i = list && list.indexOf(callback);
39648      i >= 0 && list.splice(i, 1);
39649    };
39650
39651    _proto.dispatchEvent = function dispatchEvent(type) {
39652      var _this = this;
39653
39654      var result;
39655      (this._listeners[type] || []).forEach(function (callback) {
39656        return callback.call(_this, {
39657          type: type,
39658          target: _this.target
39659        }) === false && (result = false);
39660      });
39661      return result;
39662    };
39663
39664    return EventDispatcher;
39665  }();
39666
39667  var Draggable = function (_EventDispatcher) {
39668    _inheritsLoose(Draggable, _EventDispatcher);
39669
39670    function Draggable(target, vars) {
39671      var _this2;
39672
39673      _this2 = _EventDispatcher.call(this) || this;
39674      _coreInitted || _initCore(1);
39675      target = _toArray(target)[0];
39676      _this2.styles = _getStyleSaver && _getStyleSaver(target, "transform,left,top");
39677
39678      if (!InertiaPlugin) {
39679        InertiaPlugin = gsap.plugins.inertia;
39680      }
39681
39682      _this2.vars = vars = _copy(vars || {});
39683      _this2.target = target;
39684      _this2.x = _this2.y = _this2.rotation = 0;
39685      _this2.dragResistance = parseFloat(vars.dragResistance) || 0;
39686      _this2.edgeResistance = isNaN(vars.edgeResistance) ? 1 : parseFloat(vars.edgeResistance) || 0;
39687      _this2.lockAxis = vars.lockAxis;
39688      _this2.autoScroll = vars.autoScroll || 0;
39689      _this2.lockedAxis = null;
39690      _this2.allowEventDefault = !!vars.allowEventDefault;
39691      gsap.getProperty(target, "x");
39692
39693      var type = (vars.type || "x,y").toLowerCase(),
39694          xyMode = ~type.indexOf("x") || ~type.indexOf("y"),
39695          rotationMode = type.indexOf("rotation") !== -1,
39696          xProp = rotationMode ? "rotation" : xyMode ? "x" : "left",
39697          yProp = xyMode ? "y" : "top",
39698          allowX = !!(~type.indexOf("x") || ~type.indexOf("left") || type === "scroll"),
39699          allowY = !!(~type.indexOf("y") || ~type.indexOf("top") || type === "scroll"),
39700          minimumMovement = vars.minimumMovement || 2,
39701          self = _assertThisInitialized(_this2),
39702          triggers = _toArray(vars.trigger || vars.handle || target),
39703          killProps = {},
39704          dragEndTime = 0,
39705          checkAutoScrollBounds = false,
39706          autoScrollMarginTop = vars.autoScrollMarginTop || 40,
39707          autoScrollMarginRight = vars.autoScrollMarginRight || 40,
39708          autoScrollMarginBottom = vars.autoScrollMarginBottom || 40,
39709          autoScrollMarginLeft = vars.autoScrollMarginLeft || 40,
39710          isClickable = vars.clickableTest || _isClickable,
39711          clickTime = 0,
39712          gsCache = target._gsap || gsap.core.getCache(target),
39713          isFixed = _isFixed$1(target),
39714          getPropAsNum = function getPropAsNum(property, unit) {
39715        return parseFloat(gsCache.get(target, property, unit));
39716      },
39717          ownerDoc = target.ownerDocument || _doc$1,
39718          enabled,
39719          scrollProxy,
39720          startPointerX,
39721          startPointerY,
39722          startElementX,
39723          startElementY,
39724          hasBounds,
39725          hasDragCallback,
39726          hasMoveCallback,
39727          maxX,
39728          minX,
39729          maxY,
39730          minY,
39731          touch,
39732          touchID,
39733          rotationOrigin,
39734          dirty,
39735          old,
39736          snapX,
39737          snapY,
39738          snapXY,
39739          isClicking,
39740          touchEventTarget,
39741          matrix,
39742          interrupted,
39743          allowNativeTouchScrolling,
39744          touchDragAxis,
39745          isDispatching,
39746          clickDispatch,
39747          trustedClickDispatch,
39748          isPreventingDefault,
39749          innerMatrix,
39750          dragged,
39751          onContextMenu = function onContextMenu(e) {
39752        _preventDefault(e);
39753
39754        e.stopImmediatePropagation && e.stopImmediatePropagation();
39755        return false;
39756      },
39757          render = function render(suppressEvents) {
39758        if (self.autoScroll && self.isDragging && (checkAutoScrollBounds || dirty)) {
39759          var e = target,
39760              autoScrollFactor = self.autoScroll * 15,
39761              parent,
39762              isRoot,
39763              rect,
39764              pointerX,
39765              pointerY,
39766              changeX,
39767              changeY,
39768              gap;
39769          checkAutoScrollBounds = false;
39770          _windowProxy.scrollTop = _win$1.pageYOffset != null ? _win$1.pageYOffset : ownerDoc.documentElement.scrollTop != null ? ownerDoc.documentElement.scrollTop : ownerDoc.body.scrollTop;
39771          _windowProxy.scrollLeft = _win$1.pageXOffset != null ? _win$1.pageXOffset : ownerDoc.documentElement.scrollLeft != null ? ownerDoc.documentElement.scrollLeft : ownerDoc.body.scrollLeft;
39772          pointerX = self.pointerX - _windowProxy.scrollLeft;
39773          pointerY = self.pointerY - _windowProxy.scrollTop;
39774
39775          while (e && !isRoot) {
39776            isRoot = _isRoot(e.parentNode);
39777            parent = isRoot ? _windowProxy : e.parentNode;
39778            rect = isRoot ? {
39779              bottom: Math.max(_docElement$1.clientHeight, _win$1.innerHeight || 0),
39780              right: Math.max(_docElement$1.clientWidth, _win$1.innerWidth || 0),
39781              left: 0,
39782              top: 0
39783            } : parent.getBoundingClientRect();
39784            changeX = changeY = 0;
39785
39786            if (allowY) {
39787              gap = parent._gsMaxScrollY - parent.scrollTop;
39788
39789              if (gap < 0) {
39790                changeY = gap;
39791              } else if (pointerY > rect.bottom - autoScrollMarginBottom && gap) {
39792                checkAutoScrollBounds = true;
39793                changeY = Math.min(gap, autoScrollFactor * (1 - Math.max(0, rect.bottom - pointerY) / autoScrollMarginBottom) | 0);
39794              } else if (pointerY < rect.top + autoScrollMarginTop && parent.scrollTop) {
39795                checkAutoScrollBounds = true;
39796                changeY = -Math.min(parent.scrollTop, autoScrollFactor * (1 - Math.max(0, pointerY - rect.top) / autoScrollMarginTop) | 0);
39797              }
39798
39799              if (changeY) {
39800                parent.scrollTop += changeY;
39801              }
39802            }
39803
39804            if (allowX) {
39805              gap = parent._gsMaxScrollX - parent.scrollLeft;
39806
39807              if (gap < 0) {
39808                changeX = gap;
39809              } else if (pointerX > rect.right - autoScrollMarginRight && gap) {
39810                checkAutoScrollBounds = true;
39811                changeX = Math.min(gap, autoScrollFactor * (1 - Math.max(0, rect.right - pointerX) / autoScrollMarginRight) | 0);
39812              } else if (pointerX < rect.left + autoScrollMarginLeft && parent.scrollLeft) {
39813                checkAutoScrollBounds = true;
39814                changeX = -Math.min(parent.scrollLeft, autoScrollFactor * (1 - Math.max(0, pointerX - rect.left) / autoScrollMarginLeft) | 0);
39815              }
39816
39817              if (changeX) {
39818                parent.scrollLeft += changeX;
39819              }
39820            }
39821
39822            if (isRoot && (changeX || changeY)) {
39823              _win$1.scrollTo(parent.scrollLeft, parent.scrollTop);
39824
39825              setPointerPosition(self.pointerX + changeX, self.pointerY + changeY);
39826            }
39827
39828            e = parent;
39829          }
39830        }
39831
39832        if (dirty) {
39833          var x = self.x,
39834              y = self.y;
39835
39836          if (rotationMode) {
39837            self.deltaX = x - parseFloat(gsCache.rotation);
39838            self.rotation = x;
39839            gsCache.rotation = x + "deg";
39840            gsCache.renderTransform(1, gsCache);
39841          } else {
39842            if (scrollProxy) {
39843              if (allowY) {
39844                self.deltaY = y - scrollProxy.top();
39845                scrollProxy.top(y);
39846              }
39847
39848              if (allowX) {
39849                self.deltaX = x - scrollProxy.left();
39850                scrollProxy.left(x);
39851              }
39852            } else if (xyMode) {
39853              if (allowY) {
39854                self.deltaY = y - parseFloat(gsCache.y);
39855                gsCache.y = y + "px";
39856              }
39857
39858              if (allowX) {
39859                self.deltaX = x - parseFloat(gsCache.x);
39860                gsCache.x = x + "px";
39861              }
39862
39863              gsCache.renderTransform(1, gsCache);
39864            } else {
39865              if (allowY) {
39866                self.deltaY = y - parseFloat(target.style.top || 0);
39867                target.style.top = y + "px";
39868              }
39869
39870              if (allowX) {
39871                self.deltaX = x - parseFloat(target.style.left || 0);
39872                target.style.left = x + "px";
39873              }
39874            }
39875          }
39876
39877          if (hasDragCallback && !suppressEvents && !isDispatching) {
39878            isDispatching = true;
39879
39880            if (_dispatchEvent(self, "drag", "onDrag") === false) {
39881              if (allowX) {
39882                self.x -= self.deltaX;
39883              }
39884
39885              if (allowY) {
39886                self.y -= self.deltaY;
39887              }
39888
39889              render(true);
39890            }
39891
39892            isDispatching = false;
39893          }
39894        }
39895
39896        dirty = false;
39897      },
39898          syncXY = function syncXY(skipOnUpdate, skipSnap) {
39899        var x = self.x,
39900            y = self.y,
39901            snappedValue,
39902            cs;
39903
39904        if (!target._gsap) {
39905          gsCache = gsap.core.getCache(target);
39906        }
39907
39908        gsCache.uncache && gsap.getProperty(target, "x");
39909
39910        if (xyMode) {
39911          self.x = parseFloat(gsCache.x);
39912          self.y = parseFloat(gsCache.y);
39913        } else if (rotationMode) {
39914          self.x = self.rotation = 
39914parseFloat(gsCache.rotation
vendor: 18,327 bytes, lines 39914-40464
39914);
39915        } else if (scrollProxy) {
39916          self.y = scrollProxy.top();
39917          self.x = scrollProxy.left();
39918        } else {
39919          self.y = parseFloat(target.style.top || (cs = _getComputedStyle(target)) && cs.top) || 0;
39920          self.x = parseFloat(target.style.left || (cs || {}).left) || 0;
39921        }
39922
39923        if ((snapX || snapY || snapXY) && !skipSnap && (self.isDragging || self.isThrowing)) {
39924          if (snapXY) {
39925            _temp1.x = self.x;
39926            _temp1.y = self.y;
39927            snappedValue = snapXY(_temp1);
39928
39929            if (snappedValue.x !== self.x) {
39930              self.x = snappedValue.x;
39931              dirty = true;
39932            }
39933
39934            if (snappedValue.y !== self.y) {
39935              self.y = snappedValue.y;
39936              dirty = true;
39937            }
39938          }
39939
39940          if (snapX) {
39941            snappedValue = snapX(self.x);
39942
39943            if (snappedValue !== self.x) {
39944              self.x = snappedValue;
39945
39946              if (rotationMode) {
39947                self.rotation = snappedValue;
39948              }
39949
39950              dirty = true;
39951            }
39952          }
39953
39954          if (snapY) {
39955            snappedValue = snapY(self.y);
39956
39957            if (snappedValue !== self.y) {
39958              self.y = snappedValue;
39959            }
39960
39961            dirty = true;
39962          }
39963        }
39964
39965        dirty && render(true);
39966
39967        if (!skipOnUpdate) {
39968          self.deltaX = self.x - x;
39969          self.deltaY = self.y - y;
39970
39971          _dispatchEvent(self, "throwupdate", "onThrowUpdate");
39972        }
39973      },
39974          buildSnapFunc = function buildSnapFunc(snap, min, max, factor) {
39975        if (min == null) {
39976          min = -_bigNum;
39977        }
39978
39979        if (max == null) {
39980          max = _bigNum;
39981        }
39982
39983        if (_isFunction(snap)) {
39984          return function (n) {
39985            var edgeTolerance = !self.isPressed ? 1 : 1 - self.edgeResistance;
39986            return snap.call(self, (n > max ? max + (n - max) * edgeTolerance : n < min ? min + (n - min) * edgeTolerance : n) * factor) * factor;
39987          };
39988        }
39989
39990        if (_isArray(snap)) {
39991          return function (n) {
39992            var i = snap.length,
39993                closest = 0,
39994                absDif = _bigNum,
39995                val,
39996                dif;
39997
39998            while (--i > -1) {
39999              val = snap[i];
40000              dif = val - n;
40001
40002              if (dif < 0) {
40003                dif = -dif;
40004              }
40005
40006              if (dif < absDif && val >= min && val <= max) {
40007                closest = i;
40008                absDif = dif;
40009              }
40010            }
40011
40012            return snap[closest];
40013          };
40014        }
40015
40016        return isNaN(snap) ? function (n) {
40017          return n;
40018        } : function () {
40019          return snap * factor;
40020        };
40021      },
40022          buildPointSnapFunc = function buildPointSnapFunc(snap, minX, maxX, minY, maxY, radius, factor) {
40023        radius = radius && radius < _bigNum ? radius * radius : _bigNum;
40024
40025        if (_isFunction(snap)) {
40026          return function (point) {
40027            var edgeTolerance = !self.isPressed ? 1 : 1 - self.edgeResistance,
40028                x = point.x,
40029                y = point.y,
40030                result,
40031                dx,
40032                dy;
40033            point.x = x = x > maxX ? maxX + (x - maxX) * edgeTolerance : x < minX ? minX + (x - minX) * edgeTolerance : x;
40034            point.y = y = y > maxY ? maxY + (y - maxY) * edgeTolerance : y < minY ? minY + (y - minY) * edgeTolerance : y;
40035            result = snap.call(self, point);
40036
40037            if (result !== point) {
40038              point.x = result.x;
40039              point.y = result.y;
40040            }
40041
40042            if (factor !== 1) {
40043              point.x *= factor;
40044              point.y *= factor;
40045            }
40046
40047            if (radius < _bigNum) {
40048              dx = point.x - x;
40049              dy = point.y - y;
40050
40051              if (dx * dx + dy * dy > radius) {
40052                point.x = x;
40053                point.y = y;
40054              }
40055            }
40056
40057            return point;
40058          };
40059        }
40060
40061        if (_isArray(snap)) {
40062          return function (p) {
40063            var i = snap.length,
40064                closest = 0,
40065                minDist = _bigNum,
40066                x,
40067                y,
40068                point,
40069                dist;
40070
40071            while (--i > -1) {
40072              point = snap[i];
40073              x = point.x - p.x;
40074              y = point.y - p.y;
40075              dist = x * x + y * y;
40076
40077              if (dist < minDist) {
40078                closest = i;
40079                minDist = dist;
40080              }
40081            }
40082
40083            return minDist <= radius ? snap[closest] : p;
40084          };
40085        }
40086
40087        return function (n) {
40088          return n;
40089        };
40090      },
40091          calculateBounds = function calculateBounds() {
40092        var bounds, targetBounds, snap, snapIsRaw;
40093        hasBounds = false;
40094
40095        if (scrollProxy) {
40096          scrollProxy.calibrate();
40097          self.minX = minX = -scrollProxy.maxScrollLeft();
40098          self.minY = minY = -scrollProxy.maxScrollTop();
40099          self.maxX = maxX = self.maxY = maxY = 0;
40100          hasBounds = true;
40101        } else if (!!vars.bounds) {
40102          bounds = _getBounds(vars.bounds, target.parentNode);
40103
40104          if (rotationMode) {
40105            self.minX = minX = bounds.left;
40106            self.maxX = maxX = bounds.left + bounds.width;
40107            self.minY = minY = self.maxY = maxY = 0;
40108          } else if (!_isUndefined(vars.bounds.maxX) || !_isUndefined(vars.bounds.maxY)) {
40109            bounds = vars.bounds;
40110            self.minX = minX = bounds.minX;
40111            self.minY = minY = bounds.minY;
40112            self.maxX = maxX = bounds.maxX;
40113            self.maxY = maxY = bounds.maxY;
40114          } else {
40115            targetBounds = _getBounds(target, target.parentNode);
40116            self.minX = minX = Math.round(getPropAsNum(xProp, "px") + bounds.left - targetBounds.left);
40117            self.minY = minY = Math.round(getPropAsNum(yProp, "px") + bounds.top - targetBounds.top);
40118            self.maxX = maxX = Math.round(minX + (bounds.width - targetBounds.width));
40119            self.maxY = maxY = Math.round(minY + (bounds.height - targetBounds.height));
40120          }
40121
40122          if (minX > maxX) {
40123            self.minX = maxX;
40124            self.maxX = maxX = minX;
40125            minX = self.minX;
40126          }
40127
40128          if (minY > maxY) {
40129            self.minY = maxY;
40130            self.maxY = maxY = minY;
40131            minY = self.minY;
40132          }
40133
40134          if (rotationMode) {
40135            self.minRotation = minX;
40136            self.maxRotation = maxX;
40137          }
40138
40139          hasBounds = true;
40140        }
40141
40142        if (vars.liveSnap) {
40143          snap = vars.liveSnap === true ? vars.snap || {} : vars.liveSnap;
40144          snapIsRaw = _isArray(snap) || _isFunction(snap);
40145
40146          if (rotationMode) {
40147            snapX = buildSnapFunc(snapIsRaw ? snap : snap.rotation, minX, maxX, 1);
40148            snapY = null;
40149          } else {
40150            if (snap.points) {
40151              snapXY = buildPointSnapFunc(snapIsRaw ? snap : snap.points, minX, maxX, minY, maxY, snap.radius, scrollProxy ? -1 : 1);
40152            } else {
40153              if (allowX) {
40154                snapX = buildSnapFunc(snapIsRaw ? snap : snap.x || snap.left || snap.scrollLeft, minX, maxX, scrollProxy ? -1 : 1);
40155              }
40156
40157              if (allowY) {
40158                snapY = buildSnapFunc(snapIsRaw ? snap : snap.y || snap.top || snap.scrollTop, minY, maxY, scrollProxy ? -1 : 1);
40159              }
40160            }
40161          }
40162        }
40163      },
40164          onThrowComplete = function onThrowComplete() {
40165        self.isThrowing = false;
40166
40167        _dispatchEvent(self, "throwcomplete", "onThrowComplete");
40168      },
40169          onThrowInterrupt = function onThrowInterrupt() {
40170        self.isThrowing = false;
40171      },
40172          animate = function animate(inertia, forceZeroVelocity) {
40173        var snap, snapIsRaw, tween, overshootTolerance;
40174
40175        if (inertia && InertiaPlugin) {
40176          if (inertia === true) {
40177            snap = vars.snap || vars.liveSnap || {};
40178            snapIsRaw = _isArray(snap) || _isFunction(snap);
40179            inertia = {
40180              resistance: (vars.throwResistance || vars.resistance || 1000) / (rotationMode ? 10 : 1)
40181            };
40182
40183            if (rotationMode) {
40184              inertia.rotation = _parseInertia(self, snapIsRaw ? snap : snap.rotation, maxX, minX, 1, forceZeroVelocity);
40185            } else {
40186              if (allowX) {
40187                inertia[xProp] = _parseInertia(self, snapIsRaw ? snap : snap.points || snap.x || snap.left, maxX, minX, scrollProxy ? -1 : 1, forceZeroVelocity || self.lockedAxis === "x");
40188              }
40189
40190              if (allowY) {
40191                inertia[yProp] = _parseInertia(self, snapIsRaw ? snap : snap.points || snap.y || snap.top, maxY, minY, scrollProxy ? -1 : 1, forceZeroVelocity || self.lockedAxis === "y");
40192              }
40193
40194              if (snap.points || _isArray(snap) && _isObject(snap[0])) {
40195                inertia.linkedProps = xProp + "," + yProp;
40196                inertia.radius = snap.radius;
40197              }
40198            }
40199          }
40200
40201          self.isThrowing = true;
40202          overshootTolerance = !isNaN(vars.overshootTolerance) ? vars.overshootTolerance : vars.edgeResistance === 1 ? 0 : 1 - self.edgeResistance + 0.2;
40203
40204          if (!inertia.duration) {
40205            inertia.duration = {
40206              max: Math.max(vars.minDuration || 0, "maxDuration" in vars ? vars.maxDuration : 2),
40207              min: !isNaN(vars.minDuration) ? vars.minDuration : overshootTolerance === 0 || _isObject(inertia) && inertia.resistance > 1000 ? 0 : 0.5,
40208              overshoot: overshootTolerance
40209            };
40210          }
40211
40212          self.tween = tween = gsap.to(scrollProxy || target, {
40213            inertia: inertia,
40214            data: "_draggable",
40215            inherit: false,
40216            onComplete: onThrowComplete,
40217            onInterrupt: onThrowInterrupt,
40218            onUpdate: vars.fastMode ? _dispatchEvent : syncXY,
40219            onUpdateParams: vars.fastMode ? [self, "onthrowupdate", "onThrowUpdate"] : snap && snap.radius ? [false, true] : []
40220          });
40221
40222          if (!vars.fastMode) {
40223            if (scrollProxy) {
40224              scrollProxy._skip = true;
40225            }
40226
40227            tween.render(1e9, true, true);
40228            syncXY(true, true);
40229            self.endX = self.x;
40230            self.endY = self.y;
40231
40232            if (rotationMode) {
40233              self.endRotation = self.x;
40234            }
40235
40236            tween.play(0);
40237            syncXY(true, true);
40238
40239            if (scrollProxy) {
40240              scrollProxy._skip = false;
40241            }
40242          }
40243        } else if (hasBounds) {
40244          self.applyBounds();
40245        }
40246      },
40247          updateMatrix = function updateMatrix(shiftStart) {
40248        var start = matrix,
40249            p;
40250        matrix = getGlobalMatrix(target.parentNode, true);
40251
40252        if (shiftStart && self.isPressed && !matrix.equals(start || new Matrix2D())) {
40253          p = start.inverse().apply({
40254            x: startPointerX,
40255            y: startPointerY
40256          });
40257          matrix.apply(p, p);
40258          startPointerX = p.x;
40259          startPointerY = p.y;
40260        }
40261
40262        if (matrix.equals(_identityMatrix$1)) {
40263          matrix = null;
40264        }
40265      },
40266          recordStartPositions = function recordStartPositions() {
40267        var edgeTolerance = 1 - self.edgeResistance,
40268            offsetX = isFixed ? _getDocScrollLeft$1(ownerDoc) : 0,
40269            offsetY = isFixed ? _getDocScrollTop$1(ownerDoc) : 0,
40270            parsedOrigin,
40271            x,
40272            y;
40273
40274        if (xyMode) {
40275          gsCache.x = getPropAsNum(xProp, "px") + "px";
40276          gsCache.y = getPropAsNum(yProp, "px") + "px";
40277          gsCache.renderTransform();
40278        }
40279
40280        updateMatrix(false);
40281        _point1.x = self.pointerX - offsetX;
40282        _point1.y = self.pointerY - offsetY;
40283        matrix && matrix.apply(_point1, _point1);
40284        startPointerX = _point1.x;
40285        startPointerY = _point1.y;
40286
40287        if (dirty) {
40288          setPointerPosition(self.pointerX, self.pointerY);
40289          render(true);
40290        }
40291
40292        innerMatrix = getGlobalMatrix(target);
40293
40294        if (scrollProxy) {
40295          calculateBounds();
40296          startElementY = scrollProxy.top();
40297          startElementX = scrollProxy.left();
40298        } else {
40299          if (isTweening()) {
40300            syncXY(true, true);
40301            calculateBounds();
40302          } else {
40303            self.applyBounds();
40304          }
40305
40306          if (rotationMode) {
40307            parsedOrigin = target.ownerSVGElement ? [gsCache.xOrigin - target.getBBox().x, gsCache.yOrigin - target.getBBox().y] : (_getComputedStyle(target)[_transformOriginProp$1] || "0 0").split(" ");
40308            rotationOrigin = self.rotationOrigin = getGlobalMatrix(target).apply({
40309              x: parseFloat(parsedOrigin[0]) || 0,
40310              y: parseFloat(parsedOrigin[1]) || 0
40311            });
40312            syncXY(true, true);
40313            x = self.pointerX - rotationOrigin.x - offsetX;
40314            y = rotationOrigin.y - self.pointerY + offsetY;
40315            startElementX = self.x;
40316            startElementY = self.y = Math.atan2(y, x) * _RAD2DEG;
40317          } else {
40318            startElementY = getPropAsNum(yProp, "px");
40319            startElementX = getPropAsNum(xProp, "px");
40320          }
40321        }
40322
40323        if (hasBounds && edgeTolerance) {
40324          if (startElementX > maxX) {
40325            startElementX = maxX + (startElementX - maxX) / edgeTolerance;
40326          } else if (startElementX < minX) {
40327            startElementX = minX - (minX - startElementX) / edgeTolerance;
40328          }
40329
40330          if (!rotationMode) {
40331            if (startElementY > maxY) {
40332              startElementY = maxY + (startElementY - maxY) / edgeTolerance;
40333            } else if (startElementY < minY) {
40334              startElementY = minY - (minY - startElementY) / edgeTolerance;
40335            }
40336          }
40337        }
40338
40339        self.startX = startElementX = _round(startElementX);
40340        self.startY = startElementY = _round(startElementY);
40341      },
40342          isTweening = function isTweening() {
40343        return self.tween && self.tween.isActive();
40344      },
40345          removePlaceholder = function removePlaceholder() {
40346        if (_placeholderDiv.parentNode && !isTweening() && !self.isDragging) {
40347          _placeholderDiv.parentNode.removeChild(_placeholderDiv);
40348        }
40349      },
40350          onPress = function onPress(e, force) {
40351        var i;
40352
40353        if (!enabled || self.isPressed || !e || (e.type === "mousedown" || e.type === "pointerdown") && !force && _getTime() - clickTime < 30 && _touchEventLookup[self.pointerEvent.type]) {
40354          isPreventingDefault && e && enabled && _preventDefault(e);
40355          return;
40356        }
40357
40358        interrupted = isTweening();
40359        dragged = false;
40360        self.pointerEvent = e;
40361
40362        if (_touchEventLookup[e.type]) {
40363          touchEventTarget = ~e.type.indexOf("touch") ? e.currentTarget || e.target : ownerDoc;
40364
40365          _addListener(touchEventTarget, "touchend", onRelease);
40366
40367          _addListener(touchEventTarget, "touchmove", onMove);
40368
40369          _addListener(touchEventTarget, "touchcancel", onRelease);
40370
40371          _addListener(ownerDoc, "touchstart", _onMultiTouchDocument);
40372        } else {
40373          touchEventTarget = null;
40374
40375          _addListener(ownerDoc, "mousemove", onMove);
40376        }
40377
40378        touchDragAxis = null;
40379
40380        if (!_supportsPointer || !touchEventTarget) {
40381          _addListener(ownerDoc, "mouseup", onRelease);
40382
40383          e && e.target && _addListener(e.target, "mouseup", onRelease);
40384        }
40385
40386        isClicking = isClickable.call(self, e.target) && vars.dragClickables === false && !force;
40387
40388        if (isClicking) {
40389          _addListener(e.target, "change", onRelease);
40390
40391          _dispatchEvent(self, "pressInit", "onPressInit");
40392
40393          _dispatchEvent(self, "press", "onPress");
40394
40395          _setSelectable(triggers, true);
40396
40397          isPreventingDefault = false;
40398          return;
40399        }
40400
40401        allowNativeTouchScrolling = !touchEventTarget || allowX === allowY || self.vars.allowNativeTouchScrolling === false || self.vars.allowContextMenu && e && (e.ctrlKey || e.which > 2) ? false : allowX ? "y" : "x";
40402        isPreventingDefault = !allowNativeTouchScrolling && !self.allowEventDefault;
40403
40404        if (isPreventingDefault) {
40405          _preventDefault(e);
40406
40407          _addListener(_win$1, "touchforcechange", _preventDefault);
40408        }
40409
40410        if (e.changedTouches) {
40411          e = touch = e.changedTouches[0];
40412          touchID = e.identifier;
40413        } else if (e.pointerId) {
40414          touchID = e.pointerId;
40415        } else {
40416          touch = touchID = null;
40417        }
40418
40419        _dragCount++;
40420
40421        _addToRenderQueue(render);
40422
40423        startPointerY = self.pointerY = e.pageY;
40424        startPointerX = self.pointerX = e.pageX;
40425
40426        _dispatchEvent(self, "pressInit", "onPressInit");
40427
40428        if (allowNativeTouchScrolling || self.autoScroll) {
40429          _recordMaxScrolls(target.parentNode);
40430        }
40431
40432        if (target.parentNode && self.autoScroll && !scrollProxy && !rotationMode && target.parentNode._gsMaxScrollX && !_placeholderDiv.parentNode && !target.getBBox) {
40433          _placeholderDiv.style.width = target.parentNode.scrollWidth + "px";
40434          target.parentNode.appendChild(_placeholderDiv);
40435        }
40436
40437        recordStartPositions();
40438        self.tween && self.tween.kill();
40439        self.isThrowing = false;
40440        gsap.killTweensOf(scrollProxy || target, killProps, true);
40441        scrollProxy && gsap.killTweensOf(target, {
40442          scrollTo: 1
40443        }, true);
40444        self.tween = self.lockedAxis = null;
40445
40446        if (vars.zIndexBoost || !rotationMode && !scrollProxy && vars.zIndexBoost !== false) {
40447          target.style.zIndex = Draggable.zIndex++;
40448        }
40449
40450        self.isPressed = true;
40451        hasDragCallback = !!(vars.onDrag || self._listeners.drag);
40452        hasMoveCallback = !!(vars.onMove || self._listeners.move);
40453
40454        if (vars.cursor !== false || vars.activeCursor) {
40455          i = triggers.length;
40456
40457          while (--i > -1) {
40458            gsap.set(triggers[i], {
40459              cursor: vars.activeCursor || vars.cursor || (_defaultCursor === "grab" ? "grabbing" : _defaultCursor)
40460            });
40461          }
40462        }
40463
40464        _dispatchEvent(self, "press", "onPress");
vendor: 2,447 bytes, lines 40465-40532
40465      },
40466          onMove = function onMove(e) {
40467        var originalEvent = e,
40468            touches,
40469            pointerX,
40470            pointerY,
40471            i,
40472            dx,
40473            dy;
40474
40475        if (!enabled || _isMultiTouching || !self.isPressed || !e) {
40476          isPreventingDefault && e && enabled && _preventDefault(e);
40477          return;
40478        }
40479
40480        self.pointerEvent = e;
40481        touches = e.changedTouches;
40482
40483        if (touches) {
40484          e = touches[0];
40485
40486          if (e !== touch && e.identifier !== touchID) {
40487            i = touches.length;
40488
40489            while (--i > -1 && (e = touches[i]).identifier !== touchID && e.target !== target) {}
40490
40491            if (i < 0) {
40492              return;
40493            }
40494          }
40495        } else if (e.pointerId && touchID && e.pointerId !== touchID) {
40496          return;
40497        }
40498
40499        if (touchEventTarget && allowNativeTouchScrolling && !touchDragAxis) {
40500          _point1.x = e.pageX - (isFixed ? _getDocScrollLeft$1(ownerDoc) : 0);
40501          _point1.y = e.pageY - (isFixed ? _getDocScrollTop$1(ownerDoc) : 0);
40502          matrix && matrix.apply(_point1, _point1);
40503          pointerX = _point1.x;
40504          pointerY = _point1.y;
40505          dx = Math.abs(pointerX - startPointerX);
40506          dy = Math.abs(pointerY - startPointerY);
40507
40508          if (dx !== dy && (dx > minimumMovement || dy > minimumMovement) || _isAndroid && allowNativeTouchScrolling === touchDragAxis) {
40509            touchDragAxis = dx > dy && allowX ? "x" : "y";
40510
40511            if (allowNativeTouchScrolling && touchDragAxis !== allowNativeTouchScrolling) {
40512              _addListener(_win$1, "touchforcechange", _preventDefault);
40513            }
40514
40515            if (self.vars.lockAxisOnTouchScroll !== false && allowX && allowY) {
40516              self.lockedAxis = touchDragAxis === "x" ? "y" : "x";
40517              _isFunction(self.vars.onLockAxis) && self.vars.onLockAxis.call(self, originalEvent);
40518            }
40519
40520            if (_isAndroid && allowNativeTouchScrolling === touchDragAxis) {
40521              onRelease(originalEvent);
40522              return;
40523            }
40524          }
40525        }
40526
40527        if (!self.allowEventDefault && (!allowNativeTouchScrolling || touchDragAxis && allowNativeTouchScrolling !== touchDragAxis) && originalEvent.cancelable !== false) {
40528          _preventDefault(originalEvent);
40529
40530          isPreventingDefault = true;
40531        } else if (isPreventingDefault) {
40532          isPreventingDefault = false;
vendor: 3,917 bytes, lines 40533-40661
40533        }
40534
40535        if (self.autoScroll) {
40536          checkAutoScrollBounds = true;
40537        }
40538
40539        setPointerPosition(e.pageX, e.pageY, hasMoveCallback);
40540      },
40541          setPointerPosition = function setPointerPosition(pointerX, pointerY, invokeOnMove) {
40542        var dragTolerance = 1 - self.dragResistance,
40543            edgeTolerance = 1 - self.edgeResistance,
40544            prevPointerX = self.pointerX,
40545            prevPointerY = self.pointerY,
40546            prevStartElementY = startElementY,
40547            prevX = self.x,
40548            prevY = self.y,
40549            prevEndX = self.endX,
40550            prevEndY = self.endY,
40551            prevEndRotation = self.endRotation,
40552            prevDirty = dirty,
40553            xChange,
40554            yChange,
40555            x,
40556            y,
40557            dif,
40558            temp;
40559        self.pointerX = pointerX;
40560        self.pointerY = pointerY;
40561
40562        if (isFixed) {
40563          pointerX -= _getDocScrollLeft$1(ownerDoc);
40564          pointerY -= _getDocScrollTop$1(ownerDoc);
40565        }
40566
40567        if (rotationMode) {
40568          y = Math.atan2(rotationOrigin.y - pointerY, pointerX - rotationOrigin.x) * _RAD2DEG;
40569          dif = self.y - y;
40570
40571          if (dif > 180) {
40572            startElementY -= 360;
40573            self.y = y;
40574          } else if (dif < -180) {
40575            startElementY += 360;
40576            self.y = y;
40577          }
40578
40579          if (self.x !== startElementX || Math.abs(startElementY - y) > minimumMovement) {
40580            self.y = y;
40581            x = startElementX + (startElementY - y) * dragTolerance;
40582          } else {
40583            x = startElementX;
40584          }
40585        } else {
40586          if (matrix) {
40587            temp = pointerX * matrix.a + pointerY * matrix.c + matrix.e;
40588            pointerY = pointerX * matrix.b + pointerY * matrix.d + matrix.f;
40589            pointerX = temp;
40590          }
40591
40592          yChange = pointerY - startPointerY;
40593          xChange = pointerX - startPointerX;
40594
40595          if (yChange < minimumMovement && yChange > -minimumMovement) {
40596            yChange = 0;
40597          }
40598
40599          if (xChange < minimumMovement && xChange > -minimumMovement) {
40600            xChange = 0;
40601          }
40602
40603          if ((self.lockAxis || self.lockedAxis) && (xChange || yChange)) {
40604            temp = self.lockedAxis;
40605
40606            if (!temp) {
40607              self.lockedAxis = temp = allowX && Math.abs(xChange) > Math.abs(yChange) ? "y" : allowY ? "x" : null;
40608
40609              if (temp && _isFunction(self.vars.onLockAxis)) {
40610                self.vars.onLockAxis.call(self, self.pointerEvent);
40611              }
40612            }
40613
40614            if (temp === "y") {
40615              yChange = 0;
40616            } else if (temp === "x") {
40617              xChange = 0;
40618            }
40619          }
40620
40621          x = _round(startElementX + xChange * dragTolerance);
40622          y = _round(startElementY + yChange * dragTolerance);
40623        }
40624
40625        if ((snapX || snapY || snapXY) && (self.x !== x || self.y !== y && !rotationMode)) {
40626          if (snapXY) {
40627            _temp1.x = x;
40628            _temp1.y = y;
40629            temp = snapXY(_temp1);
40630            x = _round(temp.x);
40631            y = _round(temp.y);
40632          }
40633
40634          if (snapX) {
40635            x = _round(snapX(x));
40636          }
40637
40638          if (snapY) {
40639            y = _round(snapY(y));
40640          }
40641        }
40642
40643        if (hasBounds) {
40644          if (x > maxX) {
40645            x = maxX + Math.round((x - maxX) * edgeTolerance);
40646          } else if (x < minX) {
40647            x = minX + Math.round((x - minX) * edgeTolerance);
40648          }
40649
40650          if (!rotationMode) {
40651            if (y > maxY) {
40652              y = Math.round(maxY + (y - maxY) * edgeTolerance);
40653            } else if (y < minY) {
40654              y = Math.round(minY + (y - minY) * edgeTolerance);
40655            }
40656          }
40657        }
40658
40659        if (self.x !== x || self.y !== y && !rotationMode) {
40660          if (rotationMode) {
40661            self.endRotation = self.x = self.endX = x
vendor: 13,666 bytes, lines 40661-41068
40661;
40662            dirty = true;
40663          } else {
40664            if (allowY) {
40665              self.y = self.endY = y;
40666              dirty = true;
40667            }
40668
40669            if (allowX) {
40670              self.x = self.endX = x;
40671              dirty = true;
40672            }
40673          }
40674
40675          if (!invokeOnMove || _dispatchEvent(self, "move", "onMove") !== false) {
40676            if (!self.isDragging && self.isPressed) {
40677              self.isDragging = dragged = true;
40678
40679              _dispatchEvent(self, "dragstart", "onDragStart");
40680            }
40681          } else {
40682            self.pointerX = prevPointerX;
40683            self.pointerY = prevPointerY;
40684            startElementY = prevStartElementY;
40685            self.x = prevX;
40686            self.y = prevY;
40687            self.endX = prevEndX;
40688            self.endY = prevEndY;
40689            self.endRotation = prevEndRotation;
40690            dirty = prevDirty;
40691          }
40692        }
40693      },
40694          onRelease = function onRelease(e, force) {
40695        if (!enabled || !self.isPressed || e && touchID != null && !force && (e.pointerId && e.pointerId !== touchID && e.target !== target || e.changedTouches && !_hasTouchID(e.changedTouches, touchID))) {
40696          isPreventingDefault && e && enabled && _preventDefault(e);
40697          return;
40698        }
40699
40700        self.isPressed = false;
40701        var originalEvent = e,
40702            wasDragging = self.isDragging,
40703            isContextMenuRelease = self.vars.allowContextMenu && e && (e.ctrlKey || e.which > 2),
40704            placeholderDelayedCall = gsap.delayedCall(0.001, removePlaceholder),
40705            touches,
40706            i,
40707            syntheticEvent,
40708            eventTarget,
40709            syntheticClick;
40710
40711        if (touchEventTarget) {
40712          _removeListener(touchEventTarget, "touchend", onRelease);
40713
40714          _removeListener(touchEventTarget, "touchmove", onMove);
40715
40716          _removeListener(touchEventTarget, "touchcancel", onRelease);
40717
40718          _removeListener(ownerDoc, "touchstart", _onMultiTouchDocument);
40719        } else {
40720          _removeListener(ownerDoc, "mousemove", onMove);
40721        }
40722
40723        _removeListener(_win$1, "touchforcechange", _preventDefault);
40724
40725        if (!_supportsPointer || !touchEventTarget) {
40726          _removeListener(ownerDoc, "mouseup", onRelease);
40727
40728          e && e.target && _removeListener(e.target, "mouseup", onRelease);
40729        }
40730
40731        dirty = false;
40732
40733        if (wasDragging) {
40734          dragEndTime = _lastDragTime = _getTime();
40735          self.isDragging = false;
40736        }
40737
40738        _removeFromRenderQueue(render);
40739
40740        if (isClicking && !isContextMenuRelease) {
40741          if (e) {
40742            _removeListener(e.target, "change", onRelease);
40743
40744            self.pointerEvent = originalEvent;
40745          }
40746
40747          _setSelectable(triggers, false);
40748
40749          _dispatchEvent(self, "release", "onRelease");
40750
40751          _dispatchEvent(self, "click", "onClick");
40752
40753          isClicking = false;
40754          return;
40755        }
40756
40757        i = triggers.length;
40758
40759        while (--i > -1) {
40760          _setStyle(triggers[i], "cursor", vars.cursor || (vars.cursor !== false ? _defaultCursor : null));
40761        }
40762
40763        _dragCount--;
40764
40765        if (e) {
40766          touches = e.changedTouches;
40767
40768          if (touches) {
40769            e = touches[0];
40770
40771            if (e !== touch && e.identifier !== touchID) {
40772              i = touches.length;
40773
40774              while (--i > -1 && (e = touches[i]).identifier !== touchID && e.target !== target) {}
40775
40776              if (i < 0 && !force) {
40777                return;
40778              }
40779            }
40780          }
40781
40782          self.pointerEvent = originalEvent;
40783          self.pointerX = e.pageX;
40784          self.pointerY = e.pageY;
40785        }
40786
40787        if (isContextMenuRelease && originalEvent) {
40788          _preventDefault(originalEvent);
40789
40790          isPreventingDefault = true;
40791
40792          _dispatchEvent(self, "release", "onRelease");
40793        } else if (originalEvent && !wasDragging) {
40794          isPreventingDefault = false;
40795
40796          if (interrupted && (vars.snap || vars.bounds)) {
40797            animate(vars.inertia || vars.throwProps);
40798          }
40799
40800          _dispatchEvent(self, "release", "onRelease");
40801
40802          if ((!_isAndroid || originalEvent.type !== "touchmove") && originalEvent.type.indexOf("cancel") === -1) {
40803            _dispatchEvent(self, "click", "onClick");
40804
40805            if (_getTime() - clickTime < 300) {
40806              _dispatchEvent(self, "doubleclick", "onDoubleClick");
40807            }
40808
40809            eventTarget = originalEvent.target || target;
40810            clickTime = _getTime();
40811
40812            syntheticClick = function syntheticClick() {
40813              if (clickTime !== clickDispatch && self.enabled() && !self.isPressed && !originalEvent.defaultPrevented) {
40814                if (eventTarget.click) {
40815                  eventTarget.click();
40816                } else if (ownerDoc.createEvent) {
40817                  syntheticEvent = ownerDoc.createEvent("MouseEvents");
40818                  syntheticEvent.initMouseEvent("click", true, true, _win$1, 1, self.pointerEvent.screenX, self.pointerEvent.screenY, self.pointerX, self.pointerY, false, false, false, false, 0, null);
40819                  eventTarget.dispatchEvent(syntheticEvent);
40820                }
40821              }
40822            };
40823
40824            if (!_isAndroid && !originalEvent.defaultPrevented) {
40825              gsap.delayedCall(0.05, syntheticClick);
40826            }
40827          }
40828        } else {
40829          animate(vars.inertia || vars.throwProps);
40830
40831          if (!self.allowEventDefault && originalEvent && (vars.dragClickables !== false || !isClickable.call(self, originalEvent.target)) && wasDragging && (!allowNativeTouchScrolling || touchDragAxis && allowNativeTouchScrolling === touchDragAxis) && originalEvent.cancelable !== false) {
40832            isPreventingDefault = true;
40833
40834            _preventDefault(originalEvent);
40835          } else {
40836            isPreventingDefault = false;
40837          }
40838
40839          _dispatchEvent(self, "release", "onRelease");
40840        }
40841
40842        isTweening() && placeholderDelayedCall.duration(self.tween.duration());
40843        wasDragging && _dispatchEvent(self, "dragend", "onDragEnd");
40844        return true;
40845      },
40846          updateScroll = function updateScroll(e) {
40847        if (e && self.isDragging && !scrollProxy) {
40848          var parent = e.target || target.parentNode,
40849              deltaX = parent.scrollLeft - parent._gsScrollX,
40850              deltaY = parent.scrollTop - parent._gsScrollY;
40851
40852          if (deltaX || deltaY) {
40853            if (matrix) {
40854              startPointerX -= deltaX * matrix.a + deltaY * matrix.c;
40855              startPointerY -= deltaY * matrix.d + deltaX * matrix.b;
40856            } else {
40857              startPointerX -= deltaX;
40858              startPointerY -= deltaY;
40859            }
40860
40861            parent._gsScrollX += deltaX;
40862            parent._gsScrollY += deltaY;
40863            setPointerPosition(self.pointerX, self.pointerY);
40864          }
40865        }
40866      },
40867          onClick = function onClick(e) {
40868        var time = _getTime(),
40869            recentlyClicked = time - clickTime < 100,
40870            recentlyDragged = time - dragEndTime < 50,
40871            alreadyDispatched = recentlyClicked && clickDispatch === clickTime,
40872            defaultPrevented = self.pointerEvent && self.pointerEvent.defaultPrevented,
40873            alreadyDispatchedTrusted = recentlyClicked && trustedClickDispatch === clickTime,
40874            trusted = e.isTrusted || e.isTrusted == null && recentlyClicked && alreadyDispatched;
40875
40876        if ((alreadyDispatched || recentlyDragged && self.vars.suppressClickOnDrag !== false) && e.stopImmediatePropagation) {
40877          e.stopImmediatePropagation();
40878        }
40879
40880        if (recentlyClicked && !(self.pointerEvent && self.pointerEvent.defaultPrevented) && (!alreadyDispatched || trusted && !alreadyDispatchedTrusted)) {
40881          if (trusted && alreadyDispatched) {
40882            trustedClickDispatch = clickTime;
40883          }
40884
40885          clickDispatch = clickTime;
40886          return;
40887        }
40888
40889        if (self.isPressed || recentlyDragged || recentlyClicked) {
40890          if (!trusted || !e.detail || !recentlyClicked || defaultPrevented) {
40891            _preventDefault(e);
40892          }
40893        }
40894
40895        if (!recentlyClicked && !recentlyDragged && !dragged) {
40896          e && e.target && (self.pointerEvent = e);
40897
40898          _dispatchEvent(self, "click", "onClick");
40899        }
40900      },
40901          localizePoint = function localizePoint(p) {
40902        return matrix ? {
40903          x: p.x * matrix.a + p.y * matrix.c + matrix.e,
40904          y: p.x * matrix.b + p.y * matrix.d + matrix.f
40905        } : {
40906          x: p.x,
40907          y: p.y
40908        };
40909      };
40910
40911      old = Draggable.get(target);
40912      old && old.kill();
40913
40914      _this2.startDrag = function (event, align) {
40915        var r1, r2, p1, p2;
40916        onPress(event || self.pointerEvent, true);
40917
40918        if (align && !self.hitTest(event || self.pointerEvent)) {
40919          r1 = _parseRect(event || self.pointerEvent);
40920          r2 = _parseRect(target);
40921          p1 = localizePoint({
40922            x: r1.left + r1.width / 2,
40923            y: r1.top + r1.height / 2
40924          });
40925          p2 = localizePoint({
40926            x: r2.left + r2.width / 2,
40927            y: r2.top + r2.height / 2
40928          });
40929          startPointerX -= p1.x - p2.x;
40930          startPointerY -= p1.y - p2.y;
40931        }
40932
40933        if (!self.isDragging) {
40934          self.isDragging = dragged = true;
40935
40936          _dispatchEvent(self, "dragstart", "onDragStart");
40937        }
40938      };
40939
40940      _this2.drag = onMove;
40941
40942      _this2.endDrag = function (e) {
40943        return onRelease(e || self.pointerEvent, true);
40944      };
40945
40946      _this2.timeSinceDrag = function () {
40947        return self.isDragging ? 0 : (_getTime() - dragEndTime) / 1000;
40948      };
40949
40950      _this2.timeSinceClick = function () {
40951        return (_getTime() - clickTime) / 1000;
40952      };
40953
40954      _this2.hitTest = function (target, threshold) {
40955        return Draggable.hitTest(self.target, target, threshold);
40956      };
40957
40958      _this2.getDirection = function (from, diagonalThreshold) {
40959        var mode = from === "velocity" && InertiaPlugin ? from : _isObject(from) && !rotationMode ? "element" : "start",
40960            xChange,
40961            yChange,
40962            ratio,
40963            direction,
40964            r1,
40965            r2;
40966
40967        if (mode === "element") {
40968          r1 = _parseRect(self.target);
40969          r2 = _parseRect(from);
40970        }
40971
40972        xChange = mode === "start" ? self.x - startElementX : mode === "velocity" ? InertiaPlugin.getVelocity(target, xProp) : r1.left + r1.width / 2 - (r2.left + r2.width / 2);
40973
40974        if (rotationMode) {
40975          return xChange < 0 ? "counter-clockwise" : "clockwise";
40976        } else {
40977          diagonalThreshold = diagonalThreshold || 2;
40978          yChange = mode === "start" ? self.y - startElementY : mode === "velocity" ? InertiaPlugin.getVelocity(target, yProp) : r1.top + r1.height / 2 - (r2.top + r2.height / 2);
40979          ratio = Math.abs(xChange / yChange);
40980          direction = ratio < 1 / diagonalThreshold ? "" : xChange < 0 ? "left" : "right";
40981
40982          if (ratio < diagonalThreshold) {
40983            if (direction !== "") {
40984              direction += "-";
40985            }
40986
40987            direction += yChange < 0 ? "up" : "down";
40988          }
40989        }
40990
40991        return direction;
40992      };
40993
40994      _this2.applyBounds = function (newBounds, sticky) {
40995        var x, y, forceZeroVelocity, e, parent, isRoot;
40996
40997        if (newBounds && vars.bounds !== newBounds) {
40998          vars.bounds = newBounds;
40999          return self.update(true, sticky);
41000        }
41001
41002        syncXY(true);
41003        calculateBounds();
41004
41005        if (hasBounds && !isTweening()) {
41006          x = self.x;
41007          y = self.y;
41008
41009          if (x > maxX) {
41010            x = maxX;
41011          } else if (x < minX) {
41012            x = minX;
41013          }
41014
41015          if (y > maxY) {
41016            y = maxY;
41017          } else if (y < minY) {
41018            y = minY;
41019          }
41020
41021          if (self.x !== x || self.y !== y) {
41022            forceZeroVelocity = true;
41023            self.x = self.endX = x;
41024
41025            if (rotationMode) {
41026              self.endRotation = x;
41027            } else {
41028              self.y = self.endY = y;
41029            }
41030
41031            dirty = true;
41032            render(true);
41033
41034            if (self.autoScroll && !self.isDragging) {
41035              _recordMaxScrolls(target.parentNode);
41036
41037              e = target;
41038              _windowProxy.scrollTop = _win$1.pageYOffset != null ? _win$1.pageYOffset : ownerDoc.documentElement.scrollTop != null ? ownerDoc.documentElement.scrollTop : ownerDoc.body.scrollTop;
41039              _windowProxy.scrollLeft = _win$1.pageXOffset != null ? _win$1.pageXOffset : ownerDoc.documentElement.scrollLeft != null ? ownerDoc.documentElement.scrollLeft : ownerDoc.body.scrollLeft;
41040
41041              while (e && !isRoot) {
41042                isRoot = _isRoot(e.parentNode);
41043                parent = isRoot ? _windowProxy : e.parentNode;
41044
41045                if (allowY && parent.scrollTop > parent._gsMaxScrollY) {
41046                  parent.scrollTop = parent._gsMaxScrollY;
41047                }
41048
41049                if (allowX && parent.scrollLeft > parent._gsMaxScrollX) {
41050                  parent.scrollLeft = parent._gsMaxScrollX;
41051                }
41052
41053                e = parent;
41054              }
41055            }
41056          }
41057
41058          if (self.isThrowing && (forceZeroVelocity || self.endX > maxX || self.endX < minX || self.endY > maxY || self.endY < minY)) {
41059            animate(vars.inertia || vars.throwProps, forceZeroVelocity);
41060          }
41061        }
41062
41063        return self;
41064      };
41065
41066      _this2.update = function (applyBounds, sticky, ignoreExternalChanges) {
41067        if (sticky && self.isPressed) {
41068          
vendor: 3,070 bytes, lines 41068-41169
41068var m = getGlobalMatrix(target),
41069              p = innerMatrix.apply({
41070            x: self.x - startElementX,
41071            y: self.y - startElementY
41072          }),
41073              m2 = getGlobalMatrix(target.parentNode, true);
41074          m2.apply({
41075            x: m.e - p.x,
41076            y: m.f - p.y
41077          }, p);
41078          self.x -= p.x - m2.e;
41079          self.y -= p.y - m2.f;
41080          render(true);
41081          recordStartPositions();
41082        }
41083
41084        var x = self.x,
41085            y = self.y;
41086        updateMatrix(!sticky);
41087
41088        if (applyBounds) {
41089          self.applyBounds();
41090        } else {
41091          dirty && ignoreExternalChanges && render(true);
41092          syncXY(true);
41093        }
41094
41095        if (sticky) {
41096          setPointerPosition(self.pointerX, self.pointerY);
41097          dirty && render(true);
41098        }
41099
41100        if (self.isPressed && !sticky && (allowX && Math.abs(x - self.x) > 0.01 || allowY && Math.abs(y - self.y) > 0.01 && !rotationMode)) {
41101          recordStartPositions();
41102        }
41103
41104        if (self.autoScroll) {
41105          _recordMaxScrolls(target.parentNode, self.isDragging);
41106
41107          checkAutoScrollBounds = self.isDragging;
41108          render(true);
41109
41110          _removeScrollListener(target, updateScroll);
41111
41112          _addScrollListener(target, updateScroll);
41113        }
41114
41115        return self;
41116      };
41117
41118      _this2.enable = function (type) {
41119        var setVars = {
41120          lazy: true
41121        },
41122            id,
41123            i,
41124            trigger;
41125
41126        if (vars.cursor !== false) {
41127          setVars.cursor = vars.cursor || _defaultCursor;
41128        }
41129
41130        if (gsap.utils.checkPrefix("touchCallout")) {
41131          setVars.touchCallout = "none";
41132        }
41133
41134        if (type !== "soft") {
41135          _setTouchActionForAllDescendants(triggers, allowX === allowY ? "none" : vars.allowNativeTouchScrolling && target.scrollHeight === target.clientHeight === (target.scrollWidth === target.clientHeight) || vars.allowEventDefault ? "manipulation" : allowX ? "pan-y" : "pan-x");
41136
41137          i = triggers.length;
41138
41139          while (--i > -1) {
41140            trigger = triggers[i];
41141            _supportsPointer || _addListener(trigger, "mousedown", onPress);
41142
41143            _addListener(trigger, "touchstart", onPress);
41144
41145            _addListener(trigger, "click", onClick, true);
41146
41147            gsap.set(trigger, setVars);
41148
41149            if (trigger.getBBox && trigger.ownerSVGElement && allowX !== allowY) {
41150              gsap.set(trigger.ownerSVGElement, {
41151                touchAction: vars.allowNativeTouchScrolling || vars.allowEventDefault ? "manipulation" : allowX ? "pan-y" : "pan-x"
41152              });
41153            }
41154
41155            vars.allowContextMenu || _addListener(trigger, "contextmenu", onContextMenu);
41156          }
41157
41158          _setSelectable(triggers, false);
41159        }
41160
41161        _addScrollListener(target, updateScroll);
41162
41163        enabled = true;
41164
41165        if (InertiaPlugin && type !== "soft") {
41166          InertiaPlugin.track(scrollProxy || target, xyMode ? "x,y" : rotationMode ? "rotation" : "top,left");
41167        }
41168
41169        target._gsDragID = id =
vendor: 5,466 bytes, lines 41169-41375
41169 "d" + _lookupCount++;
41170        _lookup[id] = self;
41171
41172        if (scrollProxy) {
41173          scrollProxy.enable();
41174          scrollProxy.element._gsDragID = id;
41175        }
41176
41177        (vars.bounds || rotationMode) && recordStartPositions();
41178        vars.bounds && self.applyBounds();
41179        return self;
41180      };
41181
41182      _this2.disable = function (type) {
41183        var dragging = self.isDragging,
41184            i = triggers.length,
41185            trigger;
41186
41187        while (--i > -1) {
41188          _setStyle(triggers[i], "cursor", null);
41189        }
41190
41191        if (type !== "soft") {
41192          _setTouchActionForAllDescendants(triggers, null);
41193
41194          i = triggers.length;
41195
41196          while (--i > -1) {
41197            trigger = triggers[i];
41198
41199            _setStyle(trigger, "touchCallout", null);
41200
41201            _removeListener(trigger, "mousedown", onPress);
41202
41203            _removeListener(trigger, "touchstart", onPress);
41204
41205            _removeListener(trigger, "click", onClick, true);
41206
41207            _removeListener(trigger, "contextmenu", onContextMenu);
41208          }
41209
41210          _setSelectable(triggers, true);
41211
41212          if (touchEventTarget) {
41213            _removeListener(touchEventTarget, "touchcancel", onRelease);
41214
41215            _removeListener(touchEventTarget, "touchend", onRelease);
41216
41217            _removeListener(touchEventTarget, "touchmove", onMove);
41218          }
41219
41220          _removeListener(ownerDoc, "mouseup", onRelease);
41221
41222          _removeListener(ownerDoc, "mousemove", onMove);
41223        }
41224
41225        _removeScrollListener(target, updateScroll);
41226
41227        enabled = false;
41228
41229        if (InertiaPlugin && type !== "soft") {
41230          InertiaPlugin.untrack(scrollProxy || target, xyMode ? "x,y" : rotationMode ? "rotation" : "top,left");
41231          self.tween && self.tween.kill();
41232        }
41233
41234        scrollProxy && scrollProxy.disable();
41235
41236        _removeFromRenderQueue(render);
41237
41238        self.isDragging = self.isPressed = isClicking = false;
41239        dragging && _dispatchEvent(self, "dragend", "onDragEnd");
41240        return self;
41241      };
41242
41243      _this2.enabled = function (value, type) {
41244        return arguments.length ? value ? self.enable(type) : self.disable(type) : enabled;
41245      };
41246
41247      _this2.kill = function () {
41248        self.isThrowing = false;
41249        self.tween && self.tween.kill();
41250        self.disable();
41251        gsap.set(triggers, {
41252          clearProps: "userSelect"
41253        });
41254        delete _lookup[target._gsDragID];
41255        return self;
41256      };
41257
41258      _this2.revert = function () {
41259        this.kill();
41260        this.styles && this.styles.revert();
41261      };
41262
41263      if (~type.indexOf("scroll")) {
41264        scrollProxy = _this2.scrollProxy = new ScrollProxy(target, _extend({
41265          onKill: function onKill() {
41266            self.isPressed && onRelease(null);
41267          }
41268        }, vars));
41269        target.style.overflowY = allowY && !_isTouchDevice ? "auto" : "hidden";
41270        target.style.overflowX = allowX && !_isTouchDevice ? "auto" : "hidden";
41271        target = scrollProxy.content;
41272      }
41273
41274      if (rotationMode) {
41275        killProps.rotation = 1;
41276      } else {
41277        if (allowX) {
41278          killProps[xProp] = 1;
41279        }
41280
41281        if (allowY) {
41282          killProps[yProp] = 1;
41283        }
41284      }
41285
41286      gsCache.force3D = "force3D" in vars ? vars.force3D : true;
41287
41288      _context(_assertThisInitialized(_this2));
41289
41290      _this2.enable();
41291
41292      return _this2;
41293    }
41294
41295    Draggable.register = function register(core) {
41296      gsap = core;
41297
41298      _initCore();
41299    };
41300
41301    Draggable.create = function create(targets, vars) {
41302      _coreInitted || _initCore(true);
41303      return _toArray(targets).map(function (target) {
41304        return new Draggable(target, vars);
41305      });
41306    };
41307
41308    Draggable.get = function get(target) {
41309      return _lookup[(_toArray(target)[0] || {})._gsDragID];
41310    };
41311
41312    Draggable.timeSinceDrag = function timeSinceDrag() {
41313      return (_getTime() - _lastDragTime) / 1000;
41314    };
41315
41316    Draggable.hitTest = function hitTest(obj1, obj2, threshold) {
41317      if (obj1 === obj2) {
41318        return false;
41319      }
41320
41321      var r1 = _parseRect(obj1),
41322          r2 = _parseRect(obj2),
41323          top = r1.top,
41324          left = r1.left,
41325          right = r1.right,
41326          bottom = r1.bottom,
41327          width = r1.width,
41328          height = r1.height,
41329          isOutside = r2.left > right || r2.right < left || r2.top > bottom || r2.bottom < top,
41330          overlap,
41331          area,
41332          isRatio;
41333
41334      if (isOutside || !threshold) {
41335        return !isOutside;
41336      }
41337
41338      isRatio = (threshold + "").indexOf("%") !== -1;
41339      threshold = parseFloat(threshold) || 0;
41340      overlap = {
41341        left: Math.max(left, r2.left),
41342        top: Math.max(top, r2.top)
41343      };
41344      overlap.width = Math.min(right, r2.right) - overlap.left;
41345      overlap.height = Math.min(bottom, r2.bottom) - overlap.top;
41346
41347      if (overlap.width < 0 || overlap.height < 0) {
41348        return false;
41349      }
41350
41351      if (isRatio) {
41352        threshold *= 0.01;
41353        area = overlap.width * overlap.height;
41354        return area >= width * height * threshold || area >= r2.width * r2.height * threshold;
41355      }
41356
41357      return overlap.width > threshold && overlap.height > threshold;
41358    };
41359
41360    return Draggable;
41361  }(EventDispatcher);
41362
41363  _setDefaults(Draggable.prototype, {
41364    pointerX: 0,
41365    pointerY: 0,
41366    startX: 0,
41367    startY: 0,
41368    deltaX: 0,
41369    deltaY: 0,
41370    isDragging: false,
41371    isPressed: false
41372  });
41373
41374  Draggable.zIndex = 1000;
41375  Draggable.version = "3.1
413752.5";
41376  _getGSAP() && gsap.registerPlugin(Draggable);
41377
41378  exports.Draggable = Draggable;
41379  exports.default = Draggable;
41380
41381  if (typeof(window) === 'undefined' || window !== exports) {Object.defineProperty(exports, '__esModule', { value: true });} else {delete window.default;}
41382
41383})));
41384/* ========================================================================
41385 * Bootstrap: collapse.js v3.1.1
41386 * http://getbootstrap.com/javascript/#collapse
41387 * ========================================================================
41388 * Copyright 2011-2014 Twitter, Inc.
41389 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
41390 * ======================================================================== */
41391
41392
41393+function ($) {
41394	'use strict';
41395
41396	// COLLAPSE PUBLIC CLASS DEFINITION
41397	// ================================
41398
41399	var Collapse = function (element, options) {
41400		this.$element      = $(element)
41401		this.options       = $.extend({}, Collapse.DEFAULTS, options)
41402		this.transitioning = null
41403
41404		if (this.options.parent) this.$parent = $(this.options.parent)
41405		if (this.options.toggle) this.toggle()
41406	}
41407
41408	Collapse.DEFAULTS = {
41409		toggle: true
41410	}
41411
41412	Collapse.prototype.dimension = function () {
41413		var hasWidth = this.$element.hasClass('width')
41414		return hasWidth ? 'width' : 'height'
41415	}
41416
41417	Collapse.prototype.show = function () {
41418		if (this.transitioning || this.$element.hasClass('in')) return
41419
41420		var startEvent = $.Event('show.bs.collapse')
41421		this.$element.trigger(startEvent)
41422		if (startEvent.isDefaultPrevented()) return
41423
41424		var actives = this.$parent && this.$parent.find('> .panel > .in')
41425
41426		if (actives && actives.length) {
41427			var hasData = actives.data('bs.collapse')
41428			if (hasData && hasData.transitioning) return
41429			//START UNCODE EDIT
41430			var parentNoToggle = this.$parent.data('no-toggle')
41431			if (!parentNoToggle) {
41432				actives.collapse('hide')
41433			}
41434			//END UNCODE EDIT
41435			hasData || actives.data('bs.collapse', null)
41436		}
41437
41438		var dimension = this.dimension()
41439
41440		this.$element
41441			.removeClass('collapse')
41442			.addClass('collapsing')[dimension](0)
41443
41444		this.transitioning = 1
41445
41446		var complete = function (e) {
41447			if (e && e.target != this.$element[0]) return
41448			this.$element
41449				.removeClass('collapsing')
41450				.addClass('collapse in')[dimension]('auto')
41451			this.transitioning = 0
41452			this.$element.trigger('shown.bs.collapse')
41453		}
41454
41455		if (!$.support.transition) return complete.call(this)
41456
41457		var scrollSize = $.camelCase(['scroll', dimension].join('-'))
41458
41459		this.$element
41460			.one($.support.transition.end, $.proxy(complete, this))
41461			.emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize])
41462	}
41463
41464	Collapse.prototype.hide = function () {
41465		if (this.transitioning || !this.$element.hasClass('in')) return
41466
41467		var startEvent = $.Event('hide.bs.collapse')
41468		this.$element.trigger(startEvent)
41469		if (startEvent.isDefaultPrevented()) return
41470
41471		var dimension = this.dimension()
41472
41473		this.$element[dimension](this.$element[dimension]())[0].offsetHeight
41474
41475		this.$element
41476			.addClass('collapsing')
41477			.removeClass('collapse')
41478			.removeClass('in')
41479
41480		this.transitioning = 1
41481
41482		var complete = function (e) {
41483			if (e && e.target != this.$element[0]) return
41484			this.transitioning = 0
41485			this.$element
41486				.trigger('hidden.bs.collapse')
41487				.removeClass('collapsing')
41488				.addClass('collapse')
41489		}
41490
41491		if (!$.support.transition) return complete.call(this)
41492
41493		this.$element
41494			[dimension](0)
41495			.one($.support.transition.end, $.proxy(complete, this))
41496			.emulateTransitionEnd(350)
41497	}
41498
41499	Collapse.prototype.toggle = function () {
41500		this[this.$element.hasClass('in') ? 'hide' : 'show']()
41501	}
41502
41503
41504	// COLLAPSE PLUGIN DEFINITION
41505	// ==========================
41506
41507	var old = $.fn.collapse
41508
41509	$.fn.collapse = function (option) {
41510		return this.each(function () {
41511			var $this   = $(this)
41512			var data    = $this.data('bs.collapse')
41513			var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
41514
41515			if (!data && options.toggle && option == 'show') option = !option
41516			if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
41517			if (typeof option == 'string') data[option]()
41518		})
41519	}
41520
41521	$.fn.collapse.Constructor = Collapse
41522
41523
41524	// COLLAPSE NO CONFLICT
41525	// ====================
41526
41527	$.fn.collapse.noConflict = function () {
41528		$.fn.collapse = old
41529		return this
41530	}
41531
41532
41533	// COLLAPSE DATA-API
41534	// =================
41535
41536	$(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
41537		var $this   = $(this), href
41538		var target  = $this.attr('data-target')
41539				|| e.preventDefault()
41540				|| (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
41541		//Edited by Uncode to replace ID in panel [START]
41542		var _target = href.replace(/^#/, "");
41543		if ( $('[data-id="' + _target + '"]').length ) {
41544			var $target = $('[data-id="' + _target + '"]')
41545		} else {
41546			var $target = $(target)
41547		}
41548		//Edited by Uncode to replace ID in panel [END]
41549		var data    = $target.data('bs.collapse')
41550		var option  = data ? 'toggle' : $this.data()
41551		var parent  = $this.attr('data-parent')
41552		var $parent = parent && $(parent)
41553
41554		if (!data || !data.transitioning) {
41555			if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed')
41556			$this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
41557		}
41558
41559		$target.collapse(option)
41560	})
41561
41562}(jQuery);
41563
41564/* ========================================================================
41565 * Bootstrap: tab.js v3.1.1
41566 * http://getbootstrap.com/javascript/#tabs
41567 * ========================================================================
41568 * Copyright 2011-2014 Twitter, Inc.
41569 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
41570 * ======================================================================== */
41571
41572
41573+function ($) {
41574  'use strict';
41575
41576  // TAB CLASS DEFINITION
41577  // ====================
41578
41579  var Tab = function (element) {
41580    this.element = $(element)
41581  }
41582
41583  Tab.prototype.show = function () {
41584    var $this    = this.element
41585    var $ul      = $this.closest('ul:not(.dropdown-menu)')
41586    var selector = $this.data('target')
41587
41588    if (!selector) {
41589      selector = $this.attr('href')
41590      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
41591    }
41592
41593    if ($this.parent('li').hasClass('active')) return
41594
41595    var previous = $ul.find('.active:last a')[0]
41596    var e        = $.Event('show.bs.tab', {
41597      relatedTarget: previous
41598    })
41599
41600    $this.trigger(e)
41601
41602    if (e.isDefaultPrevented()) return
41603
41604    //Edited by Uncode to replace ID in panel [START]
41605    var _target = selector.replace(/^#/, "");
41606    if ( $('[data-id="' + _target + '"]').length )
41607      var $target = $('[data-id="' + _target + '"]')
41608    else
41609      var $target = $(selector)
41610    //Edited by Uncode to replace ID in panel [END]
41611
41612    this.activate($this.parent('li'), $ul)
41613    this.activate($target, $target.parent(), function () {
41614      $this.trigger({
41615        type: 'shown.bs.tab',
41616        relatedTarget: previous
41617      })
41618    })
41619  }
41620
41621  Tab.prototype.activate = function (element, container, callback) {
41622    var $active    = container.find('> .active').add(container.find('> .active > .active'))
41623    var transition = callback
41624      && $.support.transition
41625      && $active.hasClass('fade')
41626
41627    function next() {
41628      $active
41629        .removeClass('active')
41630        .find('> .dropdown-menu > .active')
41631        .removeClass('active')
41632
41633      $active
41634        .find('.tab-excerpt').slideUp();
41635
41636      element.addClass('active')
41637      $('.tab-excerpt', element).slideDown();
41638
41639      //if (transition) {
41640        element[0].offsetWidth // reflow for transition
41641        element.add($active).addClass('in')
41642      /*} else {
41643        element.removeClass('fade')
41644      }*/
41645
41646      if (element.parent('.dropdown-menu')) {
41647        element.closest('li.dropdown').addClass('active')
41648      }
41649
41650      if ( ! element.is('li') ) {
41651        element.closest('.tab-content').find('> .active').not(element).removeClass('active');
41652      }
41653
41654      callback && callback()
41655    }
41656
41657    transition ?
41658      $active
41659        .one($.support.transition.end, next)
41660        .emulateTransitionEnd(150) :
41661      next()
41662
41663    $active.removeClass('in')
41664  }
41665
41666
41667  // TAB PLUGIN DEFINITION
41668  // =====================
41669
41670  var old = $.fn.tab
41671
41672  $.fn.tab = function ( option ) {
41673    return this.each(function () {
41674      var $this = $(this)
41675      var data  = $this.data('bs.tab')
41676
41677      if (!data) $this.data('bs.tab', (data = new Tab(this)))
41678      if (typeof option == 'string') data[option]()
41679    })
41680  }
41681
41682  $.fn.tab.Constructor = Tab
41683
41684
41685  // TAB NO CONFLICT
41686  // ===============
41687
41688  $.fn.tab.noConflict = function () {
41689    $.fn.tab = old
41690    return this
41691  }
41692
41693
41694  // TAB DATA-API
41695  // ============
41696
41697  $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
41698    e.preventDefault()
41699    $(this).tab('show')
41700  })
41701
41702}(jQuery);
41703
41704/* ========================================================================
41705 * Bootstrap: tooltip.js v3.1.1
41706 * http://getbootstrap.com/javascript/#tooltip
41707 * Inspired by the original jQuery.tipsy by Jason Frame
41708 * ========================================================================
41709 * Copyright 2011-2014 Twitter, Inc.
41710 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
41711 * ======================================================================== */
41712
41713
41714+function ($) {
41715  'use strict';
41716
41717  // TOOLTIP PUBLIC CLASS DEFINITION
41718  // ===============================
41719
41720  var Tooltip = function (element, options) {
41721    this.type       =
41722    this.options    =
41723    this.enabled    =
41724    this.timeout    =
41725    this.hoverState =
41726    this.$element   = null
41727
41728    this.init('tooltip', element, options)
41729  }
41730
41731  Tooltip.DEFAULTS = {
41732    animation: true,
41733    placement: 'top',
41734    selector: false,
41735    template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
41736    trigger: 'hover focus',
41737    title: '',
41738    delay: 0,
41739    html: false,
41740    container: false,
41741    viewport: {
41742      selector: 'body',
41743      padding: 0
41744    }
41745  }
41746
41747  Tooltip.prototype.init = function (type, element, options) {
41748    this.enabled   = true
41749    this.type      = type
41750    this.$element  = $(element)
41751    this.options   = this.getOptions(options)
41752    this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
41753
41754    var triggers = this.options.trigger.split(' ')
41755
41756    for (var i = triggers.length; i--;) {
41757      var trigger = triggers[i]
41758
41759      if (trigger == 'click') {
41760        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
41761      } else if (trigger != 'manual') {
41762        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin'
41763        var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
41764
41765        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
41766        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
41767      }
41768    }
41769
41770    this.options.selector ?
41771      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
41772      this.fixTitle()
41773  }
41774
41775  Tooltip.prototype.getDefaults = function () {
41776    return Tooltip.DEFAULTS
41777  }
41778
41779  Tooltip.prototype.getOptions = function (options) {
41780    options = $.extend({}, this.getDefaults(), this.$element.data(), options)
41781
41782    if (options.delay && typeof options.delay == 'number') {
41783      options.delay = {
41784        show: options.delay,
41785        hide: options.delay
41786      }
41787    }
41788
41789    return options
41790  }
41791
41792  Tooltip.prototype.getDelegateOptions = function () {
41793    var options  = {}
41794    var defaults = this.getDefaults()
41795
41796    this._options && $.each(this._options, function (key, value) {
41797      if (defaults[key] != value) options[key] = value
41798    })
41799
41800    return options
41801  }
41802
41803  Tooltip.prototype.enter = function (obj) {
41804    var self = obj instanceof this.constructor ?
41805      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
41806
41807    clearTimeout(self.timeout)
41808
41809    self.hoverState = 'in'
41810
41811    if (!self.options.delay || !self.options.delay.show) return self.show()
41812
41813    self.timeout = setTimeout(function () {
41814      if (self.hoverState == 'in') self.show()
41815    }, self.options.delay.show)
41816  }
41817
41818  Tooltip.prototype.leave = function (obj) {
41819    var self = obj instanceof this.constructor ?
41820      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
41821
41822    clearTimeout(self.timeout)
41823
41824    self.hoverState = 'out'
41825
41826    if (!self.options.delay || !self.options.delay.hide) return self.hide()
41827
41828    self.timeout = setTimeout(function () {
41829      if (self.hoverState == 'out') self.hide()
41830    }, self.options.delay.hide)
41831  }
41832
41833  Tooltip.prototype.show = function () {
41834    var e = $.Event('show.bs.' + this.type)
41835
41836    if (this.hasContent() && this.enabled) {
41837      this.$element.trigger(e)
41838
41839      if (e.isDefaultPrevented()) return
41840      var that = this;
41841
41842      var $tip = this.tip()
41843
41844      this.setContent()
41845
41846      if (this.options.animation) $tip.addClass('fade')
41847
41848      var placement = typeof this.options.placement == 'function' ?
41849        this.options.placement.call(this, $tip[0], this.$element[0]) :
41850        this.options.placement
41851
41852      var autoToken = /\s?auto?\s?/i
41853      var autoPlace = autoToken.test(placement)
41854      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
41855
41856      $tip
41857        .detach()
41858        .css({ top: 0, left: 0, display: 'block' })
41859        .addClass(placement)
41860
41861      this.options.container ? $tip.appendTo($(document).find(this.options.container)) : $tip.insertAfter(this.$element)
41862
41863      var pos          = this.getPosition()
41864      var actualWidth  = $tip[0].offsetWidth
41865      var actualHeight = $tip[0].offsetHeight
41866
41867      if (autoPlace) {
41868        var orgPlacement = placement
41869        var $parent      = this.$element.parent()
41870        var parentDim    = this.getPosition($parent)
41871
41872        placement = placement == 'bottom' && pos.top   + pos.height       + actualHeight - parentDim.scroll > parentDim.height ? 'top'    :
41873                    placement == 'top'    && pos.top   - parentDim.scroll - actualHeight < 0                                   ? 'bottom' :
41874                    placement == 'right'  && pos.right + actualWidth      > parentDim.width                                    ? 'left'   :
41875                    placement == 'left'   && pos.left  - actualWidth      < parentDim.left                                     ? 'right'  :
41876                    placement
41877
41878        $tip
41879          .removeClass(orgPlacement)
41880          .addClass(placement)
41881      }
41882
41883      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
41884
41885      this.applyPlacement(calculatedOffset, placement)
41886      this.hoverState = null
41887
41888      var complete = function() {
41889        that.$element.trigger('shown.bs.' + that.type)
41890      }
41891
41892      $.support.transition && this.$tip.hasClass('fade') ?
41893        $tip
41894          .one($.support.transition.end, complete)
41895          .emulateTransitionEnd(150) :
41896        complete()
41897    }
41898  }
41899
41900  Tooltip.prototype.applyPlacement = function (offset, placement) {
41901    var $tip   = this.tip()
41902    var width  = $tip[0].offsetWidth
41903    var height = $tip[0].offsetHeight
41904
41905    // manually read margins because getBoundingClientRect includes difference
41906    var marginTop = parseInt($tip.css('margin-top'), 10)
41907    var marginLeft = parseInt($tip.css('margin-left'), 10)
41908
41909    // we must check for NaN for ie 8/9
41910    if (isNaN(marginTop))  marginTop  = 0
41911    if (isNaN(marginLeft)) marginLeft = 0
41912
41913    offset.top  = offset.top  + marginTop
41914    offset.left = offset.left + marginLeft
41915
41916    // $.fn.offset doesn't round pixel values
41917    // so we use setOffset directly with our own function B-0
41918    $.offset.setOffset($tip[0], $.extend({
41919      using: function (props) {
41920        $tip.css({
41921          top: Math.round(props.top),
41922          left: Math.round(props.left)
41923        })
41924      }
41925    }, offset), 0)
41926
41927    $tip.addClass('in')
41928
41929    // check to see if placing tip in new offset caused the tip to resize itself
41930    var actualWidth  = $tip[0].offsetWidth
41931    var actualHeight = $tip[0].offsetHeight
41932
41933    if (placement == 'top' && actualHeight != height) {
41934      offset.top = offset.top + height - actualHeight
41935    }
41936
41937    var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actua
41937lHeight)
41938
41939    if (delta.left) offset.left += delta.left
41940    else offset.top += delta.top
41941
41942    var arrowDelta          = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
41943    var arrowPosition       = delta.left ? 'left'        : 'top'
41944    var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight'
41945
41946    $tip.offset(offset)
41947    this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition)
41948  }
41949
41950  Tooltip.prototype.replaceArrow = function (delta, dimension, position) {
41951    this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '')
41952  }
41953
41954  Tooltip.prototype.setContent = function () {
41955    var $tip  = this.tip()
41956    var title = this.getTitle()
41957
41958    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
41959    $tip.removeClass('fade in top bottom left right')
41960  }
41961
41962  Tooltip.prototype.hide = function () {
41963    var that = this
41964    var $tip = this.tip()
41965    var e    = $.Event('hide.bs.' + this.type)
41966
41967    function complete() {
41968      if (that.hoverState != 'in') $tip.detach()
41969      that.$element.trigger('hidden.bs.' + that.type)
41970    }
41971
41972    this.$element.trigger(e)
41973
41974    if (e.isDefaultPrevented()) return
41975
41976    $tip.removeClass('in')
41977
41978    $.support.transition && this.$tip.hasClass('fade') ?
41979      $tip
41980        .one($.support.transition.end, complete)
41981        .emulateTransitionEnd(150) :
41982      complete()
41983
41984    this.hoverState = null
41985
41986    return this
41987  }
41988
41989  Tooltip.prototype.fixTitle = function () {
41990    var $e = this.$element
41991    if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
41992      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
41993    }
41994  }
41995
41996  Tooltip.prototype.hasContent = function () {
41997    return this.getTitle()
41998  }
41999
42000  Tooltip.prototype.getPosition = function ($element) {
42001    $element   = $element || this.$element
42002    var el     = $element[0]
42003    var isBody = el.tagName == 'BODY'
42004    return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, {
42005      scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(),
42006      width:  isBody ? $(window).width()  : $element.outerWidth(),
42007      height: isBody ? $(window).height() : $element.outerHeight()
42008    }, isBody ? {top: 0, left: 0} : $element.offset())
42009  }
42010
42011  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
42012    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2  } :
42013           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2  } :
42014           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
42015        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width   }
42016
42017  }
42018
42019  Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
42020    var delta = { top: 0, left: 0 }
42021    if (!this.$viewport) return delta
42022
42023    var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
42024    var viewportDimensions = this.getPosition(this.$viewport)
42025
42026    if (/right|left/.test(placement)) {
42027      var topEdgeOffset    = pos.top - viewportPadding - viewportDimensions.scroll
42028      var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
42029      if (topEdgeOffset < viewportDimensions.top) { // top overflow
42030        delta.top = viewportDimensions.top - topEdgeOffset
42031      } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
42032        delta.top = viewportDimensions.top + viewportDimensions.height - bottom
42032EdgeOffset
42033      }
42034    } else {
42035      var leftEdgeOffset  = pos.left - viewportPadding
42036      var rightEdgeOffset = pos.left + viewportPadding + actualWidth
42037      if (leftEdgeOffset < viewportDimensions.left) { // left overflow
42038        delta.left = viewportDimensions.left - leftEdgeOffset
42039      } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
42040        delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
42041      }
42042    }
42043
42044    return delta
42045  }
42046
42047  Tooltip.prototype.getTitle = function () {
42048    var title
42049    var $e = this.$element
42050    var o  = this.options
42051
42052    title = $e.attr('data-original-title')
42053      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
42054
42055    return title
42056  }
42057
42058  Tooltip.prototype.tip = function () {
42059    return this.$tip = this.$tip || $(this.options.template)
42060  }
42061
42062  Tooltip.prototype.arrow = function () {
42063    return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')
42064  }
42065
42066  Tooltip.prototype.validate = function () {
42067    if (!this.$element[0].parentNode) {
42068      this.hide()
42069      this.$element = null
42070      this.options  = null
42071    }
42072  }
42073
42074  Tooltip.prototype.enable = function () {
42075    this.enabled = true
42076  }
42077
42078  Tooltip.prototype.disable = function () {
42079    this.enabled = false
42080  }
42081
42082  Tooltip.prototype.toggleEnabled = function () {
42083    this.enabled = !this.enabled
42084  }
42085
42086  Tooltip.prototype.toggle = function (e) {
42087    var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this
42088    self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
42089  }
42090
42091  Tooltip.prototype.destroy = function () {
42092    clearTimeout(this.timeout)
42093    this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
42094  }
42095
42096
42097  // TOOLTIP PLUGIN DEFINITION
42098  // =========================
42099
42100  var old = $.fn.tooltip
42101
42102  $.fn.tooltip = function (option) {
42103    return this.each(function () {
42104      var $this   = $(this)
42105      var data    = $this.data('bs.tooltip')
42106      var options = typeof option == 'object' && option
42107
42108      if (!data && option == 'destroy') return
42109      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
42110      if (typeof option == 'string') data[option]()
42111    })
42112  }
42113
42114  $.fn.tooltip.Constructor = Tooltip
42115
42116
42117  // TOOLTIP NO CONFLICT
42118  // ===================
42119
42120  $.fn.tooltip.noConflict = function () {
42121    $.fn.tooltip = old
42122    return this
42123  }
42124
42125}(jQuery);
42126
42127/* ========================================================================
42128 * Bootstrap: transition.js v3.1.1
42129 * http://getbootstrap.com/javascript/#transitions
42130 * ========================================================================
42131 * Copyright 2011-2014 Twitter, Inc.
42132 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
42133 * ======================================================================== */
42134
42135
42136+function ($) {
42137  'use strict';
42138
42139  // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
42140  // ============================================================
42141
42142  function transitionEnd() {
42143    var el = document.createElement('bootstrap')
42144
42145    var transEndEventNames = {
42146      WebkitTransition : 'webkitTransitionEnd',
42147      MozTransition    : 'transitionend',
42148      OTransition      : 'oTransitionEnd otransitionend',
42149      transition       : 'transitionend'
42150    }
42151
42152    for (var name in transEndEventNames) {
42153      if (el.style[name] !== undefined) {
42154        return { end: transEndEventNames[name] }
42155      }
42156    }
42157
42158    return false // explicit for ie8 (  ._.)
42159  }
42160
42161  // http://blog.alexmaccaw.com/css-transitions
42162  $.fn.emulateTransitionEnd = function (duration) {
42163    var called = false, $el = this
42164    $(this).one($.support.transition.end, function () { called = true })
42165    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
42166    setTimeout(callback, duration)
42167    return this
42168  }
42169
42170  $(function () {
42171    $.support.transition = transitionEnd()
42172  })
42173
42174}(jQuery);
42175
42176
42177// ------------------------------------------
42178// Rellax.js
42179// Buttery smooth parallax library
42180// Copyright (c) 2016 Moe Amaya (@moeamaya)
42181// MIT license
42182//
42183// Thanks to Paraxify.js and Jaime Cabllero
42184// for parallax concepts
42185// ------------------------------------------
42186
42187(function (root, factory) {
42188	if (typeof define === 'function' && define.amd) {
42189		// AMD. Register as an anonymous module.
42190		define([], factory);
42191	} else if (typeof module === 'object' && module.exports) {
42192		// Node. Does not work with strict CommonJS, but
42193		// only CommonJS-like environments that support module.exports,
42194		// like Node.
42195		module.exports = factory();
42196	} else {
42197		// Browser globals (root is window)
42198		root.Rellax = factory();
42199	}
42200}(typeof window !== "undefined" ? window : global, function () {
42201	var Rellax = function(el, options){
42202		"use strict";
42203
42204		var self = Object.create(Rellax.prototype);
42205
42206		var posY = 0;
42207		var screenY = 0;
42208		var posX = 0;
42209		var screenX = 0;
42210		var blocks = [];
42211		var pause = true;
42212
42213		// check what requestAnimationFrame to use, and if
42214		// it's not supported, use the onscroll event
42215		var loop = window.requestAnimationFrame ||
42216			window.webkitRequestAnimationFrame ||
42217			window.mozRequestAnimationFrame ||
42218			window.msRequestAnimationFrame ||
42219			window.oRequestAnimationFrame ||
42220			function(callback){ return setTimeout(callback, 1000 / 60); };
42221
42222		// store the id for later use
42223		var loopId = null;
42224
42225		// Test via a getter in the options object to see if the passive property is accessed
42226		var supportsPassive = false;
vendor: 10,724 bytes, lines 42227-42528
42227		try {
42228			var opts = Object.defineProperty({}, 'passive', {
42229				get: function() {
42230					supportsPassive = true;
42231				}
42232			});
42233			window.addEventListener("testPassive", null, opts);
42234			window.removeEventListener("testPassive", null, opts);
42235		} catch (e) {}
42236
42237		// check what cancelAnimation method to use
42238		var clearLoop = window.cancelAnimationFrame || window.mozCancelAnimationFrame || clearTimeout;
42239
42240		// check which transform property to use
42241		var transformProp = window.transformProp || (function(){
42242				var testEl = document.createElement('div');
42243				if (testEl.style.transform === null) {
42244					var vendors = ['Webkit', 'Moz', 'ms'];
42245					for (var vendor in vendors) {
42246						if (testEl.style[ vendors[vendor] + 'Transform' ] !== undefined) {
42247							return vendors[vendor] + 'Transform';
42248						}
42249					}
42250				}
42251				return 'transform';
42252			})();
42253
42254		// Default Settings
42255		self.options = {
42256			speed: -2,
42257			verticalSpeed: null,
42258			horizontalSpeed: null,
42259			breakpoints: [576, 768, 1201],
42260			center: false,
42261			wrapper: null,
42262			relativeToWrapper: false,
42263			round: true,
42264			vertical: true,
42265			horizontal: false,
42266			verticalScrollAxis: "y",
42267			horizontalScrollAxis: "x",
42268			callback: function() {},
42269		};
42270
42271		// User defined options (might have more in the future)
42272		if (options){
42273			Object.keys(options).forEach(function(key){
42274				self.options[key] = options[key];
42275			});
42276		}
42277
42278		function validateCustomBreakpoints () {
42279			if (self.options.breakpoints.length === 3 && Array.isArray(self.options.breakpoints)) {
42280				var isAscending = true;
42281				var isNumerical = true;
42282				var lastVal;
42283				self.options.breakpoints.forEach(function (i) {
42284					if (typeof i !== 'number') isNumerical = false;
42285					if (lastVal !== null) {
42286						if (i < lastVal) isAscending = false;
42287					}
42288					lastVal = i;
42289				});
42290				if (isAscending && isNumerical) return;
42291			}
42292			// revert defaults if set incorrectly
42293			self.options.breakpoints = [576, 768, 1201];
42294			console.warn("Rellax: You must pass an array of 3 numbers in ascending order to the breakpoints option. Defaults reverted");
42295		}
42296
42297		if (options && options.breakpoints) {
42298			validateCustomBreakpoints();
42299		}
42300
42301		// By default, rellax class
42302		if (!el) {
42303			el = '.rellax';
42304		}
42305
42306		// check if el is a className or a node
42307		var elements = typeof el === 'string' ? document.querySelectorAll(el) : [el];
42308
42309		// Now query selector
42310		if (elements.length > 0) {
42311			self.elems = elements;
42312		}
42313
42314		// The elements don't exist
42315		else {
42316			console.warn("Rellax: The elements you're trying to select don't exist.");
42317			return;
42318		}
42319
42320		// Has a wrapper and it exists
42321		if (self.options.wrapper) {
42322			if (!self.options.wrapper.nodeType) {
42323				var wrapper = document.querySelector(self.options.wrapper);
42324
42325				if (wrapper) {
42326					self.options.wrapper = wrapper;
42327				} else {
42328					console.warn("Rellax: The wrapper you're trying to use doesn't exist.");
42329					return;
42330				}
42331			}
42332		}
42333
42334		// set a placeholder for the current breakpoint
42335		var currentBreakpoint;
42336
42337		// helper to determine current breakpoint
42338		var getCurrentBreakpoint = function (w) {
42339			var bp = self.options.breakpoints;
42340			if (w < bp[0]) return 'xs';
42341			if (w >= bp[0] && w < bp[1]) return 'sm';
42342			if (w >= bp[1] && w < bp[2]) return 'md';
42343			return 'lg';
42344		};
42345
42346		// Get and cache initial position of all elements
42347		var cacheBlocks = function() {
42348			for (var i = 0; i < self.elems.length; i++){
42349				var block = createBlock(self.elems[i]);
42350				blocks.push(block);
42351			}
42352		};
42353
42354
42355		// Let's kick this script off
42356		// Build array for cached element values
42357		var init = function() {
42358			for (var i = 0; i < blocks.length; i++){
42359				self.elems[i].style.cssText = blocks[i].style;
42360			}
42361
42362			blocks = [];
42363
42364			screenY = window.innerHeight;
42365			screenX = window.innerWidth;
42366			currentBreakpoint = getCurrentBreakpoint(screenX);
42367
42368			setPosition();
42369
42370			cacheBlocks();
42371
42372			animate();
42373
42374			// If paused, unpause and set listener for window resizing events
42375			if (pause) {
42376				window.addEventListener('resize', init);
42377				pause = false;
42378				// Start the loop
42379				update();
42380			}
42381		};
42382
42383		// We want to cache the parallax blocks'
42384		// values: base, top, height, speed
42385		// el: is dom object, return: el cache values
42386		var createBlock = function(el) {
42387			var dataPercentage = el.getAttribute( 'data-rellax-percentage' );
42388			var dataSpeed = el.getAttribute( 'data-rellax-speed' );
42389			var dataXsSpeed = el.getAttribute( 'data-rellax-xs-speed' );
42390			var dataMobileSpeed = el.getAttribute( 'data-rellax-mobile-speed' );
42391			var dataTabletSpeed = el.getAttribute( 'data-rellax-tablet-speed' );
42392			var dataDesktopSpeed = el.getAttribute( 'data-rellax-desktop-speed' );
42393			var dataVerticalSpeed = el.getAttribute('data-rellax-vertical-speed');
42394			var dataHorizontalSpeed = el.getAttribute('data-rellax-horizontal-speed');
42395			var dataVericalScrollAxis = el.getAttribute('data-rellax-vertical-scroll-axis');
42396			var dataHorizontalScrollAxis = el.getAttribute('data-rellax-horizontal-scroll-axis');
42397			var dataZindex = el.getAttribute( 'data-rellax-zindex' ) || 0;
42398			var dataMin = el.getAttribute( 'data-rellax-min' );
42399			var dataMax = el.getAttribute( 'data-rellax-max' );
42400			var dataMinX = el.getAttribute('data-rellax-min-x');
42401			var dataMaxX = el.getAttribute('data-rellax-max-x');
42402			var dataMinY = el.getAttribute('data-rellax-min-y');
42403			var dataMaxY = el.getAttribute('data-rellax-max-y');
42404			var mapBreakpoints;
42405			var breakpoints = true;
42406
42407			if (!dataXsSpeed && !dataMobileSpeed && !dataTabletSpeed && !dataDesktopSpeed) {
42408				breakpoints = false;
42409			} else {
42410				mapBreakpoints = {
42411					'xs': dataXsSpeed,
42412					'sm': dataMobileSpeed,
42413					'md': dataTabletSpeed,
42414					'lg': dataDesktopSpeed
42415				};
42416			}
42417
42418			// initializing at scrollY = 0 (top of browser), scrollX = 0 (left of browser)
42419			// ensures elements are positioned based on HTML layout.
42420			//
42421			// If the element has the percentage attribute, the posY and posX needs to be
42422			// the current scroll position's value, so that the elements are still positioned based on HTML layout
42423			var wrapperPosY = self.options.wrapper ? self.options.wrapper.scrollTop : (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
42424			// If the option relativeToWrapper is true, use the wrappers offset to top, subtracted from the current page scroll.
42425			if (self.options.relativeToWrapper) {
42426				var scrollPosY = (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
42427				wrapperPosY = scrollPosY - self.options.wrapper.offsetTop;
42428			}
42429			var posY = self.options.vertical ? ( dataPercentage || self.options.center ? wrapperPosY : 0 ) : 0;
42430			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;
42431
42432			var blockTop = posY + el.getBoundingClientRect().top;
42433			var blockHeight = el.clientHeight || el.offsetHeight || el.scrollHeight;
42434
42435			var blockLeft = posX + el.getBoundingClientRect().left;
42436			var blockWidth = el.clientWidth || el.offsetWidth || el.scrollWidth;
42437
42438			// apparently parallax equation everyone uses
42439			var percentageY = dataPercentage ? dataPercentage : (posY - blockTop + screenY) / (blockHeight + screenY);
42440			var percentageX = dataPercentage ? dataPercentage : (posX - blockLeft + screenX) / (blockWidth + screenX);
42441			if(self.options.center){ percentageX = 0.5; percentageY = 0.5; }
42442
42443			// Optional individual block speed as data attr, otherwise global speed
42444			var speed = (breakpoints && mapBreakpoints[currentBreakpoint] !== null) ? Number(mapBreakpoints[currentBreakpoint]) : (dataSpeed ? dataSpeed : self.options.speed);
42445			var verticalSpeed = dataVerticalSpeed ? dataVerticalSpeed : self.options.verticalSpeed;
42446			var horizontalSpeed = dataHorizontalSpeed ? dataHorizontalSpeed : self.options.horizontalSpeed;
42447
42448			// Optional individual block movement axis direction as data attr, otherwise global movement direction
42449			var verticalScrollAxis = dataVericalScrollAxis ? dataVericalScrollAxis : self.options.verticalScrollAxis;
42450			var horizontalScrollAxis = dataHorizontalScrollAxis ? dataHorizontalScrollAxis : self.options.horizontalScrollAxis;
42451
42452			var bases = updatePosition(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed);
42453
42454			// ~~Store non-translate3d transforms~~
42455			// Store inline styles and extract transforms
42456			var style = el.style.cssText;
42457			var transform = '';
42458
42459			// Check if there's an inline styled transform
42460			var searchResult = /transform\s*:/i.exec(style);
42461			if (searchResult) {
42462				// Get the index of the transform
42463				var index = searchResult.index;
42464
42465				// Trim the style to the transform point and get the following semi-colon index
42466				var trimmedStyle = style.slice(index);
42467				var delimiter = trimmedStyle.indexOf(';');
42468
42469				// Remove "transform" string and save the attribute
42470				if (delimiter) {
42471					transform = " " + trimmedStyle.slice(11, delimiter).replace(/\s/g,'');
42472				} else {
42473					transform = " " + trimmedStyle.slice(11).replace(/\s/g,'');
42474				}
42475			}
42476
42477			return {
42478				baseX: bases.x,
42479				baseY: bases.y,
42480				top: blockTop,
42481				left: blockLeft,
42482				height: blockHeight,
42483				width: blockWidth,
42484				speed: speed,
42485				verticalSpeed: verticalSpeed,
42486				horizontalSpeed: horizontalSpeed,
42487				verticalScrollAxis: verticalScrollAxis,
42488				horizontalScrollAxis: horizontalScrollAxis,
42489				style: style,
42490				transform: transform,
42491				zindex: dataZindex,
42492				min: dataMin,
42493				max: dataMax,
42494				minX: dataMinX,
42495				maxX: dataMaxX,
42496				minY: dataMinY,
42497				maxY: dataMaxY
42498			};
42499		};
42500
42501		// set scroll position (posY, posX)
42502		// side effect method is not ideal, but okay for now
42503		// returns true if the scroll changed, false if nothing happened
42504		var setPosition = function() {
42505			var oldY = posY;
42506			var oldX = posX;
42507
42508			posY = self.options.wrapper ? self.options.wrapper.scrollTop : (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset;
42509			posX = self.options.wrapper ? self.options.wrapper.scrollLeft : (document.documentElement || document.body.parentNode || document.body).scrollLeft || window.pageXOffset;
42510			// If option relativeToWrapper is true, use relative wrapper value instead.
42511			if (self.options.relativeToWrapper) {
42512				var scrollPosY = (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset;
42513				posY = scrollPosY - self.options.wrapper.offsetTop;
42514			}
42515
42516
42517			if (oldY != posY && self.options.vertical) {
42518				// scroll changed, return true
42519				return true;
42520			}
42521
42522			if (oldX != posX && self.options.horizontal) {
42523				// scroll changed, return true
42524				return true;
42525			}
42526
42527			// scroll did not change
42528			return false;
42529		};
42530
42531		// Ahh a pure function, gets new transform value
42532		// based on scrollPosition and speed
42533		// Allow for decimal pixel values
42534		var updatePosition = function(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed) {
42535			var result = {};
42536			var valueX = ((horizontalSpeed ? horizontalSpeed : speed) * (100 * (1 - percentageX)));
42537			var valueY = ((verticalSpeed ? verticalSpeed : speed) * (100 * (1 - percentageY)));
42538
42539			result.x = self.options.round ? Math.round(valueX) : Math.round(valueX * 100) / 100;
42540			result.y = self.options.round ? Math.round(valueY) : Math.round(valueY * 100) / 100;
42541
42542			return result;
42543		};
42544
42545		// Remove event listeners and loop again
42546		var deferredUpdate = function() {
42547			window.removeEventListener('resize', deferredUpdate);
42548			window.removeEventListener('orientationchange', deferredUpdate);
42549			(self.options.wrapper ? self.options.wrapper : window).removeEventListener('scroll', deferredUpdate);
42550			(self.options.wrapper ? self.options.wrapper : document).removeEventListener('touchmove', deferredUpdate);
42551
42552			// loop again
42553			loopId = loop(update);
42554		};
42555
42556		// Loop
42557		var update = function() {
42558			if (setPosition() && pause === false) {
42559				animate();
42560
42561				// loop again
42562				loopId = loop(update);
42563			} else {
42564				loopId = null;
42565
42566				// Don't animate until we get a position updating event
42567				window.addEventListener('resize', deferredUpdate);
42568				window.addEventListener('orientationchange', deferredUpdate);
42569				(self.options.wrapper ? self.options.wrapper : window).addEventListener('scroll', deferredUpdate, supportsPassive ? { passive: true } : false);
42570				(self.options.wrapper ? self.options.wrapper : document).addEventListener('touchmove', deferredUpdate, supportsPassive ? { passive: true } : false);
42571			}
42572		};
42573
42574		// Transform3d on parallax element
42575		var animate = function() {
42576			var positions;
42577			for (var i = 0; i < self.elems.length; i++){
42578				// Determine relevant movement directions
42579				var verticalScrollAxis = blocks[i].verticalScrollAxis.toLowerCase();
42580				var horizontalScrollAxis = blocks[i].horizontalScrollAxis.toLowerCase();
42581				var verticalScrollX = verticalScrollAxis.indexOf("x") != -1 ? posY : 0;
42582				var verticalScrollY = verticalScrollAxis.indexOf("y") != -1 ? posY : 0;
42583				var horizontalScrollX = horizontalScrollAxis.indexOf("x") != -1 ? posX : 0;
42584				var horizontalScrollY = horizontalScrollAxis.indexOf("y") != -1 ? posX : 0;
42585
42586				var percentageY = ((verticalScrollY + horizontalScrollY - blocks[i].top + screenY) / (blocks[i].height + screenY));
42587				var percentageX = ((verticalScrollX + horizontalScrollX - blocks[i].left + screenX) / (blocks[i].width + screenX));
42588
42589				// Subtracting initialize value, so element stays in same spot as HTML
42590				positions = updatePosition(percentageX, percentageY, blocks[i].speed, blocks[i].verticalSpeed, blocks[i].horizontalSpeed);
42591				var positionY = positions.y - blocks[i].baseY;
42592				var positionX = positions.x - blocks[i].baseX;
42593
42594				// The next two "if" blocks go like this:
42595				// Check if a limit is defined (first "min", then "max");
42596				// Check if we need to change the Y or the X
42597				// (Currently working only if just one of the axes is enabled)
42598				// Then, check if the new position is inside the allowed limit
42599				// If so, use new position. If not, set position to limit.
42600
42601				// Check if a min limit is defined
42602				if (blocks[i].min !== null) {
42603					if (self.options.vertical && !self.options.horizontal) {
42604						positionY = positionY <= blocks[i].min ? blocks[i].min : positionY;
42605					}
42606					if (self.options.horizontal && !self.options.vertical) {
42607						positionX = positionX <= blocks[i].min ? blocks[i].min : positionX;
42608					}
42609				}
42610
42611				// Check if directional min limits are defined
42612				if (blocks[i].minY != null) {
42613						positionY = positionY <= blocks[i].minY ? blocks[i].minY : positionY;
42614				}
42615				if (blocks[i].minX != null) {
42616						positionX = positionX <= blocks[i].minX ? blocks[i].minX : positionX;
42617				}
42618
42619				// Check if a max limit is defined
42620				if (blocks[i].max !== null) {
42621					if (self.options.vertical && !self.options.horizontal) {
42622						positionY = positionY >= blocks[i].max ? blocks[i].max : positionY;
42623					}
42624					if (self.options.horizontal && !self.options.vertical) {
42625						positionX = positionX >= blocks[i].max ? blocks[i].max : positionX;
42626					}
42627				}
42628
42629				// Check if directional max limits are defined
42630				if (blocks[i].maxY != null) {
42631						positionY = positionY >= blocks[i].maxY ? blocks[i].maxY : positionY;
42632				}
42633				if (blocks[i].maxX != null) {
42634						positionX = positionX >= blocks[i].maxX ? blocks[i].maxX : positionX;
42635				}
42636
42637				var zindex = blocks[i].zindex;
42638
42639				// Move that element
42640				// (Set the new translation and append initial inline transforms.)
42641				var translate = 'translate3d(' + (self.options.horizontal ? positionX : '0') + 'px,' + (self.options.vertical ? positionY : '0') + 'px,' + zindex + 'px) ' + blocks[i].transform;
42642				self.elems[i].style[transformProp] = translate;
42643			}
42644			self.options.callback(positions);
42645		};
42646
42647		self.destroy = function() {
42648			for (var i = 0; i < self.elems.length; i++){
42649				self.elems[i].style.cssText = blocks[i].style;
42650			}
42651
42652			// Remove resize event listener if not pause, and pause
42653			if (!pause) {
42654				window.removeEventListener('resize', init);
42655				pause = true;
42656			}
42657
42658			// Clear the animation loop to prevent possible memory leak
42659			clearLoop(loopId);
42660			loopId = null;
42661		};
42662
42663		// Init
42664		init();
42665
42666		// Allow to recalculate the initial values whenever we want
42667		self.refresh = init;
42668
42669		return self;
42670	};
42671	return Rellax;
42672}));
42673
42674/*
42675 * OKVideo by OKFocus v2.3.2
42676 * http://okfoc.us
42677 *
42678 * Copyright 2014, OKFocus
42679 * Licensed under the MIT license.
42680 *
42681 */
42682var player, OKEvents, options, videoWidth, videoHeight, YTplayers, youtubePlayers = new Array();
42683// youtube player ready
42684function onYouTubeIframeAPIReady() {
42685	YTplayers = new Array();
42686	jQuery('.uncode-video-container.video').each(function() {
42687		var playerY;
42688		if (jQuery(this).attr('data-provider') == 'youtube') {
42689			var id = jQuery(this).attr('data-id'),
42690				start = jQuery(this).attr('data-start'),
42691				end = jQuery(this).attr('data-end');
42692			start = typeof start && start !== null ? start : 0;
42693			end = typeof end && end !== null ? end : 0;
42694			options = jQuery(window).data('okoptions-' + id);
42695			if ( typeof options === 'undefined' ) {
42696				return true;
42697			}
42698			options.time = jQuery(this).attr('data-t');
42699			playerY = new YT.Player('okplayer-' + id, {
42700				videoId: options.video ? options.video.id : null,
42701				playerVars: {
42702					'autohide': 1,
42703					'autoplay': jQuery(this).hasClass('is-no-control') ? options.autoplay : 0, //options.autoplay,
42704					'disablekb': 1,
42705					'cc_load_policy': options.captions,
42706					'controls': 0,
42707					'enablejsapi': 1,
42708					'fs': 0,
42709					'modestbranding': 1,
42710					'origin': window.location.origin || (window.location.protocol + '//' + window.location.hostname),
42711					'iv_load_policy': options.annotations,
42712					'loop': options.loop,
42713					'showinfo': 0,
42714					'rel': 0,
42715					'wmode': 'opaque',
42716					'hd': options.hd,
42717					'mute': 1,
42718					'start': start,
42719					'end': end
42720				},
42721				events: {
42722					'onReady': OKEvents.yt.ready,
42723					'onStateChange': OKEvents.yt.onStateChange,
42724					'onError': OKEvents.yt.error
42725				}
42726			});
42727			YTplayers[id] = playerY;
42728			playerY.videoId = id;
42729		}
42730
42731	});
42732}
42733// vimeo player ready
42734function vimeoPlayerReady(id) {
42735	options = jQuery(window).data('okoptions-' + id);
42736	if ( typeof options === 'undefined' ) {
42737		return true;
42738	}
42739	var jIframe = options.jobject,
42740		iframe = jIframe[0];
42741
42742	jIframe.attr('src', jIframe.data('src'));
42743	var playerV = new Vimeo.Player(iframe);
42744	// hide player until Vimeo hides controls...
42745	playerV.on('loaded', function(e) {
42746		OKEvents.v.onReady(iframe);
42747		var carouselContainer = jQuery(iframe).closest('.owl-carousel');
42748		if (carouselContainer.length) {
42749			UNCODE.owlPlayVideo(carouselContainer);
42750		}
42751		// "Do not try to add listeners or call functions before receiving this event."
42752		if (OKEvents.utils.isMobile()) {
42753			// mobile devices cannot listen for play event
42754			OKEvents.v.onPlay(playerV);
42755		} else {
42756			playerV.on('play', function(){
42757				OKEvents.v.onPlay(playerV);
42758				jQuery(window).trigger('okevents.v.play', [playerV]);
42759			});
42760			playerV.on('pause', function(){
42761				OKEvents.v.onPause;
42762				jQuery(window).trigger('okevents.v.pause', [playerV]);
42763			});
42764			playerV.on('ended', function(){
42765				OKEvents.v.onFinish
42766				jQuery(window).trigger('okevents.v.ended', [playerV]);
42767			});
42768		}
42769		if (options.time != null) {
42770			var optsTimeStr = (options.time).replace('t=', ''),
42771				timeV = '';
42772
42773			if ( /[a-zA-Z]/g.test(optsTimeStr) ) {
42774				var timeArr = optsTimeStr.split(/([^\d.-])/);
42775				for ( var i = 0; i < timeArr.length; i++ ) {
42776					if ( timeArr[i] === 'h' ) {
42777						timeV += parseFloat(timeArr[i-1]) * 3600;
42778					} else if ( timeArr[i] === 'm' ) {
42779						timeV += parseFloat(timeArr[i-1]) * 60;
42780					} else if ( timeArr[i] === 's' ) {
42781						timeV += parseFloat(timeArr[i-1]);
42782					}
42783				}
42784			} else {
42785				timeV = optsTimeStr;
42786			}
42787
42788			playerV.setCurrentTime(timeV);
42789		}
42790
42791		playerV.setVolume(0);
42792		playerV.play();
42793		jQuery(iframe).css({
42794			visibility: 'visible',
42795			opacity: 1
42796		});
42797		jQuery(iframe).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1');
42798		jQuery(iframe).closest('#page-header').addClass('video-started');
42799		jQuery(iframe).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1');
42800
42801		jQuery(window).trigger('okevents.v.loaded', [playerV]);
42802	});
42803}
42804OKEvents = {
42805	yt: {
42806		ready: function(event) {
42807			var id = event.target.videoId,
42808				$video = jQuery('#okplayer-' + id),
42809				options = jQuery(window).data('okoptions-' + id);
42810			if ( typeof options === 'undefined' ) {
42811				return true;
42812			}
42813			youtubePlayers[id] = event.target;
42814			event.target.setVolume(options.volume);
42815			if (options.autoplay === 1) {
42816				if (options.playlist.list) {
42817					player.loadPlaylist(options.playlist.list, options.playlist.index, options.playlist.startSeconds, options.playlist.suggestedQuality);
42818				} else {
42819					var inCarousel = $video.closest('.owl-item');
42820					if (!inCarousel.length || (inCarousel.length && inCarousel.hasClass('active'))) {
42821						if (options.time != null) {
42822							event.target.seekTo(parseInt(options.time));
42823						}
42824						event.target.playVideo();
42825					} else {
42826						event.target.pauseVideo();
42827					}
42828				}
42829			}
42830			OKEvents.utils.isFunction(options.onReady) && options.onReady(event.target);
42831
42832			$video.closest('[data-provider]').on('uncode-resume', function(){
42833				if (options.time != null) {
42834					event.target.seekTo(parseInt(options.time)).playVideo();
42835				} else {
42836					event.target.seekTo(0).playVideo();
42837				}
42838			});
42839
42840			$video.closest('[data-provider]').on('uncode-pause', function(){
42841				if (options.time != null) {
42842					event.target.seekTo(parseInt(options.time)).pauseVideo();
42843				} else {
42844					event.target.seekTo(0).pauseVideo();
42845				}
42846			});
42847			jQuery(window).trigger('okevents.y.loaded', [event]);
42848		},
42849		onStateChange: function(event) {
42850			var id = event.target.videoId,
42851				$video = jQuery('#okplayer-' + id),
42852				options = jQuery(window).data('okoptions-' + id);
42853			if ( typeof options === 'undefined' || typeof event.target.setVolume === 'undefined' ) {
42854				return true;
42855			}
42856			youtubePlayers[id] = event.target;
42857			event.target.setVolume(options.volume);
42858			var $fluid = $video.closest('.fluid-object'),
42859				$tmb = $video.closest('.tmb'),
42860				setTime;
42861			switch (event.data) {
42862				case -1:
42863					OKEvents.utils.isFunction(options.unstarted) && options.unstarted();
42864					break;
42865				case 0:
42866					OKEvents.utils.isFunction(options.onFinished) && options.onFinished();
42867					options.loop && event.target.playVideo();
42868					break;
42869				case 1:
42870					OKEvents.utils.isFunction(options.onPlay) && options.onPlay();
42871					setTimeout(function() {
42872						UNCODE.initVideoComponent(document.body, '.uncode-video-container.video:not(.drop-move), .uncode-video-container.self-video:not(.drop-move)');
42873						jQuery('#okplayer-' + id).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1');
42874						jQuery('#okplayer-' + id).closest('#page-header').addClass('video-started');
42875						jQuery('#okplayer-' + id).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1');
42876					}, 300);
42877				break;
42878				case 2:
42879					OKEvents.utils.isFunction(options.onPause) && options.onPause();
42880					break;
42881				case 3:
42882					OKEvents.utils.isFunction(options.buffering) && options.buffering();
42883					break;
42884				case 5:
42885					OKEvents.utils.isFunction(options.cued) && options.cued();
42886					break;
42887				default:
42888					throw "OKVideo: received invalid data from YT player.";
42889			}
42890
42891			jQuery(window).trigger('okevents.y.change', [event]);
42892		},
42893		error: function(event) {
42894			throw event;
42895		}
42896	},
42897	v: {
42898		onReady: function(target) {
42899			if ( typeof options === 'undefined' ) {
42900				return true;
42901			}
42902			OKEvents.utils.isFunction(options.onReady) && options.onReady(target);
42903		},
42904		onPlay: function(player) {
42905			if ( typeof options === 'undefined' ) {
42906				return true;
42907			}
42908			if (!OKEvents.utils.isMobile()) player.setVolume(options.volume);
42909			OKEvents.utils.isFunction(options.onPlay) && options.onPlay();
42910			jQuery(player.element).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1');
42911			jQuery(player.element).closest('#page-header').addClass('video-started');
42912			jQuery(player.element).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1');
42913		},
42914		onPause: function() {
42915			if ( typeof options === 'undefined' ) {
42916				return true;
42917			}
42918			OKEvents.utils.isFunction(options.onPause) && options.onPause();
42919		},
42920		onFinish: function() {
42921			if ( typeof options === 'undefined' ) {
42922				return true;
42923			}
42924			OKEvents.utils.isFunction(options.onFinish) && options.onFinish();
42925		}
42926	},
42927	utils: {
42928		isFunction: function(func) {
42929			if (typeof func === 'function') {
42930				return true;
42931			} else {
42932				return false;
42933			}
42934		},
42935		isMobile: function() {
42936			if (navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry)/)) {
42937				return true;
42938			} else {
42939				return false;
42940			}
42941		}
42942	}
42943};
42944/**
42945 * vivus - JavaScript library to make drawing animation on SVG
42946 * @version v0.4.4
42947 * @link https://github.com/maxwellito/vivus
42948 * @license MIT
42949 */
42950
42951'use strict';
42952
42953(function () {
42954
42955  'use strict';
42956
42957/**
42958 * Pathformer
42959 * Beta version
42960 *
42961 * Take any SVG version 1.1 and transform
42962 * child elements to 'path' elements
42963 *
42964 * This code is purely forked from
42965 * https://github.com/Waest/SVGPathConverter
42966 */
42967
42968/**
42969 * Class constructor
42970 *
42971 * @param {DOM|String} element Dom element of the SVG or id of it
42972 */
42973function Pathformer(element) {
42974  // Test params
42975  if (typeof element === 'undefined') {
42976	throw new Error('Pathformer [constructor]: "element" parameter is required');
42977  }
42978
42979  // Set the element
42980  if (element.constructor === String) {
42981	element = document.getElementById(element);
42982	if (!element) {
42983	  throw new Error('Pathformer [constructor]: "element" parameter is not related to an existing ID');
42984	}
42985  }
42986  if (element instanceof window.SVGElement ||
42987	  element instanceof window.SVGGElement ||
42988	  /^svg$/i.test(element.nodeName)) {
42989	this.el = element;
42990  } else {
42991	throw new Error('Pathformer [constructor]: "element" parameter must be a string or a SVGelement');
42992  }
42993
42994  // Start
42995  this.scan(element);
42996}
42997
42998/**
42999 * List of tags which can be transformed
43000 * to path elements
43001 *
43002 * @type {Array}
43003 */
43004Pathformer.prototype.TYPES = ['line', 'ellipse', 'circle', 'polygon', 'polyline', 'rect'];
43005
43006/**
43007 * List of attribute names which contain
43008 * data. This array list them to check if
43009 * they contain bad values, like percentage.
43010 *
43011 * @type {Array}
43012 */
43013Pathformer.prototype.ATTR_WATCH = ['cx', 'cy', 'points', 'r', 'rx', 'ry', 'x', 'x1', 'x2', 'y', '
vendor: 24,640 bytes, lines 43013-43811
43013y1', 'y2'];
43014
43015/**
43016 * Finds the elements compatible for transform
43017 * and apply the liked method
43018 *
43019 * @param  {object} options Object from the constructor
43020 */
43021Pathformer.prototype.scan = function (svg) {
43022  var fn, element, pathData, pathDom,
43023	  elements = svg.querySelectorAll(this.TYPES.join(','));
43024
43025  for (var i = 0; i < elements.length; i++) {
43026	element = elements[i];
43027	fn = this[element.tagName.toLowerCase() + 'ToPath'];
43028	pathData = fn(this.parseAttr(element.attributes));
43029	pathDom = this.pathMaker(element, pathData);
43030	element.parentNode.replaceChild(pathDom, element);
43031  }
43032};
43033
43034
43035/**
43036 * Read `line` element to extract and transform
43037 * data, to make it ready for a `path` object.
43038 *
43039 * @param  {DOMelement} element Line element to transform
43040 * @return {object}			 Data for a `path` element
43041 */
43042Pathformer.prototype.lineToPath = function (element) {
43043  var newElement = {},
43044	  x1 = element.x1 || 0,
43045	  y1 = element.y1 || 0,
43046	  x2 = element.x2 || 0,
43047	  y2 = element.y2 || 0;
43048
43049  newElement.d = 'M' + x1 + ',' + y1 + 'L' + x2 + ',' + y2;
43050  return newElement;
43051};
43052
43053/**
43054 * Read `rect` element to extract and transform
43055 * data, to make it ready for a `path` object.
43056 * The radius-border is not taken in charge yet.
43057 * (your help is more than welcomed)
43058 *
43059 * @param  {DOMelement} element Rect element to transform
43060 * @return {object}             Data for a `path` element
43061 */
43062Pathformer.prototype.rectToPath = function (element) {
43063  var newElement = {},
43064      x      = parseFloat(element.x)      || 0,
43065      y      = parseFloat(element.y)      || 0,
43066      width  = parseFloat(element.width)  || 0,
43067      height = parseFloat(element.height) || 0;
43068
43069  if (element.rx || element.ry) {
43070    var rx = parseInt(element.rx, 10) || -1,
43071        ry = parseInt(element.ry, 10) || -1;
43072    rx = Math.min(Math.max(rx < 0 ? ry : rx, 0), width/2);
43073    ry = Math.min(Math.max(ry < 0 ? rx : ry, 0), height/2);
43074
43075    newElement.d = 'M ' + (x + rx) + ',' + y + ' ' +
43076                   'L ' + (x + width - rx) + ',' + y + ' ' +
43077                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + width) + ',' + (y + ry) + ' ' +
43078                   'L ' + (x + width) + ',' + (y + height - ry) + ' ' +
43079                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + width - rx) + ',' + (y + height) + ' ' +
43080                   'L ' + (x + rx) + ',' + (y + height) + ' ' +
43081                   'A ' + rx + ',' + ry + ',0,0,1,' + x + ',' + (y + height - ry) + ' ' +
43082                   'L ' + x + ',' + (y + ry) + ' ' +
43083                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + rx) + ',' + y;
43084  }
43085  else {
43086    newElement.d = 'M' + x + ' ' + y + ' ' +
43087                   'L' + (x + width) + ' ' + y + ' ' +
43088                   'L' + (x + width) + ' ' + (y + height) + ' ' +
43089                   'L' + x + ' ' + (y + height) + ' Z';
43090  }
43091  return newElement;
43092};
43093
43094/**
43095 * Read `polyline` element to extract and transform
43096 * data, to make it ready for a `path` object.
43097 *
43098 * @param  {DOMelement} element Polyline element to transform
43099 * @return {object}             Data for a `path` element
43100 */
43101Pathformer.prototype.polylineToPath = function (element) {
43102  var newElement = {},
43103      points = element.points.trim().split(' '),
43104      i, path;
43105
43106  // Reformatting if points are defined without commas
43107  if (element.points.indexOf(',') === -1) {
43108    var formattedPoints = [];
43109    for (i = 0; i < points.length; i+=2) {
43110      formattedPoints.push(points[i] + ',' + points[i+1]);
43111    }
43112    points = formattedPoints;
43113  }
43114
43115  // Generate the path.d value
43116  path = 'M' + points[0];
43117  for(i = 1; i < points.length; i++) {
43118    if (points[i].indexOf(',') !== -1) {
43119      path += 'L' + points[i];
43120    }
43121  }
43122  newElement.d = path;
43123  return newElement;
43124};
43125
43126/**
43127 * Read `polygon` element to extract and transform
43128 * data, to make it ready for a `path` object.
43129 * This method rely on polylineToPath, because the
43130 * logic is similar. The path created is just closed,
43131 * so it needs an 'Z' at the end.
43132 *
43133 * @param  {DOMelement} element Polygon element to transform
43134 * @return {object}             Data for a `path` element
43135 */
43136Pathformer.prototype.polygonToPath = function (element) {
43137  var newElement = Pathformer.prototype.polylineToPath(element);
43138
43139  newElement.d += 'Z';
43140  return newElement;
43141};
43142
43143/**
43144 * Read `ellipse` element to extract and transform
43145 * data, to make it ready for a `path` object.
43146 *
43147 * @param  {DOMelement} element ellipse element to transform
43148 * @return {object}             Data for a `path` element
43149 */
43150Pathformer.prototype.ellipseToPath = function (element) {
43151  var newElement = {},
43152      rx = parseFloat(element.rx) || 0,
43153      ry = parseFloat(element.ry) || 0,
43154      cx = parseFloat(element.cx) || 0,
43155      cy = parseFloat(element.cy) || 0,
43156      startX = cx - rx,
43157      startY = cy,
43158      endX = parseFloat(cx) + parseFloat(rx),
43159      endY = cy;
43160
43161  newElement.d = 'M' + startX + ',' + startY +
43162                 'A' + rx + ',' + ry + ' 0,1,1 ' + endX + ',' + endY +
43163                 'A' + rx + ',' + ry + ' 0,1,1 ' + startX + ',' + endY;
43164  return newElement;
43165};
43166
43167/**
43168 * Read `circle` element to extract and transform
43169 * data, to make it ready for a `path` object.
43170 *
43171 * @param  {DOMelement} element Circle element to transform
43172 * @return {object}             Data for a `path` element
43173 */
43174Pathformer.prototype.circleToPath = function (element) {
43175  var newElement = {},
43176      r  = parseFloat(element.r)  || 0,
43177      cx = parseFloat(element.cx) || 0,
43178      cy = parseFloat(element.cy) || 0,
43179      startX = cx - r,
43180      startY = cy,
43181      endX = parseFloat(cx) + parseFloat(r),
43182      endY = cy;
43183
43184  newElement.d =  'M' + startX + ',' + startY +
43185                  'A' + r + ',' + r + ' 0,1,1 ' + endX + ',' + endY +
43186                  'A' + r + ',' + r + ' 0,1,1 ' + startX + ',' + endY;
43187  return newElement;
43188};
43189
43190/**
43191 * Create `path` elements form original element
43192 * and prepared objects
43193 *
43194 * @param  {DOMelement} element  Original element to transform
43195 * @param  {object} pathData     Path data (from `toPath` methods)
43196 * @return {DOMelement}          Path element
43197 */
43198Pathformer.prototype.pathMaker = function (element, pathData) {
43199  var i, attr, pathTag = document.createElementNS('http://www.w3.org/2000/svg','path');
43200  for(i = 0; i < element.attributes.length; i++) {
43201    attr = element.attributes[i];
43202    if (this.ATTR_WATCH.indexOf(attr.name) === -1) {
43203      pathTag.setAttribute(attr.name, attr.value);
43204    }
43205  }
43206  for(i in pathData) {
43207    pathTag.setAttribute(i, pathData[i]);
43208  }
43209  return pathTag;
43210};
43211
43212/**
43213 * Parse attributes of a DOM element to
43214 * get an object of attribute => value
43215 *
43216 * @param  {NamedNodeMap} attributes Attributes object from DOM element to parse
43217 * @return {object}                  Object of attributes
43218 */
43219Pathformer.prototype.parseAttr = function (element) {
43220  var attr, output = {};
43221  for (var i = 0; i < element.length; i++) {
43222    attr = element[i];
43223    // Check if no data attribute contains '%', or the transformation is impossible
43224    if (this.ATTR_WATCH.indexOf(attr.name) !== -1 && attr.value.indexOf('%') !== -1) {
43225      throw new Error('Pathformer [parseAttr]: a SVG shape got values in percentage. This cannot be transformed into \'path\' tags. Please use \'viewBox\'.');
43226    }
43227    output[attr.name] = attr.value;
43228  }
43229  return output;
43230};
43231
43232  'use strict';
43233
43234var setupEnv, requestAnimFrame, cancelAnimFrame, parsePositiveInt;
43235
43236/**
43237 * Vivus
43238 * Beta version
43239 *
43240 * Take any SVG and make the animation
43241 * to give give the impression of live drawing
43242 *
43243 * This in more than just inspired from codrops
43244 * At that point, it's a pure fork.
43245 */
43246
43247/**
43248 * Class constructor
43249 * option structure
43250 *   type: 'delayed'|'sync'|'oneByOne'|'script' (to know if the items must be drawn synchronously or not, default: delayed)
43251 *   duration: <int> (in frames)
43252 *   start: 'inViewport'|'manual'|'autostart' (start automatically the animation, default: inViewport)
43253 *   delay: <int> (delay between the drawing of first and last path)
43254 *   dashGap <integer> whitespace extra margin between dashes
43255 *   pathTimingFunction <function> timing animation function for each path element of the SVG
43256 *   animTimingFunction <function> timing animation function for the complete SVG
43257 *   forceRender <boolean> force the browser to re-render all updated path items
43258 *   selfDestroy <boolean> removes all extra styling on the SVG, and leaves it as original
43259 *
43260 * The attribute 'type' is by default on 'delayed'.
43261 *  - 'delayed'
43262 *    all paths are draw at the same time but with a
43263 *    little delay between them before start
43264 *  - 'sync'
43265 *    all path are start and finish at the same time
43266 *  - 'oneByOne'
43267 *    only one path is draw at the time
43268 *    the end of the first one will trigger the draw
43269 *    of the next one
43270 *
43271 * All these values can be overwritten individually
43272 * for each path item in the SVG
43273 * The value of frames will always take the advantage of
43274 * the duration value.
43275 * If you fail somewhere, an error will be thrown.
43276 * Good luck.
43277 *
43278 * @constructor
43279 * @this {Vivus}
43280 * @param {DOM|String}   element  Dom element of the SVG or id of it
43281 * @param {Object}       options  Options about the animation
43282 * @param {Function}     callback Callback for the end of the animation
43283 */
43284function Vivus (element, options, callback) {
43285
43286  setupEnv();
43287
43288  // Setup
43289  this.isReady = false;
43290  this.setElement(element, options);
43291  this.setOptions(options);
43292  this.setCallback(callback);
43293
43294  if (this.isReady) {
43295    this.init();
43296  }
43297}
43298
43299/**
43300 * Timing functions
43301 **************************************
43302 *
43303 * Default functions to help developers.
43304 * It always take a number as parameter (between 0 to 1) then
43305 * return a number (between 0 and 1)
43306 */
43307Vivus.LINEAR          = function (x) {return x;};
43308Vivus.EASE            = function (x) {return -Math.cos(x * Math.PI) / 2 + 0.5;};
43309Vivus.EASE_OUT        = function (x) {return 1 - Math.pow(1-x, 3);};
43310Vivus.EASE_IN         = function (x) {return Math.pow(x, 3);};
43311Vivus.EASE_OUT_BOUNCE = function (x) {
43312  var base = -Math.cos(x * (0.5 * Math.PI)) + 1,
43313    rate = Math.pow(base,1.5),
43314    rateR = Math.pow(1 - x, 2),
43315    progress = -Math.abs(Math.cos(rate * (2.5 * Math.PI) )) + 1;
43316  return (1- rateR) + (progress * rateR);
43317};
43318
43319
43320/**
43321 * Setters
43322 **************************************
43323 */
43324
43325/**
43326 * Check and set the element in the instance
43327 * The method will not return anything, but will throw an
43328 * error if the parameter is invalid
43329 *
43330 * @param {DOM|String}   element  SVG Dom element or id of it
43331 */
43332Vivus.prototype.setElement = function (element, options) {
43333  var onLoad, self;
43334
43335  // Basic check
43336  if (typeof element === 'undefined') {
43337    throw new Error('Vivus [constructor]: "element" parameter is required');
43338  }
43339
43340  // Set the element
43341  if (element.constructor === String) {
43342    element = document.getElementById(element);
43343    if (!element) {
43344      throw new Error('Vivus [constructor]: "element" parameter is not related to an existing ID');
43345    }
43346  }
43347  this.parentEl = element;
43348
43349  // Load the SVG with XMLHttpRequest and extract the SVG
43350  if (options && options.file) {
43351    var self = this;
43352    onLoad = function (e) {
43353      var domSandbox = document.createElement('div');
43354      domSandbox.innerHTML = this.responseText;
43355
43356      var svgTag = domSandbox.querySelector('svg');
43357      if (!svgTag) {
43358        throw new Error('Vivus [load]: Cannot find the SVG in the loaded file : ' + options.file);
43359      }
43360
43361      self.el = svgTag
43362      self.el.setAttribute('width', '100%');
43363      self.el.setAttribute('height', '100%');
43364      self.parentEl.appendChild(self.el)
43365      self.isReady = true;
43366      self.init();
43367      self = null;
43368    }
43369
43370    var oReq = new window.XMLHttpRequest();
43371    oReq.addEventListener('load', onLoad);
43372    oReq.open('GET', options.file);
43373    oReq.send();
43374    return;
43375  }
43376
43377  switch (element.constructor) {
43378  case window.SVGSVGElement:
43379  case window.SVGElement:
43380  case window.SVGGElement:
43381    this.el = element;
43382    this.isReady = true;
43383    break;
43384
43385  case window.HTMLObjectElement:
43386    self = this;
43387    onLoad = function (e) {
43388      if (self.isReady) {
43389        return;
43390      }
43391      self.el = element.contentDocument && element.contentDocument.querySelector('svg');
43392      if (!self.el && e) {
43393        throw new Error('Vivus [constructor]: object loaded does not contain any SVG');
43394      }
43395      else if (self.el) {
43396        if (element.getAttribute('built-by-vivus')) {
43397          self.parentEl.insertBefore(self.el, element);
43398          self.parentEl.removeChild(element);
43399          self.el.setAttribute('width', '100%');
43400          self.el.setAttribute('height', '100%');
43401        }
43402        self.isReady = true;
43403        self.init();
43404        self = null;
43405      }
43406    };
43407
43408    if (!onLoad()) {
43409      element.addEventListener('load', onLoad);
43410    }
43411    break;
43412
43413  default:
43414    throw new Error('Vivus [constructor]: "element" parameter is not valid (or miss the "file" attribute)');
43415  }
43416};
43417
43418/**
43419 * Set up user option to the instance
43420 * The method will not return anything, but will throw an
43421 * error if the parameter is invalid
43422 *
43423 * @param  {object} options Object from the constructor
43424 */
43425Vivus.prototype.setOptions = function (options) {
43426  var allowedTypes = ['delayed', 'sync', 'async', 'nsync', 'oneByOne', 'scenario', 'scenario-sync'];
43427  var allowedStarts =  ['inViewport', 'manual', 'autostart'];
43428
43429  // Basic check
43430  if (options !== undefined && options.constructor !== Object) {
43431    throw new Error('Vivus [constructor]: "options" parameter must be an object');
43432  }
43433  else {
43434    options = options || {};
43435  }
43436
43437  // Set the animation type
43438  if (options.type && allowedTypes.indexOf(options.type) === -1) {
43439    throw new Error('Vivus [constructor]: ' + options.type + ' is not an existing animation `type`');
43440  }
43441  else {
43442    this.type = options.type || allowedTypes[0];
43443  }
43444
43445  // Set the start type
43446  if (options.start && allowedStarts.indexOf(options.start) === -1) {
43447    throw new Error('Vivus [constructor]: ' + options.start + ' is not an existing `start` option');
43448  }
43449  else {
43450    this.start = options.start || allowedStarts[0];
43451  }
43452
43453  this.isIE         = (window.navigator.userAgent.indexOf('MSIE') !== -1 || window.navigator.userAgent.indexOf('Trident/') !== -1 || window.navigator.userAgent.indexOf('Edge/') !== -1 );
43454  this.duration     = parsePositiveInt(options.duration, 120);
43455  this.delay        = parsePositiveInt(options.delay, null);
43456  //Uncode addition
43457  this.delayStart   = parsePositiveInt(options.delayStart, null);
43458  //#END
43459  this.dashGap      = parsePositiveInt(options.dashGap, 1);
43460  this.forceRender  = options.hasOwnProperty('forceRender') ? !!options.forceRender : this.isIE;
43461  this.reverseStack = !!options.reverseStack;
43462  this.selfDestroy  = !!options.selfDestroy;
43463  this.onReady      = options.onReady;
43464  this.map          = [];
43465  this.frameLength  = this.currentFrame = this.delayUnit = this.speed = this.handle = null;
43466
43467  this.ignoreInvisible = options.hasOwnProperty('ignoreInvisible') ? !!options.ignoreInvisible : false;
43468
43469  this.animTimingFunction = options.animTimingFunction || Vivus.LINEAR;
43470  this.pathTimingFunction = options.pathTimingFunction || Vivus.LINEAR;
43471
43472  if (this.delay >= this.duration) {
43473    throw new Error('Vivus [constructor]: delay must be shorter than duration');
43474  }
43475};
43476
43477/**
43478 * Set up callback to the instance
43479 * The method will not return enything, but will throw an
43480 * error if the parameter is invalid
43481 *
43482 * @param  {Function} callback Callback for the animation end
43483 */
43484Vivus.prototype.setCallback = function (callback) {
43485  // Basic check
43486  if (!!callback && callback.constructor !== Function) {
43487    throw new Error('Vivus [constructor]: "callback" parameter must be a function');
43488  }
43489  this.callback = callback || function () {};
43490};
43491
43492
43493/**
43494 * Core
43495 **************************************
43496 */
43497
43498/**
43499 * Map the svg, path by path.
43500 * The method return nothing, it just fill the
43501 * `map` array. Each item in this array represent
43502 * a path element from the SVG, with informations for
43503 * the animation.
43504 *
43505 * ```
43506 * [
43507 *   {
43508 *     el: <DOMobj> the path element
43509 *     length: <number> length of the path line
43510 *     startAt: <number> time start of the path animation (in frames)
43511 *     duration: <number> path animation duration (in frames)
43512 *   },
43513 *   ...
43514 * ]
43515 * ```
43516 *
43517 */
43518Vivus.prototype.mapping = function () {
43519  var i, paths, path, pAttrs, pathObj, totalLength, lengthMeter, timePoint;
43520  timePoint = totalLength = lengthMeter = 0;
43521  paths = this.el.querySelectorAll('path');
43522
43523  for (i = 0; i < paths.length; i++) {
43524    path = paths[i];
43525    if (this.isInvisible(path)) {
43526      continue;
43527    }
43528    pathObj = {
43529      el: path,
43530      length: Math.ceil(path.getTotalLength())
43531    };
43532    // Test if the path length is correct
43533    if (isNaN(pathObj.length)) {
43534      if (window.console && console.warn) {
43535        console.warn('Vivus [mapping]: cannot retrieve a path element length', path);
43536      }
43537      continue;
43538    }
43539    this.map.push(pathObj);
43540    path.style.strokeDasharray  = pathObj.length + ' ' + (pathObj.length + this.dashGap * 2);
43541    path.style.strokeDashoffset = pathObj.length + this.dashGap;
43542    pathObj.length += this.dashGap;
43543    totalLength += pathObj.length;
43544
43545    this.renderPath(i);
43546  }
43547
43548  totalLength = totalLength === 0 ? 1 : totalLength;
43549  this.delay = this.delay === null ? this.duration / 3 : this.delay;
43550  this.delayUnit = this.delay / (paths.length > 1 ? paths.length - 1 : 1);
43551
43552  // Reverse stack if asked
43553  if (this.reverseStack) {
43554    this.map.reverse();
43555  }
43556
43557  for (i = 0; i < this.map.length; i++) {
43558    pathObj = this.map[i];
43559
43560    switch (this.type) {
43561    case 'delayed':
43562      pathObj.startAt = this.delayUnit * i;
43563      pathObj.duration = this.duration - this.delay;
43564      break;
43565
43566    case 'oneByOne':
43567      pathObj.startAt = lengthMeter / totalLength * this.duration;
43568      pathObj.duration = pathObj.length / totalLength * this.duration;
43569      break;
43570
43571    case 'sync':
43572    case 'async':
43573    case 'nsync':
43574      pathObj.startAt = 0;
43575      pathObj.duration = this.duration;
43576      break;
43577
43578    case 'scenario-sync':
43579      path = pathObj.el;
43580      pAttrs = this.parseAttr(path);
43581      pathObj.startAt = timePoint + (parsePositiveInt(pAttrs['data-delay'], this.delayUnit) || 0);
43582      pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration);
43583      timePoint = pAttrs['data-async'] !== undefined ? pathObj.startAt : pathObj.startAt + pathObj.duration;
43584      this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration));
43585      break;
43586
43587    case 'scenario':
43588      path = pathObj.el;
43589      pAttrs = this.parseAttr(path);
43590      pathObj.startAt = parsePositiveInt(pAttrs['data-start'], this.delayUnit) || 0;
43591      pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration);
43592      this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration));
43593      break;
43594    }
43595    lengthMeter += pathObj.length;
43596    this.frameLength = this.frameLength || this.duration;
43597  }
43598};
43599
43600/**
43601 * Interval method to draw the SVG from current
43602 * position of the animation. It update the value of
43603 * `currentFrame` and re-trace the SVG.
43604 *
43605 * It use this.handle to store the requestAnimationFrame
43606 * and clear it one the animation is stopped. So this
43607 * attribute can be used to know if the animation is
43608 * playing.
43609 *
43610 * Once the animation at the end, this method will
43611 * trigger the Vivus callback.
43612 *
43613 */
43614Vivus.prototype.drawer = function () {
43615  var self = this;
43616  this.currentFrame += this.speed;
43617
43618  if (this.currentFrame <= 0) {
43619    this.stop();
43620    this.reset();
43621  } else if (this.currentFrame >= this.frameLength) {
43622    this.stop();
43623    this.currentFrame = this.frameLength;
43624    this.trace();
43625    if (this.selfDestroy) {
43626      this.destroy();
43627    }
43628  } else {
43629    this.trace();
43630    this.handle = requestAnimFrame(function () {
43631      self.drawer();
43632    });
43633    return;
43634  }
43635
43636  this.callback(this);
43637  if (this.instanceCallback) {
43638    this.instanceCallback(this);
43639    this.instanceCallback = null;
43640  }
43641};
43642
43643/**
43644 * Draw the SVG at the current instant from the
43645 * `currentFrame` value. Here is where most of the magic is.
43646 * The trick is to use the `strokeDashoffset` style property.
43647 *
43648 * For optimisation reasons, a new property called `progress`
43649 * is added in each item of `map`. This one contain the current
43650 * progress of the path element. Only if the new value is different
43651 * the new value will be applied to the DOM element. This
43652 * method save a lot of resources to re-render the SVG. And could
43653 * be improved if the animation couldn't be played forward.
43654 *
43655 */
43656Vivus.prototype.trace = function () {
43657  var i, progress, path, currentFrame;
43658  currentFrame = this.animTimingFunction(this.currentFrame / this.frameLength) * this.frameLength;
43659  for (i = 0; i < this.map.length; i++) {
43660    path = this.map[i];
43661    progress = (currentFrame - path.startAt) / path.duration;
43662    progress = this.pathTimingFunction(Math.max(0, Math.min(1, progress)));
43663    if (path.progress !== progress) {
43664      path.progress = progress;
43665      path.el.style.strokeDashoffset = Math.floor(path.length * (1 - progress));
43666      this.renderPath(i);
43667    }
43668  }
43669};
43670
43671/**
43672 * Method forcing the browser to re-render a path element
43673 * from it's index in the map. Depending on the `forceRender`
43674 * value.
43675 * The trick is to replace the path element by it's clone.
43676 * This practice is not recommended because it's asking more
43677 * ressources, too much DOM manupulation..
43678 * but it's the only way to let the magic happen on IE.
43679 * By default, this fallback is only applied on IE.
43680 *
43681 * @param  {Number} index Path index
43682 */
43683Vivus.prototype.renderPath = function (index) {
43684  if (this.forceRender && this.map && this.map[index]) {
43685    var pathObj = this.map[index],
43686        newPath = pathObj.el.cloneNode(true);
43687    pathObj.el.parentNode.replaceChild(newPath, pathObj.el);
43688    pathObj.el = newPath;
43689  }
43690};
43691
43692/**
43693 * When the SVG object is loaded and ready,
43694 * this method will continue the initialisation.
43695 *
43696 * This this mainly due to the case of passing an
43697 * object tag in the constructor. It will wait
43698 * the end of the loading to initialise.
43699 *
43700 */
43701Vivus.prototype.init = function () {
43702  // Set object variables
43703  this.frameLength = 0;
43704  this.currentFrame = 0;
43705  this.map = [];
43706
43707  // Start
43708  new Pathformer(this.el);
43709  this.mapping();
43710  this.starter();
43711
43712  if (this.onReady) {
43713    this.onReady(this);
43714  }
43715};
43716
43717/**
43718 * Trigger to start of the animation.
43719 * Depending on the `start` value, a different script
43720 * will be applied.
43721 *
43722 * If the `start` value is not valid, an error will be thrown.
43723 * Even if technically, this is impossible.
43724 *
43725 */
43726Vivus.prototype.starter = function () {
43727  switch (this.start) {
43728  case 'manual':
43729    return;
43730
43731  case 'autostart':
43732    this.play();
43733    break;
43734
43735  case 'inViewport':
43736    var self = this,
43737    listener = function () {
43738      if (self.isInViewport(self.parentEl, 1)) {
43739        self.play();
43740        window.removeEventListener('scroll', listener);
43741        //Uncode addition
43742        window.removeEventListener('fp-slide-changed', listener);
43743        window.removeEventListener('fp-slide-scroll', listener);
43744        //#END
43745      }
43746    };
43747    window.addEventListener('scroll', listener);
43748    //Uncode addition
43749    window.addEventListener('fp-slide-changed', listener);
43750    window.addEventListener('fp-slide-scroll', listener);
43751    //#END
43752    listener();
43753    break;
43754  }
43755};
43756
43757
43758/**
43759 * Controls
43760 **************************************
43761 */
43762
43763/**
43764 * Get the current status of the animation between
43765 * three different states: 'start', 'progress', 'end'.
43766 * @return {string} Instance status
43767 */
43768Vivus.prototype.getStatus = function () {
43769  return this.currentFrame === 0 ? 'start' : this.currentFrame === this.frameLength ? 'end' : 'progress';
43770};
43771
43772/**
43773 * Reset the instance to the initial state : undraw
43774 * Be careful, it just reset the animation, if you're
43775 * playing the animation, this won't stop it. But just
43776 * make it start from start.
43777 *
43778 */
43779Vivus.prototype.reset = function () {
43780  return this.setFrameProgress(0);
43781};
43782
43783/**
43784 * Set the instance to the final state : drawn
43785 * Be careful, it just set the animation, if you're
43786 * playing the animation on rewind, this won't stop it.
43787 * But just make it start from the end.
43788 *
43789 */
43790Vivus.prototype.finish = function () {
43791  return this.setFrameProgress(1);
43792};
43793
43794/**
43795 * Set the level of progress of the drawing.
43796 *
43797 * @param {number} progress Level of progress to set
43798 */
43799Vivus.prototype.setFrameProgress = function (progress) {
43800  progress = Math.min(1, Math.max(0, progress));
43801  this.currentFrame = Math.round(this.frameLength * progress);
43802  this.trace();
43803  return this;
43804};
43805
43806/**
43807 * Play the animation at the desired speed.
43808 * Speed must be a valid number (no zero).
43809 * By default, the speed value is 1.
43810 * But a negative value is accepted to go forward.
43811 *
43812 * And works with float too.
43813 * But don't forget we are in JavaScript, se be nice
43814 * with him and give him a 1/2^x value.
43815 *
43816 * @param  {number} speed Animation speed [optional]
43817 */
43818Vivus.prototype.play = function (speed, callback) {
43819  this.instanceCallback = null;
43820
43821  if (speed && typeof speed === 'function') {
43822    this.instanceCallback = speed; // first parameter is actually the callback function
43823    speed = null;
43824  }
43825  else if (speed && typeof speed !== 'number') {
43826    throw new Error('Vivus [play]: invalid speed');
43827  }
43828  // if the first parameter wasn't the callback, check if the seconds was
43829  if (callback && typeof(callback) === 'function' && !this.instanceCallback) {
43830    this.instanceCallback = callback;
43831  }
43832
43833
43834  this.speed = speed || 1;
43835  //Uncode addition
43836  if (!this.handle) {
43837    var $this = this,
43838    delay = (this.delayStart != null) ? this.delayStart : 0;
43839    setTimeout(function() {
43840      $this.drawer();
43841    }, delay);
43842  }
43843  //#END
43844  return this;
43845};
43846
43847/**
43848 * Stop the current animation, if on progress.
43849 * Should not trigger any error.
43850 *
43851 */
43852Vivus.prototype.stop = function () {
43853  if (this.handle) {
43854    cancelAnimFrame(this.handle);
43855    this.handle = null;
43856  }
43857  return this;
43858};
43859
43860/**
43861 * Destroy the instance.
43862 * Remove all bad styling attributes on all
43863 * path tags
43864 *
43865 */
43866Vivus.prototype.destroy = function () {
43867  this.stop();
43868  var i, path;
43869  for (i = 0; i < this.map.length; i++) {
43870    path = this.map[i];
43871    path.el.style.strokeDashoffset = null;
43872    path.el.style.strokeDasharray = null;
43873    this.renderPath(i);
43874  }
43875};
43876
43877
43878/**
43879 * Utils methods
43880 * include methods from Codrops
43881 **************************************
43882 */
43883
43884/**
43885 * Method to best guess if a path should added into
43886 * the animation or not.
43887 *
43888 * 1. Use the `data-vivus-ignore` attribute if set
43889 * 2. Check if the instance must ignore invisible paths
43890 * 3. Check if the path is visible
43891 *
43892 * For now the visibility checking is unstable.
43893 * It will be used for a beta phase.
43894 *
43895 * Other improvments are planned. Like detecting
43896 * is the path got a stroke or a valid opacity.
43897 */
43898Vivus.prototype.isInvisible = function (el) {
43899  var rect,
43900    ignoreAttr = el.getAttribute('data-ignore');
43901
43902  if (ignoreAttr !== null) {
43903    return ignoreAttr !== 'false';
43904  }
43905
43906  if (this.ignoreInvisible) {
43907    rect = el.getBoundingClientRect();
43908    return !rect.width && !rect.height;
43909  }
43910  else {
43911    return false;
43912  }
43913};
43914
43915/**
43916 * Parse attributes of a DOM element to
43917 * get an object of {attributeName => attributeValue}
43918 *
43919 * @param  {object} element DOM element to parse
43920 * @return {object}         Object of attributes
43921 */
43922Vivus.prototype.parseAttr = function (element) {
43923  var attr, output = {};
43924  if (element && element.attributes) {
43925    for (var i = 0; i < element.attributes.length; i++) {
43926      attr = element.attributes[i];
43927      output[attr.name] = attr.value;
43928    }
43929  }
43930  return output;
43931};
43932
43933/**
43934 * Reply if an element is in the page viewport
43935 *
43936 * @param  {object} el Element to observe
43937 * @param  {number} h  Percentage of height
43938 * @return {boolean}
43939 */
43940Vivus.prototype.isInViewport = function (el, h) {
43941  var scrolled   = this.scrollY(),
43942    viewed       = scrolled + this.getViewportH(),
43943    elBCR        = el.getBoundingClientRect(),
43944    elHeight     = elBCR.height,
43945    elTop        = scrolled + elBCR.top,
43946    elBottom     = elTop + elHeight;
43947
43948  // if 0, the element is considered in the viewport as soon as it enters.
43949  // if 1, the element is considered in the viewport only when it's fully inside
43950  // value in percentage (1 >= h >= 0)
43951  h = h || 0;
43952
43953  return (elTop + elHeight * h) <= viewed && (elBottom) >= scrolled;
43954};
43955
43956
43957/**
43958 * Get the viewport height in pixels
43959 *
43960 * @return {integer} Viewport height
43961 */
43962Vivus.prototype.getViewportH = function () {
43963  var client = this.docElem.clientHeight,
43964    inner = window.innerHeight;
43965
43966  if (client < inner) {
43967    return inner;
43968  }
43969  else {
43970    return client;
43971  }
43972};
43973
43974/**
43975 * Get the page Y offset
43976 *
43977 * @return {integer} Page Y offset
43978 */
43979Vivus.prototype.scrollY = function () {
43980  return window.pageYOffset || this.docElem.scrollTop;
43981};
43982
43983setupEnv = function () {
43984
43985  if (Vivus.prototype.docElem) {
43986    return;
43987  }
43988
43989  /**
43990   * Alias for document element
43991   *
43992   * @type {DOMelement}
43993   */
43994  Vivus.prototype.docElem = window.document.documentElement;
43995
43996  /**
43997   * Alias for `requestAnimationFrame` or
43998   * `setTimeout` function for deprecated browsers.
43999   *
44000   */
44001  requestAnimFrame = (function () {
44002    return (
44003      window.requestAnimationFrame       ||
44004      window.webkitRequestAnimationFrame ||
44005      window.mozRequestAnimationFrame    ||
44006      window.oRequestAnimationFrame      ||
44007      window.msRequestAnimationFrame     ||
44008      function(/* function */ callback){
44009        return window.setTimeout(callback, 1000 / 60);
44010      }
44011    );
44012  })();
44013
44014  /**
44015   * Alias for `cancelAnimationFrame` or
44016   * `cancelTimeout` function for deprecated browsers.
44017   *
44018   */
44019  cancelAnimFrame = (function () {
44020    return (
44021      window.cancelAnimationFrame       ||
44022      window.webkitCancelAnimationFrame ||
44023      window.mozCancelAnimationFrame    ||
44024      window.oCancelAnimationFrame      ||
44025      window.msCancelAnimationFrame     ||
44026      function(id){
44027        return window.clearTimeout(id);
44028      }
44029    );
44030  })();
44031};
44032
44033/**
44034 * Parse string to integer.
44035 * If the number is not positive or null
44036 * the method will return the default value
44037 * or 0 if undefined
44038 *
44039 * @param {string} value String to parse
44040 * @param {*}
44040 defaultValue Value to return if the result parsed is invalid
44041 * @return {number}
44042 *
44043 */
44044parsePositiveInt = function (value, defaultValue) {
44045  var output = parseInt(value, 10);
44046  return (output >= 0) ? output : defaultValue;
44047};
44048
44049
44050  if (typeof define === 'function' && define.amd) {
44051    // AMD. Register as an anonymous module.
44052    define([], function() {
44053      return Vivus;
44054    });
44055  } else if (typeof exports === 'object') {
44056    // Node. Does not work with strict CommonJS, but
44057    // only CommonJS-like environments that support module.exports,
44058    // like Node.
44059    module.exports = Vivus;
44060  } else {
44061    // Browser globals
44062    window.Vivus = Vivus;
44063  }
44064
44065}());
44066
44067//Noise.js
44068!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)}
44068var 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.