PageSourceSearch

https://www.kwl.digital/wp-content/themes/webexperten/library/js/plugins.js?ver=1524978109

js kwl.digital collected 2026-10-09 21:57:32 UTC 1,261,823 bytes, 37,955 lines download raw bytes

vendor: 4,719 bytes, lines 1-147
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.6.1
27   * https://greensock.com
28   *
29   * @license Copyright 2008-2021, GreenSock. All rights reserved.
30   * Subject to the terms at https://greensock.com/standard-license or for
31   * Club GreenSock 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      _bigNum = 1e8,
49      _tinyNum = 1 / _bigNum,
50      _2PI = Math.PI * 2,
51      _HALF_PI = _2PI / 4,
52      _gsID = 0,
53      _sqrt = Math.sqrt,
54      _cos = Math.cos,
55      _sin = Math.sin,
56      _isString = function _isString(value) {
57    return typeof value === "string";
58  },
59      _isFunction = function _isFunction(value) {
60    return typeof value === "function";
61  },
62      _isNumber = function _isNumber(value) {
63    return typeof value === "number";
64  },
65      _isUndefined = function _isUndefined(value) {
66    return typeof value === "undefined";
67  },
68      _isObject = function _isObject(value) {
69    return typeof value === "object";
70  },
71      _isNotFalse = function _isNotFalse(value) {
72    return value !== false;
73  },
74      _windowExists = function _windowExists() {
75    return typeof window !== "undefined";
76  },
77      _isFuncOrString = function _isFuncOrString(value) {
78    return _isFunction(value) || _isString(value);
79  },
80      _isTypedArray = typeof ArrayBuffer === "function" && ArrayBuffer.isView || function () {},
81      _isArray = Array.isArray,
82      _strictNumExp = /(?:-?\.?\d|\.)+/gi,
83      _numExp = /[-+=.]*\d+[.e\-+]*\d*[e\-+]*\d*/g,
84      _numWithUnitExp = /[-+=.]*\d+[.e-]*\d*[a-z%]*/g,
85      _complexStringNumExp = /[-+=.]*\d+\.?\d*(?:e-|e\+)?\d*/gi,
86      _relExp = /[+-]=-?[.\d]+/,
87      _delimitedValueExp = /[#\-+.]*\b[a-z\d-=+%.]+/gi,
88      _unitExp = /[\d.+\-=]+(?:e[-+]\d*)*/i,
89      _globalTimeline,
90      _win,
91      _coreInitted,
92      _doc,
93      _globals = {},
94      _installScope = {},
95      _coreReady,
96      _install = function _install(scope) {
97    return (_installScope = _merge(scope, _globals)) && gsap;
98  },
99      _missingPlugin = function _missingPlugin(property, value) {
100    return console.warn("Invalid property", property, "set to", value, "Missing plugin? gsap.registerPlugin()");
101  },
102      _warn = function _warn(message, suppress) {
103    return !suppress && console.warn(message);
104  },
105      _addGlobal = function _addGlobal(name, obj) {
106    return name && (_globals[name] = obj) && _installScope && (_installScope[name] = obj) || _globals;
107  },
108      _emptyFunc = function _emptyFunc() {
109    return 0;
110  },
111      _reservedProps = {},
112      _lazyTweens = [],
113      _lazyLookup = {},
114      _lastRenderedFrame,
115      _plugins = {},
116      _effects = {},
117      _nextGCFrame = 30,
118      _harnessPlugins = [],
119      _callbackNames = "",
120      _harness = function _harness(targets) {
121    var target = targets[0],
122        harnessPlugin,
123        i;
124    _isObject(target) || _isFunction(target) || (targets = [targets]);
125
126    if (!(harnessPlugin = (target._gsap || {}).harness)) {
127      i = _harnessPlugins.length;
128
129      while (i-- && !_harnessPlugins[i].targetTest(target)) {}
130
131      harnessPlugin = _harnessPlugins[i];
132    }
133
134    i = targets.length;
135
136    while (i--) {
137      targets[i] && (targets[i]._gsap || (targets[i]._gsap = new GSCache(targets[i], harnessPlugin))) || targets.splice(i, 1);
138    }
139
140    return targets;
141  },
142      _getCache = function _getCache(target) {
143    return target._gsap || _harness(toArray(target))[0]._gsap;
144  },
145      _getProperty = function _getProperty(target, property, v) {
146    return (v = target[property]) && _isFunction(v) ? target[property]() : _isUndefined(v) && target.getAttribute && target.getAttribute(property) || v;
147  },
vendor: 7,717 bytes, lines 148-411
148      _forEachName = function _forEachName(names, func) {
149    return (names = names.split(",")).forEach(func) || names;
150  },
151      _round = function _round(value) {
152    return Math.round(value * 100000) / 100000 || 0;
153  },
154      _arrayContainsAny = function _arrayContainsAny(toSearch, toFind) {
155    var l = toFind.length,
156        i = 0;
157
158    for (; toSearch.indexOf(toFind[i]) < 0 && ++i < l;) {}
159
160    return i < l;
161  },
162      _parseVars = function _parseVars(params, type, parent) {
163    var isLegacy = _isNumber(params[1]),
164        varsIndex = (isLegacy ? 2 : 1) + (type < 2 ? 0 : 1),
165        vars = params[varsIndex],
166        irVars;
167
168    isLegacy && (vars.duration = params[1]);
169    vars.parent = parent;
170
171    if (type) {
172      irVars = vars;
173
174      while (parent && !("immediateRender" in irVars)) {
175        irVars = parent.vars.defaults || {};
176        parent = _isNotFalse(parent.vars.inherit) && parent.parent;
177      }
178
179      vars.immediateRender = _isNotFalse(irVars.immediateRender);
180      type < 2 ? vars.runBackwards = 1 : vars.startAt = params[varsIndex - 1];
181    }
182
183    return vars;
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 && _lazyRender();
201    animation.render(time, suppressEvents, force);
202    _lazyTweens.length && _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(obj, defaults) {
219    for (var p in defaults) {
220      p in obj || p === "duration" || p === "ease" || (obj[p] = defaults[p]);
221    }
222  },
223      _merge = function _merge(base, toMerge) {
224    for (var p in toMerge) {
225      base[p] = toMerge[p];
226    }
227
228    return base;
229  },
230      _mergeDeep = function _mergeDeep(base, toMerge) {
231    for (var p in toMerge) {
232      p !== "__proto__" && p !== "constructor" && p !== "prototype" && (base[p] = _isObject(toMerge[p]) ? _mergeDeep(base[p] || (base[p] = {}), toMerge[p]) : toMerge[p]);
233    }
234
235    return base;
236  },
237      _copyExcluding = function _copyExcluding(obj, excluding) {
238    var copy = {},
239        p;
240
241    for (p in obj) {
242      p in excluding || (copy[p] = obj[p]);
243    }
244
245    return copy;
246  },
247      _inheritDefaults = function _inheritDefaults(vars) {
248    var parent = vars.parent || _globalTimeline,
249        func = vars.keyframes ? _setKeyframeDefaults : _setDefaults;
250
251    if (_isNotFalse(vars.inherit)) {
252      while (parent) {
253        func(vars, parent.vars.defaults);
254        parent = parent.parent || parent._dp;
255      }
256    }
257
258    return vars;
259  },
260      _arraysMatch = function _arraysMatch(a1, a2) {
261    var i = a1.length,
262        match = i === a2.length;
263
264    while (match && i-- && a1[i] === a2[i]) {}
265
266    return i < 0;
267  },
268      _addLinkedListItem = function _addLinkedListItem(parent, child, firstProp, lastProp, sortBy) {
269    if (firstProp === void 0) {
270      firstProp = "_first";
271    }
272
273    if (lastProp === void 0) {
274      lastProp = "_last";
275    }
276
277    var prev = parent[lastProp],
278        t;
279
280    if (sortBy) {
281      t = child[sortBy];
282
283      while (prev && prev[sortBy] > t) {
284        prev = prev._prev;
285      }
286    }
287
288    if (prev) {
289      child._next = prev._next;
290      prev._next = child;
291    } else {
292      child._next = parent[firstProp];
293      parent[firstProp] = child;
294    }
295
296    if (child._next) {
297      child._next._prev = child;
298    } else {
299      parent[lastProp] = child;
300    }
301
302    child._prev = prev;
303    child.parent = child._dp = parent;
304    return child;
305  },
306      _removeLinkedListItem = function _removeLinkedListItem(parent, child, firstProp, lastProp) {
307    if (firstProp === void 0) {
308      firstProp = "_first";
309    }
310
311    if (lastProp === void 0) {
312      lastProp = "_last";
313    }
314
315    var prev = child._prev,
316        next = child._next;
317
318    if (prev) {
319      prev._next = next;
320    } else if (parent[firstProp] === child) {
321      parent[firstProp] = next;
322    }
323
324    if (next) {
325      next._prev = prev;
326    } else if (parent[lastProp] === child) {
327      parent[lastProp] = prev;
328    }
329
330    child._next = child._prev = child.parent = null;
331  },
332      _removeFromParent = function _removeFromParent(child, onlyIfParentHasAutoRemove) {
333    child.parent && (!onlyIfParentHasAutoRemove || child.parent.autoRemoveChildren) && child.parent.remove(child);
334    child._act = 0;
335  },
336      _uncache = function _uncache(animation, child) {
337    if (animation && (!child || child._end > animation._dur || child._start < 0)) {
338      var a = animation;
339
340      while (a) {
341        a._dirty = 1;
342        a = a.parent;
343      }
344    }
345
346    return animation;
347  },
348      _recacheAncestors = function _recacheAncestors(animation) {
349    var parent = animation.parent;
350
351    while (parent && parent.parent) {
352      parent._dirty = 1;
353      parent.totalDuration();
354      parent = parent.parent;
355    }
356
357    return animation;
358  },
359      _hasNoPausedAncestors = function _hasNoPausedAncestors(animation) {
360    return !animation || animation._ts && _hasNoPausedAncestors(animation.parent);
361  },
362      _elapsedCycleDuration = function _elapsedCycleDuration(animation) {
363    return animation._repeat ? _animationCycle(animation._tTime, animation = animation.duration() + animation._rDelay) * animation : 0;
364  },
365      _animationCycle = function _animationCycle(tTime, cycleDuration) {
366    var whole = Math.floor(tTime /= cycleDuration);
367    return tTime && whole === tTime ? whole - 1 : whole;
368  },
369      _parentToChildTotalTime = function _parentToChildTotalTime(parentTime, child) {
370    return (parentTime - child._start) * child._ts + (child._ts >= 0 ? 0 : child._dirty ? child.totalDuration() : child._tDur);
371  },
372      _setEnd = function _setEnd(animation) {
373    return animation._end = _round(animation._start + (animation._tDur / Math.abs(animation._ts || animation._rts || _tinyNum) || 0));
374  },
375      _alignPlayhead = function _alignPlayhead(animation, totalTime) {
376    var parent = animation._dp;
377
378    if (parent && parent.smoothChildTiming && animation._ts) {
379      animation._start = _round(parent._time - (animation._ts > 0 ? totalTime / animation._ts : ((animation._dirty ? animation.totalDuration() : animation._tDur) - totalTime) / -animation._ts));
380
381      _setEnd(animation);
382
383      parent._dirty || _uncache(parent, animation);
384    }
385
386    return animation;
387  },
388      _postAddChecks = function _postAddChecks(timeline, child) {
389    var t;
390
391    if (child._time || child._initted && !child._dur) {
392      t = _parentToChildTotalTime(timeline.rawTime(), child);
393
394      if (!child._dur || _clamp(0, child.totalDuration(), t) - child._tTime > _tinyNum) {
395        child.render(t, true);
396      }
397    }
398
399    if (_uncache(timeline, child)._dp && timeline._initted && timeline._time >= timeline._dur && timeline._ts) {
400      if (timeline._dur < timeline.duration()) {
401        t = timeline;
402
403        while (t._dp) {
404          t.rawTime() >= 0 && t.totalTime(t._tTime);
405          t = t._dp;
406        }
407      }
408
409      timeline._zTime = -_tinyNum;
410    }
411  },
412      _addToTimeline = function _addToTimeline(timeline, child, position, skipChecks) {
413    child.parent && _removeFromParent(child);
414    child._start = _round(position + child._delay);
415    child._end = _round(child._start + (child.totalDuration() / Math.abs(child.timeScale()) || 0));
416
417    _addLinkedListItem(timeline, child, "_first", "_last", timeline._sort ? "_start" : 0);
418
419    timeline._recent = child;
420    skipChecks || _postAddChecks(timeline, child);
421    return timeline;
422  },
423      _scrollTrigger = function _scrollTrigger(animation, trigger) {
424    return (_globals.ScrollTrigger || _missingPlugin("scrollTrigger", trigger)) && _globals.ScrollTrigger.create(trigger, animation);
425  },
426      _attemptInitTween = function _attemptInitTween(tween, totalTime, force, suppressEvents) {
427    _initTween(tween, totalTime);
428
429    if (!tween._initted) {
430      return 1;
431    }
432
433    if (!force && tween._pt && (tween._dur && tween.vars.lazy !== false || !tween._dur && tween.vars.lazy) && _lastRenderedFrame !== _ticker.frame) {
434      _lazyTweens.push(tween);
435
436      tween._lazy = [totalTime, suppressEvents];
437      return 1;
438    }
439  },
440      _parentPlayheadIsBeforeStart = function _parentPlayheadIsBeforeStart(_ref) {
441    var parent = _ref.parent;
442    return parent && parent._ts && parent._initted && !parent._lock && (parent.rawTime() < 0 || _parentPlayheadIsBeforeStart(parent));
443  },
444      _renderZeroDurationTween = function _renderZeroDurationTween(tween, totalTime, suppressEvents, force) {
445    var prevRatio = tween.ratio,
446        ratio = totalTime < 0 || !totalTime && (!tween._start && _parentPlayheadIsBeforeStart(tween) || (tween._ts < 0 || tween._dp._ts < 0) && tween.data !== "isFromStart" && tween.data !== "isStart") ? 0 : 1,
447        repeatDelay = tween._rDelay,
448        tTime = 0,
449        pt,
450        iteration,
451        prevIteration;
452
453    if (repeatDelay && tween._repeat) {
454      tTime = _clamp(0, tween._tDur, totalTime);
455      iteration = _animationCycle(tTime, repeatDelay);
456      prevIteration = _animationCycle(tween._tTime, repeatDelay);
457      tween._yoyo && iteration & 1 && (ratio = 1 - ratio);
458
459      if (iteration !== prevIteration) {
460        prevRatio = 1 - ratio;
461        tween.vars.repeatRefresh && tween._initted && tween.invalidate();
462      }
463    }
464
465    if (ratio !== prevRatio || force || tween._zTime === _tinyNum || !totalTime && tween._zTime) {
466      if (!tween._initted && _attemptInitTween(tween, totalTime, force, suppressEvents)) {
467        return;
468      }
469
470      prevIteration = tween._zTime;
471      tween._zTime = totalTime || (suppressEvents ? _tinyNum : 0);
472      suppressEvents || (suppressEvents = totalTime && !prevIteration);
473      tween.ratio = ratio;
474      tween._from && (ratio = 1 - ratio);
475      tween._time = 0;
476      tween._tTime = tTime;
477      pt = tween._pt;
478
479      while (pt) {
480        pt.r(ratio, pt.d);
481        pt = pt._next;
482      }
483
484      tween._startAt && totalTime < 0 && tween._startAt.render(totalTime, true, true);
vendor: 9,020 bytes, lines 485-753
485      tween._onUpdate && !suppressEvents && _callback(tween, "onUpdate");
486      tTime && tween._repeat && !suppressEvents && tween.parent && _callback(tween, "onRepeat");
487
488      if ((totalTime >= tween._tDur || totalTime < 0) && tween.ratio === ratio) {
489        ratio && _removeFromParent(tween, 1);
490
491        if (!suppressEvents) {
492          _callback(tween, ratio ? "onComplete" : "onReverseComplete", true);
493
494          tween._prom && tween._prom();
495        }
496      }
497    } else if (!tween._zTime) {
498      tween._zTime = totalTime;
499    }
500  },
501      _findNextPauseTween = function _findNextPauseTween(animation, prevTime, time) {
502    var child;
503
504    if (time > prevTime) {
505      child = animation._first;
506
507      while (child && child._start <= time) {
508        if (!child._dur && child.data === "isPause" && child._start > prevTime) {
509          return child;
510        }
511
512        child = child._next;
513      }
514    } else {
515      child = animation._last;
516
517      while (child && child._start >= time) {
518        if (!child._dur && child.data === "isPause" && child._start < prevTime) {
519          return child;
520        }
521
522        child = child._prev;
523      }
524    }
525  },
526      _setDuration = function _setDuration(animation, duration, skipUncache, leavePlayhead) {
527    var repeat = animation._repeat,
528        dur = _round(duration) || 0,
529        totalProgress = animation._tTime / animation._tDur;
530    totalProgress && !leavePlayhead && (animation._time *= dur / animation._dur);
531    animation._dur = dur;
532    animation._tDur = !repeat ? dur : repeat < 0 ? 1e10 : _round(dur * (repeat + 1) + animation._rDelay * repeat);
533    totalProgress && !leavePlayhead ? _alignPlayhead(animation, animation._tTime = animation._tDur * totalProgress) : animation.parent && _setEnd(animation);
534    skipUncache || _uncache(animation.parent, animation);
535    return animation;
536  },
537      _onUpdateTotalDuration = function _onUpdateTotalDuration(animation) {
538    return animation instanceof Timeline ? _uncache(animation) : _setDuration(animation, animation._dur);
539  },
540      _zeroPosition = {
541    _start: 0,
542    endTime: _emptyFunc
543  },
544      _parsePosition = function _parsePosition(animation, position) {
545    var labels = animation.labels,
546        recent = animation._recent || _zeroPosition,
547        clippedDuration = animation.duration() >= _bigNum ? recent.endTime(false) : animation._dur,
548        i,
549        offset;
550
551    if (_isString(position) && (isNaN(position) || position in labels)) {
552      i = position.charAt(0);
553
554      if (i === "<" || i === ">") {
555        return (i === "<" ? recent._start : recent.endTime(recent._repeat >= 0)) + (parseFloat(position.substr(1)) || 0);
556      }
557
558      i = position.indexOf("=");
559
560      if (i < 0) {
561        position in labels || (labels[position] = clippedDuration);
562        return labels[position];
563      }
564
565      offset = +(position.charAt(i - 1) + position.substr(i + 1));
566      return i > 1 ? _parsePosition(animation, position.substr(0, i - 1)) + offset : clippedDuration + offset;
567    }
568
569    return position == null ? clippedDuration : +position;
570  },
571      _conditionalReturn = function _conditionalReturn(value, func) {
572    return value || value === 0 ? func(value) : func;
573  },
574      _clamp = function _clamp(min, max, value) {
575    return value < min ? min : value > max ? max : value;
576  },
577      getUnit = function getUnit(value) {
578    if (typeof value !== "string") {
579      return "";
580    }
581
582    var v = _unitExp.exec(value);
583
584    return v ? value.substr(v.index + v[0].length) : "";
585  },
586      clamp = function clamp(min, max, value) {
587    return _conditionalReturn(value, function (v) {
588      return _clamp(min, max, v);
589    });
590  },
591      _slice = [].slice,
592      _isArrayLike = function _isArrayLike(value, nonEmpty) {
593    return value && _isObject(value) && "length" in value && (!nonEmpty && !value.length || value.length - 1 in value && _isObject(value[0])) && !value.nodeType && value !== _win;
594  },
595      _flatten = function _flatten(ar, leaveStrings, accumulator) {
596    if (accumulator === void 0) {
597      accumulator = [];
598    }
599
600    return ar.forEach(function (value) {
601      var _accumulator;
602
603      return _isString(value) && !leaveStrings || _isArrayLike(value, 1) ? (_accumulator = accumulator).push.apply(_accumulator, toArray(value)) : accumulator.push(value);
604    }) || accumulator;
605  },
606      toArray = function toArray(value, leaveStrings) {
607    return _isString(value) && !leaveStrings && (_coreInitted || !_wake()) ? _slice.call(_doc.querySelectorAll(value), 0) : _isArray(value) ? _flatten(value, leaveStrings) : _isArrayLike(value) ? _slice.call(value, 0) : value ? [value] : [];
608  },
609      shuffle = function shuffle(a) {
610    return a.sort(function () {
611      return .5 - Math.random();
612    });
613  },
614      distribute = function distribute(v) {
615    if (_isFunction(v)) {
616      return v;
617    }
618
619    var vars = _isObject(v) ? v : {
620      each: v
621    },
622        ease = _parseEase(vars.ease),
623        from = vars.from || 0,
624        base = parseFloat(vars.base) || 0,
625        cache = {},
626        isDecimal = from > 0 && from < 1,
627        ratios = isNaN(from) || isDecimal,
628        axis = vars.axis,
629        ratioX = from,
630        ratioY = from;
631
632    if (_isString(from)) {
633      ratioX = ratioY = {
634        center: .5,
635        edges: .5,
636        end: 1
637      }[from] || 0;
638    } else if (!isDecimal && ratios) {
639      ratioX = from[0];
640      ratioY = from[1];
641    }
642
643    return function (i, target, a) {
644      var l = (a || vars).length,
645          distances = cache[l],
646          originX,
647          originY,
648          x,
649          y,
650          d,
651          j,
652          max,
653          min,
654          wrapAt;
655
656      if (!distances) {
657        wrapAt = vars.grid === "auto" ? 0 : (vars.grid || [1, _bigNum])[1];
658
659        if (!wrapAt) {
660          max = -_bigNum;
661
662          while (max < (max = a[wrapAt++].getBoundingClientRect().left) && wrapAt < l) {}
663
664          wrapAt--;
665        }
666
667        distances = cache[l] = [];
668        originX = ratios ? Math.min(wrapAt, l) * ratioX - .5 : from % wrapAt;
669        originY = ratios ? l * ratioY / wrapAt - .5 : from / wrapAt | 0;
670        max = 0;
671        min = _bigNum;
672
673        for (j = 0; j < l; j++) {
674          x = j % wrapAt - originX;
675          y = originY - (j / wrapAt | 0);
676          distances[j] = d = !axis ? _sqrt(x * x + y * y) : Math.abs(axis === "y" ? y : x);
677          d > max && (max = d);
678          d < min && (min = d);
679        }
680
681        from === "random" && shuffle(distances);
682        distances.max = max - min;
683        distances.min = min;
684        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);
685        distances.b = l < 0 ? base - l : base;
686        distances.u = getUnit(vars.amount || vars.each) || 0;
687        ease = ease && l < 0 ? _invertEase(ease) : ease;
688      }
689
690      l = (distances[i] - distances.min) / distances.max || 0;
691      return _round(distances.b + (ease ? ease(l) : l) * distances.v) + distances.u;
692    };
693  },
694      _roundModifier = function _roundModifier(v) {
695    var p = v < 1 ? Math.pow(10, (v + "").length - 2) : 1;
696    return function (raw) {
697      var n = Math.round(parseFloat(raw) / v) * v * p;
698      return (n - n % 1) / p + (_isNumber(raw) ? 0 : getUnit(raw));
699    };
700  },
701      snap = function snap(snapTo, value) {
702    var isArray = _isArray(snapTo),
703        radius,
704        is2D;
705
706    if (!isArray && _isObject(snapTo)) {
707      radius = isArray = snapTo.radius || _bigNum;
708
709      if (snapTo.values) {
710        snapTo = toArray(snapTo.values);
711
712        if (is2D = !_isNumber(snapTo[0])) {
713          radius *= radius;
714        }
715      } else {
716        snapTo = _roundModifier(snapTo.increment);
717      }
718    }
719
720    return _conditionalReturn(value, !isArray ? _roundModifier(snapTo) : _isFunction(snapTo) ? function (raw) {
721      is2D = snapTo(raw);
722      return Math.abs(is2D - raw) <= radius ? is2D : raw;
723    } : function (raw) {
724      var x = parseFloat(is2D ? raw.x : raw),
725          y = parseFloat(is2D ? raw.y : 0),
726          min = _bigNum,
727          closest = 0,
728          i = snapTo.length,
729          dx,
730          dy;
731
732      while (i--) {
733        if (is2D) {
734          dx = snapTo[i].x - x;
735          dy = snapTo[i].y - y;
736          dx = dx * dx + dy * dy;
737        } else {
738          dx = Math.abs(snapTo[i] - x);
739        }
740
741        if (dx < min) {
742          min = dx;
743          closest = i;
744        }
745      }
746
747      closest = !radius || min <= radius ? snapTo[closest] : raw;
748      return is2D || closest === raw || _isNumber(raw) ? closest : closest + getUnit(raw);
749    });
750  },
751      random = function random(min, max, roundingIncrement, returnFunction) {
752    return _conditionalReturn(_isArray(min) ? !max : roundingIncrement === true ? !!(roundingIncrement = 0) : !returnFunction, function () {
753      return _isArray(min) ? min[~~(Math.random() * min.length)] : (roundingIncrement = roundingIncrement || 1e
vendor: 4,723 bytes, lines 753-909
753-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;
754    });
755  },
756      pipe = function pipe() {
757    for (var _len = arguments.length, functions = new Array(_len), _key = 0; _key < _len; _key++) {
758      functions[_key] = arguments[_key];
759    }
760
761    return function (value) {
762      return functions.reduce(function (v, f) {
763        return f(v);
764      }, value);
765    };
766  },
767      unitize = function unitize(func, unit) {
768    return function (value) {
769      return func(parseFloat(value)) + (unit || getUnit(value));
770    };
771  },
772      normalize = function normalize(min, max, value) {
773    return mapRange(min, max, 0, 1, value);
774  },
775      _wrapArray = function _wrapArray(a, wrapper, value) {
776    return _conditionalReturn(value, function (index) {
777      return a[~~wrapper(index)];
778    });
779  },
780      wrap = function wrap(min, max, value) {
781    var range = max - min;
782    return _isArray(min) ? _wrapArray(min, wrap(0, min.length), max) : _conditionalReturn(value, function (value) {
783      return (range + (value - min) % range) % range + min;
784    });
785  },
786      wrapYoyo = function wrapYoyo(min, max, value) {
787    var range = max - min,
788        total = range * 2;
789    return _isArray(min) ? _wrapArray(min, wrapYoyo(0, min.length - 1), max) : _conditionalReturn(value, function (value) {
790      value = (total + (value - min) % total) % total || 0;
791      return min + (value > range ? total - value : value);
792    });
793  },
794      _replaceRandom = function _replaceRandom(value) {
795    var prev = 0,
796        s = "",
797        i,
798        nums,
799        end,
800        isArray;
801
802    while (~(i = value.indexOf("random(", prev))) {
803      end = value.indexOf(")", i);
804      isArray = value.charAt(i + 7) === "[";
805      nums = value.substr(i + 7, end - i - 7).match(isArray ? _delimitedValueExp : _strictNumExp);
806      s += value.substr(prev, i - prev) + random(isArray ? nums : +nums[0], isArray ? 0 : +nums[1], +nums[2] || 1e-5);
807      prev = end + 1;
808    }
809
810    return s + value.substr(prev, value.length - prev);
811  },
812      mapRange = function mapRange(inMin, inMax, outMin, outMax, value) {
813    var inRange = inMax - inMin,
814        outRange = outMax - outMin;
815    return _conditionalReturn(value, function (value) {
816      return outMin + ((value - inMin) / inRange * outRange || 0);
817    });
818  },
819      interpolate = function interpolate(start, end, progress, mutate) {
820    var func = isNaN(start + end) ? 0 : function (p) {
821      return (1 - p) * start + p * end;
822    };
823
824    if (!func) {
825      var isString = _isString(start),
826          master = {},
827          p,
828          i,
829          interpolators,
830          l,
831          il;
832
833      progress === true && (mutate = 1) && (progress = null);
834
835      if (isString) {
836        start = {
837          p: start
838        };
839        end = {
840          p: end
841        };
842      } else if (_isArray(start) && !_isArray(end)) {
843        interpolators = [];
844        l = start.length;
845        il = l - 2;
846
847        for (i = 1; i < l; i++) {
848          interpolators.push(interpolate(start[i - 1], start[i]));
849        }
850
851        l--;
852
853        func = function func(p) {
854          p *= l;
855          var i = Math.min(il, ~~p);
856          return interpolators[i](p - i);
857        };
858
859        progress = end;
860      } else if (!mutate) {
861        start = _merge(_isArray(start) ? [] : {}, start);
862      }
863
864      if (!interpolators) {
865        for (p in end) {
866          _addPropTween.call(master, start, p, "get", end[p]);
867        }
868
869        func = function func(p) {
870          return _renderPropTweens(p, master) || (isString ? start.p : start);
871        };
872      }
873    }
874
875    return _conditionalReturn(progress, func);
876  },
877      _getLabelInDirection = function _getLabelInDirection(timeline, fromTime, backward) {
878    var labels = timeline.labels,
879        min = _bigNum,
880        p,
881        distance,
882        label;
883
884    for (p in labels) {
885      distance = labels[p] - fromTime;
886
887      if (distance < 0 === !!backward && distance && min > (distance = Math.abs(distance))) {
888        label = p;
889        min = distance;
890      }
891    }
892
893    return label;
894  },
895      _callback = function _callback(animation, type, executeLazyFirst) {
896    var v = animation.vars,
897        callback = v[type],
898        params,
899        scope;
900
901    if (!callback) {
902      return;
903    }
904
905    params = v[type + "Params"];
906    scope = v.callbackScope || animation;
907    executeLazyFirst && _lazyTweens.length && _lazyRender();
908    return params ? callback.apply(scope, params) : callback.call(scope);
909  },
vendor: 7,655 bytes, lines 910-1195
910      _interrupt = function _interrupt(animation) {
911    _removeFromParent(animation);
912
913    animation.scrollTrigger && animation.scrollTrigger.kill(false);
914    animation.progress() < 1 && _callback(animation, "onInterrupt");
915    return animation;
916  },
917      _quickTween,
918      _createPlugin = function _createPlugin(config) {
919    config = !config.name && config["default"] || config;
920
921    var name = config.name,
922        isFunc = _isFunction(config),
923        Plugin = name && !isFunc && config.init ? function () {
924      this._props = [];
925    } : config,
926        instanceDefaults = {
927      init: _emptyFunc,
928      render: _renderPropTweens,
929      add: _addPropTween,
930      kill: _killPropTweensOf,
931      modifier: _addPluginModifier,
932      rawVars: 0
933    },
934        statics = {
935      targetTest: 0,
936      get: 0,
937      getSetter: _getSetter,
938      aliases: {},
939      register: 0
940    };
941
942    _wake();
943
944    if (config !== Plugin) {
945      if (_plugins[name]) {
946        return;
947      }
948
949      _setDefaults(Plugin, _setDefaults(_copyExcluding(config, instanceDefaults), statics));
950
951      _merge(Plugin.prototype, _merge(instanceDefaults, _copyExcluding(config, statics)));
952
953      _plugins[Plugin.prop = name] = Plugin;
954
955      if (config.targetTest) {
956        _harnessPlugins.push(Plugin);
957
958        _reservedProps[name] = 1;
959      }
960
961      name = (name === "css" ? "CSS" : name.charAt(0).toUpperCase() + name.substr(1)) + "Plugin";
962    }
963
964    _addGlobal(name, Plugin);
965
966    config.register && config.register(gsap, Plugin, PropTween);
967  },
968      _255 = 255,
969      _colorLookup = {
970    aqua: [0, _255, _255],
971    lime: [0, _255, 0],
972    silver: [192, 192, 192],
973    black: [0, 0, 0],
974    maroon: [128, 0, 0],
975    teal: [0, 128, 128],
976    blue: [0, 0, _255],
977    navy: [0, 0, 128],
978    white: [_255, _255, _255],
979    olive: [128, 128, 0],
980    yellow: [_255, _255, 0],
981    orange: [_255, 165, 0],
982    gray: [128, 128, 128],
983    purple: [128, 0, 128],
984    green: [0, 128, 0],
985    red: [_255, 0, 0],
986    pink: [_255, 192, 203],
987    cyan: [0, _255, _255],
988    transparent: [_255, _255, _255, 0]
989  },
990      _hue = function _hue(h, m1, m2) {
991    h = h < 0 ? h + 1 : h > 1 ? h - 1 : h;
992    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;
993  },
994      splitColor = function splitColor(v, toHSL, forceAlpha) {
995    var a = !v ? _colorLookup.black : _isNumber(v) ? [v >> 16, v >> 8 & _255, v & _255] : 0,
996        r,
997        g,
998        b,
999        h,
1000        s,
1001        l,
1002        max,
1003        min,
1004        d,
1005        wasHSL;
1006
1007    if (!a) {
1008      if (v.substr(-1) === ",") {
1009        v = v.substr(0, v.length - 1);
1010      }
1011
1012      if (_colorLookup[v]) {
1013        a = _colorLookup[v];
1014      } else if (v.charAt(0) === "#") {
1015        if (v.length < 6) {
1016          r = v.charAt(1);
1017          g = v.charAt(2);
1018          b = v.charAt(3);
1019          v = "#" + r + r + g + g + b + b + (v.length === 5 ? v.charAt(4) + v.charAt(4) : "");
1020        }
1021
1022        if (v.length === 9) {
1023          a = parseInt(v.substr(1, 6), 16);
1024          return [a >> 16, a >> 8 & _255, a & _255, parseInt(v.substr(7), 16) / 255];
1025        }
1026
1027        v = parseInt(v.substr(1), 16);
1028        a = [v >> 16, v >> 8 & _255, v & _255];
1029      } else if (v.substr(0, 3) === "hsl") {
1030        a = wasHSL = v.match(_strictNumExp);
1031
1032        if (!toHSL) {
1033          h = +a[0] % 360 / 360;
1034          s = +a[1] / 100;
1035          l = +a[2] / 100;
1036          g = l <= .5 ? l * (s + 1) : l + s - l * s;
1037          r = l * 2 - g;
1038          a.length > 3 && (a[3] *= 1);
1039          a[0] = _hue(h + 1 / 3, r, g);
1040          a[1] = _hue(h, r, g);
1041          a[2] = _hue(h - 1 / 3, r, g);
1042        } else if (~v.indexOf("=")) {
1043          a = v.match(_numExp);
1044          forceAlpha && a.length < 4 && (a[3] = 1);
1045          return a;
1046        }
1047      } else {
1048        a = v.match(_strictNumExp) || _colorLookup.transparent;
1049      }
1050
1051      a = a.map(Number);
1052    }
1053
1054    if (toHSL && !wasHSL) {
1055      r = a[0] / _255;
1056      g = a[1] / _255;
1057      b = a[2] / _255;
1058      max = Math.max(r, g, b);
1059      min = Math.min(r, g, b);
1060      l = (max + min) / 2;
1061
1062      if (max === min) {
1063        h = s = 0;
1064      } else {
1065        d = max - min;
1066        s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
1067        h = max === r ? (g - b) / d + (g < b ? 6 : 0) : max === g ? (b - r) / d + 2 : (r - g) / d + 4;
1068        h *= 60;
1069      }
1070
1071      a[0] = ~~(h + .5);
1072      a[1] = ~~(s * 100 + .5);
1073      a[2] = ~~(l * 100 + .5);
1074    }
1075
1076    forceAlpha && a.length < 4 && (a[3] = 1);
1077    return a;
1078  },
1079      _colorOrderData = function _colorOrderData(v) {
1080    var values = [],
1081        c = [],
1082        i = -1;
1083    v.split(_colorExp).forEach(function (v) {
1084      var a = v.match(_numWithUnitExp) || [];
1085      values.push.apply(values, a);
1086      c.push(i += a.length + 1);
1087    });
1088    values.c = c;
1089    return values;
1090  },
1091      _formatColors = function _formatColors(s, toHSL, orderMatchData) {
1092    var result = "",
1093        colors = (s + result).match(_colorExp),
1094        type = toHSL ? "hsla(" : "rgba(",
1095        i = 0,
1096        c,
1097        shell,
1098        d,
1099        l;
1100
1101    if (!colors) {
1102      return s;
1103    }
1104
1105    colors = colors.map(function (color) {
1106      return (color = splitColor(color, toHSL, 1)) && type + (toHSL ? color[0] + "," + color[1] + "%," + color[2] + "%," + color[3] : color.join(",")) + ")";
1107    });
1108
1109    if (orderMatchData) {
1110      d = _colorOrderData(s);
1111      c = orderMatchData.c;
1112
1113      if (c.join(result) !== d.c.join(result)) {
1114        shell = s.replace(_colorExp, "1").split(_numWithUnitExp);
1115        l = shell.length - 1;
1116
1117        for (; i < l; i++) {
1118          result += shell[i] + (~c.indexOf(i) ? colors.shift() || type + "0,0,0,0)" : (d.length ? d : colors.length ? colors : orderMatchData).shift());
1119        }
1120      }
1121    }
1122
1123    if (!shell) {
1124      shell = s.split(_colorExp);
1125      l = shell.length - 1;
1126
1127      for (; i < l; i++) {
1128        result += shell[i] + colors[i];
1129      }
1130    }
1131
1132    return result + shell[l];
1133  },
1134      _colorExp = function () {
1135    var s = "(?:\\b(?:(?:rgb|rgba|hsl|hsla)\\(.+?\\))|\\B#(?:[0-9a-f]{3,4}){1,2}\\b",
1136        p;
1137
1138    for (p in _colorLookup) {
1139      s += "|" + p + "\\b";
1140    }
1141
1142    return new RegExp(s + ")", "gi");
1143  }(),
1144      _hslExp = /hsl[a]?\(/,
1145      _colorStringFilter = function _colorStringFilter(a) {
1146    var combined = a.join(" "),
1147        toHSL;
1148    _colorExp.lastIndex = 0;
1149
1150    if (_colorExp.test(combined)) {
1151      toHSL = _hslExp.test(combined);
1152      a[1] = _formatColors(a[1], toHSL);
1153      a[0] = _formatColors(a[0], toHSL, _colorOrderData(a[1]));
1154      return true;
1155    }
1156  },
1157      _tickerActive,
1158      _ticker = function () {
1159    var _getTime = Date.now,
1160        _lagThreshold = 500,
1161        _adjustedLag = 33,
1162        _startTime = _getTime(),
1163        _lastUpdate = _startTime,
1164        _gap = 1000 / 240,
1165        _nextTime = _gap,
1166        _listeners = [],
1167        _id,
1168        _req,
1169        _raf,
1170        _self,
1171        _delta,
1172        _i,
1173        _tick = function _tick(v) {
1174      var elapsed = _getTime() - _lastUpdate,
1175          manual = v === true,
1176          overlap,
1177          dispatch,
1178          time,
1179          frame;
1180
1181      elapsed > _lagThreshold && (_startTime += elapsed - _adjustedLag);
1182      _lastUpdate += elapsed;
1183      time = _lastUpdate - _startTime;
1184      overlap = time - _nextTime;
1185
1186      if (overlap > 0 || manual) {
1187        frame = ++_self.frame;
1188        _delta = time - _self.time * 1000;
1189        _self.time = time = time / 1000;
1190        _nextTime += overlap + (overlap >= _gap ? 4 : _gap - overlap);
1191        dispatch = 1;
1192      }
1193
1194      manual || (_id = _req(_tick));
1195
vendor: 4,054 bytes, lines 1196-1323
1196      if (dispatch) {
1197        for (_i = 0; _i < _listeners.length; _i++) {
1198          _listeners[_i](time, _delta, frame, v);
1199        }
1200      }
1201    };
1202
1203    _self = {
1204      time: 0,
1205      frame: 0,
1206      tick: function tick() {
1207        _tick(true);
1208      },
1209      deltaRatio: function deltaRatio(fps) {
1210        return _delta / (1000 / (fps || 60));
1211      },
1212      wake: function wake() {
1213        if (_coreReady) {
1214          if (!_coreInitted && _windowExists()) {
1215            _win = _coreInitted = window;
1216            _doc = _win.document || {};
1217            _globals.gsap = gsap;
1218            (_win.gsapVersions || (_win.gsapVersions = [])).push(gsap.version);
1219
1220            _install(_installScope || _win.GreenSockGlobals || !_win.gsap && _win || {});
1221
1222            _raf = _win.requestAnimationFrame;
1223          }
1224
1225          _id && _self.sleep();
1226
1227          _req = _raf || function (f) {
1228            return setTimeout(f, _nextTime - _self.time * 1000 + 1 | 0);
1229          };
1230
1231          _tickerActive = 1;
1232
1233          _tick(2);
1234        }
1235      },
1236      sleep: function sleep() {
1237        (_raf ? _win.cancelAnimationFrame : clearTimeout)(_id);
1238        _tickerActive = 0;
1239        _req = _emptyFunc;
1240      },
1241      lagSmoothing: function lagSmoothing(threshold, adjustedLag) {
1242        _lagThreshold = threshold || 1 / _tinyNum;
1243        _adjustedLag = Math.min(adjustedLag, _lagThreshold, 0);
1244      },
1245      fps: function fps(_fps) {
1246        _gap = 1000 / (_fps || 240);
1247        _nextTime = _self.time * 1000 + _gap;
1248      },
1249      add: function add(callback) {
1250        _listeners.indexOf(callback) < 0 && _listeners.push(callback);
1251
1252        _wake();
1253      },
1254      remove: function remove(callback) {
1255        var i;
1256        ~(i = _listeners.indexOf(callback)) && _listeners.splice(i, 1) && _i >= i && _i--;
1257      },
1258      _listeners: _listeners
1259    };
1260    return _self;
1261  }(),
1262      _wake = function _wake() {
1263    return !_tickerActive && _ticker.wake();
1264  },
1265      _easeMap = {},
1266      _customEaseExp = /^[\d.\-M][\d.\-,\s]/,
1267      _quotesExp = /["']/g,
1268      _parseObjectInString = function _parseObjectInString(value) {
1269    var obj = {},
1270        split = value.substr(1, value.length - 3).split(":"),
1271        key = split[0],
1272        i = 1,
1273        l = split.length,
1274        index,
1275        val,
1276        parsedVal;
1277
1278    for (; i < l; i++) {
1279      val = split[i];
1280      index = i !== l - 1 ? val.lastIndexOf(",") : val.length;
1281      parsedVal = val.substr(0, index);
1282      obj[key] = isNaN(parsedVal) ? parsedVal.replace(_quotesExp, "").trim() : +parsedVal;
1283      key = val.substr(index + 1).trim();
1284    }
1285
1286    return obj;
1287  },
1288      _valueInParentheses = function _valueInParentheses(value) {
1289    var open = value.indexOf("(") + 1,
1290        close = value.indexOf(")"),
1291        nested = value.indexOf("(", open);
1292    return value.substring(open, ~nested && nested < close ? value.indexOf(")", close + 1) : close);
1293  },
1294      _configEaseFromString = function _configEaseFromString(name) {
1295    var split = (name + "").split("("),
1296        ease = _easeMap[split[0]];
1297    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;
1298  },
1299      _invertEase = function _invertEase(ease) {
1300    return function (p) {
1301      return 1 - ease(1 - p);
1302    };
1303  },
1304      _propagateYoyoEase = function _propagateYoyoEase(timeline, isYoyo) {
1305    var child = timeline._first,
1306        ease;
1307
1308    while (child) {
1309      if (child instanceof Timeline) {
1310        _propagateYoyoEase(child, isYoyo);
1311      } else if (child.vars.yoyoEase && (!child._yoyo || !child._repeat) && child._yoyo !== isYoyo) {
1312        if (child.timeline) {
1313          _propagateYoyoEase(child.timeline, isYoyo);
1314        } else {
1315          ease = child._ease;
1316          child._ease = child._yEase;
1317          child._yEase = ease;
1318          child._yoyo = isYoyo;
1319        }
1320      }
1321
1322      child = child._next;
1323    }
vendor: 3,445 bytes, lines 1323-1434
1323
1324  },
1325      _parseEase = function _parseEase(ease, defaultEase) {
1326    return !ease ? defaultEase : (_isFunction(ease) ? ease : _easeMap[ease] || _configEaseFromString(ease)) || defaultEase;
1327  },
1328      _insertEase = function _insertEase(names, easeIn, easeOut, easeInOut) {
1329    if (easeOut === void 0) {
1330      easeOut = function easeOut(p) {
1331        return 1 - easeIn(1 - p);
1332      };
1333    }
1334
1335    if (easeInOut === void 0) {
1336      easeInOut = function easeInOut(p) {
1337        return p < .5 ? easeIn(p * 2) / 2 : 1 - easeIn((1 - p) * 2) / 2;
1338      };
1339    }
1340
1341    var ease = {
1342      easeIn: easeIn,
1343      easeOut: easeOut,
1344      easeInOut: easeInOut
1345    },
1346        lowercaseName;
1347
1348    _forEachName(names, function (name) {
1349      _easeMap[name] = _globals[name] = ease;
1350      _easeMap[lowercaseName = name.toLowerCase()] = easeOut;
1351
1352      for (var p in ease) {
1353        _easeMap[lowercaseName + (p === "easeIn" ? ".in" : p === "easeOut" ? ".out" : ".inOut")] = _easeMap[name + "." + p] = ease[p];
1354      }
1355    });
1356
1357    return ease;
1358  },
1359      _easeInOutFromOut = function _easeInOutFromOut(easeOut) {
1360    return function (p) {
1361      return p < .5 ? (1 - easeOut(1 - p * 2)) / 2 : .5 + easeOut((p - .5) * 2) / 2;
1362    };
1363  },
1364      _configElastic = function _configElastic(type, amplitude, period) {
1365    var p1 = amplitude >= 1 ? amplitude : 1,
1366        p2 = (period || (type ? .3 : .45)) / (amplitude < 1 ? amplitude : 1),
1367        p3 = p2 / _2PI * (Math.asin(1 / p1) || 0),
1368        easeOut = function easeOut(p) {
1369      return p === 1 ? 1 : p1 * Math.pow(2, -10 * p) * _sin((p - p3) * p2) + 1;
1370    },
1371        ease = type === "out" ? easeOut : type === "in" ? function (p) {
1372      return 1 - easeOut(1 - p);
1373    } : _easeInOutFromOut(easeOut);
1374
1375    p2 = _2PI / p2;
1376
1377    ease.config = function (amplitude, period) {
1378      return _configElastic(type, amplitude, period);
1379    };
1380
1381    return ease;
1382  },
1383      _configBack = function _configBack(type, overshoot) {
1384    if (overshoot === void 0) {
1385      overshoot = 1.70158;
1386    }
1387
1388    var easeOut = function easeOut(p) {
1389      return p ? --p * p * ((overshoot + 1) * p + overshoot) + 1 : 0;
1390    },
1391        ease = type === "out" ? easeOut : type === "in" ? function (p) {
1392      return 1 - easeOut(1 - p);
1393    } : _easeInOutFromOut(easeOut);
1394
1395    ease.config = function (overshoot) {
1396      return _configBack(type, overshoot);
1397    };
1398
1399    return ease;
1400  };
1401
1402  _forEachName("Linear,Quad,Cubic,Quart,Quint,Strong", function (name, i) {
1403    var power = i < 5 ? i + 1 : i;
1404
1405    _insertEase(name + ",Power" + (power - 1), i ? function (p) {
1406      return Math.pow(p, power);
1407    } : function (p) {
1408      return p;
1409    }, function (p) {
1410      return 1 - Math.pow(1 - p, power);
1411    }, function (p) {
1412      return p < .5 ? Math.pow(p * 2, power) / 2 : 1 - Math.pow((1 - p) * 2, power) / 2;
1413    });
1414  });
1415
1416  _easeMap.Linear.easeNone = _easeMap.none = _easeMap.Linear.easeIn;
1417
1418  _insertEase("Elastic", _configElastic("in"), _configElastic("out"), _configElastic());
1419
1420  (function (n, c) {
1421    var n1 = 1 / c,
1422        n2 = 2 * n1,
1423        n3 = 2.5 * n1,
1424        easeOut = function easeOut(p) {
1425      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;
1426    };
1427
1428    _insertEase("Bounce", function (p) {
1429      return 1 - easeOut(1 - p);
1430    }, easeOut);
1431  })(7.5625, 2.75);
1432
1433  _insertEase("Expo", function (p) {
1434    return 
vendor: 6,382 bytes, lines 1434-1617
1434p ? Math.pow(2, 10 * (p - 1)) : 0;
1435  });
1436
1437  _insertEase("Circ", function (p) {
1438    return -(_sqrt(1 - p * p) - 1);
1439  });
1440
1441  _insertEase("Sine", function (p) {
1442    return p === 1 ? 1 : -_cos(p * _HALF_PI) + 1;
1443  });
1444
1445  _insertEase("Back", _configBack("in"), _configBack("out"), _configBack());
1446
1447  _easeMap.SteppedEase = _easeMap.steps = _globals.SteppedEase = {
1448    config: function config(steps, immediateStart) {
1449      if (steps === void 0) {
1450        steps = 1;
1451      }
1452
1453      var p1 = 1 / steps,
1454          p2 = steps + (immediateStart ? 0 : 1),
1455          p3 = immediateStart ? 1 : 0,
1456          max = 1 - _tinyNum;
1457      return function (p) {
1458        return ((p2 * _clamp(0, max, p) | 0) + p3) * p1;
1459      };
1460    }
1461  };
1462  _defaults.ease = _easeMap["quad.out"];
1463
1464  _forEachName("onComplete,onUpdate,onStart,onRepeat,onReverseComplete,onInterrupt", function (name) {
1465    return _callbackNames += name + "," + name + "Params,";
1466  });
1467
1468  var GSCache = function GSCache(target, harness) {
1469    this.id = _gsID++;
1470    target._gsap = this;
1471    this.target = target;
1472    this.harness = harness;
1473    this.get = harness ? harness.get : _getProperty;
1474    this.set = harness ? harness.getSetter : _getSetter;
1475  };
1476  var Animation = function () {
1477    function Animation(vars, time) {
1478      var parent = vars.parent || _globalTimeline;
1479      this.vars = vars;
1480      this._delay = +vars.delay || 0;
1481
1482      if (this._repeat = vars.repeat === Infinity ? -2 : vars.repeat || 0) {
1483        this._rDelay = vars.repeatDelay || 0;
1484        this._yoyo = !!vars.yoyo || !!vars.yoyoEase;
1485      }
1486
1487      this._ts = 1;
1488
1489      _setDuration(this, +vars.duration, 1, 1);
1490
1491      this.data = vars.data;
1492      _tickerActive || _ticker.wake();
1493      parent && _addToTimeline(parent, this, time || time === 0 ? time : parent._time, 1);
1494      vars.reversed && this.reverse();
1495      vars.paused && this.paused(true);
1496    }
1497
1498    var _proto = Animation.prototype;
1499
1500    _proto.delay = function delay(value) {
1501      if (value || value === 0) {
1502        this.parent && this.parent.smoothChildTiming && this.startTime(this._start + value - this._delay);
1503        this._delay = value;
1504        return this;
1505      }
1506
1507      return this._delay;
1508    };
1509
1510    _proto.duration = function duration(value) {
1511      return arguments.length ? this.totalDuration(this._repeat > 0 ? value + (value + this._rDelay) * this._repeat : value) : this.totalDuration() && this._dur;
1512    };
1513
1514    _proto.totalDuration = function totalDuration(value) {
1515      if (!arguments.length) {
1516        return this._tDur;
1517      }
1518
1519      this._dirty = 0;
1520      return _setDuration(this, this._repeat < 0 ? value : (value - this._repeat * this._rDelay) / (this._repeat + 1));
1521    };
1522
1523    _proto.totalTime = function totalTime(_totalTime, suppressEvents) {
1524      _wake();
1525
1526      if (!arguments.length) {
1527        return this._tTime;
1528      }
1529
1530      var parent = this._dp;
1531
1532      if (parent && parent.smoothChildTiming && this._ts) {
1533        _alignPlayhead(this, _totalTime);
1534
1535        !parent._dp || parent.parent || _postAddChecks(parent, this);
1536
1537        while (parent.parent) {
1538          if (parent.parent._time !== parent._start + (parent._ts >= 0 ? parent._tTime / parent._ts : (parent.totalDuration() - parent._tTime) / -parent._ts)) {
1539            parent.totalTime(parent._tTime, true);
1540          }
1541
1542          parent = parent.parent;
1543        }
1544
1545        if (!this.parent && this._dp.autoRemoveChildren && (this._ts > 0 && _totalTime < this._tDur || this._ts < 0 && _totalTime > 0 || !this._tDur && !_totalTime)) {
1546          _addToTimeline(this._dp, this, this._start - this._delay);
1547        }
1548      }
1549
1550      if (this._tTime !== _totalTime || !this._dur && !suppressEvents || this._initted && Math.abs(this._zTime) === _tinyNum || !_totalTime && !this._initted && (this.add || this._ptLookup)) {
1551        this._ts || (this._pTime = _totalTime);
1552
1553        _lazySafeRender(this, _totalTime, suppressEvents);
1554      }
1555
1556      return this;
1557    };
1558
1559    _proto.time = function time(value, suppressEvents) {
1560      return arguments.length ? this.totalTime(Math.min(this.totalDuration(), value + _elapsedCycleDuration(this)) % this._dur || (value ? this._dur : 0), suppressEvents) : this._time;
1561    };
1562
1563    _proto.totalProgress = function totalProgress(value, suppressEvents) {
1564      return arguments.length ? this.totalTime(this.totalDuration() * value, suppressEvents) : this.totalDuration() ? Math.min(1, this._tTime / this._tDur) : this.ratio;
1565    };
1566
1567    _proto.progress = function progress(value, suppressEvents) {
1568      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.ratio;
1569    };
1570
1571    _proto.iteration = function iteration(value, suppressEvents) {
1572      var cycleDuration = this.duration() + this._rDelay;
1573
1574      return arguments.length ? this.totalTime(this._time + (value - 1) * cycleDuration, suppressEvents) : this._repeat ? _animationCycle(this._tTime, cycleDuration) + 1 : 1;
1575    };
1576
1577    _proto.timeScale = function timeScale(value) {
1578      if (!arguments.length) {
1579        return this._rts === -_tinyNum ? 0 : this._rts;
1580      }
1581
1582      if (this._rts === value) {
1583        return this;
1584      }
1585
1586      var tTime = this.parent && this._ts ? _parentToChildTotalTime(this.parent._time, this) : this._tTime;
1587      this._rts = +value || 0;
1588      this._ts = this._ps || value === -_tinyNum ? 0 : this._rts;
1589      return _recacheAncestors(this.totalTime(_clamp(-this._delay, this._tDur, tTime), true));
1590    };
1591
1592    _proto.paused = function paused(value) {
1593      if (!arguments.length) {
1594        return this._ps;
1595      }
1596
1597      if (this._ps !== value) {
1598        this._ps = value;
1599
1600        if (value) {
1601          this._pTime = this._tTime || Math.max(-this._delay, this.rawTime());
1602          this._ts = this._act = 0;
1603        } else {
1604          _wake();
1605
1606          this._ts = this._rts;
1607          this.totalTime(this.parent && !this.parent.smoothChildTiming ? this.rawTime() : this._tTime || this._pTime, this.progress() === 1 && (this._tTime -= _tinyNum) && Math.abs(this._zTime) !== _tinyNum);
1608        }
1609      }
1610
1611      return this;
1612    };
1613
1614    _proto.startTime = function startTime(value) {
1615      if (arguments.length) {
1616        this._start = value;
1617        var parent = this.parent || this._dp;
vendor: 2,817 bytes, lines 1618-1708
1618        parent && (parent._sort || !this.parent) && _addToTimeline(parent, this, value - this._delay);
1619        return this;
1620      }
1621
1622      return this._start;
1623    };
1624
1625    _proto.endTime = function endTime(includeRepeats) {
1626      return this._start + (_isNotFalse(includeRepeats) ? this.totalDuration() : this.duration()) / Math.abs(this._ts);
1627    };
1628
1629    _proto.rawTime = function rawTime(wrapRepeats) {
1630      var parent = this.parent || this._dp;
1631      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);
1632    };
1633
1634    _proto.globalTime = function globalTime(rawTime) {
1635      var animation = this,
1636          time = arguments.length ? rawTime : animation.rawTime();
1637
1638      while (animation) {
1639        time = animation._start + time / (animation._ts || 1);
1640        animation = animation._dp;
1641      }
1642
1643      return time;
1644    };
1645
1646    _proto.repeat = function repeat(value) {
1647      if (arguments.length) {
1648        this._repeat = value === Infinity ? -2 : value;
1649        return _onUpdateTotalDuration(this);
1650      }
1651
1652      return this._repeat === -2 ? Infinity : this._repeat;
1653    };
1654
1655    _proto.repeatDelay = function repeatDelay(value) {
1656      if (arguments.length) {
1657        this._rDelay = value;
1658        return _onUpdateTotalDuration(this);
1659      }
1660
1661      return this._rDelay;
1662    };
1663
1664    _proto.yoyo = function yoyo(value) {
1665      if (arguments.length) {
1666        this._yoyo = value;
1667        return this;
1668      }
1669
1670      return this._yoyo;
1671    };
1672
1673    _proto.seek = function seek(position, suppressEvents) {
1674      return this.totalTime(_parsePosition(this, position), _isNotFalse(suppressEvents));
1675    };
1676
1677    _proto.restart = function restart(includeDelay, suppressEvents) {
1678      return this.play().totalTime(includeDelay ? -this._delay : 0, _isNotFalse(suppressEvents));
1679    };
1680
1681    _proto.play = function play(from, suppressEvents) {
1682      from != null && this.seek(from, suppressEvents);
1683      return this.reversed(false).paused(false);
1684    };
1685
1686    _proto.reverse = function reverse(from, suppressEvents) {
1687      from != null && this.seek(from || this.totalDuration(), suppressEvents);
1688      return this.reversed(true).paused(false);
1689    };
1690
1691    _proto.pause = function pause(atTime, suppressEvents) {
1692      atTime != null && this.seek(atTime, suppressEvents);
1693      return this.paused(true);
1694    };
1695
1696    _proto.resume = function resume() {
1697      return this.paused(false);
1698    };
1699
1700    _proto.reversed = function reversed(value) {
1701      if (arguments.length) {
1702        !!value !== this.reversed() && this.timeScale(-this._rts || (value ? -_tinyNum : 0));
1703        return this;
1704      }
1705
1706      return this._rts < 0;
1707    };
1708
vendor: 8,594 bytes, lines 1709-1972
1709    _proto.invalidate = function invalidate() {
1710      this._initted = this._act = 0;
1711      this._zTime = -_tinyNum;
1712      return this;
1713    };
1714
1715    _proto.isActive = function isActive() {
1716      var parent = this.parent || this._dp,
1717          start = this._start,
1718          rawTime;
1719      return !!(!parent || this._ts && this._initted && parent.isActive() && (rawTime = parent.rawTime(true)) >= start && rawTime < this.endTime(true) - _tinyNum);
1720    };
1721
1722    _proto.eventCallback = function eventCallback(type, callback, params) {
1723      var vars = this.vars;
1724
1725      if (arguments.length > 1) {
1726        if (!callback) {
1727          delete vars[type];
1728        } else {
1729          vars[type] = callback;
1730          params && (vars[type + "Params"] = params);
1731          type === "onUpdate" && (this._onUpdate = callback);
1732        }
1733
1734        return this;
1735      }
1736
1737      return vars[type];
1738    };
1739
1740    _proto.then = function then(onFulfilled) {
1741      var self = this;
1742      return new Promise(function (resolve) {
1743        var f = _isFunction(onFulfilled) ? onFulfilled : _passThrough,
1744            _resolve = function _resolve() {
1745          var _then = self.then;
1746          self.then = null;
1747          _isFunction(f) && (f = f(self)) && (f.then || f === self) && (self.then = _then);
1748          resolve(f);
1749          self.then = _then;
1750        };
1751
1752        if (self._initted && self.totalProgress() === 1 && self._ts >= 0 || !self._tTime && self._ts < 0) {
1753          _resolve();
1754        } else {
1755          self._prom = _resolve;
1756        }
1757      });
1758    };
1759
1760    _proto.kill = function kill() {
1761      _interrupt(this);
1762    };
1763
1764    return Animation;
1765  }();
1766
1767  _setDefaults(Animation.prototype, {
1768    _time: 0,
1769    _start: 0,
1770    _end: 0,
1771    _tTime: 0,
1772    _tDur: 0,
1773    _dirty: 0,
1774    _repeat: 0,
1775    _yoyo: false,
1776    parent: null,
1777    _initted: false,
1778    _rDelay: 0,
1779    _ts: 1,
1780    _dp: 0,
1781    ratio: 0,
1782    _zTime: -_tinyNum,
1783    _prom: 0,
1784    _ps: false,
1785    _rts: 1
1786  });
1787
1788  var Timeline = function (_Animation) {
1789    _inheritsLoose(Timeline, _Animation);
1790
1791    function Timeline(vars, time) {
1792      var _this;
1793
1794      if (vars === void 0) {
1795        vars = {};
1796      }
1797
1798      _this = _Animation.call(this, vars, time) || this;
1799      _this.labels = {};
1800      _this.smoothChildTiming = !!vars.smoothChildTiming;
1801      _this.autoRemoveChildren = !!vars.autoRemoveChildren;
1802      _this._sort = _isNotFalse(vars.sortChildren);
1803      _this.parent && _postAddChecks(_this.parent, _assertThisInitialized(_this));
1804      vars.scrollTrigger && _scrollTrigger(_assertThisInitialized(_this), vars.scrollTrigger);
1805      return _this;
1806    }
1807
1808    var _proto2 = Timeline.prototype;
1809
1810    _proto2.to = function to(targets, vars, position) {
1811      new Tween(targets, _parseVars(arguments, 0, this), _parsePosition(this, _isNumber(vars) ? arguments[3] : position));
1812      return this;
1813    };
1814
1815    _proto2.from = function from(targets, vars, position) {
1816      new Tween(targets, _parseVars(arguments, 1, this), _parsePosition(this, _isNumber(vars) ? arguments[3] : position));
1817      return this;
1818    };
1819
1820    _proto2.fromTo = function fromTo(targets, fromVars, toVars, position) {
1821      new Tween(targets, _parseVars(arguments, 2, this), _parsePosition(this, _isNumber(fromVars) ? arguments[4] : position));
1822      return this;
1823    };
1824
1825    _proto2.set = function set(targets, vars, position) {
1826      vars.duration = 0;
1827      vars.parent = this;
1828      _inheritDefaults(vars).repeatDelay || (vars.repeat = 0);
1829      vars.immediateRender = !!vars.immediateRender;
1830      new Tween(targets, vars, _parsePosition(this, position), 1);
1831      return this;
1832    };
1833
1834    _proto2.call = function call(callback, params, position) {
1835      return _addToTimeline(this, Tween.delayedCall(0, callback, params), _parsePosition(this, position));
1836    };
1837
1838    _proto2.staggerTo = function staggerTo(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams) {
1839      vars.duration = duration;
1840      vars.stagger = vars.stagger || stagger;
1841      vars.onComplete = onCompleteAll;
1842      vars.onCompleteParams = onCompleteAllParams;
1843      vars.parent = this;
1844      new Tween(targets, vars, _parsePosition(this, position));
1845      return this;
1846    };
1847
1848    _proto2.staggerFrom = function staggerFrom(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams) {
1849      vars.runBackwards = 1;
1850      _inheritDefaults(vars).immediateRender = _isNotFalse(vars.immediateRender);
1851      return this.staggerTo(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams);
1852    };
1853
1854    _proto2.staggerFromTo = function staggerFromTo(targets, duration, fromVars, toVars, stagger, position, onCompleteAll, onCompleteAllParams) {
1855      toVars.startAt = fromVars;
1856      _inheritDefaults(toVars).immediateRender = _isNotFalse(toVars.immediateRender);
1857      return this.staggerTo(targets, duration, toVars, stagger, position, onCompleteAll, onCompleteAllParams);
1858    };
1859
1860    _proto2.render = function render(totalTime, suppressEvents, force) {
1861      var prevTime = this._time,
1862          tDur = this._dirty ? this.totalDuration() : this._tDur,
1863          dur = this._dur,
1864          tTime = this !== _globalTimeline && totalTime > tDur - _tinyNum && totalTime >= 0 ? tDur : totalTime < _tinyNum ? 0 : totalTime,
1865          crossingStart = this._zTime < 0 !== totalTime < 0 && (this._initted || !dur),
1866          time,
1867          child,
1868          next,
1869          iteration,
1870          cycleDuration,
1871          prevPaused,
1872          pauseTween,
1873          timeScale,
1874          prevStart,
1875          prevIteration,
1876          yoyo,
1877          isYoyo;
1878
1879      if (tTime !== this._tTime || force || crossingStart) {
1880        if (prevTime !== this._time && dur) {
1881          tTime += this._time - prevTime;
1882          totalTime += this._time - prevTime;
1883        }
1884
1885        time = tTime;
1886        prevStart = this._start;
1887        timeScale = this._ts;
1888        prevPaused = !timeScale;
1889
1890        if (crossingStart) {
1891          dur || (prevTime = this._zTime);
1892          (totalTime || !suppressEvents) && (this._zTime = totalTime);
1893        }
1894
1895        if (this._repeat) {
1896          yoyo = this._yoyo;
1897          cycleDuration = dur + this._rDelay;
1898
1899          if (this._repeat < -1 && totalTime < 0) {
1900            return this.totalTime(cycleDuration * 100 + totalTime, suppressEvents, force);
1901          }
1902
1903          time = _round(tTime % cycleDuration);
1904
1905          if (tTime === tDur) {
1906            iteration = this._repeat;
1907            time = dur;
1908          } else {
1909            iteration = ~~(tTime / cycleDuration);
1910
1911            if (iteration && iteration === tTime / cycleDuration) {
1912              time = dur;
1913              iteration--;
1914            }
1915
1916            time > dur && (time = dur);
1917          }
1918
1919          prevIteration = _animationCycle(this._tTime, cycleDuration);
1920          !prevTime && this._tTime && prevIteration !== iteration && (prevIteration = iteration);
1921
1922          if (yoyo && iteration & 1) {
1923            time = dur - time;
1924            isYoyo = 1;
1925          }
1926
1927          if (iteration !== prevIteration && !this._lock) {
1928            var rewinding = yoyo && prevIteration & 1,
1929                doesWrap = rewinding === (yoyo && iteration & 1);
1930            iteration < prevIteration && (rewinding = !rewinding);
1931            prevTime = rewinding ? 0 : dur;
1932            this._lock = 1;
1933            this.render(prevTime || (isYoyo ? 0 : _round(iteration * cycleDuration)), suppressEvents, !dur)._lock = 0;
1934            !suppressEvents && this.parent && _callback(this, "onRepeat");
1935            this.vars.repeatRefresh && !isYoyo && (this.invalidate()._lock = 1);
1936
1937            if (prevTime && prevTime !== this._time || prevPaused !== !this._ts || this.vars.onRepeat && !this.parent && !this._act) {
1938              return this;
1939            }
1940
1941            dur = this._dur;
1942            tDur = this._tDur;
1943
1944            if (doesWrap) {
1945              this._lock = 2;
1946              prevTime = rewinding ? dur : -0.0001;
1947              this.render(prevTime, true);
1948            }
1949
1950            this._lock = 0;
1951
1952            if (!this._ts && !prevPaused) {
1953              return this;
1954            }
1955
1956            _propagateYoyoEase(this, isYoyo);
1957          }
1958        }
1959
1960        if (this._hasPause && !this._forcing && this._lock < 2) {
1961          pauseTween = _findNextPauseTween(this, _round(prevTime), _round(time));
1962
1963          if (pauseTween) {
1964            tTime -= time - (time = pauseTween._start);
1965          }
1966        }
1967
1968        this._tTime = tTime;
1969        this._time = time;
1970        this._act = !timeScale;
1971
1972        if (!this._initted) {
vendor: 14,850 bytes, lines 1973-2493
1973          this._onUpdate = this.vars.onUpdate;
1974          this._initted = 1;
1975          this._zTime = totalTime;
1976          prevTime = 0;
1977        }
1978
1979        !prevTime && time && !suppressEvents && _callback(this, "onStart");
1980
1981        if (time >= prevTime && totalTime >= 0) {
1982          child = this._first;
1983
1984          while (child) {
1985            next = child._next;
1986
1987            if ((child._act || time >= child._start) && child._ts && pauseTween !== child) {
1988              if (child.parent !== this) {
1989                return this.render(totalTime, suppressEvents, force);
1990              }
1991
1992              child.render(child._ts > 0 ? (time - child._start) * child._ts : (child._dirty ? child.totalDuration() : child._tDur) + (time - child._start) * child._ts, suppressEvents, force);
1993
1994              if (time !== this._time || !this._ts && !prevPaused) {
1995                pauseTween = 0;
1996                next && (tTime += this._zTime = -_tinyNum);
1997                break;
1998              }
1999            }
2000
2001            child = next;
2002          }
2003        } else {
2004          child = this._last;
2005          var adjustedTime = totalTime < 0 ? totalTime : time;
2006
2007          while (child) {
2008            next = child._prev;
2009
2010            if ((child._act || adjustedTime <= child._end) && child._ts && pauseTween !== child) {
2011              if (child.parent !== this) {
2012                return this.render(totalTime, suppressEvents, force);
2013              }
2014
2015              child.render(child._ts > 0 ? (adjustedTime - child._start) * child._ts : (child._dirty ? child.totalDuration() : child._tDur) + (adjustedTime - child._start) * child._ts, suppressEvents, force);
2016
2017              if (time !== this._time || !this._ts && !prevPaused) {
2018                pauseTween = 0;
2019                next && (tTime += this._zTime = adjustedTime ? -_tinyNum : _tinyNum);
2020                break;
2021              }
2022            }
2023
2024            child = next;
2025          }
2026        }
2027
2028        if (pauseTween && !suppressEvents) {
2029          this.pause();
2030          pauseTween.render(time >= prevTime ? 0 : -_tinyNum)._zTime = time >= prevTime ? 1 : -1;
2031
2032          if (this._ts) {
2033            this._start = prevStart;
2034
2035            _setEnd(this);
2036
2037            return this.render(totalTime, suppressEvents, force);
2038          }
2039        }
2040
2041        this._onUpdate && !suppressEvents && _callback(this, "onUpdate", true);
2042        if (tTime === tDur && tDur >= this.totalDuration() || !tTime && prevTime) if (prevStart === this._start || Math.abs(timeScale) !== Math.abs(this._ts)) if (!this._lock) {
2043          (totalTime || !dur) && (tTime === tDur && this._ts > 0 || !tTime && this._ts < 0) && _removeFromParent(this, 1);
2044
2045          if (!suppressEvents && !(totalTime < 0 && !prevTime) && (tTime || prevTime)) {
2046            _callback(this, tTime === tDur ? "onComplete" : "onReverseComplete", true);
2047
2048            this._prom && !(tTime < tDur && this.timeScale() > 0) && this._prom();
2049          }
2050        }
2051      }
2052
2053      return this;
2054    };
2055
2056    _proto2.add = function add(child, position) {
2057      var _this2 = this;
2058
2059      _isNumber(position) || (position = _parsePosition(this, position));
2060
2061      if (!(child instanceof Animation)) {
2062        if (_isArray(child)) {
2063          child.forEach(function (obj) {
2064            return _this2.add(obj, position);
2065          });
2066          return this;
2067        }
2068
2069        if (_isString(child)) {
2070          return this.addLabel(child, position);
2071        }
2072
2073        if (_isFunction(child)) {
2074          child = Tween.delayedCall(0, child);
2075        } else {
2076          return this;
2077        }
2078      }
2079
2080      return this !== child ? _addToTimeline(this, child, position) : this;
2081    };
2082
2083    _proto2.getChildren = function getChildren(nested, tweens, timelines, ignoreBeforeTime) {
2084      if (nested === void 0) {
2085        nested = true;
2086      }
2087
2088      if (tweens === void 0) {
2089        tweens = true;
2090      }
2091
2092      if (timelines === void 0) {
2093        timelines = true;
2094      }
2095
2096      if (ignoreBeforeTime === void 0) {
2097        ignoreBeforeTime = -_bigNum;
2098      }
2099
2100      var a = [],
2101          child = this._first;
2102
2103      while (child) {
2104        if (child._start >= ignoreBeforeTime) {
2105          if (child instanceof Tween) {
2106            tweens && a.push(child);
2107          } else {
2108            timelines && a.push(child);
2109            nested && a.push.apply(a, child.getChildren(true, tweens, timelines));
2110          }
2111        }
2112
2113        child = child._next;
2114      }
2115
2116      return a;
2117    };
2118
2119    _proto2.getById = function getById(id) {
2120      var animations = this.getChildren(1, 1, 1),
2121          i = animations.length;
2122
2123      while (i--) {
2124        if (animations[i].vars.id === id) {
2125          return animations[i];
2126        }
2127      }
2128    };
2129
2130    _proto2.remove = function remove(child) {
2131      if (_isString(child)) {
2132        return this.removeLabel(child);
2133      }
2134
2135      if (_isFunction(child)) {
2136        return this.killTweensOf(child);
2137      }
2138
2139      _removeLinkedListItem(this, child);
2140
2141      if (child === this._recent) {
2142        this._recent = this._last;
2143      }
2144
2145      return _uncache(this);
2146    };
2147
2148    _proto2.totalTime = function totalTime(_totalTime2, suppressEvents) {
2149      if (!arguments.length) {
2150        return this._tTime;
2151      }
2152
2153      this._forcing = 1;
2154
2155      if (!this._dp && this._ts) {
2156        this._start = _round(_ticker.time - (this._ts > 0 ? _totalTime2 / this._ts : (this.totalDuration() - _totalTime2) / -this._ts));
2157      }
2158
2159      _Animation.prototype.totalTime.call(this, _totalTime2, suppressEvents);
2160
2161      this._forcing = 0;
2162      return this;
2163    };
2164
2165    _proto2.addLabel = function addLabel(label, position) {
2166      this.labels[label] = _parsePosition(this, position);
2167      return this;
2168    };
2169
2170    _proto2.removeLabel = function removeLabel(label) {
2171      delete this.labels[label];
2172      return this;
2173    };
2174
2175    _proto2.addPause = function addPause(position, callback, params) {
2176      var t = Tween.delayedCall(0, callback || _emptyFunc, params);
2177      t.data = "isPause";
2178      this._hasPause = 1;
2179      return _addToTimeline(this, t, _parsePosition(this, position));
2180    };
2181
2182    _proto2.removePause = function removePause(position) {
2183      var child = this._first;
2184      position = _parsePosition(this, position);
2185
2186      while (child) {
2187        if (child._start === position && child.data === "isPause") {
2188          _removeFromParent(child);
2189        }
2190
2191        child = child._next;
2192      }
2193    };
2194
2195    _proto2.killTweensOf = function killTweensOf(targets, props, onlyActive) {
2196      var tweens = this.getTweensOf(targets, onlyActive),
2197          i = tweens.length;
2198
2199      while (i--) {
2200        _overwritingTween !== tweens[i] && tweens[i].kill(targets, props);
2201      }
2202
2203      return this;
2204    };
2205
2206    _proto2.getTweensOf = function getTweensOf(targets, onlyActive) {
2207      var a = [],
2208          parsedTargets = toArray(targets),
2209          child = this._first,
2210          isGlobalTime = _isNumber(onlyActive),
2211          children;
2212
2213      while (child) {
2214        if (child instanceof Tween) {
2215          if (_arrayContainsAny(child._targets, parsedTargets) && (isGlobalTime ? (!_overwritingTween || child._initted && child._ts) && child.globalTime(0) <= onlyActive && child.globalTime(child.totalDuration()) > onlyActive : !onlyActive || child.isActive())) {
2216            a.push(child);
2217          }
2218        } else if ((children = child.getTweensOf(parsedTargets, onlyActive)).length) {
2219          a.push.apply(a, children);
2220        }
2221
2222        child = child._next;
2223      }
2224
2225      return a;
2226    };
2227
2228    _proto2.tweenTo = function tweenTo(position, vars) {
2229      vars = vars || {};
2230
2231      var tl = this,
2232          endTime = _parsePosition(tl, position),
2233          _vars = vars,
2234          startAt = _vars.startAt,
2235          _onStart = _vars.onStart,
2236          onStartParams = _vars.onStartParams,
2237          immediateRender = _vars.immediateRender,
2238          tween = Tween.to(tl, _setDefaults({
2239        ease: vars.ease || "none",
2240        lazy: false,
2241        immediateRender: false,
2242        time: endTime,
2243        overwrite: "auto",
2244        duration: vars.duration || Math.abs((endTime - (startAt && "time" in startAt ? startAt.time : tl._time)) / tl.timeScale()) || _tinyNum,
2245        onStart: function onStart() {
2246          tl.pause();
2247          var duration = vars.duration || Math.abs((endTime - tl._time) / tl.timeScale());
2248          tween._dur !== duration && _setDuration(tween, duration, 0, 1).render(tween._time, true, true);
2249          _onStart && _onStart.apply(tween, onStartParams || []);
2250        }
2251      }, vars));
2252
2253      return immediateRender ? tween.render(0) : tween;
2254    };
2255
2256    _proto2.tweenFromTo = function tweenFromTo(fromPosition, toPosition, vars) {
2257      return this.tweenTo(toPosition, _setDefaults({
2258        startAt: {
2259          time: _parsePosition(this, fromPosition)
2260        }
2261      }, vars));
2262    };
2263
2264    _proto2.recent = function recent() {
2265      return this._recent;
2266    };
2267
2268    _proto2.nextLabel = function nextLabel(afterTime) {
2269      if (afterTime === void 0) {
2270        afterTime = this._time;
2271      }
2272
2273      return _getLabelInDirection(this, _parsePosition(this, afterTime));
2274    };
2275
2276    _proto2.previousLabel = function previousLabel(beforeTime) {
2277      if (beforeTime === void 0) {
2278        beforeTime = this._time;
2279      }
2280
2281      return _getLabelInDirection(this, _parsePosition(this, beforeTime), 1);
2282    };
2283
2284    _proto2.currentLabel = function currentLabel(value) {
2285      return arguments.length ? this.seek(value, true) : this.previousLabel(this._time + _tinyNum);
2286    };
2287
2288    _proto2.shiftChildren = function shiftChildren(amount, adjustLabels, ignoreBeforeTime) {
2289      if (ignoreBeforeTime === void 0) {
2290        ignoreBeforeTime = 0;
2291      }
2292
2293      var child = this._first,
2294          labels = this.labels,
2295          p;
2296
2297      while (child) {
2298        if (child._start >= ignoreBeforeTime) {
2299          child._start += amount;
2300          child._end += amount;
2301        }
2302
2303        child = child._next;
2304      }
2305
2306      if (adjustLabels) {
2307        for (p in labels) {
2308          if (labels[p] >= ignoreBeforeTime) {
2309            labels[p] += amount;
2310          }
2311        }
2312      }
2313
2314      return _uncache(this);
2315    };
2316
2317    _proto2.invalidate = function invalidate() {
2318      var child = this._first;
2319      this._lock = 0;
2320
2321      while (child) {
2322        child.invalidate();
2323        child = child._next;
2324      }
2325
2326      return _Animation.prototype.invalidate.call(this);
2327    };
2328
2329    _proto2.clear = function clear(includeLabels) {
2330      if (includeLabels === void 0) {
2331        includeLabels = true;
2332      }
2333
2334      var child = this._first,
2335          next;
2336
2337      while (child) {
2338        next = child._next;
2339        this.remove(child);
2340        child = next;
2341      }
2342
2343      this._dp && (this._time = this._tTime = this._pTime = 0);
2344      includeLabels && (this.labels = {});
2345      return _uncache(this);
2346    };
2347
2348    _proto2.totalDuration = function totalDuration(value) {
2349      var max = 0,
2350          self = this,
2351          child = self._last,
2352          prevStart = _bigNum,
2353          prev,
2354          start,
2355          parent;
2356
2357      if (arguments.length) {
2358        return self.timeScale((self._repeat < 0 ? self.duration() : self.totalDuration()) / (self.reversed() ? -value : value));
2359      }
2360
2361      if (self._dirty) {
2362        parent = self.parent;
2363
2364        while (child) {
2365          prev = child._prev;
2366          child._dirty && child.totalDuration();
2367          start = child._start;
2368
2369          if (start > prevStart && self._sort && child._ts && !self._lock) {
2370            self._lock = 1;
2371            _addToTimeline(self, child, start - child._delay, 1)._lock = 0;
2372          } else {
2373            prevStart = start;
2374          }
2375
2376          if (start < 0 && child._ts) {
2377            max -= start;
2378
2379            if (!parent && !self._dp || parent && parent.smoothChildTiming) {
2380              self._start += start / self._ts;
2381              self._time -= start;
2382              self._tTime -= start;
2383            }
2384
2385            self.shiftChildren(-start, false, -1e999);
2386            prevStart = 0;
2387          }
2388
2389          child._end > max && child._ts && (max = child._end);
2390          child = prev;
2391        }
2392
2393        _setDuration(self, self === _globalTimeline && self._time > max ? self._time : max, 1, 1);
2394
2395        self._dirty = 0;
2396      }
2397
2398      return self._tDur;
2399    };
2400
2401    Timeline.updateRoot = function updateRoot(time) {
2402      if (_globalTimeline._ts) {
2403        _lazySafeRender(_globalTimeline, _parentToChildTotalTime(time, _globalTimeline));
2404
2405        _lastRenderedFrame = _ticker.frame;
2406      }
2407
2408      if (_ticker.frame >= _nextGCFrame) {
2409        _nextGCFrame += _config.autoSleep || 120;
2410        var child = _globalTimeline._first;
2411        if (!child || !child._ts) if (_config.autoSleep && _ticker._listeners.length < 2) {
2412          while (child && !child._ts) {
2413            child = child._next;
2414          }
2415
2416          child || _ticker.sleep();
2417        }
2418      }
2419    };
2420
2421    return Timeline;
2422  }(Animation);
2423
2424  _setDefaults(Timeline.prototype, {
2425    _lock: 0,
2426    _hasPause: 0,
2427    _forcing: 0
2428  });
2429
2430  var _addComplexStringPropTween = function _addComplexStringPropTween(target, prop, start, end, setter, stringFilter, funcParam) {
2431    var pt = new PropTween(this._pt, target, prop, 0, 1, _renderComplexString, null, setter),
2432        index = 0,
2433        matchIndex = 0,
2434        result,
2435        startNums,
2436        color,
2437        endNum,
2438        chunk,
2439        startNum,
2440        hasRandom,
2441        a;
2442    pt.b = start;
2443    pt.e = end;
2444    start += "";
2445    end += "";
2446
2447    if (hasRandom = ~end.indexOf("random(")) {
2448      end = _replaceRandom(end);
2449    }
2450
2451    if (stringFilter) {
2452      a = [start, end];
2453      stringFilter(a, target, prop);
2454      start = a[0];
2455      end = a[1];
2456    }
2457
2458    startNums = start.match(_complexStringNumExp) || [];
2459
2460    while (result = _complexStringNumExp.exec(end)) {
2461      endNum = result[0];
2462      chunk = end.substring(index, result.index);
2463
2464      if (color) {
2465        color = (color + 1) % 5;
2466      } else if (chunk.substr(-5) === "rgba(") {
2467        color = 1;
2468      }
2469
2470      if (endNum !== startNums[matchIndex++]) {
2471        startNum = parseFloat(startNums[matchIndex - 1]) || 0;
2472        pt._pt = {
2473          _next: pt._pt,
2474          p: chunk || matchIndex === 1 ? chunk : ",",
2475          s: startNum,
2476          c: endNum.charAt(1) === "=" ? parseFloat(endNum.substr(2)) * (endNum.charAt(0) === "-" ? -1 : 1) : parseFloat(endNum) - startNum,
2477          m: color && color < 4 ? Math.round : 0
2478        };
2479        index = _complexStringNumExp.lastIndex;
2480      }
2481    }
2482
2483    pt.c = index < end.length ? end.substring(index, end.length) : "";
2484    pt.fp = funcParam;
2485
2486    if (_relExp.test(end) || hasRandom) {
2487      pt.e = 0;
2488    }
2489
2490    this._pt = pt;
2491    return pt;
2492  },
2493      _addPropTween = function _addPropTween(target, prop, start, end, index, targets, modifier, stringFilter, funcParam) {
vendor: 7,950 bytes, lines 2494-2719
2494    _isFunction(end) && (end = end(index || 0, target, targets));
2495    var currentValue = target[prop],
2496        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](),
2497        setter = !_isFunction(currentValue) ? _setterPlain : funcParam ? _setterFuncWithParam : _setterFunc,
2498        pt;
2499
2500    if (_isString(end)) {
2501      if (~end.indexOf("random(")) {
2502        end = _replaceRandom(end);
2503      }
2504
2505      if (end.charAt(1) === "=") {
2506        end = parseFloat(parsedStart) + parseFloat(end.substr(2)) * (end.charAt(0) === "-" ? -1 : 1) + (getUnit(parsedStart) || 0);
2507      }
2508    }
2509
2510    if (parsedStart !== end) {
2511      if (!isNaN(parsedStart * end)) {
2512        pt = new PropTween(this._pt, target, prop, +parsedStart || 0, end - (parsedStart || 0), typeof currentValue === "boolean" ? _renderBoolean : _renderPlain, 0, setter);
2513        funcParam && (pt.fp = funcParam);
2514        modifier && pt.modifier(modifier, this, target);
2515        return this._pt = pt;
2516      }
2517
2518      !currentValue && !(prop in target) && _missingPlugin(prop, end);
2519      return _addComplexStringPropTween.call(this, target, prop, parsedStart, end, setter, stringFilter || _config.stringFilter, funcParam);
2520    }
2521  },
2522      _processVars = function _processVars(vars, index, target, targets, tween) {
2523    _isFunction(vars) && (vars = _parseFuncOrString(vars, tween, index, target, targets));
2524
2525    if (!_isObject(vars) || vars.style && vars.nodeType || _isArray(vars) || _isTypedArray(vars)) {
2526      return _isString(vars) ? _parseFuncOrString(vars, tween, index, target, targets) : vars;
2527    }
2528
2529    var copy = {},
2530        p;
2531
2532    for (p in vars) {
2533      copy[p] = _parseFuncOrString(vars[p], tween, index, target, targets);
2534    }
2535
2536    return copy;
2537  },
2538      _checkPlugin = function _checkPlugin(property, vars, tween, index, target, targets) {
2539    var plugin, pt, ptLookup, i;
2540
2541    if (_plugins[property] && (plugin = new _plugins[property]()).init(target, plugin.rawVars ? vars[property] : _processVars(vars[property], index, target, targets, tween), tween, index, targets) !== false) {
2542      tween._pt = pt = new PropTween(tween._pt, target, property, 0, 1, plugin.render, plugin, 0, plugin.priority);
2543
2544      if (tween !== _quickTween) {
2545        ptLookup = tween._ptLookup[tween._targets.indexOf(target)];
2546        i = plugin._props.length;
2547
2548        while (i--) {
2549          ptLookup[plugin._props[i]] = pt;
2550        }
2551      }
2552    }
2553
2554    return plugin;
2555  },
2556      _overwritingTween,
2557      _initTween = function _initTween(tween, time) {
2558    var vars = tween.vars,
2559        ease = vars.ease,
2560        startAt = vars.startAt,
2561        immediateRender = vars.immediateRender,
2562        lazy = vars.lazy,
2563        onUpdate = vars.onUpdate,
2564        onUpdateParams = vars.onUpdateParams,
2565        callbackScope = vars.callbackScope,
2566        runBackwards = vars.runBackwards,
2567        yoyoEase = vars.yoyoEase,
2568        keyframes = vars.keyframes,
2569        autoRevert = vars.autoRevert,
2570        dur = tween._dur,
2571        prevStartAt = tween._startAt,
2572        targets = tween._targets,
2573        parent = tween.parent,
2574        fullTargets = parent && parent.data === "nested" ? parent.parent._targets : targets,
2575        autoOverwrite = tween._overwrite === "auto" && !_suppressOverwrites,
2576        tl = tween.timeline,
2577        cleanVars,
2578        i,
2579        p,
2580        pt,
2581        target,
2582        hasPriority,
2583        gsData,
2584        harness,
2585        plugin,
2586        ptLookup,
2587        index,
2588        harnessVars,
2589        overwritten;
2590    tl && (!keyframes || !ease) && (ease = "none");
2591    tween._ease = _parseEase(ease, _defaults.ease);
2592    tween._yEase = yoyoEase ? _invertEase(_parseEase(yoyoEase === true ? ease : yoyoEase, _defaults.ease)) : 0;
2593
2594    if (yoyoEase && tween._yoyo && !tween._repeat) {
2595      yoyoEase = tween._yEase;
2596      tween._yEase = tween._ease;
2597      tween._ease = yoyoEase;
2598    }
2599
2600    if (!tl) {
2601      harness = targets[0] ? _getCache(targets[0]).harness : 0;
2602      harnessVars = harness && vars[harness.prop];
2603      cleanVars = _copyExcluding(vars, _reservedProps);
2604      prevStartAt && prevStartAt.render(-1, true).kill();
2605
2606      if (startAt) {
2607        _removeFromParent(tween._startAt = Tween.set(targets, _setDefaults({
2608          data: "isStart",
2609          overwrite: false,
2610          parent: parent,
2611          immediateRender: true,
2612          lazy: _isNotFalse(lazy),
2613          startAt: null,
2614          delay: 0,
2615          onUpdate: onUpdate,
2616          onUpdateParams: onUpdateParams,
2617          callbackScope: callbackScope,
2618          stagger: 0
2619        }, startAt)));
2620
2621        if (immediateRender) {
2622          if (time > 0) {
2623            autoRevert || (tween._startAt = 0);
2624          } else if (dur && !(time < 0 && prevStartAt)) {
2625            time && (tween._zTime = time);
2626            return;
2627          }
2628        } else if (autoRevert === false) {
2629          tween._startAt = 0;
2630        }
2631      } else if (runBackwards && dur) {
2632        if (prevStartAt) {
2633          !autoRevert && (tween._startAt = 0);
2634        } else {
2635          time && (immediateRender = false);
2636          p = _setDefaults({
2637            overwrite: false,
2638            data: "isFromStart",
2639            lazy: immediateRender && _isNotFalse(lazy),
2640            immediateRender: immediateRender,
2641            stagger: 0,
2642            parent: parent
2643          }, cleanVars);
2644          harnessVars && (p[harness.prop] = harnessVars);
2645
2646          _removeFromParent(tween._startAt = Tween.set(targets, p));
2647
2648          if (!immediateRender) {
2649            _initTween(tween._startAt, _tinyNum);
2650          } else if (!time) {
2651            return;
2652          }
2653        }
2654      }
2655
2656      tween._pt = 0;
2657      lazy = dur && _isNotFalse(lazy) || lazy && !dur;
2658
2659      for (i = 0; i < targets.length; i++) {
2660        target = targets[i];
2661        gsData = target._gsap || _harness(targets)[i]._gsap;
2662        tween._ptLookup[i] = ptLookup = {};
2663        _lazyLookup[gsData.id] && _lazyTweens.length && _lazyRender();
2664        index = fullTargets === targets ? i : fullTargets.indexOf(target);
2665
2666        if (harness && (plugin = new harness()).init(target, harnessVars || cleanVars, tween, index, fullTargets) !== false) {
2667          tween._pt = pt = new PropTween(tween._pt, target, plugin.name, 0, 1, plugin.render, plugin, 0, plugin.priority);
2668
2669          plugin._props.forEach(function (name) {
2670            ptLookup[name] = pt;
2671          });
2672
2673          plugin.priority && (hasPriority = 1);
2674        }
2675
2676        if (!harness || harnessVars) {
2677          for (p in cleanVars) {
2678            if (_plugins[p] && (plugin = _checkPlugin(p, cleanVars, tween, index, target, fullTargets))) {
2679              plugin.priority && (hasPriority = 1);
2680            } else {
2681              ptLookup[p] = pt = _addPropTween.call(tween, target, p, "get", cleanVars[p], index, fullTargets, 0, vars.stringFilter);
2682            }
2683          }
2684        }
2685
2686        tween._op && tween._op[i] && tween.kill(target, tween._op[i]);
2687
2688        if (autoOverwrite && tween._pt) {
2689          _overwritingTween = tween;
2690
2691          _globalTimeline.killTweensOf(target, ptLookup, tween.globalTime(0));
2692
2693          overwritten = !tween.parent;
2694          _overwritingTween = 0;
2695        }
2696
2697        tween._pt && lazy && (_lazyLookup[gsData.id] = 1);
2698      }
2699
2700      hasPriority && _sortPropTweensByPriority(tween);
2701      tween._onInit && tween._onInit(tween);
2702    }
2703
2704    tween._from = !tl && !!vars.runBackwards;
2705    tween._onUpdate = onUpdate;
2706    tween._initted = (!tween._op || tween._pt) && !overwritten;
2707  },
2708      _addAliasesToVars = function _addAliasesToVars(targets, vars) {
2709    var harness = targets[0] ? _getCache(targets[0]).harness : 0,
2710        propertyAliases = harness && harness.aliases,
2711        copy,
2712        p,
2713        i,
2714        aliases;
2715
2716    if (!propertyAliases) {
2717      return vars;
2718    }
2719
2720    copy = _merge({}, vars);
2721
2722    for (p in propertyAliases) {
2723      if (p in copy) {
2724        aliases = propertyAliases[p].split(",");
2725        i = aliases.length;
2726
2727        while (i--) {
2728          copy[aliases[i]] = copy[p];
2729        }
2730      }
2731    }
2732
2733    return copy;
2734  },
2735      _parseFuncOrString = function _parseFuncOrString(value, tween, i, target, targets) {
2736    return _isFunction(value) ? value.call(tween, i, target, targets) : _isString(value) && ~value.indexOf("random(") ? _replaceRandom(value) : value;
2737  },
2738      _staggerTweenProps = _callbackNames + "repeat,repeatDelay,yoyo,repeatRefresh,yoyoEase",
2739      _staggerPropsToSkip = (_staggerTweenProps + ",id,stagger,delay,duration,paused,scrollTrigger").split(",");
2740
2741  var Tween = function (_Animation2) {
2742    _inheritsLoose(Tween, _Animation2);
2743
2744    function Tween(targets, vars, time, skipInherit) {
2745      var _this3;
2746
2747      if (typeof vars === "number") {
2748        time.duration = vars;
2749        vars = time;
2750        time = null;
2751      }
2752
2753      _this3 = _Animation2.call(this, skipInherit ? vars : _inheritDefaults(vars), time) || this;
2754      var _this3$vars = _this3.vars,
2755          duration = _this3$vars.duration,
2756          delay = _this3$vars.delay,
2757          immediateRender = _this3$vars.immediateRender,
2758          stagger = _this3$vars.stagger,
2759          overwrite = _this3$vars.overwrite,
2760          keyframes = _this3$vars.keyframes,
2761          defaults = _this3$vars.defaults,
2762          scrollTrigger = _this3$vars.scrollTrigger,
2763          yoyoEase = _this3$vars.yoyoEase,
2764          parent = _this3.parent,
2765          parsedTargets = (_isArray(targets) || _isTypedArray(targets) ? _isNumber(targets[0]) : "length" in vars) ? [targets] : toArray(targets),
2766          tl,
2767          i,
2768          copy,
2769          l,
2770          p,
2771          curTarget,
2772          staggerFunc,
2773          staggerVarsToMerge;
2774      _this3._targets = parsedTargets.length ? _harness(parsedTargets) : _warn("GSAP target " + targets + " not found. https://greensock.com", !_config.nullTargetWarn) || [];
2775      _this3._ptLookup = [];
2776      _this3._overwrite = overwrite;
2777
2778      if (keyframes || stagger || _isFuncOrString(duration) || _isFuncOrString(delay)) {
2779        vars = _this3.vars;
2780        tl = _this3.timeline = new Timeline({
2781          data: "nested",
2782          defaults: defaults || {}
2783        });
2784        tl.kill();
2785        tl.parent = tl._dp = _assertThisInitialized(_this3);
2786        tl._start = 0;
2787
2788        if (keyframes) {
2789          _setDefaults(tl.vars.defaults, {
2790            ease: "none"
2791          });
2792
2793          keyframes.forEach(function (frame) {
2794            return tl.to(parsedTargets, frame, ">");
2795          });
2796        } else {
2797          l = parsedTargets.length;
2798          staggerFunc = stagger ? distribute(stagger) : _emptyFunc;
2799
2800          if (_isObject(stagger)) {
2801            for (p in stagger) {
2802              if (~_staggerTweenProps.indexOf(p)) {
2803                staggerVarsToMerge || (staggerVarsToMerge = {});
2804                staggerVarsToMerge[p] = stagger[p];
2805              }
2806            }
2807          }
2808
2809          for (i = 0; i < l; i++) {
2810            copy = {};
2811
2812            for (p in vars) {
2813              if (_staggerPropsToSkip.indexOf(p) < 0) {
2814                copy[p] = vars[p];
2815              }
2816            }
2817
2818            copy.stagger = 0;
2819            yoyoEase && (copy.yoyoEase = yoyoEase);
2820            staggerVarsToMerge && _merge(copy, staggerVarsToMerge);
2821            curTarget = parsedTargets[i];
2822            copy.duration = +_parseFuncOrString(duration, _assertThisInitialized(_this3), i, curTarget, parsedTargets);
2823            copy.delay = (+_parseFuncOrString(delay, _assertThisInitialized(_this3), i, curTarget, parsedTargets) || 0) - _this3._delay;
2824
2825            if (!stagger && l === 1 && copy.delay) {
2826              _this3._delay = delay = copy.delay;
2827              _this3._start += delay;
2828              copy.delay = 0;
2829            }
2830
2831            tl.to(curTarget, copy, staggerFunc(i, curTarget, parsedTargets));
2832          }
2833
2834          tl.duration() ? duration = delay = 0 : _this3.timeline = 0;
2835        }
2836
2837        duration || _this3.duration(duration = tl.duration());
2838      } else {
2839        _this3.timeline = 0;
2840      }
2841
2842      if (overwrite === true && !_suppressOverwrites) {
2843        _overwritingTween = _assertThisInitialized(_this3);
2844
2845        _globalTimeline.killTweensOf(parsedTargets);
2846
2847        _overwritingTween = 0;
2848      }
2849
2850      parent && _postAddChecks(parent, _assertThisInitialized(_this3));
2851
2852      if (immediateRender || !duration && !keyframes && _this3._start === _round(parent._time) && _isNotFalse(immediateRender) && _hasNoPausedAncestors(_assertThisInitialized(_this3)) && parent.data !== "nested") {
2853        _this3._tTime = -_tinyNum;
2854
2855        _this3.render(Math.max(0, -delay));
2856      }
2857
2858      scrollTrigger && _scrollTrigger(_assertThisInitialized(_this3), scrollTrigger);
2859      return _this3;
2860    }
2861
2862    var _proto3 = Tween.prototype;
2863
2864    _proto3.render = function render(totalTime, suppressEvents, force) {
2865      var prevTime = this._time,
2866          tDur = this._tDur,
2867          dur = this._dur,
2868          tTime = totalTime > tDur - _tinyNum && totalTime >= 0 ? tDur : totalTime < _tinyNum ? 0 : totalTime,
2869          time,
2870          pt,
2871          iteration,
2872          cycleDuration,
2873          prevIteration,
2874          isYoyo,
2875          ratio,
2876          timeline,
2877          yoyoEase;
2878
2879      if (!dur) {
2880        _renderZeroDurationTween(this, totalTime, suppressEvents, force);
2881      } else if (tTime !== this._tTime || !totalTime || force || !this._initted && this._tTime || this._startAt && this._zTime < 0 !== totalTime < 0) {
2882        time = tTime;
2883        timeline = this.timeline;
2884
2885        if (this._repeat) {
2886          cycleDuration = dur + this._rDelay;
2887
2888          if (this._repeat < -1 && totalTime < 0) {
2889            return this.totalTime(cycleDuration * 100 + totalTime, suppressEvents, force);
2890          }
2891
2892          time = _round(tTime % cycleDuration);
2893
2894          if (tTime === tDur) {
2895            iteration = this._repeat;
2896            time = dur;
2897          } else {
2898            iteration = ~~(tTime / cycleDuration);
2899
2900            if (iteration && iteration === tTime / cycleDuration) {
2901              time = dur;
2902              iteration--;
2903            }
2904
2905            time > dur && (time = dur);
2906          }
2907
2908          isYoyo = this._yoyo && iteration & 1;
2909
2910          if (isYoyo) {
2911            yoyoEase = this._yEase;
2912            time = dur - time;
2913          }
2914
2915          prevIteration = _animationCycle(this._tTime, cycleDuration);
2916
2917          if (time === prevTime && !force && this._initted) {
2918            return this;
2919          }
2920
2921          if (iteration !== prevIteration) {
2922            timeline && this._yEase && _propagateYoyoEase(timeline, isYoyo);
2923
2924            if (this.vars.repeatRefresh && !isYoyo && !this._lock) {
2925              this._lock = force = 1;
2926              this.render(_round(cycleDuration * iteration), true).invalidate()._lock = 0;
2927            }
2928          }
2929        }
2930
2931        if (!this._initted) {
2932          if (_attemptInitTween(this, totalTime < 0 ? totalTime : time, force, suppressEvents)) {
2933            this._tTime = 0;
2934            return this;
2935          }
2936
2937          if (dur !== this._dur) {
2938            return this.render(totalTime, suppressEvents, force);
2939          }
2940        }
2941
2942        this._tTime = tTime;
2943        this._time = time;
2944
2945        if (!this._act && this._ts) {
2946          this._act = 1;
2947          this._lazy = 0;
2948        }
2949
2950        this.ratio = ratio = (yoyoEase || this._ease)(time / dur);
2951
2952        if (this._from) {
2953          this.ratio = ratio = 1 - ratio;
2954        }
2955
2956        time && !prevTime && !suppressEvents && _callback(this, "onStart");
2957        pt = this._pt;
2958
2959        while (pt) {
2960          pt.r(ratio, pt.d);
2961          pt = pt._next;
2962        }
2963
2964        timeline && timeline.render(totalTime < 0 ? totalTime : !time && isYoyo ? -_tinyNum : timeline._dur * ratio, suppressEvents, force) || this._startAt && (this._zTime = totalTime);
2965
2966        if (this._onUpdate && !suppressEvents) {
2967          totalTime < 0 && this._startAt && this._startAt.render(totalTime, true, force);
2968
2969          _callback(this, "onUpdate");
2970        }
2971
2972        this._repeat && iteration !== prevIteration && this.vars.onRepeat && !suppressEvents && this.parent && _callback(this, "onRepeat");
2973
2974        if ((tTime === this._tDur || !tTime) && this._tTime === tTime) {
2975          totalTime < 0 && this._startAt && !this._onUpdate && this._startAt.render(totalTime, true, true);
2976          (totalTime || !dur) && (tTime === this._tDur && this._ts > 0 || !tTime && this._ts < 0) && _removeFromParent(this, 1);
2977
2978          if (!suppressEvents && !(totalTime < 0 && !prevTime) && (tTime || prevTime)) {
2979            _callback(this, tTime === tDur ? "onComplete" : "onReverseComplete", true);
2980
2981            this._prom && !(tTime < tDur && this.timeScale() > 0) && this._prom();
2982          }
2983        }
2984      }
2985
2986      return this;
2987    };
2988
2989    _proto3.targets = function targets() {
2990      return this._targets;
2991    };
2992
vendor: 12,946 bytes, lines 2993-3420
2993    _proto3.invalidate = function invalidate() {
2994      this._pt = this._op = this._startAt = this._onUpdate = this._lazy = this.ratio = 0;
2995      this._ptLookup = [];
2996      this.timeline && this.timeline.invalidate();
2997      return _Animation2.prototype.invalidate.call(this);
2998    };
2999
3000    _proto3.kill = function kill(targets, vars) {
3001      if (vars === void 0) {
3002        vars = "all";
3003      }
3004
3005      if (!targets && (!vars || vars === "all")) {
3006        this._lazy = this._pt = 0;
3007        return this.parent ? _interrupt(this) : this;
3008      }
3009
3010      if (this.timeline) {
3011        var tDur = this.timeline.totalDuration();
3012        this.timeline.killTweensOf(targets, vars, _overwritingTween && _overwritingTween.vars.overwrite !== true)._first || _interrupt(this);
3013        this.parent && tDur !== this.timeline.totalDuration() && _setDuration(this, this._dur * this.timeline._tDur / tDur, 0, 1);
3014        return this;
3015      }
3016
3017      var parsedTargets = this._targets,
3018          killingTargets = targets ? toArray(targets) : parsedTargets,
3019          propTweenLookup = this._ptLookup,
3020          firstPT = this._pt,
3021          overwrittenProps,
3022          curLookup,
3023          curOverwriteProps,
3024          props,
3025          p,
3026          pt,
3027          i;
3028
3029      if ((!vars || vars === "all") && _arraysMatch(parsedTargets, killingTargets)) {
3030        vars === "all" && (this._pt = 0);
3031        return _interrupt(this);
3032      }
3033
3034      overwrittenProps = this._op = this._op || [];
3035
3036      if (vars !== "all") {
3037        if (_isString(vars)) {
3038          p = {};
3039
3040          _forEachName(vars, function (name) {
3041            return p[name] = 1;
3042          });
3043
3044          vars = p;
3045        }
3046
3047        vars = _addAliasesToVars(parsedTargets, vars);
3048      }
3049
3050      i = parsedTargets.length;
3051
3052      while (i--) {
3053        if (~killingTargets.indexOf(parsedTargets[i])) {
3054          curLookup = propTweenLookup[i];
3055
3056          if (vars === "all") {
3057            overwrittenProps[i] = vars;
3058            props = curLookup;
3059            curOverwriteProps = {};
3060          } else {
3061            curOverwriteProps = overwrittenProps[i] = overwrittenProps[i] || {};
3062            props = vars;
3063          }
3064
3065          for (p in props) {
3066            pt = curLookup && curLookup[p];
3067
3068            if (pt) {
3069              if (!("kill" in pt.d) || pt.d.kill(p) === true) {
3070                _removeLinkedListItem(this, pt, "_pt");
3071              }
3072
3073              delete curLookup[p];
3074            }
3075
3076            if (curOverwriteProps !== "all") {
3077              curOverwriteProps[p] = 1;
3078            }
3079          }
3080        }
3081      }
3082
3083      this._initted && !this._pt && firstPT && _interrupt(this);
3084      return this;
3085    };
3086
3087    Tween.to = function to(targets, vars) {
3088      return new Tween(targets, vars, arguments[2]);
3089    };
3090
3091    Tween.from = function from(targets, vars) {
3092      return new Tween(targets, _parseVars(arguments, 1));
3093    };
3094
3095    Tween.delayedCall = function delayedCall(delay, callback, params, scope) {
3096      return new Tween(callback, 0, {
3097        immediateRender: false,
3098        lazy: false,
3099        overwrite: false,
3100        delay: delay,
3101        onComplete: callback,
3102        onReverseComplete: callback,
3103        onCompleteParams: params,
3104        onReverseCompleteParams: params,
3105        callbackScope: scope
3106      });
3107    };
3108
3109    Tween.fromTo = function fromTo(targets, fromVars, toVars) {
3110      return new Tween(targets, _parseVars(arguments, 2));
3111    };
3112
3113    Tween.set = function set(targets, vars) {
3114      vars.duration = 0;
3115      vars.repeatDelay || (vars.repeat = 0);
3116      return new Tween(targets, vars);
3117    };
3118
3119    Tween.killTweensOf = function killTweensOf(targets, props, onlyActive) {
3120      return _globalTimeline.killTweensOf(targets, props, onlyActive);
3121    };
3122
3123    return Tween;
3124  }(Animation);
3125
3126  _setDefaults(Tween.prototype, {
3127    _targets: [],
3128    _lazy: 0,
3129    _startAt: 0,
3130    _op: 0,
3131    _onInit: 0
3132  });
3133
3134  _forEachName("staggerTo,staggerFrom,staggerFromTo", function (name) {
3135    Tween[name] = function () {
3136      var tl = new Timeline(),
3137          params = _slice.call(arguments, 0);
3138
3139      params.splice(name === "staggerFromTo" ? 5 : 4, 0, 0);
3140      return tl[name].apply(tl, params);
3141    };
3142  });
3143
3144  var _setterPlain = function _setterPlain(target, property, value) {
3145    return target[property] = value;
3146  },
3147      _setterFunc = function _setterFunc(target, property, value) {
3148    return target[property](value);
3149  },
3150      _setterFuncWithParam = function _setterFuncWithParam(target, property, value, data) {
3151    return target[property](data.fp, value);
3152  },
3153      _setterAttribute = function _setterAttribute(target, property, value) {
3154    return target.setAttribute(property, value);
3155  },
3156      _getSetter = function _getSetter(target, property) {
3157    return _isFunction(target[property]) ? _setterFunc : _isUndefined(target[property]) && target.setAttribute ? _setterAttribute : _setterPlain;
3158  },
3159      _renderPlain = function _renderPlain(ratio, data) {
3160    return data.set(data.t, data.p, Math.round((data.s + data.c * ratio) * 10000) / 10000, data);
3161  },
3162      _renderBoolean = function _renderBoolean(ratio, data) {
3163    return data.set(data.t, data.p, !!(data.s + data.c * ratio), data);
3164  },
3165      _renderComplexString = function _renderComplexString(ratio, data) {
3166    var pt = data._pt,
3167        s = "";
3168
3169    if (!ratio && data.b) {
3170      s = data.b;
3171    } else if (ratio === 1 && data.e) {
3172      s = data.e;
3173    } else {
3174      while (pt) {
3175        s = pt.p + (pt.m ? pt.m(pt.s + pt.c * ratio) : Math.round((pt.s + pt.c * ratio) * 10000) / 10000) + s;
3176        pt = pt._next;
3177      }
3178
3179      s += data.c;
3180    }
3181
3182    data.set(data.t, data.p, s, data);
3183  },
3184      _renderPropTweens = function _renderPropTweens(ratio, data) {
3185    var pt = data._pt;
3186
3187    while (pt) {
3188      pt.r(ratio, pt.d);
3189      pt = pt._next;
3190    }
3191  },
3192      _addPluginModifier = function _addPluginModifier(modifier, tween, target, property) {
3193    var pt = this._pt,
3194        next;
3195
3196    while (pt) {
3197      next = pt._next;
3198      pt.p === property && pt.modifier(modifier, tween, target);
3199      pt = next;
3200    }
3201  },
3202      _killPropTweensOf = function _killPropTweensOf(property) {
3203    var pt = this._pt,
3204        hasNonDependentRemaining,
3205        next;
3206
3207    while (pt) {
3208      next = pt._next;
3209
3210      if (pt.p === property && !pt.op || pt.op === property) {
3211        _removeLinkedListItem(this, pt, "_pt");
3212      } else if (!pt.dep) {
3213        hasNonDependentRemaining = 1;
3214      }
3215
3216      pt = next;
3217    }
3218
3219    return !hasNonDependentRemaining;
3220  },
3221      _setterWithModifier = function _setterWithModifier(target, property, value, data) {
3222    data.mSet(target, property, data.m.call(data.tween, value, data.mt), data);
3223  },
3224      _sortPropTweensByPriority = function _sortPropTweensByPriority(parent) {
3225    var pt = parent._pt,
3226        next,
3227        pt2,
3228        first,
3229        last;
3230
3231    while (pt) {
3232      next = pt._next;
3233      pt2 = first;
3234
3235      while (pt2 && pt2.pr > pt.pr) {
3236        pt2 = pt2._next;
3237      }
3238
3239      if (pt._prev = pt2 ? pt2._prev : last) {
3240        pt._prev._next = pt;
3241      } else {
3242        first = pt;
3243      }
3244
3245      if (pt._next = pt2) {
3246        pt2._prev = pt;
3247      } else {
3248        last = pt;
3249      }
3250
3251      pt = next;
3252    }
3253
3254    parent._pt = first;
3255  };
3256
3257  var PropTween = function () {
3258    function PropTween(next, target, prop, start, change, renderer, data, setter, priority) {
3259      this.t = target;
3260      this.s = start;
3261      this.c = change;
3262      this.p = prop;
3263      this.r = renderer || _renderPlain;
3264      this.d = data || this;
3265      this.set = setter || _setterPlain;
3266      this.pr = priority || 0;
3267      this._next = next;
3268
3269      if (next) {
3270        next._prev = this;
3271      }
3272    }
3273
3274    var _proto4 = PropTween.prototype;
3275
3276    _proto4.modifier = function modifier(func, tween, target) {
3277      this.mSet = this.mSet || this.set;
3278      this.set = _setterWithModifier;
3279      this.m = func;
3280      this.mt = target;
3281      this.tween = tween;
3282    };
3283
3284    return PropTween;
3285  }();
3286
3287  _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) {
3288    return _reservedProps[name] = 1;
3289  });
3290
3291  _globals.TweenMax = _globals.TweenLite = Tween;
3292  _globals.TimelineLite = _globals.TimelineMax = Timeline;
3293  _globalTimeline = new Timeline({
3294    sortChildren: false,
3295    defaults: _defaults,
3296    autoRemoveChildren: true,
3297    id: "root",
3298    smoothChildTiming: true
3299  });
3300  _config.stringFilter = _colorStringFilter;
3301  var _gsap = {
3302    registerPlugin: function registerPlugin() {
3303      for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
3304        args[_key2] = arguments[_key2];
3305      }
3306
3307      args.forEach(function (config) {
3308        return _createPlugin(config);
3309      });
3310    },
3311    timeline: function timeline(vars) {
3312      return new Timeline(vars);
3313    },
3314    getTweensOf: function getTweensOf(targets, onlyActive) {
3315      return _globalTimeline.getTweensOf(targets, onlyActive);
3316    },
3317    getProperty: function getProperty(target, property, unit, uncache) {
3318      _isString(target) && (target = toArray(target)[0]);
3319
3320      var getter = _getCache(target || {}).get,
3321          format = unit ? _passThrough : _numericIfPossible;
3322
3323      unit === "native" && (unit = "");
3324      return !target ? target : !property ? function (property, unit, uncache) {
3325        return format((_plugins[property] && _plugins[property].get || getter)(target, property, unit, uncache));
3326      } : format((_plugins[property] && _plugins[property].get || getter)(target, property, unit, uncache));
3327    },
3328    quickSetter: function quickSetter(target, property, unit) {
3329      target = toArray(target);
3330
3331      if (target.length > 1) {
3332        var setters = target.map(function (t) {
3333          return gsap.quickSetter(t, property, unit);
3334        }),
3335            l = setters.length;
3336        return function (value) {
3337          var i = l;
3338
3339          while (i--) {
3340            setters[i](value);
3341          }
3342        };
3343      }
3344
3345      target = target[0] || {};
3346
3347      var Plugin = _plugins[property],
3348          cache = _getCache(target),
3349          p = cache.harness && (cache.harness.aliases || {})[property] || property,
3350          setter = Plugin ? function (value) {
3351        var p = new Plugin();
3352        _quickTween._pt = 0;
3353        p.init(target, unit ? value + unit : value, _quickTween, 0, [target]);
3354        p.render(1, p);
3355        _quickTween._pt && _renderPropTweens(1, _quickTween);
3356      } : cache.set(target, p);
3357
3358      return Plugin ? setter : function (value) {
3359        return setter(target, p, unit ? value + unit : value, cache, 1);
3360      };
3361    },
3362    isTweening: function isTweening(targets) {
3363      return _globalTimeline.getTweensOf(targets, true).length > 0;
3364    },
3365    defaults: function defaults(value) {
3366      value && value.ease && (value.ease = _parseEase(value.ease, _defaults.ease));
3367      return _mergeDeep(_defaults, value || {});
3368    },
3369    config: function config(value) {
3370      return _mergeDeep(_config, value || {});
3371    },
3372    registerEffect: function registerEffect(_ref2) {
3373      var name = _ref2.name,
3374          effect = _ref2.effect,
3375          plugins = _ref2.plugins,
3376          defaults = _ref2.defaults,
3377          extendTimeline = _ref2.extendTimeline;
3378      (plugins || "").split(",").forEach(function (pluginName) {
3379        return pluginName && !_plugins[pluginName] && !_globals[pluginName] && _warn(name + " effect requires " + pluginName + " plugin.");
3380      });
3381
3382      _effects[name] = function (targets, vars, tl) {
3383        return effect(toArray(targets), _setDefaults(vars || {}, defaults), tl);
3384      };
3385
3386      if (extendTimeline) {
3387        Timeline.prototype[name] = function (targets, vars, position) {
3388          return this.add(_effects[name](targets, _isObject(vars) ? vars : (position = vars) && {}, this), position);
3389        };
3390      }
3391    },
3392    registerEase: function registerEase(name, ease) {
3393      _easeMap[name] = _parseEase(ease);
3394    },
3395    parseEase: function parseEase(ease, defaultEase) {
3396      return arguments.length ? _parseEase(ease, defaultEase) : _easeMap;
3397    },
3398    getById: function getById(id) {
3399      return _globalTimeline.getById(id);
3400    },
3401    exportRoot: function exportRoot(vars, includeDelayedCalls) {
3402      if (vars === void 0) {
3403        vars = {};
3404      }
3405
3406      var tl = new Timeline(vars),
3407          child,
3408          next;
3409      tl.smoothChildTiming = _isNotFalse(vars.smoothChildTiming);
3410
3411      _globalTimeline.remove(tl);
3412
3413      tl._dp = 0;
3414      tl._time = tl._tTime = _globalTimeline._time;
3415      child = _globalTimeline._first;
3416
3417      while (child) {
3418        next = child._next;
3419
3420        if (includeDelayedCalls || !(!child._dur && child instanceof Tween && child.vars.onComplete === child._targets[0])) {
3421          _addToTimeline(tl, child, child._start - child._delay);
3422        }
3423
3424        child = next;
3425      }
3426
3427      _addToTimeline(_globalTimeline, tl, 0);
3428
3429      return tl;
3430    },
3431    utils: {
3432      wrap: wrap,
3433      wrapYoyo: wrapYoyo,
3434      distribute: distribute,
3435      random: random,
3436      snap: snap,
3437      normalize: normalize,
3438      getUnit: getUnit,
3439      clamp: clamp,
3440      splitColor: splitColor,
3441      toArray: toArray,
3442      mapRange: mapRange,
3443      pipe: pipe,
3444      unitize: unitize,
3445      interpolate: interpolate,
3446      shuffle: shuffle
3447    },
3448    install: _install,
3449    effects: _effects,
3450    ticker: _ticker,
3451    updateRoot: Timeline.updateRoot,
3452    plugins: _plugins,
3453    globalTimeline: _globalTimeline,
3454    core: {
3455      PropTween: PropTween,
3456      globals: _addGlobal,
3457      Tween: Tween,
3458      Timeline: Timeline,
3459      Animation: Animation,
3460      getCache: _getCache,
3461      _removeLinkedListItem: _removeLinkedListItem,
3462      suppressOverwrites: function suppressOverwrites(value) {
3463        return _suppressOverwrites = value;
3464      }
3465    }
3466  };
3467
3468  _forEachName("to,from,fromTo,delayedCall,set,killTweensOf", function (name) {
3469    return _gsap[name] = Tween[name];
3470  });
3471
3472  _ticker.add(Timeline.updateRoot);
3473
3474  _quickTween = _gsap.to({}, {
3475    duration: 0
3476  });
3477
3478  var _getPluginPropTween = function _getPluginPropTween(plugin, prop
vendor: 18,114 bytes, lines 3478-4050
3478) {
3479    var pt = plugin._pt;
3480
3481    while (pt && pt.p !== prop && pt.op !== prop && pt.fp !== prop) {
3482      pt = pt._next;
3483    }
3484
3485    return pt;
3486  },
3487      _addModifiers = function _addModifiers(tween, modifiers) {
3488    var targets = tween._targets,
3489        p,
3490        i,
3491        pt;
3492
3493    for (p in modifiers) {
3494      i = targets.length;
3495
3496      while (i--) {
3497        pt = tween._ptLookup[i][p];
3498
3499        if (pt && (pt = pt.d)) {
3500          if (pt._pt) {
3501            pt = _getPluginPropTween(pt, p);
3502          }
3503
3504          pt && pt.modifier && pt.modifier(modifiers[p], tween, targets[i], p);
3505        }
3506      }
3507    }
3508  },
3509      _buildModifierPlugin = function _buildModifierPlugin(name, modifier) {
3510    return {
3511      name: name,
3512      rawVars: 1,
3513      init: function init(target, vars, tween) {
3514        tween._onInit = function (tween) {
3515          var temp, p;
3516
3517          if (_isString(vars)) {
3518            temp = {};
3519
3520            _forEachName(vars, function (name) {
3521              return temp[name] = 1;
3522            });
3523
3524            vars = temp;
3525          }
3526
3527          if (modifier) {
3528            temp = {};
3529
3530            for (p in vars) {
3531              temp[p] = modifier(vars[p]);
3532            }
3533
3534            vars = temp;
3535          }
3536
3537          _addModifiers(tween, vars);
3538        };
3539      }
3540    };
3541  };
3542
3543  var gsap = _gsap.registerPlugin({
3544    name: "attr",
3545    init: function init(target, vars, tween, index, targets) {
3546      var p, pt;
3547
3548      for (p in vars) {
3549        pt = this.add(target, "setAttribute", (target.getAttribute(p) || 0) + "", vars[p], index, targets, 0, 0, p);
3550        pt && (pt.op = p);
3551
3552        this._props.push(p);
3553      }
3554    }
3555  }, {
3556    name: "endArray",
3557    init: function init(target, value) {
3558      var i = value.length;
3559
3560      while (i--) {
3561        this.add(target, i, target[i] || 0, value[i]);
3562      }
3563    }
3564  }, _buildModifierPlugin("roundProps", _roundModifier), _buildModifierPlugin("modifiers"), _buildModifierPlugin("snap", snap)) || _gsap;
3565  Tween.version = Timeline.version = gsap.version = "3.6.1";
3566  _coreReady = 1;
3567
3568  if (_windowExists()) {
3569    _wake();
3570  }
3571
3572  var Power0 = _easeMap.Power0,
3573      Power1 = _easeMap.Power1,
3574      Power2 = _easeMap.Power2,
3575      Power3 = _easeMap.Power3,
3576      Power4 = _easeMap.Power4,
3577      Linear = _easeMap.Linear,
3578      Quad = _easeMap.Quad,
3579      Cubic = _easeMap.Cubic,
3580      Quart = _easeMap.Quart,
3581      Quint = _easeMap.Quint,
3582      Strong = _easeMap.Strong,
3583      Elastic = _easeMap.Elastic,
3584      Back = _easeMap.Back,
3585      SteppedEase = _easeMap.SteppedEase,
3586      Bounce = _easeMap.Bounce,
3587      Sine = _easeMap.Sine,
3588      Expo = _easeMap.Expo,
3589      Circ = _easeMap.Circ;
3590
3591  var _win$1,
3592      _doc$1,
3593      _docElement,
3594      _pluginInitted,
3595      _tempDiv,
3596      _tempDivStyler,
3597      _recentSetterPlugin,
3598      _windowExists$1 = function _windowExists() {
3599    return typeof window !== "undefined";
3600  },
3601      _transformProps = {},
3602      _RAD2DEG = 180 / Math.PI,
3603      _DEG2RAD = Math.PI / 180,
3604      _atan2 = Math.atan2,
3605      _bigNum$1 = 1e8,
3606      _capsExp = /([A-Z])/g,
3607      _horizontalExp = /(?:left|right|width|margin|padding|x)/i,
3608      _complexExp = /[\s,\(]\S/,
3609      _propertyAliases = {
3610    autoAlpha: "opacity,visibility",
3611    scale: "scaleX,scaleY",
3612    alpha: "opacity"
3613  },
3614      _renderCSSProp = function _renderCSSProp(ratio, data) {
3615    return data.set(data.t, data.p, Math.round((data.s + data.c * ratio) * 10000) / 10000 + data.u, data);
3616  },
3617      _renderPropWithEnd = function _renderPropWithEnd(ratio, data) {
3618    return data.set(data.t, data.p, ratio === 1 ? data.e : Math.round((data.s + data.c * ratio) * 10000) / 10000 + data.u, data);
3619  },
3620      _renderCSSPropWithBeginning = function _renderCSSPropWithBeginning(ratio, data) {
3621    return data.set(data.t, data.p, ratio ? Math.round((data.s + data.c * ratio) * 10000) / 10000 + data.u : data.b, data);
3622  },
3623      _renderRoundedCSSProp = function _renderRoundedCSSProp(ratio, data) {
3624    var value = data.s + data.c * ratio;
3625    data.set(data.t, data.p, ~~(value + (value < 0 ? -.5 : .5)) + data.u, data);
3626  },
3627      _renderNonTweeningValue = function _renderNonTweeningValue(ratio, data) {
3628    return data.set(data.t, data.p, ratio ? data.e : data.b, data);
3629  },
3630      _renderNonTweeningValueOnlyAtEnd = function _renderNonTweeningValueOnlyAtEnd(ratio, data) {
3631    return data.set(data.t, data.p, ratio !== 1 ? data.b : data.e, data);
3632  },
3633      _setterCSSStyle = function _setterCSSStyle(target, property, value) {
3634    return target.style[property] = value;
3635  },
3636      _setterCSSProp = function _setterCSSProp(target, property, value) {
3637    return target.style.setProperty(property, value);
3638  },
3639      _setterTransform = function _setterTransform(target, property, value) {
3640    return target._gsap[property] = value;
3641  },
3642      _setterScale = function _setterScale(target, property, value) {
3643    return target._gsap.scaleX = target._gsap.scaleY = value;
3644  },
3645      _setterScaleWithRender = function _setterScaleWithRender(target, property, value, data, ratio) {
3646    var cache = target._gsap;
3647    cache.scaleX = cache.scaleY = value;
3648    cache.renderTransform(ratio, cache);
3649  },
3650      _setterTransformWithRender = function _setterTransformWithRender(target, property, value, data, ratio) {
3651    var cache = target._gsap;
3652    cache[property] = value;
3653    cache.renderTransform(ratio, cache);
3654  },
3655      _transformProp = "transform",
3656      _transformOriginProp = _transformProp + "Origin",
3657      _supports3D,
3658      _createElement = function _createElement(type, ns) {
3659    var e = _doc$1.createElementNS ? _doc$1.createElementNS((ns || "http://www.w3.org/1999/xhtml").replace(/^https/, "http"), type) : _doc$1.createElement(type);
3660    return e.style ? e : _doc$1.createElement(type);
3661  },
3662      _getComputedProperty = function _getComputedProperty(target, property, skipPrefixFallback) {
3663    var cs = getComputedStyle(target);
3664    return cs[property] || cs.getPropertyValue(property.replace(_capsExp, "-$1").toLowerCase()) || cs.getPropertyValue(property) || !skipPrefixFallback && _getComputedProperty(target, _checkPropPrefix(property) || property, 1) || "";
3665  },
3666      _prefixes = "O,Moz,ms,Ms,Webkit".split(","),
3667      _checkPropPrefix = function _checkPropPrefix(property, element, preferPrefix) {
3668    var e = element || _tempDiv,
3669        s = e.style,
3670        i = 5;
3671
3672    if (property in s && !preferPrefix) {
3673      return property;
3674    }
3675
3676    property = property.charAt(0).toUpperCase() + property.substr(1);
3677
3678    while (i-- && !(_prefixes[i] + property in s)) {}
3679
3680    return i < 0 ? null : (i === 3 ? "ms" : i >= 0 ? _prefixes[i] : "") + property;
3681  },
3682      _initCore = function _initCore() {
3683    if (_windowExists$1() && window.document) {
3684      _win$1 = window;
3685      _doc$1 = _win$1.document;
3686      _docElement = _doc$1.documentElement;
3687      _tempDiv = _createElement("div") || {
3688        style: {}
3689      };
3690      _tempDivStyler = _createElement("div");
3691      _transformProp = _checkPropPrefix(_transformProp);
3692      _transformOriginProp = _transformProp + "Origin";
3693      _tempDiv.style.cssText = "border-width:0;line-height:0;position:absolute;padding:0";
3694      _supports3D = !!_checkPropPrefix("perspective");
3695      _pluginInitted = 1;
3696    }
3697  },
3698      _getBBoxHack = function _getBBoxHack(swapIfPossible) {
3699    var svg = _createElement("svg", this.ownerSVGElement && this.ownerSVGElement.getAttribute("xmlns") || "http://www.w3.org/2000/svg"),
3700        oldParent = this.parentNode,
3701        oldSibling = this.nextSibling,
3702        oldCSS = this.style.cssText,
3703        bbox;
3704
3705    _docElement.appendChild(svg);
3706
3707    svg.appendChild(this);
3708    this.style.display = "block";
3709
3710    if (swapIfPossible) {
3711      try {
3712        bbox = this.getBBox();
3713        this._gsapBBox = this.getBBox;
3714        this.getBBox = _getBBoxHack;
3715      } catch (e) {}
3716    } else if (this._gsapBBox) {
3717      bbox = this._gsapBBox();
3718    }
3719
3720    if (oldParent) {
3721      if (oldSibling) {
3722        oldParent.insertBefore(this, oldSibling);
3723      } else {
3724        oldParent.appendChild(this);
3725      }
3726    }
3727
3728    _docElement.removeChild(svg);
3729
3730    this.style.cssText = oldCSS;
3731    return bbox;
3732  },
3733      _getAttributeFallbacks = function _getAttributeFallbacks(target, attributesArray) {
3734    var i = attributesArray.length;
3735
3736    while (i--) {
3737      if (target.hasAttribute(attributesArray[i])) {
3738        return target.getAttribute(attributesArray[i]);
3739      }
3740    }
3741  },
3742      _getBBox = function _getBBox(target) {
3743    var bounds;
3744
3745    try {
3746      bounds = target.getBBox();
3747    } catch (error) {
3748      bounds = _getBBoxHack.call(target, true);
3749    }
3750
3751    bounds && (bounds.width || bounds.height) || target.getBBox === _getBBoxHack || (bounds = _getBBoxHack.call(target, true));
3752    return bounds && !bounds.width && !bounds.x && !bounds.y ? {
3753      x: +_getAttributeFallbacks(target, ["x", "cx", "x1"]) || 0,
3754      y: +_getAttributeFallbacks(target, ["y", "cy", "y1"]) || 0,
3755      width: 0,
3756      height: 0
3757    } : bounds;
3758  },
3759      _isSVG = function _isSVG(e) {
3760    return !!(e.getCTM && (!e.parentNode || e.ownerSVGElement) && _getBBox(e));
3761  },
3762      _removeProperty = function _removeProperty(target, property) {
3763    if (property) {
3764      var style = target.style;
3765
3766      if (property in _transformProps && property !== _transformOriginProp) {
3767        property = _transformProp;
3768      }
3769
3770      if (style.removeProperty) {
3771        if (property.substr(0, 2) === "ms" || property.substr(0, 6) === "webkit") {
3772          property = "-" + property;
3773        }
3774
3775        style.removeProperty(property.replace(_capsExp, "-$1").toLowerCase());
3776      } else {
3777        style.removeAttribute(property);
3778      }
3779    }
3780  },
3781      _addNonTweeningPT = function _addNonTweeningPT(plugin, target, property, beginning, end, onlySetAtEnd) {
3782    var pt = new PropTween(plugin._pt, target, property, 0, 1, onlySetAtEnd ? _renderNonTweeningValueOnlyAtEnd : _renderNonTweeningValue);
3783    plugin._pt = pt;
3784    pt.b = beginning;
3785    pt.e = end;
3786
3787    plugin._props.push(property);
3788
3789    return pt;
3790  },
3791      _nonConvertibleUnits = {
3792    deg: 1,
3793    rad: 1,
3794    turn: 1
3795  },
3796      _convertToUnit = function _convertToUnit(target, property, value, unit) {
3797    var curValue = parseFloat(value) || 0,
3798        curUnit = (value + "").trim().substr((curValue + "").length) || "px",
3799        style = _tempDiv.style,
3800        horizontal = _horizontalExp.test(property),
3801        isRootSVG = target.tagName.toLowerCase() === "svg",
3802        measureProperty = (isRootSVG ? "client" : "offset") + (horizontal ? "Width" : "Height"),
3803        amount = 100,
3804        toPixels = unit === "px",
3805        toPercent = unit === "%",
3806        px,
3807        parent,
3808        cache,
3809        isSVG;
3810
3811    if (unit === curUnit || !curValue || _nonConvertibleUnits[unit] || _nonConvertibleUnits[curUnit]) {
3812      return curValue;
3813    }
3814
3815    curUnit !== "px" && !toPixels && (curValue = _convertToUnit(target, property, value, "px"));
3816    isSVG = target.getCTM && _isSVG(target);
3817
3818    if ((toPercent || curUnit === "%") && (_transformProps[property] || ~property.indexOf("adius"))) {
3819      px = isSVG ? target.getBBox()[horizontal ? "width" : "height"] : target[measureProperty];
3820      return _round(toPercent ? curValue / px * amount : curValue / 100 * px);
3821    }
3822
3823    style[horizontal ? "width" : "height"] = amount + (toPixels ? curUnit : unit);
3824    parent = ~property.indexOf("adius") || unit === "em" && target.appendChild && !isRootSVG ? target : target.parentNode;
3825
3826    if (isSVG) {
3827      parent = (target.ownerSVGElement || {}).parentNode;
3828    }
3829
3830    if (!parent || parent === _doc$1 || !parent.appendChild) {
3831      parent = _doc$1.body;
3832    }
3833
3834    cache = parent._gsap;
3835
3836    if (cache && toPercent && cache.width && horizontal && cache.time === _ticker.time) {
3837      return _round(curValue / cache.width * amount);
3838    } else {
3839      (toPercent || curUnit === "%") && (style.position = _getComputedProperty(target, "position"));
3840      parent === target && (style.position = "static");
3841      parent.appendChild(_tempDiv);
3842      px = _tempDiv[measureProperty];
3843      parent.removeChild(_tempDiv);
3844      style.position = "absolute";
3845
3846      if (horizontal && toPercent) {
3847        cache = _getCache(parent);
3848        cache.time = _ticker.time;
3849        cache.width = parent[measureProperty];
3850      }
3851    }
3852
3853    return _round(toPixels ? px * curValue / amount : px && curValue ? amount / px * curValue : 0);
3854  },
3855      _get = function _get(target, property, unit, uncache) {
3856    var value;
3857    _pluginInitted || _initCore();
3858
3859    if (property in _propertyAliases && property !== "transform") {
3860      property = _propertyAliases[property];
3861
3862      if (~property.indexOf(",")) {
3863        property = property.split(",")[0];
3864      }
3865    }
3866
3867    if (_transformProps[property] && property !== "transform") {
3868      value = _parseTransform(target, uncache);
3869      value = property !== "transformOrigin" ? value[property] : _firstTwoOnly(_getComputedProperty(target, _transformOriginProp)) + " " + value.zOrigin + "px";
3870    } else {
3871      value = target.style[property];
3872
3873      if (!value || value === "auto" || uncache || ~(value + "").indexOf("calc(")) {
3874        value = _specialProps[property] && _specialProps[property](target, property, unit) || _getComputedProperty(target, property) || _getProperty(target, property) || (property === "opacity" ? 1 : 0);
3875      }
3876    }
3877
3878    return unit && !~(value + "").trim().indexOf(" ") ? _convertToUnit(target, property, value, unit) + unit : value;
3879  },
3880      _tweenComplexCSSString = function _tweenComplexCSSString(target, prop, start, end) {
3881    if (!start || start === "none") {
3882      var p = _checkPropPrefix(prop, target, 1),
3883          s = p && _getComputedProperty(target, p, 1);
3884
3885      if (s && s !== start) {
3886        prop = p;
3887        start = s;
3888      } else if (prop === "borderColor") {
3889        start = _getComputedProperty(target, "borderTopColor");
3890      }
3891    }
3892
3893    var pt = new PropTween(this._pt, target.style, prop, 0, 1, _renderComplexString),
3894        index = 0,
3895        matchIndex = 0,
3896        a,
3897        result,
3898        startValues,
3899        startNum,
3900        color,
3901        startValue,
3902        endValue,
3903        endNum,
3904        chunk,
3905        endUnit,
3906        startUnit,
3907        relative,
3908        endValues;
3909    pt.b = start;
3910    pt.e = end;
3911    start += "";
3912    end += "";
3913
3914    if (end === "auto") {
3915      target.style[prop] = end;
3916      end = _getComputedProperty(target, prop) || end;
3917      target.style[prop] = start;
3918    }
3919
3920    a = [start, end];
3921
3922    _colorStringFilter(a);
3923
3924    start = a[0];
3925    end = a[1];
3926    startValues = start.match(_numWithUnitExp) || [];
3927    endValues = end.match(_numWithUnitExp) || [];
3928
3929    if (endValues.length) {
3930      while (result = _numWithUnitExp.exec(end)) {
3931        endValue = result[0];
3932        chunk = end.substring(index, result.index);
3933
3934        if (color) {
3935          color = (color + 1) % 5;
3936        } else if (chunk.substr(-5) === "rgba(" || chunk.substr(-5) === "hsla(") {
3937          color = 1;
3938        }
3939
3940        if (endValue !== (startValue = startValues[matchIndex++] || "")) {
3941          startNum = parseFloat(startValue) || 0;
3942          startUnit = startValue.substr((startNum + "").length);
3943          relative = endValue.charAt(1) === "=" ? +(endValue.charAt(0) + "1") : 0;
3944
3945          if (relative) {
3946            endValue = endValue.substr(2);
3947          }
3948
3949          endNum = parseFloat(endValue);
3950          endUnit = endValue.substr((endNum + "").length);
3951          index = _numWithUnitExp.lastIndex - endUnit.length;
3952
3953          if (!endUnit) {
3954            endUnit = endUnit || _config.units[prop] || startUnit;
3955
3956            if (index === end.length) {
3957              end += endUnit;
3958              pt.e += endUnit;
3959            }
3960          }
3961
3962          if (startUnit !== endUnit) {
3963            startNum = _convertToUnit(target, prop, startValue, endUnit) || 0;
3964          }
3965
3966          pt._pt = {
3967            _next: pt._pt,
3968            p: chunk || matchIndex === 1 ? chunk : ",",
3969            s: startNum,
3970            c: relative ? relative * endNum : endNum - startNum,
3971            m: color && color < 4 || prop === "zIndex" ? Math.round : 0
3972          };
3973        }
3974      }
3975
3976      pt.c = index < end.length ? end.substring(index, end.length) : "";
3977    } else {
3978      pt.r = prop === "display" && end === "none" ? _renderNonTweeningValueOnlyAtEnd : _renderNonTweeningValue;
3979    }
3980
3981    _relExp.test(end) && (pt.e = 0);
3982    this._pt = pt;
3983    return pt;
3984  },
3985      _keywordToPercent = {
3986    top: "0%",
3987    bottom: "100%",
3988    left: "0%",
3989    right: "100%",
3990    center: "50%"
3991  },
3992      _convertKeywordsToPercentages = function _convertKeywordsToPercentages(value) {
3993    var split = value.split(" "),
3994        x = split[0],
3995        y = split[1] || "50%";
3996
3997    if (x === "top" || x === "bottom" || y === "left" || y === "right") {
3998      value = x;
3999      x = y;
4000      y = value;
4001    }
4002
4003    split[0] = _keywordToPercent[x] || x;
4004    split[1] = _keywordToPercent[y] || y;
4005    return split.join(" ");
4006  },
4007      _renderClearProps = function _renderClearProps(ratio, data) {
4008    if (data.tween && data.tween._time === data.tween._dur) {
4009      var target = data.t,
4010          style = target.style,
4011          props = data.u,
4012          cache = target._gsap,
4013          prop,
4014          clearTransforms,
4015          i;
4016
4017      if (props === "all" || props === true) {
4018        style.cssText = "";
4019        clearTransforms = 1;
4020      } else {
4021        props = props.split(",");
4022        i = props.length;
4023
4024        while (--i > -1) {
4025          prop = props[i];
4026
4027          if (_transformProps[prop]) {
4028            clearTransforms = 1;
4029            prop = prop === "transformOrigin" ? _transformOriginProp : _transformProp;
4030          }
4031
4032          _removeProperty(target, prop);
4033        }
4034      }
4035
4036      if (clearTransforms) {
4037        _removeProperty(target, _transformProp);
4038
4039        if (cache) {
4040          cache.svg && target.removeAttribute("transform");
4041
4042          _parseTransform(target, 1);
4043
4044          cache.uncache = 1;
4045        }
4046      }
4047    }
4048  },
4049      _specialProps = {
4050    clearProps: function clearProps(plugin, target, property, endValue, tween) {
vendor: 3,001 bytes, lines 4051-4131
4051      if (tween.data !== "isFromStart") {
4052        var pt = plugin._pt = new PropTween(plugin._pt, target, property, 0, 0, _renderClearProps);
4053        pt.u = endValue;
4054        pt.pr = -10;
4055        pt.tween = tween;
4056
4057        plugin._props.push(property);
4058
4059        return 1;
4060      }
4061    }
4062  },
4063      _identity2DMatrix = [1, 0, 0, 1, 0, 0],
4064      _rotationalProperties = {},
4065      _isNullTransform = function _isNullTransform(value) {
4066    return value === "matrix(1, 0, 0, 1, 0, 0)" || value === "none" || !value;
4067  },
4068      _getComputedTransformMatrixAsArray = function _getComputedTransformMatrixAsArray(target) {
4069    var matrixString = _getComputedProperty(target, _transformProp);
4070
4071    return _isNullTransform(matrixString) ? _identity2DMatrix : matrixString.substr(7).match(_numExp).map(_round);
4072  },
4073      _getMatrix = function _getMatrix(target, force2D) {
4074    var cache = target._gsap || _getCache(target),
4075        style = target.style,
4076        matrix = _getComputedTransformMatrixAsArray(target),
4077        parent,
4078        nextSibling,
4079        temp,
4080        addedToDOM;
4081
4082    if (cache.svg && target.getAttribute("transform")) {
4083      temp = target.transform.baseVal.consolidate().matrix;
4084      matrix = [temp.a, temp.b, temp.c, temp.d, temp.e, temp.f];
4085      return matrix.join(",") === "1,0,0,1,0,0" ? _identity2DMatrix : matrix;
4086    } else if (matrix === _identity2DMatrix && !target.offsetParent && target !== _docElement && !cache.svg) {
4087      temp = style.display;
4088      style.display = "block";
4089      parent = target.parentNode;
4090
4091      if (!parent || !target.offsetParent) {
4092        addedToDOM = 1;
4093        nextSibling = target.nextSibling;
4094
4095        _docElement.appendChild(target);
4096      }
4097
4098      matrix = _getComputedTransformMatrixAsArray(target);
4099      temp ? style.display = temp : _removeProperty(target, "display");
4100
4101      if (addedToDOM) {
4102        nextSibling ? parent.insertBefore(target, nextSibling) : parent ? parent.appendChild(target) : _docElement.removeChild(target);
4103      }
4104    }
4105
4106    return force2D && matrix.length > 6 ? [matrix[0], matrix[1], matrix[4], matrix[5], matrix[12], matrix[13]] : matrix;
4107  },
4108      _applySVGOrigin = function _applySVGOrigin(target, origin, originIsAbsolute, smooth, matrixArray, pluginToAddPropTweensTo) {
4109    var cache = target._gsap,
4110        matrix = matrixArray || _getMatrix(target, true),
4111        xOriginOld = cache.xOrigin || 0,
4112        yOriginOld = cache.yOrigin || 0,
4113        xOffsetOld = cache.xOffset || 0,
4114        yOffsetOld = cache.yOffset || 0,
4115        a = matrix[0],
4116        b = matrix[1],
4117        c = matrix[2],
4118        d = matrix[3],
4119        tx = matrix[4],
4120        ty = matrix[5],
4121        originSplit = origin.split(" "),
4122        xOrigin = parseFloat(originSplit[0]) || 0,
4123        yOrigin = parseFloat(originSplit[1]) || 0,
4124        bounds,
4125        determinant,
4126        x,
4127        y;
4128
4129    if (!originIsAbsolute) {
4130      bounds = _getBBox(target);
4131      xOrigin = bounds.x + (~originSplit[0].indexOf("%") ? xOrigin / 100 * boun
vendor: 6,518 bytes, lines 4131-4339
4131ds.width : xOrigin);
4132      yOrigin = bounds.y + (~(originSplit[1] || originSplit[0]).indexOf("%") ? yOrigin / 100 * bounds.height : yOrigin);
4133    } else if (matrix !== _identity2DMatrix && (determinant = a * d - b * c)) {
4134      x = xOrigin * (d / determinant) + yOrigin * (-c / determinant) + (c * ty - d * tx) / determinant;
4135      y = xOrigin * (-b / determinant) + yOrigin * (a / determinant) - (a * ty - b * tx) / determinant;
4136      xOrigin = x;
4137      yOrigin = y;
4138    }
4139
4140    if (smooth || smooth !== false && cache.smooth) {
4141      tx = xOrigin - xOriginOld;
4142      ty = yOrigin - yOriginOld;
4143      cache.xOffset = xOffsetOld + (tx * a + ty * c) - tx;
4144      cache.yOffset = yOffsetOld + (tx * b + ty * d) - ty;
4145    } else {
4146      cache.xOffset = cache.yOffset = 0;
4147    }
4148
4149    cache.xOrigin = xOrigin;
4150    cache.yOrigin = yOrigin;
4151    cache.smooth = !!smooth;
4152    cache.origin = origin;
4153    cache.originIsAbsolute = !!originIsAbsolute;
4154    target.style[_transformOriginProp] = "0px 0px";
4155
4156    if (pluginToAddPropTweensTo) {
4157      _addNonTweeningPT(pluginToAddPropTweensTo, cache, "xOrigin", xOriginOld, xOrigin);
4158
4159      _addNonTweeningPT(pluginToAddPropTweensTo, cache, "yOrigin", yOriginOld, yOrigin);
4160
4161      _addNonTweeningPT(pluginToAddPropTweensTo, cache, "xOffset", xOffsetOld, cache.xOffset);
4162
4163      _addNonTweeningPT(pluginToAddPropTweensTo, cache, "yOffset", yOffsetOld, cache.yOffset);
4164    }
4165
4166    target.setAttribute("data-svg-origin", xOrigin + " " + yOrigin);
4167  },
4168      _parseTransform = function _parseTransform(target, uncache) {
4169    var cache = target._gsap || new GSCache(target);
4170
4171    if ("x" in cache && !uncache && !cache.uncache) {
4172      return cache;
4173    }
4174
4175    var style = target.style,
4176        invertedScaleX = cache.scaleX < 0,
4177        px = "px",
4178        deg = "deg",
4179        origin = _getComputedProperty(target, _transformOriginProp) || "0",
4180        x,
4181        y,
4182        z,
4183        scaleX,
4184        scaleY,
4185        rotation,
4186        rotationX,
4187        rotationY,
4188        skewX,
4189        skewY,
4190        perspective,
4191        xOrigin,
4192        yOrigin,
4193        matrix,
4194        angle,
4195        cos,
4196        sin,
4197        a,
4198        b,
4199        c,
4200        d,
4201        a12,
4202        a22,
4203        t1,
4204        t2,
4205        t3,
4206        a13,
4207        a23,
4208        a33,
4209        a42,
4210        a43,
4211        a32;
4212    x = y = z = rotation = rotationX = rotationY = skewX = skewY = perspective = 0;
4213    scaleX = scaleY = 1;
4214    cache.svg = !!(target.getCTM && _isSVG(target));
4215    matrix = _getMatrix(target, cache.svg);
4216
4217    if (cache.svg) {
4218      t1 = !cache.uncache && !uncache && target.getAttribute("data-svg-origin");
4219
4220      _applySVGOrigin(target, t1 || origin, !!t1 || cache.originIsAbsolute, cache.smooth !== false, matrix);
4221    }
4222
4223    xOrigin = cache.xOrigin || 0;
4224    yOrigin = cache.yOrigin || 0;
4225
4226    if (matrix !== _identity2DMatrix) {
4227      a = matrix[0];
4228      b = matrix[1];
4229      c = matrix[2];
4230      d = matrix[3];
4231      x = a12 = matrix[4];
4232      y = a22 = matrix[5];
4233
4234      if (matrix.length === 6) {
4235        scaleX = Math.sqrt(a * a + b * b);
4236        scaleY = Math.sqrt(d * d + c * c);
4237        rotation = a || b ? _atan2(b, a) * _RAD2DEG : 0;
4238        skewX = c || d ? _atan2(c, d) * _RAD2DEG + rotation : 0;
4239        skewX && (scaleY *= Math.abs(Math.cos(skewX * _DEG2RAD)));
4240
4241        if (cache.svg) {
4242          x -= xOrigin - (xOrigin * a + yOrigin * c);
4243          y -= yOrigin - (xOrigin * b + yOrigin * d);
4244        }
4245      } else {
4246        a32 = matrix[6];
4247        a42 = matrix[7];
4248        a13 = matrix[8];
4249        a23 = matrix[9];
4250        a33 = matrix[10];
4251        a43 = matrix[11];
4252        x = matrix[12];
4253        y = matrix[13];
4254        z = matrix[14];
4255        angle = _atan2(a32, a33);
4256        rotationX = angle * _RAD2DEG;
4257
4258        if (angle) {
4259          cos = Math.cos(-angle);
4260          sin = Math.sin(-angle);
4261          t1 = a12 * cos + a13 * sin;
4262          t2 = a22 * cos + a23 * sin;
4263          t3 = a32 * cos + a33 * sin;
4264          a13 = a12 * -sin + a13 * cos;
4265          a23 = a22 * -sin + a23 * cos;
4266          a33 = a32 * -sin + a33 * cos;
4267          a43 = a42 * -sin + a43 * cos;
4268          a12 = t1;
4269          a22 = t2;
4270          a32 = t3;
4271        }
4272
4273        angle = _atan2(-c, a33);
4274        rotationY = angle * _RAD2DEG;
4275
4276        if (angle) {
4277          cos = Math.cos(-angle);
4278          sin = Math.sin(-angle);
4279          t1 = a * cos - a13 * sin;
4280          t2 = b * cos - a23 * sin;
4281          t3 = c * cos - a33 * sin;
4282          a43 = d * sin + a43 * cos;
4283          a = t1;
4284          b = t2;
4285          c = t3;
4286        }
4287
4288        angle = _atan2(b, a);
4289        rotation = angle * _RAD2DEG;
4290
4291        if (angle) {
4292          cos = Math.cos(angle);
4293          sin = Math.sin(angle);
4294          t1 = a * cos + b * sin;
4295          t2 = a12 * cos + a22 * sin;
4296          b = b * cos - a * sin;
4297          a22 = a22 * cos - a12 * sin;
4298          a = t1;
4299          a12 = t2;
4300        }
4301
4302        if (rotationX && Math.abs(rotationX) + Math.abs(rotation) > 359.9) {
4303          rotationX = rotation = 0;
4304          rotationY = 180 - rotationY;
4305        }
4306
4307        scaleX = _round(Math.sqrt(a * a + b * b + c * c));
4308        scaleY = _round(Math.sqrt(a22 * a22 + a32 * a32));
4309        angle = _atan2(a12, a22);
4310        skewX = Math.abs(angle) > 0.0002 ? angle * _RAD2DEG : 0;
4311        perspective = a43 ? 1 / (a43 < 0 ? -a43 : a43) : 0;
4312      }
4313
4314      if (cache.svg) {
4315        t1 = target.getAttribute("transform");
4316        cache.forceCSS = target.setAttribute("transform", "") || !_isNullTransform(_getComputedProperty(target, _transformProp));
4317        t1 && target.setAttribute("transform", t1);
4318      }
4319    }
4320
4321    if (Math.abs(skewX) > 90 && Math.abs(skewX) < 270) {
4322      if (invertedScaleX) {
4323        scaleX *= -1;
4324        skewX += rotation <= 0 ? 180 : -180;
4325        rotation += rotation <= 0 ? 180 : -180;
4326      } else {
4327        scaleY *= -1;
4328        skewX += skewX <= 0 ? 180 : -180;
4329      }
4330    }
4331
4332    cache.x = x - ((cache.xPercent = x && (cache.xPercent || (Math.round(target.offsetWidth / 2) === Math.round(-x) ? -50 : 0))) ? target.offsetWidth * cache.xPercent / 100 : 0) + px;
4333    cache.y = y - ((cache.yPercent = y && (cache.yPercent || (Math.round(target.offsetHeight / 2) === Math.round(-y) ? -50 : 0))) ? target.offsetHeight * cache.yPercent / 100 : 0) + px;
4334    cache.z = z + px;
4335    cache.scaleX = _round(scaleX);
4336    cache.scaleY = _round(scaleY);
4337    cache.rotation = _round(rotation) + deg;
4338    cache.rotationX = _round(rotationX) + deg;
4339    cache.rotationY = _round(rotationY) + deg;
vendor: 4,199 bytes, lines 4340-4467
4340    cache.skewX = skewX + deg;
4341    cache.skewY = skewY + deg;
4342    cache.transformPerspective = perspective + px;
4343
4344    if (cache.zOrigin = parseFloat(origin.split(" ")[2]) || 0) {
4345      style[_transformOriginProp] = _firstTwoOnly(origin);
4346    }
4347
4348    cache.xOffset = cache.yOffset = 0;
4349    cache.force3D = _config.force3D;
4350    cache.renderTransform = cache.svg ? _renderSVGTransforms : _supports3D ? _renderCSSTransforms : _renderNon3DTransforms;
4351    cache.uncache = 0;
4352    return cache;
4353  },
4354      _firstTwoOnly = function _firstTwoOnly(value) {
4355    return (value = value.split(" "))[0] + " " + value[1];
4356  },
4357      _addPxTranslate = function _addPxTranslate(target, start, value) {
4358    var unit = getUnit(start);
4359    return _round(parseFloat(start) + parseFloat(_convertToUnit(target, "x", value + "px", unit))) + unit;
4360  },
4361      _renderNon3DTransforms = function _renderNon3DTransforms(ratio, cache) {
4362    cache.z = "0px";
4363    cache.rotationY = cache.rotationX = "0deg";
4364    cache.force3D = 0;
4365
4366    _renderCSSTransforms(ratio, cache);
4367  },
4368      _zeroDeg = "0deg",
4369      _zeroPx = "0px",
4370      _endParenthesis = ") ",
4371      _renderCSSTransforms = function _renderCSSTransforms(ratio, cache) {
4372    var _ref = cache || this,
4373        xPercent = _ref.xPercent,
4374        yPercent = _ref.yPercent,
4375        x = _ref.x,
4376        y = _ref.y,
4377        z = _ref.z,
4378        rotation = _ref.rotation,
4379        rotationY = _ref.rotationY,
4380        rotationX = _ref.rotationX,
4381        skewX = _ref.skewX,
4382        skewY = _ref.skewY,
4383        scaleX = _ref.scaleX,
4384        scaleY = _ref.scaleY,
4385        transformPerspective = _ref.transformPerspective,
4386        force3D = _ref.force3D,
4387        target = _ref.target,
4388        zOrigin = _ref.zOrigin,
4389        transforms = "",
4390        use3D = force3D === "auto" && ratio && ratio !== 1 || force3D === true;
4391
4392    if (zOrigin && (rotationX !== _zeroDeg || rotationY !== _zeroDeg)) {
4393      var angle = parseFloat(rotationY) * _DEG2RAD,
4394          a13 = Math.sin(angle),
4395          a33 = Math.cos(angle),
4396          cos;
4397
4398      angle = parseFloat(rotationX) * _DEG2RAD;
4399      cos = Math.cos(angle);
4400      x = _addPxTranslate(target, x, a13 * cos * -zOrigin);
4401      y = _addPxTranslate(target, y, -Math.sin(angle) * -zOrigin);
4402      z = _addPxTranslate(target, z, a33 * cos * -zOrigin + zOrigin);
4403    }
4404
4405    if (transformPerspective !== _zeroPx) {
4406      transforms += "perspective(" + transformPerspective + _endParenthesis;
4407    }
4408
4409    if (xPercent || yPercent) {
4410      transforms += "translate(" + xPercent + "%, " + yPercent + "%) ";
4411    }
4412
4413    if (use3D || x !== _zeroPx || y !== _zeroPx || z !== _zeroPx) {
4414      transforms += z !== _zeroPx || use3D ? "translate3d(" + x + ", " + y + ", " + z + ") " : "translate(" + x + ", " + y + _endParenthesis;
4415    }
4416
4417    if (rotation !== _zeroDeg) {
4418      transforms += "rotate(" + rotation + _endParenthesis;
4419    }
4420
4421    if (rotationY !== _zeroDeg) {
4422      transforms += "rotateY(" + rotationY + _endParenthesis;
4423    }
4424
4425    if (rotationX !== _zeroDeg) {
4426      transforms += "rotateX(" + rotationX + _endParenthesis;
4427    }
4428
4429    if (skewX !== _zeroDeg || skewY !== _zeroDeg) {
4430      transforms += "skew(" + skewX + ", " + skewY + _endParenthesis;
4431    }
4432
4433    if (scaleX !== 1 || scaleY !== 1) {
4434      transforms += "scale(" + scaleX + ", " + scaleY + _endParenthesis;
4435    }
4436
4437    target.style[_transformProp] = transforms || "translate(0, 0)";
4438  },
4439      _renderSVGTransforms = function _renderSVGTransforms(ratio, cache) {
4440    var _ref2 = cache || this,
4441        xPercent = _ref2.xPercent,
4442        yPercent = _ref2.yPercent,
4443        x = _ref2.x,
4444        y = _ref2.y,
4445        rotation = _ref2.rotation,
4446        skewX = _ref2.skewX,
4447        skewY = _ref2.skewY,
4448        scaleX = _ref2.scaleX,
4449        scaleY = _ref2.scaleY,
4450        target = _ref2.target,
4451        xOrigin = _ref2.xOrigin,
4452        yOrigin = _ref2.yOrigin,
4453        xOffset = _ref2.xOffset,
4454        yOffset = _ref2.yOffset,
4455        forceCSS = _ref2.forceCSS,
4456        tx = parseFloat(x),
4457        ty = parseFloat(y),
4458        a11,
4459        a21,
4460        a12,
4461        a22,
4462        temp;
4463
4464    rotation = parseFloat(rotation);
4465    skewX = parseFloat(skewX);
4466    skewY = parseFloat(skewY);
4467
vendor: 4,432 bytes, lines 4468-4616
4468    if (skewY) {
4469      skewY = parseFloat(skewY);
4470      skewX += skewY;
4471      rotation += skewY;
4472    }
4473
4474    if (rotation || skewX) {
4475      rotation *= _DEG2RAD;
4476      skewX *= _DEG2RAD;
4477      a11 = Math.cos(rotation) * scaleX;
4478      a21 = Math.sin(rotation) * scaleX;
4479      a12 = Math.sin(rotation - skewX) * -scaleY;
4480      a22 = Math.cos(rotation - skewX) * scaleY;
4481
4482      if (skewX) {
4483        skewY *= _DEG2RAD;
4484        temp = Math.tan(skewX - skewY);
4485        temp = Math.sqrt(1 + temp * temp);
4486        a12 *= temp;
4487        a22 *= temp;
4488
4489        if (skewY) {
4490          temp = Math.tan(skewY);
4491          temp = Math.sqrt(1 + temp * temp);
4492          a11 *= temp;
4493          a21 *= temp;
4494        }
4495      }
4496
4497      a11 = _round(a11);
4498      a21 = _round(a21);
4499      a12 = _round(a12);
4500      a22 = _round(a22);
4501    } else {
4502      a11 = scaleX;
4503      a22 = scaleY;
4504      a21 = a12 = 0;
4505    }
4506
4507    if (tx && !~(x + "").indexOf("px") || ty && !~(y + "").indexOf("px")) {
4508      tx = _convertToUnit(target, "x", x, "px");
4509      ty = _convertToUnit(target, "y", y, "px");
4510    }
4511
4512    if (xOrigin || yOrigin || xOffset || yOffset) {
4513      tx = _round(tx + xOrigin - (xOrigin * a11 + yOrigin * a12) + xOffset);
4514      ty = _round(ty + yOrigin - (xOrigin * a21 + yOrigin * a22) + yOffset);
4515    }
4516
4517    if (xPercent || yPercent) {
4518      temp = target.getBBox();
4519      tx = _round(tx + xPercent / 100 * temp.width);
4520      ty = _round(ty + yPercent / 100 * temp.height);
4521    }
4522
4523    temp = "matrix(" + a11 + "," + a21 + "," + a12 + "," + a22 + "," + tx + "," + ty + ")";
4524    target.setAttribute("transform", temp);
4525    forceCSS && (target.style[_transformProp] = temp);
4526  },
4527      _addRotationalPropTween = function _addRotationalPropTween(plugin, target, property, startNum, endValue, relative) {
4528    var cap = 360,
4529        isString = _isString(endValue),
4530        endNum = parseFloat(endValue) * (isString && ~endValue.indexOf("rad") ? _RAD2DEG : 1),
4531        change = relative ? endNum * relative : endNum - startNum,
4532        finalValue = startNum + change + "deg",
4533        direction,
4534        pt;
4535
4536    if (isString) {
4537      direction = endValue.split("_")[1];
4538
4539      if (direction === "short") {
4540        change %= cap;
4541
4542        if (change !== change % (cap / 2)) {
4543          change += change < 0 ? cap : -cap;
4544        }
4545      }
4546
4547      if (direction === "cw" && change < 0) {
4548        change = (change + cap * _bigNum$1) % cap - ~~(change / cap) * cap;
4549      } else if (direction === "ccw" && change > 0) {
4550        change = (change - cap * _bigNum$1) % cap - ~~(change / cap) * cap;
4551      }
4552    }
4553
4554    plugin._pt = pt = new PropTween(plugin._pt, target, property, startNum, change, _renderPropWithEnd);
4555    pt.e = finalValue;
4556    pt.u = "deg";
4557
4558    plugin._props.push(property);
4559
4560    return pt;
4561  },
4562      _assign = function _assign(target, source) {
4563    for (var p in source) {
4564      target[p] = source[p];
4565    }
4566
4567    return target;
4568  },
4569      _addRawTransformPTs = function _addRawTransformPTs(plugin, transforms, target) {
4570    var startCache = _assign({}, target._gsap),
4571        exclude = "perspective,force3D,transformOrigin,svgOrigin",
4572        style = target.style,
4573        endCache,
4574        p,
4575        startValue,
4576        endValue,
4577        startNum,
4578        endNum,
4579        startUnit,
4580        endUnit;
4581
4582    if (startCache.svg) {
4583      startValue = target.getAttribute("transform");
4584      target.setAttribute("transform", "");
4585      style[_transformProp] = transforms;
4586      endCache = _parseTransform(target, 1);
4587
4588      _removeProperty(target, _transformProp);
4589
4590      target.setAttribute("transform", startValue);
4591    } else {
4592      startValue = getComputedStyle(target)[_transformProp];
4593      style[_transformProp] = transforms;
4594      endCache = _parseTransform(target, 1);
4595      style[_transformProp] = startValue;
4596    }
4597
4598    for (p in _transformProps) {
4599      startValue = startCache[p];
4600      endValue = endCache[p];
4601
4602      if (startValue !== endValue && exclude.indexOf(p) < 0) {
4603        startUnit = getUnit(startValue);
4604        endUnit = getUnit(endValue);
4605        startNum = startUnit !== endUnit ? _convertToUnit(target, p, startValue, endUnit) : parseFloat(startValue);
4606        endNum = parseFloat(endValue);
4607        plugin._pt = new PropTween(plugin._pt, endCache, p, startNum, endNum - startNum, _renderCSSProp);
4608        plugin._pt.u = endUnit || 0;
4609
4610        plugin._props.push(p);
4611      }
4612    }
4613
4614    _assign(endCache, startCache);
4615  };
4616
vendor: 4,076 bytes, lines 4617-4738
4617  _forEachName("padding,margin,Width,Radius", function (name, index) {
4618    var t = "Top",
4619        r = "Right",
4620        b = "Bottom",
4621        l = "Left",
4622        props = (index < 3 ? [t, r, b, l] : [t + l, t + r, b + r, b + l]).map(function (side) {
4623      return index < 2 ? name + side : "border" + side + name;
4624    });
4625
4626    _specialProps[index > 1 ? "border" + name : name] = function (plugin, target, property, endValue, tween) {
4627      var a, vars;
4628
4629      if (arguments.length < 4) {
4630        a = props.map(function (prop) {
4631          return _get(plugin, prop, property);
4632        });
4633        vars = a.join(" ");
4634        return vars.split(a[0]).length === 5 ? a[0] : vars;
4635      }
4636
4637      a = (endValue + "").split(" ");
4638      vars = {};
4639      props.forEach(function (prop, i) {
4640        return vars[prop] = a[i] = a[i] || a[(i - 1) / 2 | 0];
4641      });
4642      plugin.init(target, vars, tween);
4643    };
4644  });
4645
4646  var CSSPlugin = {
4647    name: "css",
4648    register: _initCore,
4649    targetTest: function targetTest(target) {
4650      return target.style && target.nodeType;
4651    },
4652    init: function init(target, vars, tween, index, targets) {
4653      var props = this._props,
4654          style = target.style,
4655          startAt = tween.vars.startAt,
4656          startValue,
4657          endValue,
4658          endNum,
4659          startNum,
4660          type,
4661          specialProp,
4662          p,
4663          startUnit,
4664          endUnit,
4665          relative,
4666          isTransformRelated,
4667          transformPropTween,
4668          cache,
4669          smooth,
4670          hasPriority;
4671      _pluginInitted || _initCore();
4672
4673      for (p in vars) {
4674        if (p === "autoRound") {
4675          continue;
4676        }
4677
4678        endValue = vars[p];
4679
4680        if (_plugins[p] && _checkPlugin(p, vars, tween, index, target, targets)) {
4681          continue;
4682        }
4683
4684        type = typeof endValue;
4685        specialProp = _specialProps[p];
4686
4687        if (type === "function") {
4688          endValue = endValue.call(tween, index, target, targets);
4689          type = typeof endValue;
4690        }
4691
4692        if (type === "string" && ~endValue.indexOf("random(")) {
4693          endValue = _replaceRandom(endValue);
4694        }
4695
4696        if (specialProp) {
4697          specialProp(this, target, p, endValue, tween) && (hasPriority = 1);
4698        } else if (p.substr(0, 2) === "--") {
4699          startValue = (getComputedStyle(target).getPropertyValue(p) + "").trim();
4700          endValue += "";
4701          _colorExp.lastIndex = 0;
4702
4703          if (!_colorExp.test(startValue)) {
4704            startUnit = getUnit(startValue);
4705            endUnit = getUnit(endValue);
4706          }
4707
4708          endUnit ? startUnit !== endUnit && (startValue = _convertToUnit(target, p, startValue, endUnit) + endUnit) : startUnit && (endValue += startUnit);
4709          this.add(style, "setProperty", startValue, endValue, index, targets, 0, 0, p);
4710        } else if (type !== "undefined") {
4711          if (startAt && p in startAt) {
4712            startValue = typeof startAt[p] === "function" ? startAt[p].call(tween, index, target, targets) : startAt[p];
4713            p in _config.units && !getUnit(startValue) && (startValue += _config.units[p]);
4714            (startValue + "").charAt(1) === "=" && (startValue = _get(target, p));
4715          } else {
4716            startValue = _get(target, p);
4717          }
4718
4719          startNum = parseFloat(startValue);
4720          relative = type === "string" && endValue.charAt(1) === "=" ? +(endValue.charAt(0) + "1") : 0;
4721          relative && (endValue = endValue.substr(2));
4722          endNum = parseFloat(endValue);
4723
4724          if (p in _propertyAliases) {
4725            if (p === "autoAlpha") {
4726              if (startNum === 1 && _get(target, "visibility") === "hidden" && endNum) {
4727                startNum = 0;
4728              }
4729
4730              _addNonTweeningPT(this, style, "visibility", startNum ? "inherit" : "hidden", endNum ? "inherit" : "hidden", !endNum);
4731            }
4732
4733            if (p !== "scale" && p !== "transform") {
4734              p = _propertyAliases[p];
4735              ~p.indexOf(",") && (p = p.split(",")[0]);
4736            }
4737          }
4738
vendor: 4,279 bytes, lines 4739-4832
4739          isTransformRelated = p in _transformProps;
4740
4741          if (isTransformRelated) {
4742            if (!transformPropTween) {
4743              cache = target._gsap;
4744              cache.renderTransform && !vars.parseTransform || _parseTransform(target, vars.parseTransform);
4745              smooth = vars.smoothOrigin !== false && cache.smooth;
4746              transformPropTween = this._pt = new PropTween(this._pt, style, _transformProp, 0, 1, cache.renderTransform, cache, 0, -1);
4747              transformPropTween.dep = 1;
4748            }
4749
4750            if (p === "scale") {
4751              this._pt = new PropTween(this._pt, cache, "scaleY", cache.scaleY, relative ? relative * endNum : endNum - cache.scaleY);
4752              props.push("scaleY", p);
4753              p += "X";
4754            } else if (p === "transformOrigin") {
4755              endValue = _convertKeywordsToPercentages(endValue);
4756
4757              if (cache.svg) {
4758                _applySVGOrigin(target, endValue, 0, smooth, 0, this);
4759              } else {
4760                endUnit = parseFloat(endValue.split(" ")[2]) || 0;
4761                endUnit !== cache.zOrigin && _addNonTweeningPT(this, cache, "zOrigin", cache.zOrigin, endUnit);
4762
4763                _addNonTweeningPT(this, style, p, _firstTwoOnly(startValue), _firstTwoOnly(endValue));
4764              }
4765
4766              continue;
4767            } else if (p === "svgOrigin") {
4768              _applySVGOrigin(target, endValue, 1, smooth, 0, this);
4769
4770              continue;
4771            } else if (p in _rotationalProperties) {
4772              _addRotationalPropTween(this, cache, p, startNum, endValue, relative);
4773
4774              continue;
4775            } else if (p === "smoothOrigin") {
4776              _addNonTweeningPT(this, cache, "smooth", cache.smooth, endValue);
4777
4778              continue;
4779            } else if (p === "force3D") {
4780              cache[p] = endValue;
4781              continue;
4782            } else if (p === "transform") {
4783              _addRawTransformPTs(this, endValue, target);
4784
4785              continue;
4786            }
4787          } else if (!(p in style)) {
4788            p = _checkPropPrefix(p) || p;
4789          }
4790
4791          if (isTransformRelated || (endNum || endNum === 0) && (startNum || startNum === 0) && !_complexExp.test(endValue) && p in style) {
4792            startUnit = (startValue + "").substr((startNum + "").length);
4793            endNum || (endNum = 0);
4794            endUnit = getUnit(endValue) || (p in _config.units ? _config.units[p] : startUnit);
4795            startUnit !== endUnit && (startNum = _convertToUnit(target, p, startValue, endUnit));
4796            this._pt = new PropTween(this._pt, isTransformRelated ? cache : style, p, startNum, relative ? relative * endNum : endNum - startNum, !isTransformRelated && (endUnit === "px" || p === "zIndex") && vars.autoRound !== false ? _renderRoundedCSSProp : _renderCSSProp);
4797            this._pt.u = endUnit || 0;
4798
4799            if (startUnit !== endUnit) {
4800              this._pt.b = startValue;
4801              this._pt.r = _renderCSSPropWithBeginning;
4802            }
4803          } else if (!(p in style)) {
4804            if (p in target) {
4805              this.add(target, p, target[p], endValue, index, targets);
4806            } else {
4807              _missingPlugin(p, endValue);
4808
4809              continue;
4810            }
4811          } else {
4812            _tweenComplexCSSString.call(this, target, p, startValue, endValue);
4813          }
4814
4815          props.push(p);
4816        }
4817      }
4818
4819      hasPriority && _sortPropTweensByPriority(this);
4820    },
4821    get: _get,
4822    aliases: _propertyAliases,
4823    getSetter: function getSetter(target, property, plugin) {
4824      var p = _propertyAliases[property];
4825      p && p.indexOf(",") < 0 && (property = p);
4826      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);
4827    },
4828    core: {
4829      _removeProperty: _removeProperty,
4830      _getMatrix: _getMatrix
4831    }
4832  };
4833  gsap.utils.checkPrefix = _checkPropPrefix;
4834
4835  (function (positionAndScale, rotation, others, aliases) {
4836    var all = _forEachName(positionAndScale + "," + rotation + "," + others, function (name) {
4837      _transformProps[name] = 1;
4838    });
4839
4840    _forEachName(rotation, function (name) {
4841      _config.units[name] = "deg";
4842      _rotationalProperties[name] = 1;
4843    });
4844
4845    _propertyAliases[all[13]] = positionAndScale + "," + rotation;
4846
4847    _forEachName(aliases, function (name) {
4848      var split = name.split(":");
4849      _propertyAliases[split[1]] = all[split[0]];
4850    });
4851  })("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");
4852
4853  _forEachName("x,y,z,top,right,bottom,left,width,height,fontSize,padding,margin,perspective", function (name) {
4854    _config.units[name] = "px";
4855  });
4856
4857  gsap.registerPlugin(CSSPlugin);
4858
4859  var gsapWithCSS = gsap.registerPlugin(CSSPlugin) || gsap,
4860      TweenMaxWithCSS = gsapWithCSS.core.Tween;
4861
4862  exports.Back = Back;
4863  exports.Bounce = Bounce;
4864  exports.CSSPlugin = CSSPlugin;
4865  exports.Circ = Circ;
4866  exports.Cubic = Cubic;
4867  exports.Elastic = Elastic;
4868  exports.Expo = Expo;
4869  exports.Linear = Linear;
4870  exports.Power0 = Power0;
4871  exports.Power1 = Power1;
4872  exports.Power2 = Power2;
4873  exports.Power3 = Power3;
4874  exports.Power4 = Power4;
4875  exports.Quad = Quad;
4876  exports.Quart = Quart;
4877  exports.Quint = Quint;
4878  exports.Sine = Sine;
4879  exports.SteppedEase = SteppedEase;
4880  exports.Strong = Strong;
4881  exports.TimelineLite = Timeline;
4882  exports.TimelineMax = Timeline;
4883  exports.TweenLite = Tween;
4884  exports.TweenMax = TweenMaxWithCSS;
4885  exports.default = gsapWithCSS;
4886  exports.gsap = gsapWithCSS;
4887
4888  if (typeof(window) === 'undefined' || window !== exports) {Object.defineProperty(exports, '__esModule', { value: true });} else {delete window.default;}
4889
4890})));
4891
4892(function(window, $) {
4893  'use strict';
4894  var counter = 0,
4895    $headCache = $('head'),
4896    oldBigText = window.BigText,
4897    oldjQueryMethod = $.fn.bigtext,
4898    BigText = {
4899      DEBUG_MODE: false,
4900      DEFAULT_MIN_FONT_SIZE_PX: null,
4901      DEFAULT_MAX_FONT_SIZE_PX: 528,
4902      GLOBAL_STYLE_ID: 'bigtext-style',
4903      STYLE_ID: 'bigtext-id',
4904      LINE_CLASS_PREFIX: 'bigtext-line',
4905      EXEMPT_CLASS: 'bigtext-exempt',
4906      noConflict: function(restore)
4907      {
4908        if(restore) {
4909          $.fn.bigtext = oldjQueryMethod;
4910          window.BigText = oldBigText;
4911        }
4912        return BigText;
4913      },
4914      supports: {
4915        wholeNumberFontSizeOnly: (function() {
4916          if( !( 'getComputedStyle' in window ) ) {
4917            return true;
4918          }
4919          var test = $('<div/>').css({
4920              position: 'absolute',
4921              'font-size': '14.1px'
4922            }).insertBefore( $('script').eq(0) ),
4923            computedStyle = window.getComputedStyle( test[0], null );
4924
4925          var ret = computedStyle && computedStyle.getPropertyValue( 'font-size' ) === '14px';
4926          test.remove();
4927          return ret;
4928        })()
4929      },
4930      init: function() {
4931        if(!$('#'+BigText.GLOBAL_STYLE_ID).length) {
4932          $headCache.append(BigText.generateStyleTag(BigText.GLOBAL_STYLE_ID, ['.bigtext * { white-space: nowrap; } .bigtext > * { display: block; }',
4933                                          '.bigtext .' + BigText.EXEMPT_CLASS + ', .bigtext .' + BigText.EXEMPT_CLASS + ' * { white-space: normal; }']));
4934        }
4935      },
4936      bindResize: function(eventName, resizeFunction) {
4937        var timeoutId;
4938        $(window).unbind(eventName).bind(eventName, function() {
4939          if( timeoutId ) {
4940            clearTimeout( timeoutId );
4941          }
4942          timeoutId = setTimeout( resizeFunction, 300 );
4943        });
4944      },
4945      getStyleId: function(id)
4946      {
4947        return BigText.STYLE_ID + '-' + id;
4948      },
4949      generateStyleTag: function(id, css)
4950      {
4951        return $('<style>' + css.join('\n') + '</style>').attr('id', id);
4952      },
4953      clearCss: function(id)
4954      {
4955        var styleId = BigText.getStyleId(id);
4956        $('#' + styleId).remove();
4957      },
4958      generateCss: function(id, linesFontSizes, lineWordSpacings, minFontSizes)
4959      {
4960        var css = [];
4961
4962        BigText.clearCss(id);
4963
4964        for(var j=0, k=linesFontSizes.length; j<k; j++) {
4965          css.push('#' + id + ' .' + BigText.LINE_CLASS_PREFIX + j + ' {' +
4966            (minFontSizes[j] ? ' white-space: normal;' : '') +
4967            (linesFontSizes[j] ? ' font-size: ' + linesFontSizes[j] + 'px;' : '') +
4968            (lineWordSpacings[j] ? ' word-spacing: ' + lineWordSpacings[j] + 'px;' : '') +
4969            '}');
4970        }
4971
4972        return BigText.generateStyleTag(BigText.getStyleId(id), css);
4973      },
4974      jQueryMethod: function(options)
4975      {
4976        BigText.init();
4977
4978        options = $.extend({
4979          minfontsize: BigText.DEFAULT_MIN_FONT_SIZE_PX,
4980          maxfontsize: BigText.DEFAULT_MAX_FONT_SIZE_PX,
4981          childSelector: '',
4982          resize: true
4983        }, options || {});
4984
4985        this.each(function()
4986        {
4987          var $t = $(this).addClass('bigtext'),
4988            maxWidth = $t.width(),
4989            id = $t.attr('id'),
4990            $children = options.childSelector ? $t.find( options.childSelector ) : $t.children();
4991
4992          if(!id) {
4993            id = 'bigtext-id' + (counter++);
4994            $t.attr('id', id);
4995          }
4996
4997          if(options.resize) {
4998            BigText.bindResize('resize.bigtext-event-' + id, function()
4999            {
5000              // TODO only call this if the width has changed.
5001              BigText.jQueryMethod.call($('#' + id), options);
5002            });
5003          }
5004
5005          BigText.clearCss(id);
5006
5007          $children.addClass(function(lineNumber, className)
5008          {
5009            // remove existing line classes.
5010            return [className.replace(new RegExp('\\b' + BigText.LINE_CLASS_PREFIX + '\\d+\\b'), ''),
5011                BigText.LINE_CLASS_PREFIX + lineNumber].join(' ');
5012          });
5013
5014          var sizes = calculateSizes($t, $children, maxWidth, options.maxfontsize, options.minfontsize);
5015          $headCache.append(BigText.generateCss(id, sizes.fontSizes, sizes.wordSpacings, sizes.minFontSizes));
5016        });
5017
5018        return this.trigger('bigtext:complete');
5019      }
5020    };
5021
5022  function testLineDimensions($line, maxWidth, property, size, interval, units, previousWidth)
5023  {
5024    var width;
5025    previousWidth = typeof previousWidth === 'number' ? previousWidth : 0;
5026    $line.css(property, size + units);
5027
5028    width = $line.width();
5029
5030    if(width >= maxWidth) {
5031
5032      $line.css(property, '');
5033
5034      if(width === maxWidth) {
5035        return {
5036          match: 'exact',
5037          size: parseFloat((parseFloat(size) - 0.1).toFixed(3))
5038        };
5039      }
5040
5041      // Since this is an estimate, we calculate how far over the width we went with the new value.
5042      // If this is word-spacing (our last resort guess) and the over is less than the under, we keep the higher value.
5043      // Otherwise, we revert to the underestimate.
5044      var under = maxWidth - previousWidth,
5045        over = width - maxWidth;
5046
5047      return {
5048        match: 'estimate',
5049        size: parseFloat((parseFloat(size) - (property === 'word-spacing' && previousWidth && ( over < under ) ? 0 : interval)).toFixed(3))
5050      };
5051    }
5052
5053    return width;
5054  }
5055
5056  function calculateSizes($t, $children, maxWidth, maxFontSize, minFontSize)
5057  {
5058    var $c = $t.clone(true)
5059      .addClass('bigtext-cloned')
5060      .css({
5061        fontFamily: $t.css('font-family'),
5062        textTransform: $t.css('text-transform'),
5063        wordSpacing: $t.css('word-spacing'),
5064        letterSpacing: $t.css('letter-spacing'),
5065        position: 'absolute',
5066        left: BigText.DEBUG_MODE ? 0 : -9999,
5067        top: BigText.DEBUG_MODE ? 0 : -9999
5068      })
5069      .appendTo(document.body);
5070
5071    // font-size isn't the only thing we can modify, we can also mess with:
5072    // word-spacing and letter-spacing. WebKit does not respect subpixel
5073    // letter-spacing, word-spacing, or font-size.
5074    // TODO try -webkit-transform: scale() as a workaround.
5075    var fontSizes = [],
5076      wordSpacings = [],
5077      minFontSizes = [],
5078      ratios = [];
5079
5080    $children.css('float', 'left').each(function() {
5081      var $line = $(this),
5082        // TODO replace 8, 4 with a proportional size to the calculated font-size.
5083        intervals = BigText.supports.wholeNumberFontSizeOnly ? [8, 4, 1] : [8, 4, 1, 0.1],
5084        lineMax,
5085        newFontSize;
5086
5087      if($line.hasClass(BigText.EXEMPT_CLASS)) {
5088        fontSizes.push(null);
5089        ratios.push(null);
5090        minFontSizes.push(false);
5091        return;
5092      }
5093
5094      // TODO we can cache this ratio?
5095      var autoGuessSubtraction = 32, // font size in px
5096        currentFontSize = parseFloat($line.css('font-size')),
5097        ratio = ( $line.width() / currentFontSize ).toFixed(6);
5098
5099      newFontSize = parseInt( maxWidth / ratio, 10 ) - autoGuessSubtraction;
5100
5101      outer: for(var m=0, n=intervals.length; m<n; m++) {
5102        inner: for(var j=1, k=10; j<=k; j++) {
5103          if(newFontSize + j*intervals[m] > maxFontSize) {
5104            newFontSize = maxFontSize;
5105            break outer;
5106          }
5107
5108          lineMax = testLineDimensions($line, maxWidth, 'font-size', newFontSize + j*intervals[m], intervals[m], 'px', lineMax);
5109          if(typeof lineMax !== 'number') {
5110            newFontSize = lineMax.size;
5111
5112            if(lineMax.match === 'exact') {
5113              break outer;
5114            }
5115            break inner;
5116          }
5117        }
5118      }
5119
5120      ratios.push(maxWidth / newFontSize);
5121
5122      if(newFontSize > maxFontSize) {
5123        fontSizes.push(maxFontSize);
5124        minFontSizes.push(false);
5125      } else if(!!minFontSize && newFontSize < minFontSize) {
5126        fontSizes.push(minFontSize);
5127        minFontSizes.push(true);
5128      } else {
5129        fontSizes.push(newFontSize);
5130        minFontSizes.push(false);
5131      }
5132    }).each(function(lineNumber) {
5133      var $line = $(this),
5134        wordSpacing = 0,
5135        interval = 1,
5136        maxWordSpacing;
5137
5138      if($line.hasClass(BigText.EXEMPT_CLASS)) {
5139        wordSpacings.push(null);
5140        return;
5141      }
5142
5143      // must re-use font-size, even though it was removed above.
5144      $line.css('font-size', fontSizes[lineNumber] + 'px');
5145
5146      for(var m=1, n=3; m<n; m+=interval) {
5147        maxWordSpacing = testLineDimensions($line, maxWidth, 'word-spacing', m, interval, 'px', maxWordSpacing);
5148        if(typeof maxWordSpacing !== 'number') {
5149          wordSpacing = maxWordSpacing.size;
5150          break;
5151        }
5152      }
5153
5154      $line.css('font-size', '');
5155      wordSpacings.push(wordSpacing);
5156    }).removeAttr('style');
5157
5158    if( !BigText.DEBUG_MODE ) {
5159      $c.remove();
5160    } else {
5161      $c.css({
5162        'background-color': 'rgba(255,255,255,.4)'
5163      });
5164    }
5165
5166    return {
5167      fontSizes: fontSizes,
5168      wordSpacings: wordSpacings,
5169      ratios: ratios,
5170      minFontSizes: minFontSizes
5171    };
5172  }
5173
5174  $.fn.bigtext = BigText.jQueryMethod;
5175  window.BigText = BigText;
5176
5177})(this, jQuery);
5178/*!
5179 * Isotope PACKAGED v3.0.6
5180 *
5181 * Licensed GPLv3 for open source use
5182 * or Isotope Commercial License for commercial use
5183 *
5184 * https://isotope.metafizzy.co
5185 * Copyright 2010-2018 Metafizzy
vendor: 15,902 bytes, lines 5185-5835
5185
5186 */
5187
5188/**
5189 * Bridget makes jQuery widgets
5190 * v2.0.1
5191 * MIT license
5192 */
5193
5194/* jshint browser: true, strict: true, undef: true, unused: true */
5195
5196( function( window, factory ) {
5197  // universal module definition
5198  /*jshint strict: false */ /* globals define, module, require */
5199  if ( typeof define == 'function' && define.amd ) {
5200    // AMD
5201    define( 'jquery-bridget/jquery-bridget',[ 'jquery' ], function( jQuery ) {
5202      return factory( window, jQuery );
5203    });
5204  } else if ( typeof module == 'object' && module.exports ) {
5205    // CommonJS
5206    module.exports = factory(
5207      window,
5208      require('jquery')
5209    );
5210  } else {
5211    // browser global
5212    window.jQueryBridget = factory(
5213      window,
5214      window.jQuery
5215    );
5216  }
5217
5218}( window, function factory( window, jQuery ) {
5219'use strict';
5220
5221// ----- utils ----- //
5222
5223var arraySlice = Array.prototype.slice;
5224
5225// helper function for logging errors
5226// $.error breaks jQuery chaining
5227var console = window.console;
5228var logError = typeof console == 'undefined' ? function() {} :
5229  function( message ) {
5230    console.error( message );
5231  };
5232
5233// ----- jQueryBridget ----- //
5234
5235function jQueryBridget( namespace, PluginClass, $ ) {
5236  $ = $ || jQuery || window.jQuery;
5237  if ( !$ ) {
5238    return;
5239  }
5240
5241  // add option method -> $().plugin('option', {...})
5242  if ( !PluginClass.prototype.option ) {
5243    // option setter
5244    PluginClass.prototype.option = function( opts ) {
5245      // bail out if not an object
5246      if ( !$.isPlainObject( opts ) ){
5247        return;
5248      }
5249      this.options = $.extend( true, this.options, opts );
5250    };
5251  }
5252
5253  // make jQuery plugin
5254  $.fn[ namespace ] = function( arg0 /*, arg1 */ ) {
5255    if ( typeof arg0 == 'string' ) {
5256      // method call $().plugin( 'methodName', { options } )
5257      // shift arguments by 1
5258      var args = arraySlice.call( arguments, 1 );
5259      return methodCall( this, arg0, args );
5260    }
5261    // just $().plugin({ options })
5262    plainCall( this, arg0 );
5263    return this;
5264  };
5265
5266  // $().plugin('methodName')
5267  function methodCall( $elems, methodName, args ) {
5268    var returnValue;
5269    var pluginMethodStr = '$().' + namespace + '("' + methodName + '")';
5270
5271    $elems.each( function( i, elem ) {
5272      // get instance
5273      var instance = $.data( elem, namespace );
5274      if ( !instance ) {
5275        logError( namespace + ' not initialized. Cannot call methods, i.e. ' +
5276          pluginMethodStr );
5277        return;
5278      }
5279
5280      var method = instance[ methodName ];
5281      if ( !method || methodName.charAt(0) == '_' ) {
5282        logError( pluginMethodStr + ' is not a valid method' );
5283        return;
5284      }
5285
5286      // apply method, get return value
5287      var value = method.apply( instance, args );
5288      // set return value if value is returned, use only first value
5289      returnValue = returnValue === undefined ? value : returnValue;
5290    });
5291
5292    return returnValue !== undefined ? returnValue : $elems;
5293  }
5294
5295  function plainCall( $elems, options ) {
5296    $elems.each( function( i, elem ) {
5297      var instance = $.data( elem, namespace );
5298      if ( instance ) {
5299        // set options & init
5300        instance.option( options );
5301        instance._init();
5302      } else {
5303        // initialize new instance
5304        instance = new PluginClass( elem, options );
5305        $.data( elem, namespace, instance );
5306      }
5307    });
5308  }
5309
5310  updateJQuery( $ );
5311
5312}
5313
5314// ----- updateJQuery ----- //
5315
5316// set $.bridget for v1 backwards compatibility
5317function updateJQuery( $ ) {
5318  if ( !$ || ( $ && $.bridget ) ) {
5319    return;
5320  }
5321  $.bridget = jQueryBridget;
5322}
5323
5324updateJQuery( jQuery || window.jQuery );
5325
5326// -----  ----- //
5327
5328return jQueryBridget;
5329
5330}));
5331
5332/**
5333 * EvEmitter v1.1.0
5334 * Lil' event emitter
5335 * MIT License
5336 */
5337
5338/* jshint unused: true, undef: true, strict: true */
5339
5340( function( global, factory ) {
5341  // universal module definition
5342  /* jshint strict: false */ /* globals define, module, window */
5343  if ( typeof define == 'function' && define.amd ) {
5344    // AMD - RequireJS
5345    define( 'ev-emitter/ev-emitter',factory );
5346  } else if ( typeof module == 'object' && module.exports ) {
5347    // CommonJS - Browserify, Webpack
5348    module.exports = factory();
5349  } else {
5350    // Browser globals
5351    global.EvEmitter = factory();
5352  }
5353
5354}( typeof window != 'undefined' ? window : this, function() {
5355
5356
5357
5358function EvEmitter() {}
5359
5360var proto = EvEmitter.prototype;
5361
5362proto.on = function( eventName, listener ) {
5363  if ( !eventName || !listener ) {
5364    return;
5365  }
5366  // set events hash
5367  var events = this._events = this._events || {};
5368  // set listeners array
5369  var listeners = events[ eventName ] = events[ eventName ] || [];
5370  // only add once
5371  if ( listeners.indexOf( listener ) == -1 ) {
5372    listeners.push( listener );
5373  }
5374
5375  return this;
5376};
5377
5378proto.once = function( eventName, listener ) {
5379  if ( !eventName || !listener ) {
5380    return;
5381  }
5382  // add event
5383  this.on( eventName, listener );
5384  // set once flag
5385  // set onceEvents hash
5386  var onceEvents = this._onceEvents = this._onceEvents || {};
5387  // set onceListeners object
5388  var onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {};
5389  // set flag
5390  onceListeners[ listener ] = true;
5391
5392  return this;
5393};
5394
5395proto.off = function( eventName, listener ) {
5396  var listeners = this._events && this._events[ eventName ];
5397  if ( !listeners || !listeners.length ) {
5398    return;
5399  }
5400  var index = listeners.indexOf( listener );
5401  if ( index != -1 ) {
5402    listeners.splice( index, 1 );
5403  }
5404
5405  return this;
5406};
5407
5408proto.emitEvent = function( eventName, args ) {
5409  var listeners = this._events && this._events[ eventName ];
5410  if ( !listeners || !listeners.length ) {
5411    return;
5412  }
5413  // copy over to avoid interference if .off() in listener
5414  listeners = listeners.slice(0);
5415  args = args || [];
5416  // once stuff
5417  var onceListeners = this._onceEvents && this._onceEvents[ eventName ];
5418
5419  for ( var i=0; i < listeners.length; i++ ) {
5420    var listener = listeners[i]
5421    var isOnce = onceListeners && onceListeners[ listener ];
5422    if ( isOnce ) {
5423      // remove listener
5424      // remove before trigger to prevent recursion
5425      this.off( eventName, listener );
5426      // unset once flag
5427      delete onceListeners[ listener ];
5428    }
5429    // trigger listener
5430    listener.apply( this, args );
5431  }
5432
5433  return this;
5434};
5435
5436proto.allOff = function() {
5437  delete this._events;
5438  delete this._onceEvents;
5439};
5440
5441return EvEmitter;
5442
5443}));
5444
5445/*!
5446 * getSize v2.0.3
5447 * measure size of elements
5448 * MIT license
5449 */
5450
5451/* jshint browser: true, strict: true, undef: true, unused: true */
5452/* globals console: false */
5453
5454( function( window, factory ) {
5455  /* jshint strict: false */ /* globals define, module */
5456  if ( typeof define == 'function' && define.amd ) {
5457    // AMD
5458    define( 'get-size/get-size',factory );
5459  } else if ( typeof module == 'object' && module.exports ) {
5460    // CommonJS
5461    module.exports = factory();
5462  } else {
5463    // browser global
5464    window.getSize = factory();
5465  }
5466
5467})( window, function factory() {
5468'use strict';
5469
5470// -------------------------- helpers -------------------------- //
5471
5472// get a number from a string, not a percentage
5473function getStyleSize( value ) {
5474  var num = parseFloat( value );
5475  // not a percent like '100%', and a number
5476  var isValid = value.indexOf('%') == -1 && !isNaN( num );
5477  return isValid && num;
5478}
5479
5480function noop() {}
5481
5482var logError = typeof console == 'undefined' ? noop :
5483  function( message ) {
5484    console.error( message );
5485  };
5486
5487// -------------------------- measurements -------------------------- //
5488
5489var measurements = [
5490  'paddingLeft',
5491  'paddingRight',
5492  'paddingTop',
5493  'paddingBottom',
5494  'marginLeft',
5495  'marginRight',
5496  'marginTop',
5497  'marginBottom',
5498  'borderLeftWidth',
5499  'borderRightWidth',
5500  'borderTopWidth',
5501  'borderBottomWidth'
5502];
5503
5504var measurementsLength = measurements.length;
5505
5506function getZeroSize() {
5507  var size = {
5508    width: 0,
5509    height: 0,
5510    innerWidth: 0,
5511    innerHeight: 0,
5512    outerWidth: 0,
5513    outerHeight: 0
5514  };
5515  for ( var i=0; i < measurementsLength; i++ ) {
5516    var measurement = measurements[i];
5517    size[ measurement ] = 0;
5518  }
5519  return size;
5520}
5521
5522// -------------------------- getStyle -------------------------- //
5523
5524/**
5525 * getStyle, get style of element, check for Firefox bug
5526 * https://bugzilla.mozilla.org/show_bug.cgi?id=548397
5527 */
5528function getStyle( elem ) {
5529  var style = getComputedStyle( elem );
5530  if ( !style ) {
5531    logError( 'Style returned ' + style +
5532      '. Are you running this code in a hidden iframe on Firefox? ' +
5533      'See https://bit.ly/getsizebug1' );
5534  }
5535  return style;
5536}
5537
5538// -------------------------- setup -------------------------- //
5539
5540var isSetup = false;
5541
5542var isBoxSizeOuter;
5543
5544/**
5545 * setup
5546 * check isBoxSizerOuter
5547 * do on first getSize() rather than on page load for Firefox bug
5548 */
5549function setup() {
5550  // setup once
5551  if ( isSetup ) {
5552    return;
5553  }
5554  isSetup = true;
5555
5556  // -------------------------- box sizing -------------------------- //
5557
5558  /**
5559   * Chrome & Safari measure the outer-width on style.width on border-box elems
5560   * IE11 & Firefox<29 measures the inner-width
5561   */
5562  var div = document.createElement('div');
5563  div.style.width = '200px';
5564  div.style.padding = '1px 2px 3px 4px';
5565  div.style.borderStyle = 'solid';
5566  div.style.borderWidth = '1px 2px 3px 4px';
5567  div.style.boxSizing = 'border-box';
5568
5569  var body = document.body || document.documentElement;
5570  body.appendChild( div );
5571  var style = getStyle( div );
5572  // round value for browser zoom. desandro/masonry#928
5573  isBoxSizeOuter = Math.round( getStyleSize( style.width ) ) == 200;
5574  getSize.isBoxSizeOuter = isBoxSizeOuter;
5575
5576  body.removeChild( div );
5577}
5578
5579// -------------------------- getSize -------------------------- //
5580
5581function getSize( elem ) {
5582  setup();
5583
5584  // use querySeletor if elem is string
5585  if ( typeof elem == 'string' ) {
5586    elem = document.querySelector( elem );
5587  }
5588
5589  // do not proceed on non-objects
5590  if ( !elem || typeof elem != 'object' || !elem.nodeType ) {
5591    return;
5592  }
5593
5594  var style = getStyle( elem );
5595
5596  // if hidden, everything is 0
5597  if ( style.display == 'none' ) {
5598    return getZeroSize();
5599  }
5600
5601  var size = {};
5602  size.width = elem.offsetWidth;
5603  size.height = elem.offsetHeight;
5604
5605  var isBorderBox = size.isBorderBox = style.boxSizing == 'border-box';
5606
5607  // get all measurements
5608  for ( var i=0; i < measurementsLength; i++ ) {
5609    var measurement = measurements[i];
5610    var value = style[ measurement ];
5611    var num = parseFloat( value );
5612    // any 'auto', 'medium' value will be 0
5613    size[ measurement ] = !isNaN( num ) ? num : 0;
5614  }
5615
5616  var paddingWidth = size.paddingLeft + size.paddingRight;
5617  var paddingHeight = size.paddingTop + size.paddingBottom;
5618  var marginWidth = size.marginLeft + size.marginRight;
5619  var marginHeight = size.marginTop + size.marginBottom;
5620  var borderWidth = size.borderLeftWidth + size.borderRightWidth;
5621  var borderHeight = size.borderTopWidth + size.borderBottomWidth;
5622
5623  var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter;
5624
5625  // overwrite width and height if we can get it from style
5626  var styleWidth = getStyleSize( style.width );
5627  if ( styleWidth !== false ) {
5628    size.width = styleWidth +
5629      // add padding and border unless it's already including it
5630      ( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth );
5631  }
5632
5633  var styleHeight = getStyleSize( style.height );
5634  if ( styleHeight !== false ) {
5635    size.height = styleHeight +
5636      // add padding and border unless it's already including it
5637      ( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight );
5638  }
5639
5640  size.innerWidth = size.width - ( paddingWidth + borderWidth );
5641  size.innerHeight = size.height - ( paddingHeight + borderHeight );
5642
5643  size.outerWidth = size.width + marginWidth;
5644  size.outerHeight = size.height + marginHeight;
5645
5646  return size;
5647}
5648
5649return getSize;
5650
5651});
5652
5653/**
5654 * matchesSelector v2.0.2
5655 * matchesSelector( element, '.selector' )
5656 * MIT license
5657 */
5658
5659/*jshint browser: true, strict: true, undef: true, unused: true */
5660
5661( function( window, factory ) {
5662  /*global define: false, module: false */
5663  'use strict';
5664  // universal module definition
5665  if ( typeof define == 'function' && define.amd ) {
5666    // AMD
5667    define( 'desandro-matches-selector/matches-selector',factory );
5668  } else if ( typeof module == 'object' && module.exports ) {
5669    // CommonJS
5670    module.exports = factory();
5671  } else {
5672    // browser global
5673    window.matchesSelector = factory();
5674  }
5675
5676}( window, function factory() {
5677  'use strict';
5678
5679  var matchesMethod = ( function() {
5680    var ElemProto = window.Element.prototype;
5681    // check for the standard method name first
5682    if ( ElemProto.matches ) {
5683      return 'matches';
5684    }
5685    // check un-prefixed
5686    if ( ElemProto.matchesSelector ) {
5687      return 'matchesSelector';
5688    }
5689    // check vendor prefixes
5690    var prefixes = [ 'webkit', 'moz', 'ms', 'o' ];
5691
5692    for ( var i=0; i < prefixes.length; i++ ) {
5693      var prefix = prefixes[i];
5694      var method = prefix + 'MatchesSelector';
5695      if ( ElemProto[ method ] ) {
5696        return method;
5697      }
5698    }
5699  })();
5700
5701  return function matchesSelector( elem, selector ) {
5702    return elem[ matchesMethod ]( selector );
5703  };
5704
5705}));
5706
5707/**
5708 * Fizzy UI utils v2.0.7
5709 * MIT license
5710 */
5711
5712/*jshint browser: true, undef: true, unused: true, strict: true */
5713
5714( function( window, factory ) {
5715  // universal module definition
5716  /*jshint strict: false */ /*globals define, module, require */
5717
5718  if ( typeof define == 'function' && define.amd ) {
5719    // AMD
5720    define( 'fizzy-ui-utils/utils',[
5721      'desandro-matches-selector/matches-selector'
5722    ], function( matchesSelector ) {
5723      return factory( window, matchesSelector );
5724    });
5725  } else if ( typeof module == 'object' && module.exports ) {
5726    // CommonJS
5727    module.exports = factory(
5728      window,
5729      require('desandro-matches-selector')
5730    );
5731  } else {
5732    // browser global
5733    window.fizzyUIUtils = factory(
5734      window,
5735      window.matchesSelector
5736    );
5737  }
5738
5739}( window, function factory( window, matchesSelector ) {
5740
5741
5742
5743var utils = {};
5744
5745// ----- extend ----- //
5746
5747// extends objects
5748utils.extend = function( a, b ) {
5749  for ( var prop in b ) {
5750    a[ prop ] = b[ prop ];
5751  }
5752  return a;
5753};
5754
5755// ----- modulo ----- //
5756
5757utils.modulo = function( num, div ) {
5758  return ( ( num % div ) + div ) % div;
5759};
5760
5761// ----- makeArray ----- //
5762
5763var arraySlice = Array.prototype.slice;
5764
5765// turn element or nodeList into an array
5766utils.makeArray = function( obj ) {
5767  if ( Array.isArray( obj ) ) {
5768    // use object if already an array
5769    return obj;
5770  }
5771  // return empty array if undefined or null. #6
5772  if ( obj === null || obj === undefined ) {
5773    return [];
5774  }
5775
5776  var isArrayLike = typeof obj == 'object' && typeof obj.length == 'number';
5777  if ( isArrayLike ) {
5778    // convert nodeList to array
5779    return arraySlice.call( obj );
5780  }
5781
5782  // array of single index
5783  return [ obj ];
5784};
5785
5786// ----- removeFrom ----- //
5787
5788utils.removeFrom = function( ary, obj ) {
5789  var index = ary.indexOf( obj );
5790  if ( index != -1 ) {
5791    ary.splice( index, 1 );
5792  }
5793};
5794
5795// ----- getParent ----- //
5796
5797utils.getParent = function( elem, selector ) {
5798  while ( elem.parentNode && elem != document.body ) {
5799    elem = elem.parentNode;
5800    if ( matchesSelector( elem, selector ) ) {
5801      return elem;
5802    }
5803  }
5804};
5805
5806// ----- getQueryElement ----- //
5807
5808// use element as selector string
5809utils.getQueryElement = function( elem ) {
5810  if ( typeof elem == 'string' ) {
5811    return document.querySelector( elem );
5812  }
5813  return elem;
5814};
5815
5816// ----- handleEvent ----- //
5817
5818// enable .ontype to trigger from .addEventListener( elem, 'type' )
5819utils.handleEvent = function( event ) {
5820  var method = 'on' + event.type;
5821  if ( this[ method ] ) {
5822    this[ method ]( event );
5823  }
5824};
5825
5826// ----- filterFindElements ----- //
5827
5828utils.filterFindElements = function( elems, selector ) {
5829  // make array of elems
5830  elems = utils.makeArray( elems );
5831  var ffElems = [];
5832
5833  elems.forEach( function( elem ) {
5834    // check that elem is an actual element
5835    
5835// START UNCODE EDIT
5836    // if ( !( elem instanceof HTMLElement ) ) {
5837    if ( !( elem instanceof HTMLElement ) && !SiteParameters.is_frontend_editor ) {
5838    // END UNCODE EDIT
vendor: 23,480 bytes, lines 5838-6750
5838
5839      return;
5840    }
5841    // add elem if no selector
5842    if ( !selector ) {
5843      ffElems.push( elem );
5844      return;
5845    }
5846    // filter & find items if we have a selector
5847    // filter
5848    if ( matchesSelector( elem, selector ) ) {
5849      ffElems.push( elem );
5850    }
5851    // find children
5852    var childElems = elem.querySelectorAll( selector );
5853    // concat childElems to filterFound array
5854    for ( var i=0; i < childElems.length; i++ ) {
5855      ffElems.push( childElems[i] );
5856    }
5857  });
5858
5859  return ffElems;
5860};
5861
5862// ----- debounceMethod ----- //
5863
5864utils.debounceMethod = function( _class, methodName, threshold ) {
5865  threshold = threshold || 100;
5866  // original method
5867  var method = _class.prototype[ methodName ];
5868  var timeoutName = methodName + 'Timeout';
5869
5870  _class.prototype[ methodName ] = function() {
5871    var timeout = this[ timeoutName ];
5872    clearTimeout( timeout );
5873
5874    var args = arguments;
5875    var _this = this;
5876    this[ timeoutName ] = setTimeout( function() {
5877      method.apply( _this, args );
5878      delete _this[ timeoutName ];
5879    }, threshold );
5880  };
5881};
5882
5883// ----- docReady ----- //
5884
5885utils.docReady = function( callback ) {
5886  var readyState = document.readyState;
5887  if ( readyState == 'complete' || readyState == 'interactive' ) {
5888    // do async to allow for other scripts to run. metafizzy/flickity#441
5889    setTimeout( callback );
5890  } else {
5891    document.addEventListener( 'DOMContentLoaded', callback );
5892  }
5893};
5894
5895// ----- htmlInit ----- //
5896
5897// http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/
5898utils.toDashed = function( str ) {
5899  return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) {
5900    return $1 + '-' + $2;
5901  }).toLowerCase();
5902};
5903
5904var console = window.console;
5905/**
5906 * allow user to initialize classes via [data-namespace] or .js-namespace class
5907 * htmlInit( Widget, 'widgetName' )
5908 * options are parsed from data-namespace-options
5909 */
5910utils.htmlInit = function( WidgetClass, namespace ) {
5911  utils.docReady( function() {
5912    var dashedNamespace = utils.toDashed( namespace );
5913    var dataAttr = 'data-' + dashedNamespace;
5914    var dataAttrElems = document.querySelectorAll( '[' + dataAttr + ']' );
5915    var jsDashElems = document.querySelectorAll( '.js-' + dashedNamespace );
5916    var elems = utils.makeArray( dataAttrElems )
5917      .concat( utils.makeArray( jsDashElems ) );
5918    var dataOptionsAttr = dataAttr + '-options';
5919    var jQuery = window.jQuery;
5920
5921    elems.forEach( function( elem ) {
5922      var attr = elem.getAttribute( dataAttr ) ||
5923        elem.getAttribute( dataOptionsAttr );
5924      var options;
5925      try {
5926        options = attr && JSON.parse( attr );
5927      } catch ( error ) {
5928        // log error, do not initialize
5929        if ( console ) {
5930          console.error( 'Error parsing ' + dataAttr + ' on ' + elem.className +
5931          ': ' + error );
5932        }
5933        return;
5934      }
5935      // initialize
5936      var instance = new WidgetClass( elem, options );
5937      // make available via $().data('namespace')
5938      if ( jQuery ) {
5939        jQuery.data( elem, namespace, instance );
5940      }
5941    });
5942
5943  });
5944};
5945
5946// -----  ----- //
5947
5948return utils;
5949
5950}));
5951
5952/**
5953 * Outlayer Item
5954 */
5955
5956( function( window, factory ) {
5957  // universal module definition
5958  /* jshint strict: false */ /* globals define, module, require */
5959  if ( typeof define == 'function' && define.amd ) {
5960    // AMD - RequireJS
5961    define( 'outlayer/item',[
5962        'ev-emitter/ev-emitter',
5963        'get-size/get-size'
5964      ],
5965      factory
5966    );
5967  } else if ( typeof module == 'object' && module.exports ) {
5968    // CommonJS - Browserify, Webpack
5969    module.exports = factory(
5970      require('ev-emitter'),
5971      require('get-size')
5972    );
5973  } else {
5974    // browser global
5975    window.Outlayer = {};
5976    window.Outlayer.Item = factory(
5977      window.EvEmitter,
5978      window.getSize
5979    );
5980  }
5981
5982}( window, function factory( EvEmitter, getSize ) {
5983'use strict';
5984
5985// ----- helpers ----- //
5986
5987function isEmptyObj( obj ) {
5988  for ( var prop in obj ) {
5989    return false;
5990  }
5991  prop = null;
5992  return true;
5993}
5994
5995// -------------------------- CSS3 support -------------------------- //
5996
5997
5998var docElemStyle = document.documentElement.style;
5999
6000var transitionProperty = typeof docElemStyle.transition == 'string' ?
6001  'transition' : 'WebkitTransition';
6002var transformProperty = typeof docElemStyle.transform == 'string' ?
6003  'transform' : 'WebkitTransform';
6004
6005var transitionEndEvent = {
6006  WebkitTransition: 'webkitTransitionEnd',
6007  transition: 'transitionend'
6008}[ transitionProperty ];
6009
6010// cache all vendor properties that could have vendor prefix
6011var vendorProperties = {
6012  transform: transformProperty,
6013  transition: transitionProperty,
6014  transitionDuration: transitionProperty + 'Duration',
6015  transitionProperty: transitionProperty + 'Property',
6016  transitionDelay: transitionProperty + 'Delay'
6017};
6018
6019// -------------------------- Item -------------------------- //
6020
6021function Item( element, layout ) {
6022  if ( !element ) {
6023    return;
6024  }
6025
6026  this.element = element;
6027  // parent layout class, i.e. Masonry, Isotope, or Packery
6028  this.layout = layout;
6029  this.position = {
6030    x: 0,
6031    y: 0
6032  };
6033
6034  this._create();
6035}
6036
6037// inherit EvEmitter
6038var proto = Item.prototype = Object.create( EvEmitter.prototype );
6039proto.constructor = Item;
6040
6041proto._create = function() {
6042  // transition objects
6043  this._transn = {
6044    ingProperties: {},
6045    clean: {},
6046    onEnd: {}
6047  };
6048
6049  this.css({
6050    position: 'absolute'
6051  });
6052};
6053
6054// trigger specified handler for event type
6055proto.handleEvent = function( event ) {
6056  var method = 'on' + event.type;
6057  if ( this[ method ] ) {
6058    this[ method ]( event );
6059  }
6060};
6061
6062proto.getSize = function() {
6063  this.size = getSize( this.element );
6064};
6065
6066/**
6067 * apply CSS styles to element
6068 * @param {Object} style
6069 */
6070proto.css = function( style ) {
6071  var elemStyle = this.element.style;
6072
6073  for ( var prop in style ) {
6074    // use vendor property if available
6075    var supportedProp = vendorProperties[ prop ] || prop;
6076    elemStyle[ supportedProp ] = style[ prop ];
6077  }
6078};
6079
6080 // measure position, and sets it
6081proto.getPosition = function() {
6082  var style = getComputedStyle( this.element );
6083  var isOriginLeft = this.layout._getOption('originLeft');
6084  var isOriginTop = this.layout._getOption('originTop');
6085  var xValue = style[ isOriginLeft ? 'left' : 'right' ];
6086  var yValue = style[ isOriginTop ? 'top' : 'bottom' ];
6087  var x = parseFloat( xValue );
6088  var y = parseFloat( yValue );
6089  // convert percent to pixels
6090  var layoutSize = this.layout.size;
6091  if ( xValue.indexOf('%') != -1 ) {
6092    x = ( x / 100 ) * layoutSize.width;
6093  }
6094  if ( yValue.indexOf('%') != -1 ) {
6095    y = ( y / 100 ) * layoutSize.height;
6096  }
6097  // clean up 'auto' or other non-integer values
6098  x = isNaN( x ) ? 0 : x;
6099  y = isNaN( y ) ? 0 : y;
6100  // remove padding from measurement
6101  x -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight;
6102  y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom;
6103
6104  this.position.x = x;
6105  this.position.y = y;
6106};
6107
6108// set settled position, apply padding
6109proto.layoutPosition = function() {
6110  var layoutSize = this.layout.size;
6111  var style = {};
6112  var isOriginLeft = this.layout._getOption('originLeft');
6113  var isOriginTop = this.layout._getOption('originTop');
6114
6115  // x
6116  var xPadding = isOriginLeft ? 'paddingLeft' : 'paddingRight';
6117  var xProperty = isOriginLeft ? 'left' : 'right';
6118  var xResetProperty = isOriginLeft ? 'right' : 'left';
6119
6120  var x = this.position.x + layoutSize[ xPadding ];
6121  // set in percentage or pixels
6122  style[ xProperty ] = this.getXValue( x );
6123  // reset other property
6124  style[ xResetProperty ] = '';
6125
6126  // y
6127  var yPadding = isOriginTop ? 'paddingTop' : 'paddingBottom';
6128  var yProperty = isOriginTop ? 'top' : 'bottom';
6129  var yResetProperty = isOriginTop ? 'bottom' : 'top';
6130
6131  var y = this.position.y + layoutSize[ yPadding ];
6132  // set in percentage or pixels
6133  style[ yProperty ] = this.getYValue( y );
6134  // reset other property
6135  style[ yResetProperty ] = '';
6136
6137  this.css( style );
6138  this.emitEvent( 'layout', [ this ] );
6139};
6140
6141proto.getXValue = function( x ) {
6142  var isHorizontal = this.layout._getOption('horizontal');
6143  return this.layout.options.percentPosition && !isHorizontal ?
6144    ( ( x / this.layout.size.width ) * 100 ) + '%' : x + 'px';
6145};
6146
6147proto.getYValue = function( y ) {
6148  var isHorizontal = this.layout._getOption('horizontal');
6149  return this.layout.options.percentPosition && isHorizontal ?
6150    ( ( y / this.layout.size.height ) * 100 ) + '%' : y + 'px';
6151};
6152
6153proto._transitionTo = function( x, y ) {
6154  this.getPosition();
6155  // get current x & y from top/left
6156  var curX = this.position.x;
6157  var curY = this.position.y;
6158
6159  var didNotMove = x == this.position.x && y == this.position.y;
6160
6161  // save end position
6162  this.setPosition( x, y );
6163
6164  // if did not move and not transitioning, just go to layout
6165  if ( didNotMove && !this.isTransitioning ) {
6166    this.layoutPosition();
6167    return;
6168  }
6169
6170  var transX = x - curX;
6171  var transY = y - curY;
6172  var transitionStyle = {};
6173  transitionStyle.transform = this.getTranslate( transX, transY );
6174
6175  this.transition({
6176    to: transitionStyle,
6177    onTransitionEnd: {
6178      transform: this.layoutPosition
6179    },
6180    isCleaning: true
6181  });
6182};
6183
6184proto.getTranslate = function( x, y ) {
6185  // flip cooridinates if origin on right or bottom
6186  var isOriginLeft = this.layout._getOption('originLeft');
6187  var isOriginTop = this.layout._getOption('originTop');
6188  x = isOriginLeft ? x : -x;
6189  y = isOriginTop ? y : -y;
6190  return 'translate3d(' + x + 'px, ' + y + 'px, 0)';
6191};
6192
6193// non transition + transform support
6194proto.goTo = function( x, y ) {
6195  this.setPosition( x, y );
6196  this.layoutPosition();
6197};
6198
6199proto.moveTo = proto._transitionTo;
6200
6201proto.setPosition = function( x, y ) {
6202  this.position.x = parseFloat( x );
6203  this.position.y = parseFloat( y );
6204};
6205
6206// ----- transition ----- //
6207
6208/**
6209 * @param {Object} style - CSS
6210 * @param {Function} onTransitionEnd
6211 */
6212
6213// non transition, just trigger callback
6214proto._nonTransition = function( args ) {
6215  this.css( args.to );
6216  if ( args.isCleaning ) {
6217    this._removeStyles( args.to );
6218  }
6219  for ( var prop in args.onTransitionEnd ) {
6220    args.onTransitionEnd[ prop ].call( this );
6221  }
6222};
6223
6224/**
6225 * proper transition
6226 * @param {Object} args - arguments
6227 *   @param {Object} to - style to transition to
6228 *   @param {Object} from - style to start transition from
6229 *   @param {Boolean} isCleaning - removes transition styles after transition
6230 *   @param {Function} onTransitionEnd - callback
6231 */
6232proto.transition = function( args ) {
6233  // redirect to nonTransition if no transition duration
6234  if ( !parseFloat( this.layout.options.transitionDuration ) ) {
6235    this._nonTransition( args );
6236    return;
6237  }
6238
6239  var _transition = this._transn;
6240  // keep track of onTransitionEnd callback by css property
6241  for ( var prop in args.onTransitionEnd ) {
6242    _transition.onEnd[ prop ] = args.onTransitionEnd[ prop ];
6243  }
6244  // keep track of properties that are transitioning
6245  for ( prop in args.to ) {
6246    _transition.ingProperties[ prop ] = true;
6247    // keep track of properties to clean up when transition is done
6248    if ( args.isCleaning ) {
6249      _transition.clean[ prop ] = true;
6250    }
6251  }
6252
6253  // set from styles
6254  if ( args.from ) {
6255    this.css( args.from );
6256    // force redraw. http://blog.alexmaccaw.com/css-transitions
6257    var h = this.element.offsetHeight;
6258    // hack for JSHint to hush about unused var
6259    h = null;
6260  }
6261  // enable transition
6262  this.enableTransition( args.to );
6263  // set styles that are transitioning
6264  this.css( args.to );
6265
6266  this.isTransitioning = true;
6267
6268};
6269
6270// dash before all cap letters, including first for
6271// WebkitTransform => -webkit-transform
6272function toDashedAll( str ) {
6273  return str.replace( /([A-Z])/g, function( $1 ) {
6274    return '-' + $1.toLowerCase();
6275  });
6276}
6277
6278var transitionProps = 'opacity,' + toDashedAll( transformProperty );
6279
6280proto.enableTransition = function(/* style */) {
6281  // HACK changing transitionProperty during a transition
6282  // will cause transition to jump
6283  if ( this.isTransitioning ) {
6284    return;
6285  }
6286
6287  // make `transition: foo, bar, baz` from style object
6288  // HACK un-comment this when enableTransition can work
6289  // while a transition is happening
6290  // var transitionValues = [];
6291  // for ( var prop in style ) {
6292  //   // dash-ify camelCased properties like WebkitTransition
6293  //   prop = vendorProperties[ prop ] || prop;
6294  //   transitionValues.push( toDashedAll( prop ) );
6295  // }
6296  // munge number to millisecond, to match stagger
6297  var duration = this.layout.options.transitionDuration;
6298  duration = typeof duration == 'number' ? duration + 'ms' : duration;
6299  // enable transition styles
6300  this.css({
6301    transitionProperty: transitionProps,
6302    transitionDuration: duration,
6303    transitionDelay: this.staggerDelay || 0
6304  });
6305  // listen for transition end event
6306  this.element.addEventListener( transitionEndEvent, this, false );
6307};
6308
6309// ----- events ----- //
6310
6311proto.onwebkitTransitionEnd = function( event ) {
6312  this.ontransitionend( event );
6313};
6314
6315proto.onotransitionend = function( event ) {
6316  this.ontransitionend( event );
6317};
6318
6319// properties that I munge to make my life easier
6320var dashedVendorProperties = {
6321  '-webkit-transform': 'transform'
6322};
6323
6324proto.ontransitionend = function( event ) {
6325  // disregard bubbled events from children
6326  if ( event.target !== this.element ) {
6327    return;
6328  }
6329  var _transition = this._transn;
6330  // get property name of transitioned property, convert to prefix-free
6331  var propertyName = dashedVendorProperties[ event.propertyName ] || event.propertyName;
6332
6333  // remove property that has completed transitioning
6334  delete _transition.ingProperties[ propertyName ];
6335  // check if any properties are still transitioning
6336  if ( isEmptyObj( _transition.ingProperties ) ) {
6337    // all properties have completed transitioning
6338    this.disableTransition();
6339  }
6340  // clean style
6341  if ( propertyName in _transition.clean ) {
6342    // clean up style
6343    this.element.style[ event.propertyName ] = '';
6344    delete _transition.clean[ propertyName ];
6345  }
6346  // trigger onTransitionEnd callback
6347  if ( propertyName in _transition.onEnd ) {
6348    var onTransitionEnd = _transition.onEnd[ propertyName ];
6349    onTransitionEnd.call( this );
6350    delete _transition.onEnd[ propertyName ];
6351  }
6352
6353  this.emitEvent( 'transitionEnd', [ this ] );
6354};
6355
6356proto.disableTransition = function() {
6357  this.removeTransitionStyles();
6358  this.element.removeEventListener( transitionEndEvent, this, false );
6359  this.isTransitioning = false;
6360};
6361
6362/**
6363 * removes style property from element
6364 * @param {Object} style
6365**/
6366proto._removeStyles = function( style ) {
6367  // clean up transition styles
6368  var cleanStyle = {};
6369  for ( var prop in style ) {
6370    cleanStyle[ prop ] = '';
6371  }
6372  this.css( cleanStyle );
6373};
6374
6375var cleanTransitionStyle = {
6376  transitionProperty: '',
6377  transitionDuration: '',
6378  transitionDelay: ''
6379};
6380
6381proto.removeTransitionStyles = function() {
6382  // remove transition
6383  this.css( cleanTransitionStyle );
6384};
6385
6386// ----- stagger ----- //
6387
6388proto.stagger = function( delay ) {
6389  delay = isNaN( delay ) ? 0 : delay;
6390  this.staggerDelay = delay + 'ms';
6391};
6392
6393// ----- show/hide/remove ----- //
6394
6395// remove element from DOM
6396proto.removeElem = function() {
6397  this.element.parentNode.removeChild( this.element );
6398  // remove display: none
6399  this.css({ display: '' });
6400  this.emitEvent( 'remove', [ this ] );
6401};
6402
6403proto.remove = function() {
6404  // just remove element if no transition support or no transition
6405  if ( !transitionProperty || !parseFloat( this.layout.options.transitionDuration ) ) {
6406    this.removeElem();
6407    return;
6408  }
6409
6410  // start transition
6411  this.once( 'transitionEnd', function() {
6412    this.removeElem();
6413  });
6414  this.hide();
6415};
6416
6417proto.reveal = function() {
6418  delete this.isHidden;
6419  // remove display: none
6420  this.css({ display: '' });
6421
6422  var options = this.layout.options;
6423
6424  var onTransitionEnd = {};
6425  var transitionEndProperty = this.getHideRevealTransitionEndProperty('visibleStyle');
6426  onTransitionEnd[ transitionEndProperty ] = this.onRevealTransitionEnd;
6427
6428  this.transition({
6429    from: options.hiddenStyle,
6430    to: options.visibleStyle,
6431    isCleaning: true,
6432    onTransitionEnd: onTransitionEnd
6433  });
6434};
6435
6436proto.onRevealTransitionEnd = function() {
6437  // check if still visible
6438  // during transition, item may have been hidden
6439  if ( !this.isHidden ) {
6440    this.emitEvent('reveal');
6441  }
6442};
6443
6444/**
6445 * get style property use for hide/reveal transition end
6446 * @param {String} styleProperty - hiddenStyle/visibleStyle
6447 * @returns {String}
6448 */
6449proto.getHideRevealTransitionEndProperty = function( styleProperty ) {
6450  var optionStyle = this.layout.options[ styleProperty ];
6451  // use opacity
6452  if ( optionStyle.opacity ) {
6453    return 'opacity';
6454  }
6455  // get first property
6456  for ( var prop in optionStyle ) {
6457    return prop;
6458  }
6459};
6460
6461proto.hide = function() {
6462  // set flag
6463  this.isHidden = true;
6464  // remove display: none
6465  this.css({ display: '' });
6466
6467  var options = this.layout.options;
6468
6469  var onTransitionEnd = {};
6470  var transitionEndProperty = this.getHideRevealTransitionEndProperty('hiddenStyle');
6471  onTransitionEnd[ transitionEndProperty ] = this.onHideTransitionEnd;
6472
6473  this.transition({
6474    from: options.visibleStyle,
6475    to: options.hiddenStyle,
6476    // keep hidden stuff hidden
6477    isCleaning: true,
6478    onTransitionEnd: onTransitionEnd
6479  });
6480};
6481
6482proto.onHideTransitionEnd = function() {
6483  // check if still hidden
6484  // during transition, item may have been un-hidden
6485  if ( this.isHidden ) {
6486    this.css({ display: 'none' });
6487    this.emitEvent('hide');
6488  }
6489};
6490
6491proto.destroy = function() {
6492  this.css({
6493    position: '',
6494    left: '',
6495    right: '',
6496    top: '',
6497    bottom: '',
6498    transition: '',
6499    transform: ''
6500  });
6501};
6502
6503return Item;
6504
6505}));
6506
6507/*!
6508 * Outlayer v2.1.1
6509 * the brains and guts of a layout library
6510 * MIT license
6511 */
6512
6513( function( window, factory ) {
6514  'use strict';
6515  // universal module definition
6516  /* jshint strict: false */ /* globals define, module, require */
6517  if ( typeof define == 'function' && define.amd ) {
6518    // AMD - RequireJS
6519    define( 'outlayer/outlayer',[
6520        'ev-emitter/ev-emitter',
6521        'get-size/get-size',
6522        'fizzy-ui-utils/utils',
6523        './item'
6524      ],
6525      function( EvEmitter, getSize, utils, Item ) {
6526        return factory( window, EvEmitter, getSize, utils, Item);
6527      }
6528    );
6529  } else if ( typeof module == 'object' && module.exports ) {
6530    // CommonJS - Browserify, Webpack
6531    module.exports = factory(
6532      window,
6533      require('ev-emitter'),
6534      require('get-size'),
6535      require('fizzy-ui-utils'),
6536      require('./item')
6537    );
6538  } else {
6539    // browser global
6540    window.Outlayer = factory(
6541      window,
6542      window.EvEmitter,
6543      window.getSize,
6544      window.fizzyUIUtils,
6545      window.Outlayer.Item
6546    );
6547  }
6548
6549}( window, function factory( window, EvEmitter, getSize, utils, Item ) {
6550'use strict';
6551
6552// ----- vars ----- //
6553
6554var console = window.console;
6555var jQuery = window.jQuery;
6556var noop = function() {};
6557
6558// -------------------------- Outlayer -------------------------- //
6559
6560// globally unique identifiers
6561var GUID = 0;
6562// internal store of all Outlayer intances
6563var instances = {};
6564
6565
6566/**
6567 * @param {Element, String} element
6568 * @param {Object} options
6569 * @constructor
6570 */
6571function Outlayer( element, options ) {
6572  var queryElement = utils.getQueryElement( element );
6573  if ( !queryElement ) {
6574    if ( console ) {
6575      console.error( 'Bad element for ' + this.constructor.namespace +
6576        ': ' + ( queryElement || element ) );
6577    }
6578    return;
6579  }
6580  this.element = queryElement;
6581  // add jQuery
6582  if ( jQuery ) {
6583    this.$element = jQuery( this.element );
6584  }
6585
6586  // options
6587  this.options = utils.extend( {}, this.constructor.defaults );
6588  this.option( options );
6589
6590  // add id for Outlayer.getFromElement
6591  var id = ++GUID;
6592  this.element.outlayerGUID = id; // expando
6593  instances[ id ] = this; // associate via id
6594
6595  // kick it off
6596  this._create();
6597
6598  var isInitLayout = this._getOption('initLayout');
6599  if ( isInitLayout ) {
6600    this.layout();
6601  }
6602}
6603
6604// settings are for internal use only
6605Outlayer.namespace = 'outlayer';
6606Outlayer.Item = Item;
6607
6608// default options
6609Outlayer.defaults = {
6610  containerStyle: {
6611    position: 'relative'
6612  },
6613  initLayout: true,
6614  originLeft: true,
6615  originTop: true,
6616  resize: true,
6617  resizeContainer: true,
6618  // item options
6619  transitionDuration: '0.4s',
6620  hiddenStyle: {
6621    opacity: 0,
6622    transform: 'scale(0.001)'
6623  },
6624  visibleStyle: {
6625    opacity: 1,
6626    transform: 'scale(1)'
6627  }
6628};
6629
6630var proto = Outlayer.prototype;
6631// inherit EvEmitter
6632utils.extend( proto, EvEmitter.prototype );
6633
6634/**
6635 * set options
6636 * @param {Object} opts
6637 */
6638proto.option = function( opts ) {
6639  utils.extend( this.options, opts );
6640};
6641
6642/**
6643 * get backwards compatible option value, check old name
6644 */
6645proto._getOption = function( option ) {
6646  var oldOption = this.constructor.compatOptions[ option ];
6647  return oldOption && this.options[ oldOption ] !== undefined ?
6648    this.options[ oldOption ] : this.options[ option ];
6649};
6650
6651Outlayer.compatOptions = {
6652  // currentName: oldName
6653  initLayout: 'isInitLayout',
6654  horizontal: 'isHorizontal',
6655  layoutInstant: 'isLayoutInstant',
6656  originLeft: 'isOriginLeft',
6657  originTop: 'isOriginTop',
6658  resize: 'isResizeBound',
6659  resizeContainer: 'isResizingContainer'
6660};
6661
6662proto._create = function() {
6663  // get items from children
6664  this.reloadItems();
6665  // elements that affect layout, but are not laid out
6666  this.stamps = [];
6667  this.stamp( this.options.stamp );
6668  // set container style
6669  utils.extend( this.element.style, this.options.containerStyle );
6670
6671  // bind resize method
6672  var canBindResize = this._getOption('resize');
6673  if ( canBindResize ) {
6674    this.bindResize();
6675  }
6676};
6677
6678// goes through all children again and gets bricks in proper order
6679proto.reloadItems = function() {
6680  // collection of item elements
6681  this.items = this._itemize( this.element.children );
6682};
6683
6684
6685/**
6686 * turn elements into Outlayer.Items to be used in layout
6687 * @param {Array or NodeList or HTMLElement} elems
6688 * @returns {Array} items - collection of new Outlayer Items
6689 */
6690proto._itemize = function( elems ) {
6691
6692  var itemElems = this._filterFindItemElements( elems );
6693  var Item = this.constructor.Item;
6694
6695  // create new Outlayer Items for collection
6696  var items = [];
6697  for ( var i=0; i < itemElems.length; i++ ) {
6698    var elem = itemElems[i];
6699    var item = new Item( elem, this );
6700    items.push( item );
6701  }
6702
6703  return items;
6704};
6705
6706/**
6707 * get item elements to be used in layout
6708 * @param {Array or NodeList or HTMLElement} elems
6709 * @returns {Array} items - item elements
6710 */
6711proto._filterFindItemElements = function( elems ) {
6712  return utils.filterFindElements( elems, this.options.itemSelector );
6713};
6714
6715/**
6716 * getter method for getting item elements
6717 * @returns {Array} elems - collection of item elements
6718 */
6719proto.getItemElements = function() {
6720  return this.items.map( function( item ) {
6721    return item.element;
6722  });
6723};
6724
6725// ----- init & layout ----- //
6726
6727/**
6728 * lays out all items
6729 */
6730proto.layout = function() {
6731  this._resetLayout();
6732  this._manageStamps();
6733
6734  // don't animate first layout
6735  var layoutInstant = this._getOption('layoutInstant');
6736  var isInstant = layoutInstant !== undefined ?
6737    layoutInstant : !this._isLayoutInited;
6738  this.layoutItems( this.items, isInstant );
6739
6740  // flag for initalized
6741  this._isLayoutInited = true;
6742};
6743
6744// _init is alias for layout
6745proto._init = proto.layout;
6746
6747/**
6748 * logic before any new layout
6749 */
6750proto._resetLayout = function() {
vendor: 13,499 bytes, lines 6751-7319
6751  this.getSize();
6752};
6753
6754
6755proto.getSize = function() {
6756  this.size = getSize( this.element );
6757};
6758
6759/**
6760 * get measurement from option, for columnWidth, rowHeight, gutter
6761 * if option is String -> get element from selector string, & get size of element
6762 * if option is Element -> get size of element
6763 * else use option as a number
6764 *
6765 * @param {String} measurement
6766 * @param {String} size - width or height
6767 * @private
6768 */
6769proto._getMeasurement = function( measurement, size ) {
6770  var option = this.options[ measurement ];
6771  var elem;
6772  if ( !option ) {
6773    // default to 0
6774    this[ measurement ] = 0;
6775  } else {
6776    // use option as an element
6777    if ( typeof option == 'string' ) {
6778      elem = this.element.querySelector( option );
6779    } else if ( option instanceof HTMLElement ) {
6780      elem = option;
6781    }
6782    // use size of element, if element
6783    this[ measurement ] = elem ? getSize( elem )[ size ] : option;
6784  }
6785};
6786
6787/**
6788 * layout a collection of item elements
6789 * @api public
6790 */
6791proto.layoutItems = function( items, isInstant ) {
6792  items = this._getItemsForLayout( items );
6793
6794  this._layoutItems( items, isInstant );
6795
6796  this._postLayout();
6797};
6798
6799/**
6800 * get the items to be laid out
6801 * you may want to skip over some items
6802 * @param {Array} items
6803 * @returns {Array} items
6804 */
6805proto._getItemsForLayout = function( items ) {
6806  return items.filter( function( item ) {
6807    return !item.isIgnored;
6808  });
6809};
6810
6811/**
6812 * layout items
6813 * @param {Array} items
6814 * @param {Boolean} isInstant
6815 */
6816proto._layoutItems = function( items, isInstant ) {
6817  this._emitCompleteOnItems( 'layout', items );
6818
6819  if ( !items || !items.length ) {
6820    // no items, emit event with empty array
6821    return;
6822  }
6823
6824  var queue = [];
6825
6826  items.forEach( function( item ) {
6827    // get x/y object from method
6828    var position = this._getItemLayoutPosition( item );
6829    // enqueue
6830    position.item = item;
6831    position.isInstant = isInstant || item.isLayoutInstant;
6832    queue.push( position );
6833  }, this );
6834
6835  this._processLayoutQueue( queue );
6836};
6837
6838/**
6839 * get item layout position
6840 * @param {Outlayer.Item} item
6841 * @returns {Object} x and y position
6842 */
6843proto._getItemLayoutPosition = function( /* item */ ) {
6844  return {
6845    x: 0,
6846    y: 0
6847  };
6848};
6849
6850/**
6851 * iterate over array and position each item
6852 * Reason being - separating this logic prevents 'layout invalidation'
6853 * thx @paul_irish
6854 * @param {Array} queue
6855 */
6856proto._processLayoutQueue = function( queue ) {
6857  this.updateStagger();
6858  queue.forEach( function( obj, i ) {
6859    this._positionItem( obj.item, obj.x, obj.y, obj.isInstant, i );
6860  }, this );
6861};
6862
6863// set stagger from option in milliseconds number
6864proto.updateStagger = function() {
6865  var stagger = this.options.stagger;
6866  if ( stagger === null || stagger === undefined ) {
6867    this.stagger = 0;
6868    return;
6869  }
6870  this.stagger = getMilliseconds( stagger );
6871  return this.stagger;
6872};
6873
6874/**
6875 * Sets position of item in DOM
6876 * @param {Outlayer.Item} item
6877 * @param {Number} x - horizontal position
6878 * @param {Number} y - vertical position
6879 * @param {Boolean} isInstant - disables transitions
6880 */
6881proto._positionItem = function( item, x, y, isInstant, i ) {
6882  if ( isInstant ) {
6883    // if not transition, just set CSS
6884    item.goTo( x, y );
6885  } else {
6886    item.stagger( i * this.stagger );
6887    item.moveTo( x, y );
6888  }
6889};
6890
6891/**
6892 * Any logic you want to do after each layout,
6893 * i.e. size the container
6894 */
6895proto._postLayout = function() {
6896  this.resizeContainer();
6897};
6898
6899proto.resizeContainer = function() {
6900  var isResizingContainer = this._getOption('resizeContainer');
6901  if ( !isResizingContainer ) {
6902    return;
6903  }
6904  var size = this._getContainerSize();
6905  if ( size ) {
6906    this._setContainerMeasure( size.width, true );
6907    this._setContainerMeasure( size.height, false );
6908  }
6909};
6910
6911/**
6912 * Sets width or height of container if returned
6913 * @returns {Object} size
6914 *   @param {Number} width
6915 *   @param {Number} height
6916 */
6917proto._getContainerSize = noop;
6918
6919/**
6920 * @param {Number} measure - size of width or height
6921 * @param {Boolean} isWidth
6922 */
6923proto._setContainerMeasure = function( measure, isWidth ) {
6924  if ( measure === undefined ) {
6925    return;
6926  }
6927
6928  var elemSize = this.size;
6929  // add padding and border width if border box
6930  if ( elemSize.isBorderBox ) {
6931    measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight +
6932      elemSize.borderLeftWidth + elemSize.borderRightWidth :
6933      elemSize.paddingBottom + elemSize.paddingTop +
6934      elemSize.borderTopWidth + elemSize.borderBottomWidth;
6935  }
6936
6937  measure = Math.max( measure, 0 );
6938  this.element.style[ isWidth ? 'width' : 'height' ] = measure + 'px';
6939};
6940
6941/**
6942 * emit eventComplete on a collection of items events
6943 * @param {String} eventName
6944 * @param {Array} items - Outlayer.Items
6945 */
6946proto._emitCompleteOnItems = function( eventName, items ) {
6947  var _this = this;
6948  function onComplete() {
6949    _this.dispatchEvent( eventName + 'Complete', null, [ items ] );
6950  }
6951
6952  var count = items.length;
6953  if ( !items || !count ) {
6954    onComplete();
6955    return;
6956  }
6957
6958  var doneCount = 0;
6959  function tick() {
6960    doneCount++;
6961    if ( doneCount == count ) {
6962      onComplete();
6963    }
6964  }
6965
6966  // bind callback
6967  items.forEach( function( item ) {
6968    item.once( eventName, tick );
6969  });
6970};
6971
6972/**
6973 * emits events via EvEmitter and jQuery events
6974 * @param {String} type - name of event
6975 * @param {Event} event - original event
6976 * @param {Array} args - extra arguments
6977 */
6978proto.dispatchEvent = function( type, event, args ) {
6979  // add original event to arguments
6980  var emitArgs = event ? [ event ].concat( args ) : args;
6981  this.emitEvent( type, emitArgs );
6982
6983  if ( jQuery ) {
6984    // set this.$element
6985    this.$element = this.$element || jQuery( this.element );
6986    if ( event ) {
6987      // create jQuery event
6988      var $event = jQuery.Event( event );
6989      $event.type = type;
6990      this.$element.trigger( $event, args );
6991    } else {
6992      // just trigger with type if no event available
6993      this.$element.trigger( type, args );
6994    }
6995  }
6996};
6997
6998// -------------------------- ignore & stamps -------------------------- //
6999
7000
7001/**
7002 * keep item in collection, but do not lay it out
7003 * ignored items do not get skipped in layout
7004 * @param {Element} elem
7005 */
7006proto.ignore = function( elem ) {
7007  var item = this.getItem( elem );
7008  if ( item ) {
7009    item.isIgnored = true;
7010  }
7011};
7012
7013/**
7014 * return item to layout collection
7015 * @param {Element} elem
7016 */
7017proto.unignore = function( elem ) {
7018  var item = this.getItem( elem );
7019  if ( item ) {
7020    delete item.isIgnored;
7021  }
7022};
7023
7024/**
7025 * adds elements to stamps
7026 * @param {NodeList, Array, Element, or String} elems
7027 */
7028proto.stamp = function( elems ) {
7029  elems = this._find( elems );
7030  if ( !elems ) {
7031    return;
7032  }
7033
7034  this.stamps = this.stamps.concat( elems );
7035  // ignore
7036  elems.forEach( this.ignore, this );
7037};
7038
7039/**
7040 * removes elements to stamps
7041 * @param {NodeList, Array, or Element} elems
7042 */
7043proto.unstamp = function( elems ) {
7044  elems = this._find( elems );
7045  if ( !elems ){
7046    return;
7047  }
7048
7049  elems.forEach( function( elem ) {
7050    // filter out removed stamp elements
7051    utils.removeFrom( this.stamps, elem );
7052    this.unignore( elem );
7053  }, this );
7054};
7055
7056/**
7057 * finds child elements
7058 * @param {NodeList, Array, Element, or String} elems
7059 * @returns {Array} elems
7060 */
7061proto._find = function( elems ) {
7062  if ( !elems ) {
7063    return;
7064  }
7065  // if string, use argument as selector string
7066  if ( typeof elems == 'string' ) {
7067    elems = this.element.querySelectorAll( elems );
7068  }
7069  elems = utils.makeArray( elems );
7070  return elems;
7071};
7072
7073proto._manageStamps = function() {
7074  if ( !this.stamps || !this.stamps.length ) {
7075    return;
7076  }
7077
7078  this._getBoundingRect();
7079
7080  this.stamps.forEach( this._manageStamp, this );
7081};
7082
7083// update boundingLeft / Top
7084proto._getBoundingRect = function() {
7085  // get bounding rect for container element
7086  var boundingRect = this.element.getBoundingClientRect();
7087  var size = this.size;
7088  this._boundingRect = {
7089    left: boundingRect.left + size.paddingLeft + size.borderLeftWidth,
7090    top: boundingRect.top + size.paddingTop + size.borderTopWidth,
7091    right: boundingRect.right - ( size.paddingRight + size.borderRightWidth ),
7092    bottom: boundingRect.bottom - ( size.paddingBottom + size.borderBottomWidth )
7093  };
7094};
7095
7096/**
7097 * @param {Element} stamp
7098**/
7099proto._manageStamp = noop;
7100
7101/**
7102 * get x/y position of element relative to container element
7103 * @param {Element} elem
7104 * @returns {Object} offset - has left, top, right, bottom
7105 */
7106proto._getElementOffset = function( elem ) {
7107  var boundingRect = elem.getBoundingClientRect();
7108  var thisRect = this._boundingRect;
7109  var size = getSize( elem );
7110  var offset = {
7111    left: boundingRect.left - thisRect.left - size.marginLeft,
7112    top: boundingRect.top - thisRect.top - size.marginTop,
7113    right: thisRect.right - boundingRect.right - size.marginRight,
7114    bottom: thisRect.bottom - boundingRect.bottom - size.marginBottom
7115  };
7116  return offset;
7117};
7118
7119// -------------------------- resize -------------------------- //
7120
7121// enable event handlers for listeners
7122// i.e. resize -> onresize
7123proto.handleEvent = utils.handleEvent;
7124
7125/**
7126 * Bind layout to window resizing
7127 */
7128proto.bindResize = function() {
7129  window.addEventListener( 'resize', this );
7130  this.isResizeBound = true;
7131};
7132
7133/**
7134 * Unbind layout to window resizing
7135 */
7136proto.unbindResize = function() {
7137  window.removeEventListener( 'resize', this );
7138  this.isResizeBound = false;
7139};
7140
7141proto.onresize = function() {
7142  this.resize();
7143};
7144
7145utils.debounceMethod( Outlayer, 'onresize', 100 );
7146
7147proto.resize = function() {
7148  // don't trigger if size did not change
7149  // or if resize was unbound. See #9
7150  if ( !this.isResizeBound || !this.needsResizeLayout() ) {
7151    return;
7152  }
7153
7154  this.layout();
7155};
7156
7157/**
7158 * check if layout is needed post layout
7159 * @returns Boolean
7160 */
7161proto.needsResizeLayout = function() {
7162  var size = getSize( this.element );
7163  // check that this.size and size are there
7164  // IE8 triggers resize on body size change, so they might not be
7165  var hasSizes = this.size && size;
7166  return hasSizes && size.innerWidth !== this.size.innerWidth;
7167};
7168
7169// -------------------------- methods -------------------------- //
7170
7171/**
7172 * add items to Outlayer instance
7173 * @param {Array or NodeList or Element} elems
7174 * @returns {Array} items - Outlayer.Items
7175**/
7176proto.addItems = function( elems ) {
7177  var items = this._itemize( elems );
7178  // add items to collection
7179  if ( items.length ) {
7180    this.items = this.items.concat( items );
7181  }
7182  return items;
7183};
7184
7185/**
7186 * Layout newly-appended item elements
7187 * @param {Array or NodeList or Element} elems
7188 */
7189proto.appended = function( elems ) {
7190  var items = this.addItems( elems );
7191  if ( !items.length ) {
7192    return;
7193  }
7194  // layout and reveal just the new items
7195  this.layoutItems( items, true );
7196  this.reveal( items );
7197};
7198
7199/**
7200 * Layout prepended elements
7201 * @param {Array or NodeList or Element} elems
7202 */
7203proto.prepended = function( elems ) {
7204  var items = this._itemize( elems );
7205  if ( !items.length ) {
7206    return;
7207  }
7208  // add items to beginning of collection
7209  var previousItems = this.items.slice(0);
7210  this.items = items.concat( previousItems );
7211  // start new layout
7212  this._resetLayout();
7213  this._manageStamps();
7214  // layout new stuff without transition
7215  this.layoutItems( items, true );
7216  this.reveal( items );
7217  // layout previous items
7218  this.layoutItems( previousItems );
7219};
7220
7221/**
7222 * reveal a collection of items
7223 * @param {Array of Outlayer.Items} items
7224 */
7225proto.reveal = function( items ) {
7226  this._emitCompleteOnItems( 'reveal', items );
7227  if ( !items || !items.length ) {
7228    return;
7229  }
7230  var stagger = this.updateStagger();
7231  items.forEach( function( item, i ) {
7232    item.stagger( i * stagger );
7233    item.reveal();
7234  });
7235};
7236
7237/**
7238 * hide a collection of items
7239 * @param {Array of Outlayer.Items} items
7240 */
7241proto.hide = function( items ) {
7242  this._emitCompleteOnItems( 'hide', items );
7243  if ( !items || !items.length ) {
7244    return;
7245  }
7246  var stagger = this.updateStagger();
7247  items.forEach( function( item, i ) {
7248    item.stagger( i * stagger );
7249    item.hide();
7250  });
7251};
7252
7253/**
7254 * reveal item elements
7255 * @param {Array}, {Element}, {NodeList} items
7256 */
7257proto.revealItemElements = function( elems ) {
7258  var items = this.getItems( elems );
7259  this.reveal( items );
7260};
7261
7262/**
7263 * hide item elements
7264 * @param {Array}, {Element}, {NodeList} items
7265 */
7266proto.hideItemElements = function( elems ) {
7267  var items = this.getItems( elems );
7268  this.hide( items );
7269};
7270
7271/**
7272 * get Outlayer.Item, given an Element
7273 * @param {Element} elem
7274 * @param {Function} callback
7275 * @returns {Outlayer.Item} item
7276 */
7277proto.getItem = function( elem ) {
7278  // loop through items to get the one that matches
7279  for ( var i=0; i < this.items.length; i++ ) {
7280    var item = this.items[i];
7281    if ( item.element == elem ) {
7282      // return item
7283      return item;
7284    }
7285  }
7286};
7287
7288/**
7289 * get collection of Outlayer.Items, given Elements
7290 * @param {Array} elems
7291 * @returns {Array} items - Outlayer.Items
7292 */
7293proto.getItems = function( elems ) {
7294  elems = utils.makeArray( elems );
7295  var items = [];
7296  elems.forEach( function( elem ) {
7297    var item = this.getItem( elem );
7298    if ( item ) {
7299      items.push( item );
7300    }
7301  }, this );
7302
7303  return items;
7304};
7305
7306/**
7307 * remove element(s) from instance and DOM
7308 * @param {Array or NodeList or Element} elems
7309 */
7310proto.remove = function( elems ) {
7311  var removeItems = this.getItems( elems );
7312
7313  this._emitCompleteOnItems( 'remove', removeItems );
7314
7315  // bail if no items to remove
7316  if ( !removeItems || !removeItems.length ) {
7317    return;
7318  }
7319
vendor: 38,285 bytes, lines 7320-8743
7320  removeItems.forEach( function( item ) {
7321    item.remove();
7322    // remove item from collection
7323    utils.removeFrom( this.items, item );
7324  }, this );
7325};
7326
7327// ----- destroy ----- //
7328
7329// remove and disable Outlayer instance
7330proto.destroy = function() {
7331  // clean up dynamic styles
7332  var style = this.element.style;
7333  style.height = '';
7334  style.position = '';
7335  style.width = '';
7336  // destroy items
7337  this.items.forEach( function( item ) {
7338    item.destroy();
7339  });
7340
7341  this.unbindResize();
7342
7343  var id = this.element.outlayerGUID;
7344  delete instances[ id ]; // remove reference to instance by id
7345  delete this.element.outlayerGUID;
7346  // remove data for jQuery
7347  if ( jQuery ) {
7348    jQuery.removeData( this.element, this.constructor.namespace );
7349  }
7350
7351};
7352
7353// -------------------------- data -------------------------- //
7354
7355/**
7356 * get Outlayer instance from element
7357 * @param {Element} elem
7358 * @returns {Outlayer}
7359 */
7360Outlayer.data = function( elem ) {
7361  elem = utils.getQueryElement( elem );
7362  var id = elem && elem.outlayerGUID;
7363  return id && instances[ id ];
7364};
7365
7366
7367// -------------------------- create Outlayer class -------------------------- //
7368
7369/**
7370 * create a layout class
7371 * @param {String} namespace
7372 */
7373Outlayer.create = function( namespace, options ) {
7374  // sub-class Outlayer
7375  var Layout = subclass( Outlayer );
7376  // apply new options and compatOptions
7377  Layout.defaults = utils.extend( {}, Outlayer.defaults );
7378  utils.extend( Layout.defaults, options );
7379  Layout.compatOptions = utils.extend( {}, Outlayer.compatOptions  );
7380
7381  Layout.namespace = namespace;
7382
7383  Layout.data = Outlayer.data;
7384
7385  // sub-class Item
7386  Layout.Item = subclass( Item );
7387
7388  // -------------------------- declarative -------------------------- //
7389
7390  utils.htmlInit( Layout, namespace );
7391
7392  // -------------------------- jQuery bridge -------------------------- //
7393
7394  // make into jQuery plugin
7395  if ( jQuery && jQuery.bridget ) {
7396    jQuery.bridget( namespace, Layout );
7397  }
7398
7399  return Layout;
7400};
7401
7402function subclass( Parent ) {
7403  function SubClass() {
7404    Parent.apply( this, arguments );
7405  }
7406
7407  SubClass.prototype = Object.create( Parent.prototype );
7408  SubClass.prototype.constructor = SubClass;
7409
7410  return SubClass;
7411}
7412
7413// ----- helpers ----- //
7414
7415// how many milliseconds are in each unit
7416var msUnits = {
7417  ms: 1,
7418  s: 1000
7419};
7420
7421// munge time-like parameter into millisecond number
7422// '0.4s' -> 40
7423function getMilliseconds( time ) {
7424  if ( typeof time == 'number' ) {
7425    return time;
7426  }
7427  var matches = time.match( /(^\d*\.?\d*)(\w*)/ );
7428  var num = matches && matches[1];
7429  var unit = matches && matches[2];
7430  if ( !num.length ) {
7431    return 0;
7432  }
7433  num = parseFloat( num );
7434  var mult = msUnits[ unit ] || 1;
7435  return num * mult;
7436}
7437
7438// ----- fin ----- //
7439
7440// back in global
7441Outlayer.Item = Item;
7442
7443return Outlayer;
7444
7445}));
7446
7447/**
7448 * Isotope Item
7449**/
7450
7451( function( window, factory ) {
7452  // universal module definition
7453  /* jshint strict: false */ /*globals define, module, require */
7454  if ( typeof define == 'function' && define.amd ) {
7455    // AMD
7456    define( 'isotope-layout/js/item',[
7457        'outlayer/outlayer'
7458      ],
7459      factory );
7460  } else if ( typeof module == 'object' && module.exports ) {
7461    // CommonJS
7462    module.exports = factory(
7463      require('outlayer')
7464    );
7465  } else {
7466    // browser global
7467    window.Isotope = window.Isotope || {};
7468    window.Isotope.Item = factory(
7469      window.Outlayer
7470    );
7471  }
7472
7473}( window, function factory( Outlayer ) {
7474'use strict';
7475
7476// -------------------------- Item -------------------------- //
7477
7478// sub-class Outlayer Item
7479function Item() {
7480  Outlayer.Item.apply( this, arguments );
7481}
7482
7483var proto = Item.prototype = Object.create( Outlayer.Item.prototype );
7484
7485var _create = proto._create;
7486proto._create = function() {
7487  // assign id, used for original-order sorting
7488  this.id = this.layout.itemGUID++;
7489  _create.call( this );
7490  this.sortData = {};
7491};
7492
7493proto.updateSortData = function() {
7494  if ( this.isIgnored ) {
7495    return;
7496  }
7497  // default sorters
7498  this.sortData.id = this.id;
7499  // for backward compatibility
7500  this.sortData['original-order'] = this.id;
7501  this.sortData.random = Math.random();
7502  // go thru getSortData obj and apply the sorters
7503  var getSortData = this.layout.options.getSortData;
7504  var sorters = this.layout._sorters;
7505  for ( var key in getSortData ) {
7506    var sorter = sorters[ key ];
7507    this.sortData[ key ] = sorter( this.element, this );
7508  }
7509};
7510
7511var _destroy = proto.destroy;
7512proto.destroy = function() {
7513  // call super
7514  _destroy.apply( this, arguments );
7515  // reset display, #741
7516  this.css({
7517    display: ''
7518  });
7519};
7520
7521return Item;
7522
7523}));
7524
7525/**
7526 * Isotope LayoutMode
7527 */
7528
7529( function( window, factory ) {
7530  // universal module definition
7531  /* jshint strict: false */ /*globals define, module, require */
7532  if ( typeof define == 'function' && define.amd ) {
7533    // AMD
7534    define( 'isotope-layout/js/layout-mode',[
7535        'get-size/get-size',
7536        'outlayer/outlayer'
7537      ],
7538      factory );
7539  } else if ( typeof module == 'object' && module.exports ) {
7540    // CommonJS
7541    module.exports = factory(
7542      require('get-size'),
7543      require('outlayer')
7544    );
7545  } else {
7546    // browser global
7547    window.Isotope = window.Isotope || {};
7548    window.Isotope.LayoutMode = factory(
7549      window.getSize,
7550      window.Outlayer
7551    );
7552  }
7553
7554}( window, function factory( getSize, Outlayer ) {
7555  'use strict';
7556
7557  // layout mode class
7558  function LayoutMode( isotope ) {
7559    this.isotope = isotope;
7560    // link properties
7561    if ( isotope ) {
7562      this.options = isotope.options[ this.namespace ];
7563      this.element = isotope.element;
7564      this.items = isotope.filteredItems;
7565      this.size = isotope.size;
7566    }
7567  }
7568
7569  var proto = LayoutMode.prototype;
7570
7571  /**
7572   * some methods should just defer to default Outlayer method
7573   * and reference the Isotope instance as `this`
7574  **/
7575  var facadeMethods = [
7576    '_resetLayout',
7577    '_getItemLayoutPosition',
7578    '_manageStamp',
7579    '_getContainerSize',
7580    '_getElementOffset',
7581    'needsResizeLayout',
7582    '_getOption'
7583  ];
7584
7585  facadeMethods.forEach( function( methodName ) {
7586    proto[ methodName ] = function() {
7587      return Outlayer.prototype[ methodName ].apply( this.isotope, arguments );
7588    };
7589  });
7590
7591  // -----  ----- //
7592
7593  // for horizontal layout modes, check vertical size
7594  proto.needsVerticalResizeLayout = function() {
7595    // don't trigger if size did not change
7596    var size = getSize( this.isotope.element );
7597    // check that this.size and size are there
7598    // IE8 triggers resize on body size change, so they might not be
7599    var hasSizes = this.isotope.size && size;
7600    return hasSizes && size.innerHeight != this.isotope.size.innerHeight;
7601  };
7602
7603  // ----- measurements ----- //
7604
7605  proto._getMeasurement = function() {
7606    this.isotope._getMeasurement.apply( this, arguments );
7607  };
7608
7609  proto.getColumnWidth = function() {
7610    this.getSegmentSize( 'column', 'Width' );
7611  };
7612
7613  proto.getRowHeight = function() {
7614    this.getSegmentSize( 'row', 'Height' );
7615  };
7616
7617  /**
7618   * get columnWidth or rowHeight
7619   * segment: 'column' or 'row'
7620   * size 'Width' or 'Height'
7621  **/
7622  proto.getSegmentSize = function( segment, size ) {
7623    var segmentName = segment + size;
7624    var outerSize = 'outer' + size;
7625    // columnWidth / outerWidth // rowHeight / outerHeight
7626    this._getMeasurement( segmentName, outerSize );
7627    // got rowHeight or columnWidth, we can chill
7628    if ( this[ segmentName ] ) {
7629      return;
7630    }
7631    // fall back to item of first element
7632    var firstItemSize = this.getFirstItemSize();
7633    this[ segmentName ] = firstItemSize && firstItemSize[ outerSize ] ||
7634      // or size of container
7635      this.isotope.size[ 'inner' + size ];
7636  };
7637
7638  proto.getFirstItemSize = function() {
7639    var firstItem = this.isotope.filteredItems[0];
7640    return firstItem && firstItem.element && getSize( firstItem.element );
7641  };
7642
7643  // ----- methods that should reference isotope ----- //
7644
7645  proto.layout = function() {
7646    this.isotope.layout.apply( this.isotope, arguments );
7647  };
7648
7649  proto.getSize = function() {
7650    this.isotope.getSize();
7651    this.size = this.isotope.size;
7652  };
7653
7654  // -------------------------- create -------------------------- //
7655
7656  LayoutMode.modes = {};
7657
7658  LayoutMode.create = function( namespace, options ) {
7659
7660    function Mode() {
7661      LayoutMode.apply( this, arguments );
7662    }
7663
7664    Mode.prototype = Object.create( proto );
7665    Mode.prototype.constructor = Mode;
7666
7667    // default options
7668    if ( options ) {
7669      Mode.options = options;
7670    }
7671
7672    Mode.prototype.namespace = namespace;
7673    // register in Isotope
7674    LayoutMode.modes[ namespace ] = Mode;
7675
7676    return Mode;
7677  };
7678
7679  return LayoutMode;
7680
7681}));
7682
7683/*!
7684 * Masonry v4.2.1
7685 * Cascading grid layout library
7686 * https://masonry.desandro.com
7687 * MIT License
7688 * by David DeSandro
7689 */
7690
7691( function( window, factory ) {
7692  // universal module definition
7693  /* jshint strict: false */ /*globals define, module, require */
7694  if ( typeof define == 'function' && define.amd ) {
7695    // AMD
7696    define( 'masonry-layout/masonry',[
7697        'outlayer/outlayer',
7698        'get-size/get-size'
7699      ],
7700      factory );
7701  } else if ( typeof module == 'object' && module.exports ) {
7702    // CommonJS
7703    module.exports = factory(
7704      require('outlayer'),
7705      require('get-size')
7706    );
7707  } else {
7708    // browser global
7709    window.Masonry = factory(
7710      window.Outlayer,
7711      window.getSize
7712    );
7713  }
7714
7715}( window, function factory( Outlayer, getSize ) {
7716
7717
7718
7719// -------------------------- masonryDefinition -------------------------- //
7720
7721  // create an Outlayer layout class
7722  var Masonry = Outlayer.create('masonry');
7723  // isFitWidth -> fitWidth
7724  Masonry.compatOptions.fitWidth = 'isFitWidth';
7725
7726  var proto = Masonry.prototype;
7727
7728  proto._resetLayout = function() {
7729    this.getSize();
7730    this._getMeasurement( 'columnWidth', 'outerWidth' );
7731    this._getMeasurement( 'gutter', 'outerWidth' );
7732    this.measureColumns();
7733
7734    // reset column Y
7735    this.colYs = [];
7736    for ( var i=0; i < this.cols; i++ ) {
7737      this.colYs.push( 0 );
7738    }
7739
7740    this.maxY = 0;
7741    this.horizontalColIndex = 0;
7742  };
7743
7744  proto.measureColumns = function() {
7745    this.getContainerWidth();
7746    // if columnWidth is 0, default to outerWidth of first item
7747    if ( !this.columnWidth ) {
7748      var firstItem = this.items[0];
7749      var firstItemElem = firstItem && firstItem.element;
7750      // columnWidth fall back to item of first element
7751      this.columnWidth = firstItemElem && getSize( firstItemElem ).outerWidth ||
7752        // if first elem has no width, default to size of container
7753        this.containerWidth;
7754    }
7755
7756    var columnWidth = this.columnWidth += this.gutter;
7757
7758    // calculate columns
7759    var containerWidth = this.containerWidth + this.gutter;
7760    var cols = containerWidth / columnWidth;
7761    // fix rounding errors, typically with gutters
7762    var excess = columnWidth - containerWidth % columnWidth;
7763    // if overshoot is less than a pixel, round up, otherwise floor it
7764    var mathMethod = excess && excess < 1 ? 'round' : 'floor';
7765    cols = Math[ mathMethod ]( cols );
7766    this.cols = Math.max( cols, 1 );
7767  };
7768
7769  proto.getContainerWidth = function() {
7770    // container is parent if fit width
7771    var isFitWidth = this._getOption('fitWidth');
7772    var container = isFitWidth ? this.element.parentNode : this.element;
7773    // check that this.size and size are there
7774    // IE8 triggers resize on body size change, so they might not be
7775    var size = getSize( container );
7776    this.containerWidth = size && size.innerWidth;
7777  };
7778
7779  proto._getItemLayoutPosition = function( item ) {
7780    item.getSize();
7781    // how many columns does this brick span
7782    var remainder = item.size.outerWidth % this.columnWidth;
7783    var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil';
7784    // round if off by 1 pixel, otherwise use ceil
7785    var colSpan = Math[ mathMethod ]( item.size.outerWidth / this.columnWidth );
7786    colSpan = Math.min( colSpan, this.cols );
7787    // use horizontal or top column position
7788    var colPosMethod = this.options.horizontalOrder ?
7789      '_getHorizontalColPosition' : '_getTopColPosition';
7790    var colPosition = this[ colPosMethod ]( colSpan, item );
7791    // position the brick
7792    var position = {
7793      x: this.columnWidth * colPosition.col,
7794      y: colPosition.y
7795    };
7796    // apply setHeight to necessary columns
7797    var setHeight = colPosition.y + item.size.outerHeight;
7798    var setMax = colSpan + colPosition.col;
7799    for ( var i = colPosition.col; i < setMax; i++ ) {
7800      this.colYs[i] = setHeight;
7801    }
7802
7803    return position;
7804  };
7805
7806  proto._getTopColPosition = function( colSpan ) {
7807    var colGroup = this._getTopColGroup( colSpan );
7808    // get the minimum Y value from the columns
7809    var minimumY = Math.min.apply( Math, colGroup );
7810
7811    return {
7812      col: colGroup.indexOf( minimumY ),
7813      y: minimumY,
7814    };
7815  };
7816
7817  /**
7818   * @param {Number} colSpan - number of columns the element spans
7819   * @returns {Array} colGroup
7820   */
7821  proto._getTopColGroup = function( colSpan ) {
7822    if ( colSpan < 2 ) {
7823      // if brick spans only one column, use all the column Ys
7824      return this.colYs;
7825    }
7826
7827    var colGroup = [];
7828    // how many different places could this brick fit horizontally
7829    var groupCount = this.cols + 1 - colSpan;
7830    // for each group potential horizontal position
7831    for ( var i = 0; i < groupCount; i++ ) {
7832      colGroup[i] = this._getColGroupY( i, colSpan );
7833    }
7834    return colGroup;
7835  };
7836
7837  proto._getColGroupY = function( col, colSpan ) {
7838    if ( colSpan < 2 ) {
7839      return this.colYs[ col ];
7840    }
7841    // make an array of colY values for that one group
7842    var groupColYs = this.colYs.slice( col, col + colSpan );
7843    // and get the max value of the array
7844    return Math.max.apply( Math, groupColYs );
7845  };
7846
7847  // get column position based on horizontal index. #873
7848  proto._getHorizontalColPosition = function( colSpan, item ) {
7849    var col = this.horizontalColIndex % this.cols;
7850    var isOver = colSpan > 1 && col + colSpan > this.cols;
7851    // shift to next row if item can't fit on current row
7852    col = isOver ? 0 : col;
7853    // don't let zero-size items take up space
7854    var hasSize = item.size.outerWidth && item.size.outerHeight;
7855    this.horizontalColIndex = hasSize ? col + colSpan : this.horizontalColIndex;
7856
7857    return {
7858      col: col,
7859      y: this._getColGroupY( col, colSpan ),
7860    };
7861  };
7862
7863  proto._manageStamp = function( stamp ) {
7864    var stampSize = getSize( stamp );
7865    var offset = this._getElementOffset( stamp );
7866    // get the columns that this stamp affects
7867    var isOriginLeft = this._getOption('originLeft');
7868    var firstX = isOriginLeft ? offset.left : offset.right;
7869    var lastX = firstX + stampSize.outerWidth;
7870    var firstCol = Math.floor( firstX / this.columnWidth );
7871    firstCol = Math.max( 0, firstCol );
7872    var lastCol = Math.floor( lastX / this.columnWidth );
7873    // lastCol should not go over if multiple of columnWidth #425
7874    lastCol -= lastX % this.columnWidth ? 0 : 1;
7875    lastCol = Math.min( this.cols - 1, lastCol );
7876    // set colYs to bottom of the stamp
7877
7878    var isOriginTop = this._getOption('originTop');
7879    var stampMaxY = ( isOriginTop ? offset.top : offset.bottom ) +
7880      stampSize.outerHeight;
7881    for ( var i = firstCol; i <= lastCol; i++ ) {
7882      this.colYs[i] = Math.max( stampMaxY, this.colYs[i] );
7883    }
7884  };
7885
7886  proto._getContainerSize = function() {
7887    this.maxY = Math.max.apply( Math, this.colYs );
7888    var size = {
7889      height: this.maxY
7890    };
7891
7892    if ( this._getOption('fitWidth') ) {
7893      size.width = this._getContainerFitWidth();
7894    }
7895
7896    return size;
7897  };
7898
7899  proto._getContainerFitWidth = function() {
7900    var unusedCols = 0;
7901    // count unused columns
7902    var i = this.cols;
7903    while ( --i ) {
7904      if ( this.colYs[i] !== 0 ) {
7905        break;
7906      }
7907      unusedCols++;
7908    }
7909    // fit container to columns that have been used
7910    return ( this.cols - unusedCols ) * this.columnWidth - this.gutter;
7911  };
7912
7913  proto.needsResizeLayout = function() {
7914    var previousWidth = this.containerWidth;
7915    this.getContainerWidth();
7916    return previousWidth != this.containerWidth;
7917  };
7918
7919  return Masonry;
7920
7921}));
7922
7923/*!
7924 * Masonry layout mode
7925 * sub-classes Masonry
7926 * https://masonry.desandro.com
7927 */
7928
7929( function( window, factory ) {
7930  // universal module definition
7931  /* jshint strict: false */ /*globals define, module, require */
7932  if ( typeof define == 'function' && define.amd ) {
7933    // AMD
7934    define( 'isotope-layout/js/layout-modes/masonry',[
7935        '../layout-mode',
7936        'masonry-layout/masonry'
7937      ],
7938      factory );
7939  } else if ( typeof module == 'object' && module.exports ) {
7940    // CommonJS
7941    module.exports = factory(
7942      require('../layout-mode'),
7943      require('masonry-layout')
7944    );
7945  } else {
7946    // browser global
7947    factory(
7948      window.Isotope.LayoutMode,
7949      window.Masonry
7950    );
7951  }
7952
7953}( window, function factory( LayoutMode, Masonry ) {
7954'use strict';
7955
7956// -------------------------- masonryDefinition -------------------------- //
7957
7958  // create an Outlayer layout class
7959  var MasonryMode = LayoutMode.create('masonry');
7960
7961  var proto = MasonryMode.prototype;
7962
7963  var keepModeMethods = {
7964    _getElementOffset: true,
7965    layout: true,
7966    _getMeasurement: true
7967  };
7968
7969  // inherit Masonry prototype
7970  for ( var method in Masonry.prototype ) {
7971    // do not inherit mode methods
7972    if ( !keepModeMethods[ method ] ) {
7973      proto[ method ] = Masonry.prototype[ method ];
7974    }
7975  }
7976
7977  var measureColumns = proto.measureColumns;
7978  proto.measureColumns = function() {
7979    // set items, used if measuring first item
7980    this.items = this.isotope.filteredItems;
7981    measureColumns.call( this );
7982  };
7983
7984  // point to mode options for fitWidth
7985  var _getOption = proto._getOption;
7986  proto._getOption = function( option ) {
7987    if ( option == 'fitWidth' ) {
7988      return this.options.isFitWidth !== undefined ?
7989        this.options.isFitWidth : this.options.fitWidth;
7990    }
7991    return _getOption.apply( this.isotope, arguments );
7992  };
7993
7994  return MasonryMode;
7995
7996}));
7997
7998/**
7999 * fitRows layout mode
8000 */
8001
8002( function( window, factory ) {
8003  // universal module definition
8004  /* jshint strict: false */ /*globals define, module, require */
8005  if ( typeof define == 'function' && define.amd ) {
8006    // AMD
8007    define( 'isotope-layout/js/layout-modes/fit-rows',[
8008        '../layout-mode'
8009      ],
8010      factory );
8011  } else if ( typeof exports == 'object' ) {
8012    // CommonJS
8013    module.exports = factory(
8014      require('../layout-mode')
8015    );
8016  } else {
8017    // browser global
8018    factory(
8019      window.Isotope.LayoutMode
8020    );
8021  }
8022
8023}( window, function factory( LayoutMode ) {
8024'use strict';
8025
8026var FitRows = LayoutMode.create('fitRows');
8027
8028var proto = FitRows.prototype;
8029
8030proto._resetLayout = function() {
8031  this.x = 0;
8032  this.y = 0;
8033  this.maxY = 0;
8034  this._getMeasurement( 'gutter', 'outerWidth' );
8035};
8036
8037proto._getItemLayoutPosition = function( item ) {
8038  item.getSize();
8039
8040  var itemWidth = item.size.outerWidth + this.gutter;
8041  // if this element cannot fit in the current row
8042  var containerWidth = this.isotope.size.innerWidth + this.gutter;
8043  if ( this.x !== 0 && itemWidth + this.x > containerWidth ) {
8044    this.x = 0;
8045    this.y = this.maxY;
8046  }
8047
8048  var position = {
8049    x: this.x,
8050    y: this.y
8051  };
8052
8053  this.maxY = Math.max( this.maxY, this.y + item.size.outerHeight );
8054  this.x += itemWidth;
8055
8056  return position;
8057};
8058
8059proto._getContainerSize = function() {
8060  return { height: this.maxY };
8061};
8062
8063return FitRows;
8064
8065}));
8066
8067/**
8068 * vertical layout mode
8069 */
8070
8071( function( window, factory ) {
8072  // universal module definition
8073  /* jshint strict: false */ /*globals define, module, require */
8074  if ( typeof define == 'function' && define.amd ) {
8075    // AMD
8076    define( 'isotope-layout/js/layout-modes/vertical',[
8077        '../layout-mode'
8078      ],
8079      factory );
8080  } else if ( typeof module == 'object' && module.exports ) {
8081    // CommonJS
8082    module.exports = factory(
8083      require('../layout-mode')
8084    );
8085  } else {
8086    // browser global
8087    factory(
8088      window.Isotope.LayoutMode
8089    );
8090  }
8091
8092}( window, function factory( LayoutMode ) {
8093'use strict';
8094
8095var Vertical = LayoutMode.create( 'vertical', {
8096  horizontalAlignment: 0
8097});
8098
8099var proto = Vertical.prototype;
8100
8101proto._resetLayout = function() {
8102  this.y = 0;
8103};
8104
8105proto._getItemLayoutPosition = function( item ) {
8106  item.getSize();
8107  var x = ( this.isotope.size.innerWidth - item.size.outerWidth ) *
8108    this.options.horizontalAlignment;
8109  var y = this.y;
8110  this.y += item.size.outerHeight;
8111  return { x: x, y: y };
8112};
8113
8114proto._getContainerSize = function() {
8115  return { height: this.y };
8116};
8117
8118return Vertical;
8119
8120}));
8121
8122/*!
8123 * Isotope v3.0.6
8124 *
8125 * Licensed GPLv3 for open source use
8126 * or Isotope Commercial License for commercial use
8127 *
8128 * https://isotope.metafizzy.co
8129 * Copyright 2010-2018 Metafizzy
8130 */
8131
8132( function( window, factory ) {
8133  // universal module definition
8134  /* jshint strict: false */ /*globals define, module, require */
8135  if ( typeof define == 'function' && define.amd ) {
8136    // AMD
8137    define( [
8138        'outlayer/outlayer',
8139        'get-size/get-size',
8140        'desandro-matches-selector/matches-selector',
8141        'fizzy-ui-utils/utils',
8142        'isotope-layout/js/item',
8143        'isotope-layout/js/layout-mode',
8144        // include default layout modes
8145        'isotope-layout/js/layout-modes/masonry',
8146        'isotope-layout/js/layout-modes/fit-rows',
8147        'isotope-layout/js/layout-modes/vertical'
8148      ],
8149      function( Outlayer, getSize, matchesSelector, utils, Item, LayoutMode ) {
8150        return factory( window, Outlayer, getSize, matchesSelector, utils, Item, LayoutMode );
8151      });
8152  } else if ( typeof module == 'object' && module.exports ) {
8153    // CommonJS
8154    module.exports = factory(
8155      window,
8156      require('outlayer'),
8157      require('get-size'),
8158      require('desandro-matches-selector'),
8159      require('fizzy-ui-utils'),
8160      require('isotope-layout/js/item'),
8161      require('isotope-layout/js/layout-mode'),
8162      // include default layout modes
8163      require('isotope-layout/js/layout-modes/masonry'),
8164      require('isotope-layout/js/layout-modes/fit-rows'),
8165      require('isotope-layout/js/layout-modes/vertical')
8166    );
8167  } else {
8168    // browser global
8169    window.Isotope = factory(
8170      window,
8171      window.Outlayer,
8172      window.getSize,
8173      window.matchesSelector,
8174      window.fizzyUIUtils,
8175      window.Isotope.Item,
8176      window.Isotope.LayoutMode
8177    );
8178  }
8179
8180}( window, function factory( window, Outlayer, getSize, matchesSelector, utils,
8181  Item, LayoutMode ) {
8182
8183
8184
8185// -------------------------- vars -------------------------- //
8186
8187var jQuery = window.jQuery;
8188
8189// -------------------------- helpers -------------------------- //
8190
8191var trim = String.prototype.trim ?
8192  function( str ) {
8193    return str.trim();
8194  } :
8195  function( str ) {
8196    return str.replace( /^\s+|\s+$/g, '' );
8197  };
8198
8199// -------------------------- isotopeDefinition -------------------------- //
8200
8201  // create an Outlayer layout class
8202  var Isotope = Outlayer.create( 'isotope', {
8203    layoutMode: 'masonry',
8204    isJQueryFiltering: true,
8205    sortAscending: true
8206  });
8207
8208  Isotope.Item = Item;
8209  Isotope.LayoutMode = LayoutMode;
8210
8211  var proto = Isotope.prototype;
8212
8213  proto._create = function() {
8214    this.itemGUID = 0;
8215    // functions that sort items
8216    this._sorters = {};
8217    this._getSorters();
8218    // call super
8219    Outlayer.prototype._create.call( this );
8220
8221    // create layout modes
8222    this.modes = {};
8223    // start filteredItems with all items
8224    this.filteredItems = this.items;
8225    // keep of track of sortBys
8226    this.sortHistory = [ 'original-order' ];
8227    // create from registered layout modes
8228    for ( var name in LayoutMode.modes ) {
8229      this._initLayoutMode( name );
8230    }
8231  };
8232
8233  proto.reloadItems = function() {
8234    // reset item ID counter
8235    this.itemGUID = 0;
8236    // call super
8237    Outlayer.prototype.reloadItems.call( this );
8238  };
8239
8240  proto._itemize = function() {
8241    var items = Outlayer.prototype._itemize.apply( this, arguments );
8242    // assign ID for original-order
8243    for ( var i=0; i < items.length; i++ ) {
8244      var item = items[i];
8245      item.id = this.itemGUID++;
8246    }
8247    this._updateItemsSortData( items );
8248    return items;
8249  };
8250
8251
8252  // -------------------------- layout -------------------------- //
8253
8254  proto._initLayoutMode = function( name ) {
8255    var Mode = LayoutMode.modes[ name ];
8256    // set mode options
8257    // HACK extend initial options, back-fill in default options
8258    var initialOpts = this.options[ name ] || {};
8259    this.options[ name ] = Mode.options ?
8260      utils.extend( Mode.options, initialOpts ) : initialOpts;
8261    // init layout mode instance
8262    this.modes[ name ] = new Mode( this );
8263  };
8264
8265
8266  proto.layout = function() {
8267    // if first time doing layout, do all magic
8268    if ( !this._isLayoutInited && this._getOption('initLayout') ) {
8269      this.arrange();
8270      return;
8271    }
8272    this._layout();
8273  };
8274
8275  // private method to be used in layout() & magic()
8276  proto._layout = function() {
8277    // don't animate first layout
8278    var isInstant = this._getIsInstant();
8279    // layout flow
8280    this._resetLayout();
8281    this._manageStamps();
8282    this.layoutItems( this.filteredItems, isInstant );
8283
8284    // flag for initalized
8285    this._isLayoutInited = true;
8286  };
8287
8288  // filter + sort + layout
8289  proto.arrange = function( opts ) {
8290    // set any options pass
8291    this.option( opts );
8292    this._getIsInstant();
8293    // filter, sort, and layout
8294
8295    // filter
8296    var filtered = this._filter( this.items );
8297    this.filteredItems = filtered.matches;
8298
8299    this._bindArrangeComplete();
8300
8301    if ( this._isInstant ) {
8302      this._noTransition( this._hideReveal, [ filtered ] );
8303    } else {
8304      this._hideReveal( filtered );
8305    }
8306
8307    this._sort();
8308    this._layout();
8309  };
8310  // alias to _init for main plugin method
8311  proto._init = proto.arrange;
8312
8313  proto._hideReveal = function( filtered ) {
8314    this.reveal( filtered.needReveal );
8315    this.hide( filtered.needHide );
8316  };
8317
8318  // HACK
8319  // Don't animate/transition first layout
8320  // Or don't animate/transition other layouts
8321  proto._getIsInstant = function() {
8322    var isLayoutInstant = this._getOption('layoutInstant');
8323    var isInstant = isLayoutInstant !== undefined ? isLayoutInstant :
8324      !this._isLayoutInited;
8325    this._isInstant = isInstant;
8326    return isInstant;
8327  };
8328
8329  // listen for layoutComplete, hideComplete and revealComplete
8330  // to trigger arrangeComplete
8331  proto._bindArrangeComplete = function() {
8332    // listen for 3 events to trigger arrangeComplete
8333    var isLayoutComplete, isHideComplete, isRevealComplete;
8334    var _this = this;
8335    function arrangeParallelCallback() {
8336      if ( isLayoutComplete && isHideComplete && isRevealComplete ) {
8337        _this.dispatchEvent( 'arrangeComplete', null, [ _this.filteredItems ] );
8338      }
8339    }
8340    this.once( 'layoutComplete', function() {
8341      isLayoutComplete = true;
8342      arrangeParallelCallback();
8343    });
8344    this.once( 'hideComplete', function() {
8345      isHideComplete = true;
8346      arrangeParallelCallback();
8347    });
8348    this.once( 'revealComplete', function() {
8349      isRevealComplete = true;
8350      arrangeParallelCallback();
8351    });
8352  };
8353
8354  // -------------------------- filter -------------------------- //
8355
8356  proto._filter = function( items ) {
8357    var filter = this.options.filter;
8358    filter = filter || '*';
8359    var matches = [];
8360    var hiddenMatched = [];
8361    var visibleUnmatched = [];
8362
8363    var test = this._getFilterTest( filter );
8364
8365    // test each item
8366    for ( var i=0; i < items.length; i++ ) {
8367      var item = items[i];
8368      if ( item.isIgnored ) {
8369        continue;
8370      }
8371      // add item to either matched or unmatched group
8372      var isMatched = test( item );
8373      // item.isFilterMatched = isMatched;
8374      // add to matches if its a match
8375      if ( isMatched ) {
8376        matches.push( item );
8377      }
8378      // add to additional group if item needs to be hidden or revealed
8379      if ( isMatched && item.isHidden ) {
8380        hiddenMatched.push( item );
8381      } else if ( !isMatched && !item.isHidden ) {
8382        visibleUnmatched.push( item );
8383      }
8384    }
8385
8386    // return collections of items to be manipulated
8387    return {
8388      matches: matches,
8389      needReveal: hiddenMatched,
8390      needHide: visibleUnmatched
8391    };
8392  };
8393
8394  // get a jQuery, function, or a matchesSelector test given the filter
8395  proto._getFilterTest = function( filter ) {
8396    if ( jQuery && this.options.isJQueryFiltering ) {
8397      // use jQuery
8398      return function( item ) {
8399        return jQuery( item.element ).is( filter );
8400      };
8401    }
8402    if ( typeof filter == 'function' ) {
8403      // use filter as function
8404      return function( item ) {
8405        return filter( item.element );
8406      };
8407    }
8408    // default, use filter as selector string
8409    return function( item ) {
8410      return matchesSelector( item.element, filter );
8411    };
8412  };
8413
8414  // -------------------------- sorting -------------------------- //
8415
8416  /**
8417   * @params {Array} elems
8418   * @public
8419   */
8420  proto.updateSortData = function( elems ) {
8421    // get items
8422    var items;
8423    if ( elems ) {
8424      elems = utils.makeArray( elems );
8425      items = this.getItems( elems );
8426    } else {
8427      // update all items if no elems provided
8428      items = this.items;
8429    }
8430
8431    this._getSorters();
8432    this._updateItemsSortData( items );
8433  };
8434
8435  proto._getSorters = function() {
8436    var getSortData = this.options.getSortData;
8437    for ( var key in getSortData ) {
8438      var sorter = getSortData[ key ];
8439      this._sorters[ key ] = mungeSorter( sorter );
8440    }
8441  };
8442
8443  /**
8444   * @params {Array} items - of Isotope.Items
8445   * @private
8446   */
8447  proto._updateItemsSortData = function( items ) {
8448    // do not update if no items
8449    var len = items && items.length;
8450
8451    for ( var i=0; len && i < len; i++ ) {
8452      var item = items[i];
8453      item.updateSortData();
8454    }
8455  };
8456
8457  // ----- munge sorter ----- //
8458
8459  // encapsulate this, as we just need mungeSorter
8460  // other functions in here are just for munging
8461  var mungeSorter = ( function() {
8462    // add a magic layer to sorters for convienent shorthands
8463    // `.foo-bar` will use the text of .foo-bar querySelector
8464    // `[foo-bar]` will use attribute
8465    // you can also add parser
8466    // `.foo-bar parseInt` will parse that as a number
8467    function mungeSorter( sorter ) {
8468      // if not a string, return function or whatever it is
8469      if ( typeof sorter != 'string' ) {
8470        return sorter;
8471      }
8472      // parse the sorter string
8473      var args = trim( sorter ).split(' ');
8474      var query = args[0];
8475      // check if query looks like [an-attribute]
8476      var attrMatch = query.match( /^\[(.+)\]$/ );
8477      var attr = attrMatch && attrMatch[1];
8478      var getValue = getValueGetter( attr, query );
8479      // use second argument as a parser
8480      var parser = Isotope.sortDataParsers[ args[1] ];
8481      // parse the value, if there was a parser
8482      sorter = parser ? function( elem ) {
8483        return elem && parser( getValue( elem ) );
8484      } :
8485      // otherwise just return value
8486      function( elem ) {
8487        return elem && getValue( elem );
8488      };
8489
8490      return sorter;
8491    }
8492
8493    // get an attribute getter, or get text of the querySelector
8494    function getValueGetter( attr, query ) {
8495      // if query looks like [foo-bar], get attribute
8496      if ( attr ) {
8497        return function getAttribute( elem ) {
8498          return elem.getAttribute( attr );
8499        };
8500      }
8501
8502      // otherwise, assume its a querySelector, and get its text
8503      return function getChildText( elem ) {
8504        var child = elem.querySelector( query );
8505        return child && child.textContent;
8506      };
8507    }
8508
8509    return mungeSorter;
8510  })();
8511
8512  // parsers used in getSortData shortcut strings
8513  Isotope.sortDataParsers = {
8514    'parseInt': function( val ) {
8515      return parseInt( val, 10 );
8516    },
8517    'parseFloat': function( val ) {
8518      return parseFloat( val );
8519    }
8520  };
8521
8522  // ----- sort method ----- //
8523
8524  // sort filteredItem order
8525  proto._sort = function() {
8526    if ( !this.options.sortBy ) {
8527      return;
8528    }
8529    // keep track of sortBy History
8530    var sortBys = utils.makeArray( this.options.sortBy );
8531    if ( !this._getIsSameSortBy( sortBys ) ) {
8532      // concat all sortBy and sortHistory, add to front, oldest goes in last
8533      this.sortHistory = sortBys.concat( this.sortHistory );
8534    }
8535    // sort magic
8536    var itemSorter = getItemSorter( this.sortHistory, this.options.sortAscending );
8537    this.filteredItems.sort( itemSorter );
8538  };
8539
8540  // check if sortBys is same as start of sortHistory
8541  proto._getIsSameSortBy = function( sortBys ) {
8542    for ( var i=0; i < sortBys.length; i++ ) {
8543      if ( sortBys[i] != this.sortHistory[i] ) {
8544        return false;
8545      }
8546    }
8547    return true;
8548  };
8549
8550  // returns a function used for sorting
8551  function getItemSorter( sortBys, sortAsc ) {
8552    return function sorter( itemA, itemB ) {
8553      // cycle through all sortKeys
8554      for ( var i = 0; i < sortBys.length; i++ ) {
8555        var sortBy = sortBys[i];
8556        var a = itemA.sortData[ sortBy ];
8557        var b = itemB.sortData[ sortBy ];
8558        if ( a > b || a < b ) {
8559          // if sortAsc is an object, use the value given the sortBy key
8560          var isAscending = sortAsc[ sortBy ] !== undefined ? sortAsc[ sortBy ] : sortAsc;
8561          var direction = isAscending ? 1 : -1;
8562          return ( a > b ? 1 : -1 ) * direction;
8563        }
8564      }
8565      return 0;
8566    };
8567  }
8568
8569  // -------------------------- methods -------------------------- //
8570
8571  // get layout mode
8572  proto._mode = function() {
8573    var layoutMode = this.options.layoutMode;
8574    var mode = this.modes[ layoutMode ];
8575    if ( !mode ) {
8576      // TODO console.error
8577      throw new Error( 'No layout mode: ' + layoutMode );
8578    }
8579    // HACK sync mode's options
8580    // any options set after init for layout mode need to be synced
8581    mode.options = this.options[ layoutMode ];
8582    return mode;
8583  };
8584
8585  proto._resetLayout = function() {
8586    // trigger original reset layout
8587    Outlayer.prototype._resetLayout.call( this );
8588    this._mode()._resetLayout();
8589  };
8590
8591  proto._getItemLayoutPosition = function( item  ) {
8592    return this._mode()._getItemLayoutPosition( item );
8593  };
8594
8595  proto._manageStamp = function( stamp ) {
8596    this._mode()._manageStamp( stamp );
8597  };
8598
8599  proto._getContainerSize = function() {
8600    return this._mode()._getContainerSize();
8601  };
8602
8603  proto.needsResizeLayout = function() {
8604    return this._mode().needsResizeLayout();
8605  };
8606
8607  // -------------------------- adding & removing -------------------------- //
8608
8609  // HEADS UP overwrites default Outlayer appended
8610  proto.appended = function( elems ) {
8611    var items = this.addItems( elems );
8612    if ( !items.length ) {
8613      return;
8614    }
8615    // filter, layout, reveal new items
8616    var filteredItems = this._filterRevealAdded( items );
8617    // add to filteredItems
8618    this.filteredItems = this.filteredItems.concat( filteredItems );
8619  };
8620
8621  // HEADS UP overwrites default Outlayer prepended
8622  proto.prepended = function( elems ) {
8623    var items = this._itemize( elems );
8624    if ( !items.length ) {
8625      return;
8626    }
8627    // start new layout
8628    this._resetLayout();
8629    this._manageStamps();
8630    // filter, layout, reveal new items
8631    var filteredItems = this._filterRevealAdded( items );
8632    // layout previous items
8633    this.layoutItems( this.filteredItems );
8634    // add to items and filteredItems
8635    this.filteredItems = filteredItems.concat( this.filteredItems );
8636    this.items = items.concat( this.items );
8637  };
8638
8639  proto._filterRevealAdded = function( items ) {
8640    var filtered = this._filter( items );
8641    this.hide( filtered.needHide );
8642    // reveal all new items
8643    this.reveal( filtered.matches );
8644    // layout new items, no transition
8645    this.layoutItems( filtered.matches, true );
8646    return filtered.matches;
8647  };
8648
8649  /**
8650   * Filter, sort, and layout newly-appended item elements
8651   * @param {Array or NodeList or Element} elems
8652   */
8653  proto.insert = function( elems ) {
8654    var items = this.addItems( elems );
8655    if ( !items.length ) {
8656      return;
8657    }
8658    // append item elements
8659    var i, item;
8660    var len = items.length;
8661    for ( i=0; i < len; i++ ) {
8662      item = items[i];
8663      this.element.appendChild( item.element );
8664    }
8665    // filter new stuff
8666    var filteredInsertItems = this._filter( items ).matches;
8667    // set flag
8668    for ( i=0; i < len; i++ ) {
8669      items[i].isLayoutInstant = true;
8670    }
8671    this.arrange();
8672    // reset flag
8673    for ( i=0; i < len; i++ ) {
8674      delete items[i].isLayoutInstant;
8675    }
8676    this.reveal( filteredInsertItems );
8677  };
8678
8679  var _remove = proto.remove;
8680  proto.remove = function( elems ) {
8681    elems = utils.makeArray( elems );
8682    var removeItems = this.getItems( elems );
8683    // do regular thing
8684    _remove.call( this, elems );
8685    // bail if no items to remove
8686    var len = removeItems && removeItems.length;
8687    // remove elems from filteredItems
8688    for ( var i=0; len && i < len; i++ ) {
8689      var item = removeItems[i];
8690      // remove item from collection
8691      utils.removeFrom( this.filteredItems, item );
8692    }
8693  };
8694
8695  proto.shuffle = function() {
8696    // update random sortData
8697    for ( var i=0; i < this.items.length; i++ ) {
8698      var item = this.items[i];
8699      item.sortData.random = Math.random();
8700    }
8701    this.options.sortBy = 'random';
8702    this._sort();
8703    this._layout();
8704  };
8705
8706  /**
8707   * trigger fn without transition
8708   * kind of hacky to have this in the first place
8709   * @param {Function} fn
8710   * @param {Array} args
8711   * @returns ret
8712   * @private
8713   */
8714  proto._noTransition = function( fn, args ) {
8715    // save transitionDuration before disabling
8716    var transitionDuration = this.options.transitionDuration;
8717    // disable transition
8718    this.options.transitionDuration = 0;
8719    // do it
8720    var returnValue = fn.apply( this, args );
8721    // re-enable transition for reveal
8722    this.options.transitionDuration = transitionDuration;
8723    return returnValue;
8724  };
8725
8726  // ----- helper methods ----- //
8727
8728  /**
8729   * getter method for getting filtered item elements
8730   * @returns {Array} elems - collection of item elements
8731   */
8732  proto.getFilteredItemElements = function() {
8733    return this.filteredItems.map( function( item ) {
8734      return item.element;
8735    });
8736  };
8737
8738  // -----  ----- //
8739
8740  return Isotope;
8741
8742}));
8743
vendor: 29,252 bytes, lines 8744-9900
8744/*!
8745 * Packery layout mode PACKAGED v2.0.1
8746 * sub-classes Packery
8747 */
8748
8749/**
8750 * Rect
8751 * low-level utility class for basic geometry
8752 */
8753
8754( function( window, factory ) {
8755  // universal module definition
8756  /* jshint strict: false */ /* globals define, module */
8757  if ( typeof define == 'function' && define.amd ) {
8758    // AMD
8759    define( 'packery/js/rect',factory );
8760  } else if ( typeof module == 'object' && module.exports ) {
8761    // CommonJS
8762    module.exports = factory();
8763  } else {
8764    // browser global
8765    window.Packery = window.Packery || {};
8766    window.Packery.Rect = factory();
8767  }
8768
8769}( window, function factory() {
8770
8771
8772// -------------------------- Rect -------------------------- //
8773
8774function Rect( props ) {
8775  // extend properties from defaults
8776  for ( var prop in Rect.defaults ) {
8777    this[ prop ] = Rect.defaults[ prop ];
8778  }
8779
8780  for ( prop in props ) {
8781    this[ prop ] = props[ prop ];
8782  }
8783
8784}
8785
8786Rect.defaults = {
8787  x: 0,
8788  y: 0,
8789  width: 0,
8790  height: 0
8791};
8792
8793var proto = Rect.prototype;
8794
8795/**
8796 * Determines whether or not this rectangle wholly encloses another rectangle or point.
8797 * @param {Rect} rect
8798 * @returns {Boolean}
8799**/
8800proto.contains = function( rect ) {
8801  // points don't have width or height
8802  var otherWidth = rect.width || 0;
8803  var otherHeight = rect.height || 0;
8804  return this.x <= rect.x &&
8805    this.y <= rect.y &&
8806    this.x + this.width >= rect.x + otherWidth &&
8807    this.y + this.height >= rect.y + otherHeight;
8808};
8809
8810/**
8811 * Determines whether or not the rectangle intersects with another.
8812 * @param {Rect} rect
8813 * @returns {Boolean}
8814**/
8815proto.overlaps = function( rect ) {
8816  var thisRight = this.x + this.width;
8817  var thisBottom = this.y + this.height;
8818  var rectRight = rect.x + rect.width;
8819  var rectBottom = rect.y + rect.height;
8820
8821  // http://stackoverflow.com/a/306332
8822  return this.x < rectRight &&
8823    thisRight > rect.x &&
8824    this.y < rectBottom &&
8825    thisBottom > rect.y;
8826};
8827
8828/**
8829 * @param {Rect} rect - the overlapping rect
8830 * @returns {Array} freeRects - rects representing the area around the rect
8831**/
8832proto.getMaximalFreeRects = function( rect ) {
8833
8834  // if no intersection, return false
8835  if ( !this.overlaps( rect ) ) {
8836    return false;
8837  }
8838
8839  var freeRects = [];
8840  var freeRect;
8841
8842  var thisRight = this.x + this.width;
8843  var thisBottom = this.y + this.height;
8844  var rectRight = rect.x + rect.width;
8845  var rectBottom = rect.y + rect.height;
8846
8847  // top
8848  if ( this.y < rect.y ) {
8849    freeRect = new Rect({
8850      x: this.x,
8851      y: this.y,
8852      width: this.width,
8853      height: rect.y - this.y
8854    });
8855    freeRects.push( freeRect );
8856  }
8857
8858  // right
8859  if ( thisRight > rectRight ) {
8860    freeRect = new Rect({
8861      x: rectRight,
8862      y: this.y,
8863      width: thisRight - rectRight,
8864      height: this.height
8865    });
8866    freeRects.push( freeRect );
8867  }
8868
8869  // bottom
8870  if ( thisBottom > rectBottom ) {
8871    freeRect = new Rect({
8872      x: this.x,
8873      y: rectBottom,
8874      width: this.width,
8875      height: thisBottom - rectBottom
8876    });
8877    freeRects.push( freeRect );
8878  }
8879
8880  // left
8881  if ( this.x < rect.x ) {
8882    freeRect = new Rect({
8883      x: this.x,
8884      y: this.y,
8885      width: rect.x - this.x,
8886      height: this.height
8887    });
8888    freeRects.push( freeRect );
8889  }
8890
8891  return freeRects;
8892};
8893
8894proto.canFit = function( rect ) {
8895  return this.width >= rect.width && this.height >= rect.height;
8896};
8897
8898return Rect;
8899
8900}));
8901
8902/**
8903 * Packer
8904 * bin-packing algorithm
8905 */
8906
8907( function( window, factory ) {
8908  // universal module definition
8909  /* jshint strict: false */ /* globals define, module, require */
8910  if ( typeof define == 'function' && define.amd ) {
8911    // AMD
8912    define( 'packery/js/packer',[ './rect' ], factory );
8913  } else if ( typeof module == 'object' && module.exports ) {
8914    // CommonJS
8915    module.exports = factory(
8916      require('./rect')
8917    );
8918  } else {
8919    // browser global
8920    var Packery = window.Packery = window.Packery || {};
8921    Packery.Packer = factory( Packery.Rect );
8922  }
8923
8924}( window, function factory( Rect ) {
8925
8926
8927// -------------------------- Packer -------------------------- //
8928
8929/**
8930 * @param {Number} width
8931 * @param {Number} height
8932 * @param {String} sortDirection
8933 *   topLeft for vertical, leftTop for horizontal
8934 */
8935function Packer( width, height, sortDirection ) {
8936  this.width = width || 0;
8937  this.height = height || 0;
8938  this.sortDirection = sortDirection || 'downwardLeftToRight';
8939
8940  this.reset();
8941}
8942
8943var proto = Packer.prototype;
8944
8945proto.reset = function() {
8946  this.spaces = [];
8947
8948  var initialSpace = new Rect({
8949    x: 0,
8950    y: 0,
8951    width: this.width,
8952    height: this.height
8953  });
8954
8955  this.spaces.push( initialSpace );
8956  // set sorter
8957  this.sorter = sorters[ this.sortDirection ] || sorters.downwardLeftToRight;
8958};
8959
8960// change x and y of rect to fit with in Packer's available spaces
8961proto.pack = function( rect ) {
8962  for ( var i=0; i < this.spaces.length; i++ ) {
8963    var space = this.spaces[i];
8964    if ( space.canFit( rect ) ) {
8965      this.placeInSpace( rect, space );
8966      break;
8967    }
8968  }
8969};
8970
8971proto.columnPack = function( rect ) {
8972  for ( var i=0; i < this.spaces.length; i++ ) {
8973    var space = this.spaces[i];
8974    var canFitInSpaceColumn = space.x <= rect.x &&
8975      space.x + space.width >= rect.x + rect.width &&
8976      space.height >= rect.height - 0.01; // fudge number for rounding error
8977    if ( canFitInSpaceColumn ) {
8978      rect.y = space.y;
8979      this.placed( rect );
8980      break;
8981    }
8982  }
8983};
8984
8985proto.rowPack = function( rect ) {
8986  for ( var i=0; i < this.spaces.length; i++ ) {
8987    var space = this.spaces[i];
8988    var canFitInSpaceRow = space.y <= rect.y &&
8989      space.y + space.height >= rect.y + rect.height &&
8990      space.width >= rect.width - 0.01; // fudge number for rounding error
8991    if ( canFitInSpaceRow ) {
8992      rect.x = space.x;
8993      this.placed( rect );
8994      break;
8995    }
8996  }
8997};
8998
8999proto.placeInSpace = function( rect, space ) {
9000  // place rect in space
9001  rect.x = space.x;
9002  rect.y = space.y;
9003
9004  this.placed( rect );
9005};
9006
9007// update spaces with placed rect
9008proto.placed = function( rect ) {
9009  // update spaces
9010  var revisedSpaces = [];
9011  for ( var i=0; i < this.spaces.length; i++ ) {
9012    var space = this.spaces[i];
9013    var newSpaces = space.getMaximalFreeRects( rect );
9014    // add either the original space or the new spaces to the revised spaces
9015    if ( newSpaces ) {
9016      revisedSpaces.push.apply( revisedSpaces, newSpaces );
9017    } else {
9018      revisedSpaces.push( space );
9019    }
9020  }
9021
9022  this.spaces = revisedSpaces;
9023
9024  this.mergeSortSpaces();
9025};
9026
9027proto.mergeSortSpaces = function() {
9028  // remove redundant spaces
9029  Packer.mergeRects( this.spaces );
9030  this.spaces.sort( this.sorter );
9031};
9032
9033// add a space back
9034proto.addSpace = function( rect ) {
9035  this.spaces.push( rect );
9036  this.mergeSortSpaces();
9037};
9038
9039// -------------------------- utility functions -------------------------- //
9040
9041/**
9042 * Remove redundant rectangle from array of rectangles
9043 * @param {Array} rects: an array of Rects
9044 * @returns {Array} rects: an array of Rects
9045**/
9046Packer.mergeRects = function( rects ) {
9047  var i = 0;
9048  var rect = rects[i];
9049
9050  rectLoop:
9051  while ( rect ) {
9052    var j = 0;
9053    var compareRect = rects[ i + j ];
9054
9055    while ( compareRect ) {
9056      if  ( compareRect == rect ) {
9057        j++; // next
9058      } else if ( compareRect.contains( rect ) ) {
9059        // remove rect
9060        rects.splice( i, 1 );
9061        rect = rects[i]; // set next rect
9062        continue rectLoop; // bail on compareLoop
9063      } else if ( rect.contains( compareRect ) ) {
9064        // remove compareRect
9065        rects.splice( i + j, 1 );
9066      } else {
9067        j++;
9068      }
9069      compareRect = rects[ i + j ]; // set next compareRect
9070    }
9071    i++;
9072    rect = rects[i];
9073  }
9074
9075  return rects;
9076};
9077
9078
9079// -------------------------- sorters -------------------------- //
9080
9081// functions for sorting rects in order
9082var sorters = {
9083  // top down, then left to right
9084  downwardLeftToRight: function( a, b ) {
9085    return a.y - b.y || a.x - b.x;
9086  },
9087  // left to right, then top down
9088  rightwardTopToBottom: function( a, b ) {
9089    return a.x - b.x || a.y - b.y;
9090  }
9091};
9092
9093
9094// --------------------------  -------------------------- //
9095
9096return Packer;
9097
9098}));
9099
9100/**
9101 * Packery Item Element
9102**/
9103
9104( function( window, factory ) {
9105  // universal module definition
9106  /* jshint strict: false */ /* globals define, module, require */
9107  if ( typeof define == 'function' && define.amd ) {
9108    // AMD
9109    define( 'packery/js/item',[
9110        'outlayer/outlayer',
9111        './rect'
9112      ],
9113      factory );
9114  } else if ( typeof module == 'object' && module.exports ) {
9115    // CommonJS
9116    module.exports = factory(
9117      require('outlayer'),
9118      require('./rect')
9119    );
9120  } else {
9121    // browser global
9122    window.Packery.Item = factory(
9123      window.Outlayer,
9124      window.Packery.Rect
9125    );
9126  }
9127
9128}( window, function factory( Outlayer, Rect ) {
9129
9130
9131// -------------------------- Item -------------------------- //
9132
9133var docElemStyle = document.documentElement.style;
9134
9135var transformProperty = typeof docElemStyle.transform == 'string' ?
9136  'transform' : 'WebkitTransform';
9137
9138// sub-class Item
9139var Item = function PackeryItem() {
9140  Outlayer.Item.apply( this, arguments );
9141};
9142
9143var proto = Item.prototype = Object.create( Outlayer.Item.prototype );
9144
9145var __create = proto._create;
9146proto._create = function() {
9147  // call default _create logic
9148  __create.call( this );
9149  this.rect = new Rect();
9150};
9151
9152var _moveTo = proto.moveTo;
9153proto.moveTo = function( x, y ) {
9154  // don't shift 1px while dragging
9155  var dx = Math.abs( this.position.x - x );
9156  var dy = Math.abs( this.position.y - y );
9157
9158  var canHackGoTo = this.layout.dragItemCount && !this.isPlacing &&
9159    !this.isTransitioning && dx < 1 && dy < 1;
9160  if ( canHackGoTo ) {
9161    this.goTo( x, y );
9162    return;
9163  }
9164  _moveTo.apply( this, arguments );
9165};
9166
9167// -------------------------- placing -------------------------- //
9168
9169proto.enablePlacing = function() {
9170  this.removeTransitionStyles();
9171  // remove transform property from transition
9172  if ( this.isTransitioning && transformProperty ) {
9173    this.element.style[ transformProperty ] = 'none';
9174  }
9175  this.isTransitioning = false;
9176  this.getSize();
9177  this.layout._setRectSize( this.element, this.rect );
9178  this.isPlacing = true;
9179};
9180
9181proto.disablePlacing = function() {
9182  this.isPlacing = false;
9183};
9184
9185// -----  ----- //
9186
9187// remove element from DOM
9188proto.removeElem = function() {
9189  this.element.parentNode.removeChild( this.element );
9190  // add space back to packer
9191  this.layout.packer.addSpace( this.rect );
9192  this.emitEvent( 'remove', [ this ] );
9193};
9194
9195// ----- dropPlaceholder ----- //
9196
9197proto.showDropPlaceholder = function() {
9198  var dropPlaceholder = this.dropPlaceholder;
9199  if ( !dropPlaceholder ) {
9200    // create dropPlaceholder
9201    dropPlaceholder = this.dropPlaceholder = document.createElement('div');
9202    dropPlaceholder.className = 'packery-drop-placeholder';
9203    dropPlaceholder.style.position = 'absolute';
9204  }
9205
9206  dropPlaceholder.style.width = this.size.width + 'px';
9207  dropPlaceholder.style.height = this.size.height + 'px';
9208  this.positionDropPlaceholder();
9209  this.layout.element.appendChild( dropPlaceholder );
9210};
9211
9212proto.positionDropPlaceholder = function() {
9213  this.dropPlaceholder.style[ transformProperty ] = 'translate(' +
9214    this.rect.x + 'px, ' + this.rect.y + 'px)';
9215};
9216
9217proto.hideDropPlaceholder = function() {
9218  this.layout.element.removeChild( this.dropPlaceholder );
9219};
9220
9221// -----  ----- //
9222
9223return Item;
9224
9225}));
9226
9227/*!
9228 * Packery v2.0.0
9229 * Gapless, draggable grid layouts
9230 *
9231 * Licensed GPLv3 for open source use
9232 * or Packery Commercial License for commercial use
9233 *
9234 * http://packery.metafizzy.co
9235 * Copyright 2016 Metafizzy
9236 */
9237
9238( function( window, factory ) {
9239  // universal module definition
9240  /* jshint strict: false */ /* globals define, module, require */
9241  if ( typeof define == 'function' && define.amd ) {
9242    // AMD
9243    define( 'packery/js/packery',[
9244        'get-size/get-size',
9245        'outlayer/outlayer',
9246        './rect',
9247        './packer',
9248        './item'
9249      ],
9250      factory );
9251  } else if ( typeof module == 'object' && module.exports ) {
9252    // CommonJS
9253    module.exports = factory(
9254      require('get-size'),
9255      require('outlayer'),
9256      require('./rect'),
9257      require('./packer'),
9258      require('./item')
9259    );
9260  } else {
9261    // browser global
9262    window.Packery = factory(
9263      window.getSize,
9264      window.Outlayer,
9265      window.Packery.Rect,
9266      window.Packery.Packer,
9267      window.Packery.Item
9268    );
9269  }
9270
9271}( window, function factory( getSize, Outlayer, Rect, Packer, Item ) {
9272
9273
9274// ----- Rect ----- //
9275
9276// allow for pixel rounding errors IE8-IE11 & Firefox; #227
9277Rect.prototype.canFit = function( rect ) {
9278  return this.width >= rect.width - 1 && this.height >= rect.height - 1;
9279};
9280
9281// -------------------------- Packery -------------------------- //
9282
9283// create an Outlayer layout class
9284var Packery = Outlayer.create('packery');
9285Packery.Item = Item;
9286
9287var proto = Packery.prototype;
9288
9289proto._create = function() {
9290  // call super
9291  Outlayer.prototype._create.call( this );
9292
9293  // initial properties
9294  this.packer = new Packer();
9295  // packer for drop targets
9296  this.shiftPacker = new Packer();
9297  this.isEnabled = true;
9298
9299  this.dragItemCount = 0;
9300
9301  // create drag handlers
9302  var _this = this;
9303  this.handleDraggabilly = {
9304    dragStart: function() {
9305      _this.itemDragStart( this.element );
9306    },
9307    dragMove: function() {
9308      _this.itemDragMove( this.element, this.position.x, this.position.y );
9309    },
9310    dragEnd: function() {
9311      _this.itemDragEnd( this.element );
9312    }
9313  };
9314
9315  this.handleUIDraggable = {
9316    start: function handleUIDraggableStart( event, ui ) {
9317      // HTML5 may trigger dragstart, dismiss HTML5 dragging
9318      if ( !ui ) {
9319        return;
9320      }
9321      _this.itemDragStart( event.currentTarget );
9322    },
9323    drag: function handleUIDraggableDrag( event, ui ) {
9324      if ( !ui ) {
9325        return;
9326      }
9327      _this.itemDragMove( event.currentTarget, ui.position.left, ui.position.top );
9328    },
9329    stop: function handleUIDraggableStop( event, ui ) {
9330      if ( !ui ) {
9331        return;
9332      }
9333      _this.itemDragEnd( event.currentTarget );
9334    }
9335  };
9336
9337};
9338
9339
9340// ----- init & layout ----- //
9341
9342/**
9343 * logic before any new layout
9344 */
9345proto._resetLayout = function() {
9346  this.getSize();
9347
9348  this._getMeasurements();
9349
9350  // reset packer
9351  var width, height, sortDirection;
9352  // packer settings, if horizontal or vertical
9353  if ( this._getOption('horizontal') ) {
9354    width = Infinity;
9355    height = this.size.innerHeight + this.gutter;
9356    sortDirection = 'rightwardTopToBottom';
9357  } else {
9358    width = this.size.innerWidth + this.gutter;
9359    height = Infinity;
9360    sortDirection = 'downwardLeftToRight';
9361  }
9362
9363  this.packer.width = this.shiftPacker.width = width;
9364  this.packer.height = this.shiftPacker.height = height;
9365  this.packer.sortDirection = this.shiftPacker.sortDirection = sortDirection;
9366
9367  this.packer.reset();
9368
9369  // layout
9370  this.maxY = 0;
9371  this.maxX = 0;
9372};
9373
9374/**
9375 * update columnWidth, rowHeight, & gutter
9376 * @private
9377 */
9378proto._getMeasurements = function() {
9379  this._getMeasurement( 'columnWidth', 'width' );
9380  this._getMeasurement( 'rowHeight', 'height' );
9381  this._getMeasurement( 'gutter', 'width' );
9382};
9383
9384proto._getItemLayoutPosition = function( item ) {
9385  this._setRectSize( item.element, item.rect );
9386  if ( this.isShifting || this.dragItemCount > 0 ) {
9387    var packMethod = this._getPackMethod();
9388    this.packer[ packMethod ]( item.rect );
9389  } else {
9390    this.packer.pack( item.rect );
9391  }
9392
9393  this._setMaxXY( item.rect );
9394  return item.rect;
9395};
9396
9397proto.shiftLayout = function() {
9398  this.isShifting = true;
9399  this.layout();
9400  delete this.isShifting;
9401};
9402
9403proto._getPackMethod = function() {
9404  return this._getOption('horizontal') ? 'rowPack' : 'columnPack';
9405};
9406
9407
9408/**
9409 * set max X and Y value, for size of container
9410 * @param {Packery.Rect} rect
9411 * @private
9412 */
9413proto._setMaxXY = function( rect ) {
9414  this.maxX = Math.max( rect.x + rect.width, this.maxX );
9415  this.maxY = Math.max( rect.y + rect.height, this.maxY );
9416};
9417
9418/**
9419 * set the width and height of a rect, applying columnWidth and rowHeight
9420 * @param {Element} elem
9421 * @param {Packery.Rect} rect
9422 */
9423proto._setRectSize = function( elem, rect ) {
9424  var size = getSize( elem );
9425  var w = size.outerWidth;
9426  var h = size.outerHeight;
9427  // size for columnWidth and rowHeight, if available
9428  // only check if size is non-zero, #177
9429  if ( w || h ) {
9430    w = this._applyGridGutter( w, this.columnWidth );
9431    h = this._applyGridGutter( h, this.rowHeight );
9432  }
9433  // rect must fit in packer
9434  rect.width = Math.min( w, this.packer.width );
9435  rect.height = Math.min( h, this.packer.height );
9436};
9437
9438/**
9439 * fits item to columnWidth/rowHeight and adds gutter
9440 * @param {Number} measurement - item width or height
9441 * @param {Number} gridSize - columnWidth or rowHeight
9442 * @returns measurement
9443 */
9444proto._applyGridGutter = function( measurement, gridSize ) {
9445  // just add gutter if no gridSize
9446  if ( !gridSize ) {
9447    return measurement + this.gutter;
9448  }
9449  gridSize += this.gutter;
9450  // fit item to columnWidth/rowHeight
9451  var remainder = measurement % gridSize;
9452  var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil';
9453  measurement = Math[ mathMethod ]( measurement / gridSize ) * gridSize;
9454  return measurement;
9455};
9456
9457proto._getContainerSize = function() {
9458  if ( this._getOption('horizontal') ) {
9459    return {
9460      width: this.maxX - this.gutter
9461    };
9462  } else {
9463    return {
9464      height: this.maxY - this.gutter
9465    };
9466  }
9467};
9468
9469
9470// -------------------------- stamp -------------------------- //
9471
9472/**
9473 * makes space for element
9474 * @param {Element} elem
9475 */
9476proto._manageStamp = function( elem ) {
9477
9478  var item = this.getItem( elem );
9479  var rect;
9480  if ( item && item.isPlacing ) {
9481    rect = item.rect;
9482  } else {
9483    var offset = this._getElementOffset( elem );
9484    rect = new Rect({
9485      x: this._getOption('originLeft') ? offset.left : offset.right,
9486      y: this._getOption('originTop') ? offset.top : offset.bottom
9487    });
9488  }
9489
9490  this._setRectSize( elem, rect );
9491  // save its space in the packer
9492  this.packer.placed( rect );
9493  this._setMaxXY( rect );
9494};
9495
9496// -------------------------- methods -------------------------- //
9497
9498function verticalSorter( a, b ) {
9499  return a.position.y - b.position.y || a.position.x - b.position.x;
9500}
9501
9502function horizontalSorter( a, b ) {
9503  return a.position.x - b.position.x || a.position.y - b.position.y;
9504}
9505
9506proto.sortItemsByPosition = function() {
9507  var sorter = this._getOption('horizontal') ? horizontalSorter : verticalSorter;
9508  this.items.sort( sorter );
9509};
9510
9511/**
9512 * Fit item element in its current position
9513 * Packery will position elements around it
9514 * useful for expanding elements
9515 *
9516 * @param {Element} elem
9517 * @param {Number} x - horizontal destination position, optional
9518 * @param {Number} y - vertical destination position, optional
9519 */
9520proto.fit = function( elem, x, y ) {
9521  var item = this.getItem( elem );
9522  if ( !item ) {
9523    return;
9524  }
9525
9526  // stamp item to get it out of layout
9527  this.stamp( item.element );
9528  // set placing flag
9529  item.enablePlacing();
9530  this.updateShiftTargets( item );
9531  // fall back to current position for fitting
9532  x = x === undefined ? item.rect.x: x;
9533  y = y === undefined ? item.rect.y: y;
9534  // position it best at its destination
9535  this.shift( item, x, y );
9536  this._bindFitEvents( item );
9537  item.moveTo( item.rect.x, item.rect.y );
9538  // layout everything else
9539  this.shiftLayout();
9540  // return back to regularly scheduled programming
9541  this.unstamp( item.element );
9542  this.sortItemsByPosition();
9543  item.disablePlacing();
9544};
9545
9546/**
9547 * emit event when item is fit and other items are laid out
9548 * @param {Packery.Item} item
9549 * @private
9550 */
9551proto._bindFitEvents = function( item ) {
9552  var _this = this;
9553  var ticks = 0;
9554  function onLayout() {
9555    ticks++;
9556    if ( ticks != 2 ) {
9557      return;
9558    }
9559    _this.dispatchEvent( 'fitComplete', null, [ item ] );
9560  }
9561  // when item is laid out
9562  item.once( 'layout', onLayout );
9563  // when all items are laid out
9564  this.once( 'layoutComplete', onLayout );
9565};
9566
9567// -------------------------- resize -------------------------- //
9568
9569// debounced, layout on resize
9570proto.resize = function() {
9571  // don't trigger if size did not change
9572  // or if resize was unbound. See #285, outlayer#9
9573  if ( !this.isResizeBound || !this.needsResizeLayout() ) {
9574    return;
9575  }
9576
9577  if ( this.options.shiftPercentResize ) {
9578    this.resizeShiftPercentLayout();
9579  } else {
9580    this.layout();
9581  }
9582};
9583
9584/**
9585 * check if layout is needed post layout
9586 * @returns Boolean
9587 */
9588proto.needsResizeLayout = function() {
9589  var size = getSize( this.element );
9590  var innerSize = this._getOption('horizontal') ? 'innerHeight' : 'innerWidth';
9591  return size[ innerSize ] != this.size[ innerSize ];
9592};
9593
9594proto.resizeShiftPercentLayout = function() {
9595  var items = this._getItemsForLayout( this.items );
9596
9597  var isHorizontal = this._getOption('horizontal');
9598  var coord = isHorizontal ? 'y' : 'x';
9599  var measure = isHorizontal ? 'height' : 'width';
9600  var segmentName = isHorizontal ? 'rowHeight' : 'columnWidth';
9601  var innerSize = isHorizontal ? 'innerHeight' : 'innerWidth';
9602
9603  // proportional re-align items
9604  var previousSegment = this[ segmentName ];
9605  previousSegment = previousSegment && previousSegment + this.gutter;
9606
9607  if ( previousSegment ) {
9608    this._getMeasurements();
9609    var currentSegment = this[ segmentName ] + this.gutter;
9610    items.forEach( function( item ) {
9611      var seg = Math.round( item.rect[ coord ] / previousSegment );
9612      item.rect[ coord ] = seg * currentSegment;
9613    });
9614  } else {
9615    var currentSize = getSize( this.element )[ innerSize ] + this.gutter;
9616    var previousSize = this.packer[ measure ];
9617    items.forEach( function( item ) {
9618      item.rect[ coord ] = ( item.rect[ coord ] / previousSize ) * currentSize;
9619    });
9620  }
9621
9622  this.shiftLayout();
9623};
9624
9625// -------------------------- drag -------------------------- //
9626
9627/**
9628 * handle an item drag start event
9629 * @param {Element} elem
9630 */
9631proto.itemDragStart = function( elem ) {
9632  if ( !this.isEnabled ) {
9633    return;
9634  }
9635  this.stamp( elem );
9636  // this.ignore( elem );
9637  var item = this.getItem( elem );
9638  if ( !item ) {
9639    return;
9640  }
9641
9642  item.enablePlacing();
9643  item.showDropPlaceholder();
9644  this.dragItemCount++;
9645  this.updateShiftTargets( item );
9646};
9647
9648proto.updateShiftTargets = function( dropItem ) {
9649  this.shiftPacker.reset();
9650
9651  // pack stamps
9652  this._getBoundingRect();
9653  var isOriginLeft = this._getOption('originLeft');
9654  var isOriginTop = this._getOption('originTop');
9655  this.stamps.forEach( function( stamp ) {
9656    // ignore dragged item
9657    var item = this.getItem( stamp );
9658    if ( item && item.isPlacing ) {
9659      return;
9660    }
9661    var offset = this._getElementOffset( stamp );
9662    var rect = new Rect({
9663      x: isOriginLeft ? offset.left : offset.right,
9664      y: isOriginTop ? offset.top : offset.bottom
9665    });
9666    this._setRectSize( stamp, rect );
9667    // save its space in the packer
9668    this.shiftPacker.placed( rect );
9669  }, this );
9670
9671  // reset shiftTargets
9672  var isHorizontal = this._getOption('horizontal');
9673  var segmentName = isHorizontal ? 'rowHeight' : 'columnWidth';
9674  var measure = isHorizontal ? 'height' : 'width';
9675
9676  this.shiftTargetKeys = [];
9677  this.shiftTargets = [];
9678  var boundsSize;
9679  var segment = this[ segmentName ];
9680  segment = segment && segment + this.gutter;
9681
9682  if ( segment ) {
9683    var segmentSpan = Math.ceil( dropItem.rect[ measure ] / segment );
9684    var segs = Math.floor( ( this.shiftPacker[ measure ] + this.gutter ) / segment );
9685    boundsSize = ( segs - segmentSpan ) * segment;
9686    // add targets on top
9687    for ( var i=0; i < segs; i++ ) {
9688      this._addShiftTarget( i * segment, 0, boundsSize );
9689    }
9690  } else {
9691    boundsSize = ( this.shiftPacker[ measure ] + this.gutter ) - dropItem.rect[ measure ];
9692    this._addShiftTarget( 0, 0, boundsSize );
9693  }
9694
9695  // pack each item to measure where shiftTargets are
9696  var items = this._getItemsForLayout( this.items );
9697  var packMethod = this._getPackMethod();
9698  items.forEach( function( item ) {
9699    var rect = item.rect;
9700    this._setRectSize( item.element, rect );
9701    this.shiftPacker[ packMethod ]( rect );
9702
9703    // add top left corner
9704    this._addShiftTarget( rect.x, rect.y, boundsSize );
9705    // add bottom left / top right corner
9706    var cornerX = isHorizontal ? rect.x + rect.width : rect.x;
9707    var cornerY = isHorizontal ? rect.y : rect.y + rect.height;
9708    this._addShiftTarget( cornerX, cornerY, boundsSize );
9709
9710    if ( segment ) {
9711      // add targets for each column on bottom / row on right
9712      var segSpan = Math.round( rect[ measure ] / segment );
9713      for ( var i=1; i < segSpan; i++ ) {
9714        var segX = isHorizontal ? cornerX : rect.x + segment * i;
9715        var segY = isHorizontal ? rect.y + segment * i : cornerY;
9716        this._addShiftTarget( segX, segY, boundsSize );
9717      }
9718    }
9719  }, this );
9720
9721};
9722
9723proto._addShiftTarget = function( x, y, boundsSize ) {
9724  var checkCoord = this._getOption('horizontal') ? y : x;
9725  if ( checkCoord !== 0 && checkCoord > boundsSize ) {
9726    return;
9727  }
9728  // create string for a key, easier to keep track of what targets
9729  var key = x + ',' + y;
9730  var hasKey = this.shiftTargetKeys.indexOf( key ) != -1;
9731  if ( hasKey ) {
9732    return;
9733  }
9734  this.shiftTargetKeys.push( key );
9735  this.shiftTargets.push({ x: x, y: y });
9736};
9737
9738// -------------------------- drop -------------------------- //
9739
9740proto.shift = function( item, x, y ) {
9741  var shiftPosition;
9742  var minDistance = Infinity;
9743  var position = { x: x, y: y };
9744  this.shiftTargets.forEach( function( target ) {
9745    var distance = getDistance( target, position );
9746    if ( distance < minDistance ) {
9747      shiftPosition = target;
9748      minDistance = distance;
9749    }
9750  });
9751  item.rect.x = shiftPosition.x;
9752  item.rect.y = shiftPosition.y;
9753};
9754
9755function getDistance( a, b ) {
9756  var dx = b.x - a.x;
9757  var dy = b.y - a.y;
9758  return Math.sqrt( dx * dx + dy * dy );
9759}
9760
9761// -------------------------- drag move -------------------------- //
9762
9763var DRAG_THROTTLE_TIME = 120;
9764
9765/**
9766 * handle an item drag move event
9767 * @param {Element} elem
9768 * @param {Number} x - horizontal change in position
9769 * @param {Number} y - vertical change in position
9770 */
9771proto.itemDragMove = function( elem, x, y ) {
9772  var item = this.isEnabled && this.getItem( elem );
9773  if ( !item ) {
9774    return;
9775  }
9776
9777  x -= this.size.paddingLeft;
9778  y -= this.size.paddingTop;
9779
9780  var _this = this;
9781  function onDrag() {
9782    _this.shift( item, x, y );
9783    item.positionDropPlaceholder();
9784    _this.layout();
9785  }
9786
9787  // throttle
9788  var now = new Date();
9789  if ( this._itemDragTime && now - this._itemDragTime < DRAG_THROTTLE_TIME ) {
9790    clearTimeout( this.dragTimeout );
9791    this.dragTimeout = setTimeout( onDrag, DRAG_THROTTLE_TIME );
9792  } else {
9793    onDrag();
9794    this._itemDragTime = now;
9795  }
9796};
9797
9798// -------------------------- drag end -------------------------- //
9799
9800/**
9801 * handle an item drag end event
9802 * @param {Element} elem
9803 */
9804proto.itemDragEnd = function( elem ) {
9805  var item = this.isEnabled && this.getItem( elem );
9806  if ( !item ) {
9807    return;
9808  }
9809
9810  clearTimeout( this.dragTimeout );
9811  item.element.classList.add('is-positioning-post-drag');
9812
9813  var completeCount = 0;
9814  var _this = this;
9815  function onDragEndLayoutComplete() {
9816    completeCount++;
9817    if ( completeCount != 2 ) {
9818      return;
9819    }
9820    // reset drag item
9821    item.element.classList.remove('is-positioning-post-drag');
9822    item.hideDropPlaceholder();
9823    _this.dispatchEvent( 'dragItemPositioned', null, [ item ] );
9824  }
9825
9826  item.once( 'layout', onDragEndLayoutComplete );
9827  this.once( 'layoutComplete', onDragEndLayoutComplete );
9828  item.moveTo( item.rect.x, item.rect.y );
9829  this.layout();
9830  this.dragItemCount = Math.max( 0, this.dragItemCount - 1 );
9831  this.sortItemsByPosition();
9832  item.disablePlacing();
9833  this.unstamp( item.element );
9834};
9835
9836/**
9837 * binds Draggabilly events
9838 * @param {Draggabilly} draggie
9839 */
9840proto.bindDraggabillyEvents = function( draggie ) {
9841  this._bindDraggabillyEvents( draggie, 'on' );
9842};
9843
9844proto.unbindDraggabillyEvents = function( draggie ) {
9845  this._bindDraggabillyEvents( draggie, 'off' );
9846};
9847
9848proto._bindDraggabillyEvents = function( draggie, method ) {
9849  var handlers = this.handleDraggabilly;
9850  draggie[ method ]( 'dragStart', handlers.dragStart );
9851  draggie[ method ]( 'dragMove', handlers.dragMove );
9852  draggie[ method ]( 'dragEnd', handlers.dragEnd );
9853};
9854
9855/**
9856 * binds jQuery UI Draggable events
9857 * @param {jQuery} $elems
9858 */
9859proto.bindUIDraggableEvents = function( $elems ) {
9860  this._bindUIDraggableEvents( $elems, 'on' );
9861};
9862
9863proto.unbindUIDraggableEvents = function( $elems ) {
9864  this._bindUIDraggableEvents( $elems, 'off' );
9865};
9866
9867proto._bindUIDraggableEvents = function( $elems, method ) {
9868  var handlers = this.handleUIDraggable;
9869  $elems
9870    [ method ]( 'dragstart', handlers.start )
9871    [ method ]( 'drag', handlers.drag )
9872    [ method ]( 'dragstop', handlers.stop );
9873};
9874
9875// ----- destroy ----- //
9876
9877var _destroy = proto.destroy;
9878proto.destroy = function() {
9879  _destroy.apply( this, arguments );
9880  // disable flag; prevent drag events from triggering. #72
9881  this.isEnabled = false;
9882};
9883
9884// -----  ----- //
9885
9886Packery.Rect = Rect;
9887Packery.Packer = Packer;
9888
9889return Packery;
9890
9891}));
9892
9893/*!
9894 * Packery layout mode v2.0.1
9895 * sub-classes Packery
9896 */
9897
9898/*jshint browser: true, strict: true, undef: true, unused: true */
9899
9900( function( window, factory ) {
9901
9902  // universal module definition
9903  if ( typeof define == 'function' && define.amd ) {
9904    // AMD
9905    define( [
9906        'isotope-layout/js/layout-mode',
9907        'packery/js/packery'
9908      ],
9909      factory );
9910  } else if ( typeof module == 'object' && module.exports ) {
9911    // CommonJS
9912    module.exports = factory(
9913      require('isotope-layout/js/layout-mode'),
9914      require('packery')
9915    );
9916  } else {
9917    // browser global
9918    factory(
9919      window.Isotope.LayoutMode,
9920      window.Packery
9921    );
9922  }
9923
9924}( window, function factor( LayoutMode, Packery ) {
9925
9926
9927  // create an Outlayer layout class
9928  var PackeryMode = LayoutMode.create('packery');
9929  var proto = PackeryMode.prototype;
9930
9931  var keepModeMethods = {
9932    _getElementOffset: true,
9933    _getMeasurement: true
9934  };
9935
9936  // inherit Packery prototype
9937  for ( var method in Packery.prototype ) {
9938    // do not inherit mode methods
9939    if ( !keepModeMethods[ method ] ) {
9940      proto[ method ] = Packery.prototype[ method ];
9941    }
9942  }
9943
9944  // set packer in _resetLayout
9945  var _resetLayout = proto._resetLayout;
9946  proto._resetLayout = function() {
9947    this.packer = this.packer || new Packery.Packer();
9948    this.shiftPacker = this.shiftPacker || new Packery.Packer();
9949    _resetLayout.apply( this, arguments );
9950  };
9951
9952  var _getItemLayoutPosition = proto._getItemLayoutPosition;
9953  proto._getItemLayoutPosition = function( item ) {
9954    // set packery rect
9955    item.rect = item.rect || new Packery.Rect();
9956    return _getItemLayoutPosition.call( this, item );
9957  };
9958
9959  // needsResizeLayout for vertical or horizontal
9960  var _needsResizeLayout = proto.needsResizeLayout;
9961  proto.needsResizeLayout = function() {
9962    if ( this._getOption('horizontal') ) {
9963      return this.needsVerticalResizeLayout();
9964    } else {
9965      return _needsResizeLayout.call( this );
9966    }
9967  };
9968
9969  // point to mode options for horizontal
9970  var _getOption = proto._getOption;
9971  proto._getOption = function( option ) {
9972    if ( option == 'horizontal' ) {
9973      return this.options.isHorizontal !== undefined ?
9974        this.options.isHorizontal : this.options.horizontal;
9975    }
9976    return _getOption.apply( this.isotope, arguments );
9977  };
9978
9979  return PackeryMode;
9980
9981}));
9982
9983/*!
9984 * cellsByRows layout mode for Isotope
9985 * v1.1.3
9986 * http://isotope.metafizzy.co/layout-modes/cellsbyrow.html
9987 */
9988
9989/*jshint browser: true, devel: false, strict: true, undef: true, unused: true */
9990
9991( function( window, factory ) {
9992  // universal module definition
9993  /* jshint strict: false */ /*globals define, module, require */
9994  if ( typeof define === 'function' && define.amd ) {
9995    // AMD
9996    define( [
9997        'isotope/js/layout-mode'
9998      ],
9999      factory );
10000  } else if ( typeof exports === 'object' ) {
10001    // CommonJS
10002    module.exports = factory(
10003      require('isotope-layout/js/layout-mode')
10004    );
10005  } else {
10006    // browser global
10007    factory(
10008      window.Isotope.LayoutMode
10009    );
10010  }
10011
10012}( window, function factory( LayoutMode ) {
10013  'use strict';
10014
10015  var CellsByRow = LayoutMode.create( 'cellsByRow' );
10016  var proto = CellsByRow.prototype;
10017
10018  proto._resetLayout = function() {
10019    // reset properties
10020    this.itemIndex = 0;
10021    // measurements
10022    this.getColumnWidth();
10023    this.getRowHeight();
10024    // set cols
10025    this.cols = Math.floor( this.isotope.size.innerWidth / this.columnWidth );
10026    this.cols = Math.max( this.cols, 1 );
10027  };
10028
10029  proto._getItemLayoutPosition = function( item ) {
10030    item.getSize();
10031    var col = this.itemIndex % this.cols;
10032    var row = Math.floor( this.itemIndex / this.cols );
10033    // center item within cell
10034    var x = ( col + 0.5 ) * this.columnWidth - item.size.outerWidth / 2;
10035    var y = ( row + 0.5 ) * this.rowHeight - item.size.outerHeight / 2;
10036    this.itemIndex++;
10037    return { x: x, y: y };
10038  };
10039
10040  proto._getContainerSize = function() {
10041    return {
10042      height: Math.ceil( this.itemIndex / this.cols ) * this.rowHeight
10043    };
10044  };
10045
10046  return CellsByRow;
10047
10048}));
10049/*global jQuery: true */
10050
10051/*!
10052   --------------------------------
10053   Infinite Scroll
10054   --------------------------------
10055   + https://github.com/paulirish/infinite-scroll
10056   + version 2.1.0
10057   + Copyright 2011/12 Paul Irish & Luke Shumard
10058   + Licensed under the MIT license
10059
10060   + Documentation: http://infinite-scroll.com/
10061*/
10062
10063// Uses AMD or browser globals to create a jQuery plugin.
10064(function (factory) {
10065    if (typeof define === 'function' && define.amd) {
10066        // AMD. Register as an anonymous module.
10067        define(['jquery'], factory);
10068    } else {
10069        // Browser globals
10070        factory(jQuery);
10071    }
10072}(function ($, undefined) {
10073    'use strict';
10074
10075    $.infinitescroll = function infscr(options, callback, element) {
10076        this.element = $(element);
10077
10078        // Flag the object in the event of a failed creation
10079        if (!this._create(options, callback)) {
10080            this.failed = true;
10081        }
10082    };
10083
10084    $.infinitescroll.defaults = {
10085        loading: {
10086            finished: undefined,
10087            finishedMsg: "<em>Congratulations, you've reached the end of the internet.</em>",
10088            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
10088MzExnbRvQ2Sy7vN0zvVtNfU2tLY3rPgLdnDvca4VQS/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
10088iqpQpZ4apwSwRtjqrB3muoF9BboaXKmshlqWqsWiGt2wphJkQbAU5hoCACH5BAUKABsALAcABADOAAsAAAX/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',
10089            msg: null,
10090            msgText: '<em>Loading the next set of posts...</em>',
10091            selector: null,
10092            speed: 'fast',
10093            start: undefined
10094        },
10095        state: {
10096            isDuringAjax: false,
10097            isInvalidPage: false,
10098            isDestroyed: false,
10099            isDone: false, // For when it goes all the way through the archive.
10100            isPaused: false,
10101            isBeyondMaxPage: false,
10102            currPage: 1
10103        },
10104        debug: false,
10105        behavior: undefined,
10106        binder: $(window), // used to cache the selector
10107        nextSelector: 'div.navigation a:first',
10108        navSelector: 'div.navigation',
10109        contentSelector: null, // rename to pageFragment
10110        extraScrollPx: 150,
10111        itemSelector: 'div.post',
10112        animate: false,
10113        pathParse: undefined,
10114        dataType: 'html',
10115        appendCallback: true,
10116        bufferPx: 40,
10117        errorCallback: function () { },
10118        infid: 0, //Instance ID
10119        pixelsFromNavToBottom: undefined,
10120        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
10121        prefill: false, // When the document is smaller than the window, load data until the document is larger or links are exhausted
10122        maxPage: undefined // to manually control maximum page (when maxPage is undefined, maximum page limitation is not work)
10123    };
10124
10125    $.infinitescroll.prototype = {
10126
10127        /*
10128            ----------------------------
10129            Private methods
10130            ----------------------------
10131            */
10132
10133        // Bind or unbind from scroll
10134        _binding: function infscr_binding(binding) {
10135
10136            var instance = this,
10137            opts = instance.options;
10138
10139            opts.v = '2.0b2.120520';
10140
10141            // if behavior is defined and this function is extended, call that instead of default
10142            if (!!opts.behavior && this['_binding_'+opts.behavior] !== undefined) {
10143                this['_binding_'+opts.behavior].call(this);
10144                return;
10145            }
10146
10147            if (binding !== 'bind' && binding !== 'unbind') {
10148                this._debug('Binding value  ' + binding + ' not valid');
10149                return false;
10150            }
10151
10152            if (binding === 'unbind') {
10153                (this.options.binder).unbind('smartscroll.infscr.' + instance.options.infid);
10154            } else {
10155                (this.options.binder)[binding]('smartscroll.infscr.' + instance.options.infid, function () {
10156                    instance.scroll();
10157                });
10158            }
10159
10160            this._debug('Binding', binding);
10161        },
10162
10163        // Fundamental aspects of the plugin are initialized
10164        _create: function infscr_create(options, callback) {
10165
10166            // Add custom options to defaults
10167            var opts = $.extend(true, {}, $.infinitescroll.defaults, options);
10168            this.options = opts;
10169            var $window = $(window);
10170            var instance = this;
10171
10172            // Validate selectors
10173            if (!instance._validate(options)) {
10174                return false;
10175            }
10176
10177            // Validate page fragment path
10178            var path = $(opts.nextSelector).attr('href');
10179            if (!path) {
10180                this._debug('Navigation selector not found');
10181                return false;
10182            }
10183
10184            // Set the path to be a relative URL from root.
10185            opts.path = opts.path || this._determinepath(path);
10186
10187            // contentSelector is 'page fragment' option for .load() / .ajax() calls
10188            opts.contentSelector = opts.contentSelector || this.element;
10189
10190            // loading.selector - if we want to place the load message in a specific selector, defaulted to the contentSelector
10191            opts.loading.selector = opts.loading.selector || opts.contentSelector;
10192
10193            // Define loading.msg
10194            opts.loading.msg = opts.loading.msg || $('<div id="infscr-loading"><img alt="Loading..." src="' + opts.loading.img + '" /><div>' + opts.loading.msgText + '</div></div>');
10195
10196            // Preload loading.img
10197            (new Image()).src = opts.loading.img;
10198
10199            // distance from nav links to bottom
10200            // computed as: height of the document + top offset of container - top offset of nav link
10201            if(opts.pixelsFromNavToBottom === undefined) {
10202                opts.pixelsFromNavToBottom = $(document).height() - $(opts.navSelector).offset().top;
10203                this._debug('pixelsFromNavToBottom: ' + opts.pixelsFromNavToBottom);
10204            }
10205
10206            var self = this;
10207
10208            // determine loading.start actions
10209            opts.loading.start = opts.loading.start || function() {
10210                $(opts.navSelector).hide();
10211                opts.loading.msg
10212                .appendTo(opts.loading.selector)
10213                .show(opts.loading.speed, $.proxy(function() {
10214                    this.beginAjax(opts);
10215                }, self));
10216            };
10217
10218            // determine loading.finished actions
10219            opts.loading.finished = opts.loading.finished || function() {
10220                if (!opts.state.isBeyondMaxPage)
10221                    opts.loading.msg.fadeOut(opts.loading.speed);
10222            };
10223
10224            // callback loading
10225            opts.callback = function(instance, data, url) {
10226                if (!!opts.behavior && instance['_callback_'+opts.behavior] !== undefined) {
10227                    instance['_callback_'+opts.behavior].call($(opts.contentSelector)[0], data, url);
10228                }
10229
10230                if (callback) {
10231                    callback.call($(opts.contentSelector)[0], data, opts, url);
10232                }
10233
10234                if (opts.prefill) {
10235                    $window.bind('resize.infinite-scroll', instance._prefill);
10236                }
10237            };
10238
10239            if (options.debug) {
10240                // Tell IE9 to use its built-in console
10241                if (Function.prototype.bind && (typeof console === 'object' || typeof console === 'function') && typeof console.log === 'object') {
10242                    ['log','info','warn','error','assert','dir','clear','profile','profileEnd']
10243                        .forEach(function (method) {
10244                            console[method] = this.call(console[method], console);
10245                        }, Function.prototype.bind);
10246                }
10247            }
10248
10249            this._setup();
10250
10251            // Setups the prefill method for use
10252            if (opts.prefill) {
10253                this._prefill();
10254            }
10255
10256            // Return true to indicate successful creation
10257            return true;
10258        },
10259
10260        _prefill: function infscr_prefill() {
10261            var instance = this;
10262            var $window = $(window);
10263
10264            function needsPrefill() {
10265                return ( $(instance.options.contentSelector).height() <= $window.height() );
10266            }
10267
10268            this._prefill = function() {
10269                if (needsPrefill()) {
10270                    instance.scroll();
10271                }
10272
10273                $window.bind('resize.infinite-scroll', function() {
10274                    if (needsPrefill()) {
10275                        $window.unbind('resize.infinite-scroll');
10276                        instance.scroll();
10277                    }
10278                });
10279            };
10280
10281            // Call self after setting up the new function
10282            this._prefill();
10283        },
10284
10285        // Console log wrapper
10286        _debug: function infscr_debug() {
10287            if (true !== this.options.debug) {
10288                return;
10289            }
10290
10291            if (typeof console !== 'undefined' && typeof console.log === 'function') {
10292                // Modern browsers
10293                // Single argument, which is a string
10294                if ((Array.prototype.slice.call(arguments)).length === 1 && typeof Array.prototype.slice.call(arguments)[0] === 'string') {
10295                    console.log( (Array.prototype.slice.call(arguments)).toString() );
10296                } else {
10297                    console.log( Array.prototype.slice.call(arguments) );
10298                }
10299            } else if (!Function.prototype.bind && typeof console !== 'undefined' && typeof console.log === 'object') {
10300                // IE8
10301                Function.prototype.call.call(console.log, console, Array.prototype.slice.call(arguments));
10302            }
10303        },
10304
10305        // find the number to increment in the path.
10306        _determinepath: function infscr_determinepath(path) {
10307
10308            var opts = this.options;
10309
10310            // if behavior is defined and this function is extended, call that instead of default
10311            if (!!opts.behavior && this['_determinepath_'+opts.behavior] !== undefined) {
10312                return this['_determinepath_'+opts.behavior].call(this,path);
10313            }
10314
10315            if (!!opts.pathParse) {
10316
10317                this._debug('pathParse manual');
10318                return opts.pathParse(path, this.options.state.currPage+1);
10319
10320            } else if (path.match(/^(.*?)\b2\b(.*?$)/)) {
10321                path = path.match(/^(.*?)\b2\b(.*?$)/).slice(1);
10322
10323                // if there is any 2 in the url at all.
10324            } else if (path.match(/^(.*?)2(.*?$)/)) {
10325
10326                // page= is used in django:
10327                // http://www.infinite-scroll.com/changelog/comment-page-1/#comment-127
10328                if (path.match(/^(.*?page=)2(\/.*|$)/)) {
10329                    path = path.match(/^(.*?page=)2(\/.*|$)/).slice(1);
10330                    return path;
10331                }
10332
10333                path = path.match(/^(.*?)2(.*?$)/).slice(1);
10334
10335            } else {
10336
10337                // page= is used in drupal too but second page is page=1 not page=2:
10338                // thx Jerod Fritz, vladikoff
10339                if (path.match(/^(.*?page=)1(\/.*|$)/)) {
10340                    path = path.match(/^(.*?page=)1(\/.*|$)/).slice(1);
10341                    return path;
10342                } else {
10343                    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.");
10344                    // Get rid of isInvalidPage to allow permalink to state
10345                    opts.state.isInvalidPage = true;  //prevent it from running on this page.
10346                }
10347            }
10348            this._debug('determinePath', path);
10349            return path;
10350
10351        },
10352
10353        // Custom error
10354        _error: function infscr_error(xhr) {
10355
10356            var opts = this.options;
10357
10358            // if behavior is defined and this function is extended, call that instead of default
10359            if (!!opts.behavior && this['_error_'+opts.behavior] !== undefined) {
10360                this['_error_'+opts.behavior].call(this,xhr);
10361                return;
10362            }
10363
10364            if (xhr !== 'destroy' && xhr !== 'end') {
10365                xhr = 'unknown';
10366            }
10367
10368            this._debug('Error', xhr);
10369
10370            if (xhr === 'end' || opts.state.isBeyondMaxPage) {
10371                this._showdonemsg();
10372            }
10373
10374            opts.state.isDone = true;
10375            opts.state.currPage = 1; // if you need to go back to this instance
10376            opts.state.isPaused = false;
10377            opts.state.isBeyondMaxPage = false;
10378            this._binding('unbind');
10379
10380        },
10381
10382        // Load Callback
10383        _loadcallback: function infscr_loadcallback(box, data, url) {
10384            var opts = this.options,
10385            callback = this.options.callback, // GLOBAL OBJECT FOR CALLBACK
10386            result = (opts.state.isDone) ? 'done' : (!opts.appendCallback) ? 'no-append' : 'append',
10387            frag;
10388
10389            // if behavior is defined and this function is extended, call that instead of default
10390            if (!!opts.behavior && this['_loadcallback_'+opts.behavior] !== undefined) {
10391                this['_loadcallback_'+opts.behavior].call(this,box,data);
10392                return;
10393            }
10394
10395            switch (result) {
10396                case 'done':
10397                    this._showdonemsg();
10398                    return false;
10399
10400                case 'no-append':
10401                    if (opts.dataType === 'html') {
10402                        data = '<div>' + data + '</div>';
10403                        data = $(data).find(opts.itemSelector);
10404                    }
10405
10406                    // if it didn't return anything
10407                    if (data.length === 0) {
10408                        return this._error('end');
10409                    }
10410
10411                    break;
10412
10413                case 'append':
10414                    var children = box.children();
10415                    // if it didn't return anything
10416                    if (children.length === 0) {
10417                        return this._error('end');
10418                    }
10419
10420                    // use a documentFragment because it works when content is going into a table or UL
10421                    frag = document.createDocumentFragment();
10422                    while (box[0].firstChild) {
10423                        frag.appendChild(box[0].firstChild);
10424                    }
10425
10426                    this._debug('contentSelector', $(opts.contentSelector)[0]);
10427                    $(opts.contentSelector)[0].appendChild(frag);
10428                    // previously, we would pass in the new DOM element as context for the callback
10429                    // however we're now using a documentfragment, which doesn't have parents or children,
10430                    // so the context is the contentContainer guy, and we pass in an array
10431                    // of the elements collected as the first argument.
10432
10433                    data = children.get();
10434                    break;
10435            }
10436
10437            // loadingEnd function
10438            opts.loading.finished.call($(opts.contentSelector)[0],opts);
10439
10440            // smooth scroll to ease in the new content
10441            if (opts.animate) {
10442                var scrollTo = $(window).scrollTop() + $(opts.loading.msg).height() + opts.extraScrollPx + 'px';
10443                $('html,body').animate({ scrollTop: scrollTo }, 800, function () { opts.state.isDuringAjax = false; });
10444            }
10445
10446            if (!opts.animate) {
10447                // once the call is done, we can allow it again.
10448                opts.state.isDuringAjax = false;
10449            }
10450
10451            callback(this, data, url);
10452
10453            if (opts.prefill) {
10454                this._prefill();
10455            }
10456        },
10457
10458        _nearbottom: function infscr_nearbottom() {
10459
10460            var opts = this.options,
10461            pixelsFromWindowBottomToBottom = 0 + $(document).height() - (opts.binder.scrollTop()) - $(window).height();
10462
10463            // if behavior is defined and this function is extended, call that instead of default
10464            if (!!opts.behavior && this['_nearbottom_'+opts.behavior] !== undefined) {
10465                return this['_nearbottom_'+opts.behavior].call(this);
10466            }
10467
10468            this._debug('math:', pixelsFromWindowBottomToBottom, opts.pixelsFromNavToBottom);
10469
10470            // if distance remaining in the scroll (including buffer) is less than the orignal nav to bottom....
10471            return (pixelsFromWindowBottomToBottom - opts.bufferPx < opts.pixelsFromNavToBottom);
10472
10473        },
10474
10475        // Pause / temporarily disable plugin from firing
10476        _pausing: function infscr_pausing(pause) {
10477
10478            var opts = this.options;
10479
10480            // if behavior is defined and this function is extended, call that instead of default
10481            if (!!opts.behavior && this['_pausing_'+opts.behavior] !== undefined) {
10482                this['_pausing_'+opts.behavior].call(this,pause);
10483                return;
10484            }
10485
10486            // If pause is not 'pause' or 'resume', toggle it's value
10487            if (pause !== 'pause' && pause !== 'resume' && pause !== null) {
10488                this._debug('Invalid argument. Toggling pause value instead');
10489            }
10490
10491            pause = (pause && (pause === 'pause' || pause === 'resume')) ? pause : 'toggle';
10492
10493            switch (pause) {
10494                case 'pause':
10495                    opts.state.isPaused = true;
10496                break;
10497
10498                case 'resume':
10499                    opts.state.isPaused = false;
10500                break;
10501
10502                case 'toggle':
10503                    opts.state.isPaused = !opts.state.isPaused;
10504                break;
10505            }
10506
10507            this._debug('Paused', opts.state.isPaused);
10508            return false;
10509
10510        },
10511
10512        // Behavior is determined
10513        // If the behavior option is undefined, it will set to default and bind to scroll
10514        _setup: function infscr_setup() {
10515
10516            var opts = this.options;
10517
10518            // if behavior is defined and this function is extended, call that instead of default
10519            if (!!opts.behavior && this['_setup_'+opts.behavior] !== undefined) {
10520                this['_setup_'+opts.behavior].call(this);
10521                return;
10522            }
10523
10524            this._binding('bind');
10525
10526            return false;
10527
10528        },
10529
10530        // Show done message
10531        _showdonemsg: function infscr_showdonemsg() {
10532
10533            var opts = this.options;
10534
10535            // if behavior is defined and this function is extended, call that instead of default
10536            if (!!opts.behavior && this['_showdonemsg_'+opts.behavior] !== undefined) {
10537                this['_showdonemsg_'+opts.behavior].call(this);
10538                return;
10539            }
10540
10541            opts.loading.msg
10542            .find('img')
10543            .hide()
10544            .parent()
10545            .find('div').html(opts.loading.finishedMsg).animate({ opacity: 1 }, 2000, function () {
10546                $(this).parent().fadeOut(opts.loading.speed);
10547            });
10548
10549            // user provided callback when done
10550            opts.errorCallback.call($(opts.contentSelector)[0],'done');
10551        },
10552
10553        // grab each selector option and see if any fail
10554        _validate: function infscr_validate(opts) {
10555            for (var key in opts) {
10556                if (key.indexOf && key.indexOf('Selector') > -1 && $(opts[key]).length === 0) {
10557                    this._debug('Your ' + key + ' found no elements.');
10558                    return false;
10559                }
10560            }
10561
10562            return true;
10563        },
10564
10565        /*
10566            ----------------------------
10567            Public methods
10568            ----------------------------
10569            */
10570
10571        // Bind to scroll
10572        bind: function infscr_bind() {
10573            this._binding('bind');
10574        },
10575
10576        // Destroy current instance of plugin
10577        destroy: function infscr_destroy() {
10578            this.options.state.isDestroyed = true;
10579            this.options.loading.finished();
10580            return this._error('destroy');
10581        },
10582
10583        // Set pause value to false
10584        pause: function infscr_pause() {
10585            this._pausing('pause');
10586        },
10587
10588        // Set pause value to false
10589        resume: function infscr_resume() {
10590            this._pausing('resume');
10591        },
10592
10593        beginAjax: function infscr_ajax(opts) {
10594            var instance = this,
10595                path = opts.path,
10596                box, desturl, method, condition;
10597
10598            // increment the URL bit. e.g. /page/3/
10599            opts.state.currPage++;
10600
10601            // Manually control maximum page
10602            if ( opts.maxPage !== undefined && opts.state.currPage > opts.maxPage ){
10603                opts.state.isBeyondMaxPage = true;
10604                this.destroy();
10605                return;
10606            }
10607
10608            // if we're dealing with a table we can't use DIVs
10609            box = $(opts.contentSelector).is('table, tbody') ? $('<tbody/>') : $('<div/>');
10610
10611            desturl = (typeof path === 'function') ? path(opts.state.currPage) : path.join(opts.state.currPage);
10612            instance._debug('heading into ajax', desturl);
10613
10614            method = (opts.dataType === 'html' || opts.dataType === 'json' ) ? opts.dataType : 'html+callback';
10615            if (opts.appendCallback && opts.dataType === 'html') {
10616                method += '+callback';
10617            }
10618
10619            switch (method) {
10620                case 'html+callback':
10621                    instance._debug('Using HTML via .load() method');
10622                    box.load(desturl + ' ' + opts.itemSelector, undefined, function infscr_ajax_callback(responseText) {
10623                        instance._loadcallback(box, responseText, desturl);
10624                    });
10625
10626                    break;
10627
10628                case 'html':
10629                    instance._debug('Using ' + (method.toUpperCase()) + ' via $.ajax() method');
10630                    $.ajax({
10631                        // params
10632                        url: desturl,
10633                        dataType: opts.dataType,
10634                        complete: function infscr_ajax_callback(jqXHR, textStatus) {
10635                            condition = (typeof (jqXHR.isResolved) !== 'undefined') ? (jqXHR.isResolved()) : (textStatus === 'success' || textStatus === 'notmodified');
10636                            if (condition) {
10637                                instance._loadcallback(box, jqXHR.responseText, desturl);
10638                            } else {
10639                                instance._error('end');
10640                            }
10641                        }
10642                    });
10643
10644                    break;
10645                case 'json':
10646                    instance._debug('Using ' + (method.toUpperCase()) + ' via $.ajax() method');
10647                    $.ajax({
10648                        dataType: 'json',
10649                        type: 'GET',
10650                        url: desturl,
10651                        success: function (data, textStatus, jqXHR) {
10652                            condition = (typeof (jqXHR.isResolved) !== 'undefined') ? (jqXHR.isResolved()) : (textStatus === 'success' || textStatus === 'notmodified');
10653                            if (opts.appendCallback) {
10654                                // if appendCallback is true, you must defined template in options.
10655                                // note that data passed into _loadcallback is already an html (after processed in opts.template(data)).
10656                                if (opts.template !== undefined) {
10657                                    var theData = opts.template(data);
10658                                    box.append(theData);
10659                                    if (condition) {
10660                                        instance._loadcallback(box, theData);
10661                                    } else {
10662                                        instance._error('end');
10663                                    }
10664                                } else {
10665                                    instance._debug('template must be defined.');
10666                                    instance._error('end');
10667                                }
10668                            } else {
10669                                // if appendCallback is false, we will pass in the JSON object. you should handle it yourself in your callback.
10670                                if (condition) {
10671                                    instance._loadcallback(box, data, desturl);
10672                                } else {
10673                                    instance._error('end');
10674                                }
10675                            }
10676                        },
10677                        error: function() {
10678                            instance._debug('JSON ajax request failed.');
10679                            instance._error('end');
10680                        }
10681                    });
10682
10683                    break;
10684            }
10685        },
10686
10687        // Retrieve next set of content items
10688        retrieve: function infscr_retrieve(pageNum) {
10689            pageNum = pageNum || null;
10690
10691            var instance = this,
10692            opts = instance.options;
10693
10694            // if behavior is defined and this function is extended, call that instead of default
10695            if (!!opts.behavior && this['retrieve_'+opts.behavior] !== undefined) {
10696                this['retrieve_'+opts.behavior].call(this,pageNum);
10697                return;
10698            }
10699
10700            // for manual triggers, if destroyed, get out of here
10701            if (opts.state.isDestroyed) {
10702                this._debug('Instance is destroyed');
10703                return false;
10704            }
10705
10706            // we dont want to fire the ajax multiple times
10707            opts.state.isDuringAjax = true;
10708
10709            opts.loading.start.call($(opts.contentSelector)[0],opts);
10710        },
10711
10712        // Check to see next page is needed
10713        scroll: function infscr_scroll() {
10714
10715            var opts = this.options,
10716            state = opts.state;
10717
10718            // if behavior is defined and this function is extended, call that instead of default
10719            if (!!opts.behavior && this['scroll_'+opts.behavior] !== undefined) {
10720                this['scroll_'+opts.behavior].call(this);
10721                return;
10722            }
10723
10724            if (state.isDuringAjax || state.isInvalidPage || state.isDone || state.isDestroyed || state.isPaused) {
10725                return;
10726            }
10727
10728            if (!this._nearbottom()) {
10729                return;
10730            }
10731
10732            this.retrieve();
10733
10734        },
10735
10736        // Toggle pause value
10737        toggle: function infscr_toggle() {
10738            this._pausing();
10739        },
10740
10741        // Unbind from scroll
10742        unbind: function infscr_unbind() {
10743            this._binding('unbind');
10744        },
10745
10746        // update options
10747        update: function infscr_options(key) {
10748            if ($.isPlainObject(key)) {
10749                this.options = $.extend(true,this.options,key);
10750            }
10751        }
10752    };
10753
10754
10755    /*
10756        ----------------------------
10757        Infinite Scroll function
10758        ----------------------------
10759
10760        Borrowed logic from the following...
10761
10762        jQuery UI
10763        - https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.widget.js
10764
10765        jCarousel
10766        - https://github.com/jsor/jcarousel/blob/master/lib/jquery.jcarousel.js
10767
10768        Masonry
10769        - https://github.com/desandro/masonry/blob/master/jquery.masonry.js
10770
10771*/
10772
10773    $.fn.infinitescroll = function infscr_init(options, callback) {
10774
10775
10776        var thisCall = typeof options;
10777
10778        switch (thisCall) {
10779
10780            // method
10781            case 'string':
10782                var args = Array.prototype.slice.call(arguments, 1);
10783
10784                this.each(function () {
10785                    var instance = $.data(this, 'infinitescroll');
10786
10787                    if (!instance) {
10788                        // not setup yet
10789                        // return $.error('Method ' + options + ' cannot be called until Infinite Scroll is setup');
10790                        return false;
10791                    }
10792
10793                    if (!$.isFunction(instance[options]) || options.charAt(0) === '_') {
10794                        // return $.error('No such method ' + options + ' for Infinite Scroll');
10795                        return false;
10796                    }
10797
10798                    // no errors!
10799                    instance[options].apply(instance, args);
10800                });
10801
10802            break;
10803
10804            // creation
10805            case 'object':
10806
10807                this.each(function () {
10808
10809                var instance = $.data(this, 'infinitescroll');
10810
10811                if (instance) {
10812
10813                    // update options of current instance
10814                    instance.update(options);
10815
10816                } else {
10817
10818                    // initialize new instance
10819                    instance = new $.infinitescroll(options, callback, this);
10820
10821                    // don't attach if instantiation failed
10822                    if (!instance.failed) {
10823                        $.data(this, 'infinitescroll', instance);
10824                    }
10825
10826                }
10827
10828            });
10829
10830            break;
10831
10832        }
10833
10834        return this;
10835    };
10836
10837
10838
10839    /*
10840     * smartscroll: debounced scroll event for jQuery *
10841     * https://github.com/lukeshumard/smartscroll
10842     * Based on smartresize by @louis_remi: https://github.com/lrbabe/jquery.smartresize.js *
10843     * Copyright 2011 Louis-Remi & Luke Shumard * Licensed under the MIT license. *
10844     */
10845
10846    var event = $.event,
10847    scrollTimeout;
10848
10849    event.special.smartscroll = {
10850        setup: function () {
10851            $(this).bind('scroll', event.special.smartscroll.handler);
10852        },
10853        teardown: function () {
10854            $(this).unbind('scroll', event.special.smartscroll.handler);
10855        },
10856        handler: function (event, execAsap) {
10857            // Save the context
10858            var context = this,
10859            args = arguments;
10860
10861            // set correct event type
10862            event.type = 'smartscroll';
10863
10864            if (scrollTimeout) { clearTimeout(scrollTimeout); }
10865            scrollTimeout = setTimeout(function () {
10866                $(context).trigger('smartscroll', args);
10867            }, execAsap === 'execAsap' ? 0 : 100);
10868        }
10869    };
10870
10871    $.fn.smartscroll = function (fn) {
10872        return fn ? this.bind('smartscroll', fn) : this.trigger('smartscroll', ['execAsap']);
10873    };
10874
10875}));
10876
10877/*!
10878Waypoints - 4.0.1
10879Copyright © 2011-2016 Caleb Troughton
10880Licensed under the MIT license.
10881https://github.com/imakewebthings/waypoints/blob/master/licenses.txt
10882*/
10883(function() {
10884  'use strict'
10885
10886  var keyCounter = 0
10887  var allWaypoints = {}
10888
10889  /* http://imakewebthings.com/waypoints/api/waypoint */
10890  function Waypoint(options) {
10891    if (!options) {
10892      throw new Error('No options passed to Waypoint constructor')
10893    }
10894    if (!options.element) {
10895      throw new Error('No element option passed to Waypoint constructor')
10896    }
10897    if (!options.handler) {
10898      throw new Error('No handler option passed to Waypoint constructor')
10899    }
10900
10901    this.key = 'waypoint-' + keyCounter
10902    this.options = Waypoint.Adapter.extend({}, Waypoint.defaults, options)
10903    this.element = this.options.element
10904    this.adapter = new Waypoint.Adapter(this.element)
10905    this.callback = options.handler
10906    this.axis = this.options.horizontal ? 'horizontal' : 'vertical'
10907    this.enabled = this.options.enabled
10908    this.triggerPoint = null
10909    this.group = Waypoint.Group.findOrCreate({
10910      name: this.options.group,
10911      axis: this.axis
10912    })
10913    this.context = Waypoint.Context.findOrCreateByElement(this.options.context)
10914
10915    if (Waypoint.offsetAliases[this.options.offset]) {
10916      this.options.offset = Waypoint.offsetAliases[this.options.offset]
10917    }
10918    this.group.add(this)
10919    this.context.add(this)
10920    allWaypoints[this.key] = this
10921    keyCounter += 1
10922  }
10923
10924  /* Private */
10925  Waypoint.prototype.queueTrigger = function(direction) {
10926    this.group.queueTrigger(this, direction)
10927  }
10928
10929  /* Private */
10930  Waypoint.prototype.trigger = function(args) {
10931    if (!this.enabled) {
10932      return
10933    }
10934    if (this.callback) {
10935      this.callback.apply(this, args)
10936    }
10937  }
10938
10939  /* Public */
10940  /* http://imakewebthings.com/waypoints/api/destroy */
10941  Waypoint.prototype.destroy = function() {
10942    this.context.remove(this)
10943    this.group.remove(this)
10944    delete allWaypoints[this.key]
10945  }
10946
10947  /* Public */
10948  /* http://imakewebthings.com/waypoints/api/disable */
10949  Waypoint.prototype.disable = function() {
10950    this.enabled = false
10951    return this
10952  }
10953
10954  /* Public */
10955  /* http://imakewebthings.com/waypoints/api/enable */
10956  Waypoint.prototype.enable = function() {
10957    this.context.refresh()
10958    this.enabled = true
10959    return this
10960  }
10961
10962  /* Public */
10963  /* http://imakewebthings.com/waypoints/api/next */
10964  Waypoint.prototype.next = function() {
10965    return this.group.next(this)
10966  }
10967
10968  /* Public */
10969  /* http://imakewebthings.com/waypoints/api/previous */
10970  Waypoint.prototype.previous = function() {
10971    return this.group.previous(this)
10972  }
10973
10974  /* Private */
10975  Waypoint.invokeAll = function(method) {
10976    var allWaypointsArray = []
10977    for (var waypointKey in allWaypoints) {
10978      allWaypointsArray.push(allWaypoints[waypointKey])
10979    }
10980    for (var i = 0, end = allWaypointsArray.length; i < end; i++) {
10981      allWaypointsArray[i][method]()
10982    }
10983  }
10984
10985  /* Public */
10986  /* http://imakewebthings.com/waypoints/api/destroy-all */
10987  Waypoint.destroyAll = function() {
10988    Waypoint.invokeAll('destroy')
10989  }
10990
10991  /* Public */
10992  /* http://imakewebthings.com/waypoints/api/disable-all */
10993  Waypoint.disableAll = function() {
10994    Waypoint.invokeAll('disable')
10995  }
10996
10997  /* Public */
10998  /* http://imakewebthings.com/waypoints/api/enable-all */
10999  Waypoint.enableAll = function() {
11000    Waypoint.Context.refreshAll()
11001    for (var waypointKey in allWaypoints) {
11002      allWaypoints[waypointKey].enabled = true
11003    }
11004    return this
11005  }
11006
11007  /* Public */
11008  /* http://imakewebthings.com/waypoints/api/refresh-all */
11009  Waypoint.refreshAll = function() {
11010    Waypoint.Context.refreshAll()
11011  }
11012
11013  /* Public */
11014  /* http://imakewebthings.com/waypoints/api/viewport-height */
11015  Waypoint.viewportHeight = function() {
11016    return window.innerHeight || document.documentElement.clientHeight
11017  }
11018
11019  /* Public */
11020  /* http://imakewebthings.com/waypoints/api/viewport-width */
11021  Waypoint.viewportWidth = function() {
11022    return document.documentElement.clientWidth
11023  }
11024
11025  Waypoint.adapters = []
11026
11027  Waypoint.defaults = {
11028    context: window,
11029    continuous: true,
11030    enabled: true,
11031    group: 'default',
11032    horizontal: false,
11033    offset: 0
11034  }
11035
11036  Waypoint.offsetAliases = {
11037    'bottom-in-view': function() {
11038      return this.context.innerHeight() - this.adapter.outerHeight()
11039    },
11040    'right-in-view': function() {
11041      return this.context.innerWidth() - this.adapter.outerWidth()
11042    }
11043  }
11044
11045  window.Waypoint = Waypoint
11046}())
11047;(function() {
11048  'use strict'
11049
11050  function requestAnimationFrameShim(callback) {
11051    window.setTimeout(callback, 1000 / 60)
11052  }
11053
11054  var keyCounter = 0
11055  var contexts = {}
11056  var Waypoint = window.Waypoint
11057  var oldWindowLoad = window.onload
11058
11059  /* http://imakewebthings.com/waypoints/api/context */
11060  function Context(element) {
11061    this.element = element
11062    this.Adapter = Waypoint.Adapter
11063    this.adapter = new this.Adapter(element)
11064    this.key = 'waypoint-context-' + keyCounter
11065    this.didScroll = false
11066    this.didResize = false
11067    this.oldScroll = {
11068      x: this.adapter.scrollLeft(),
11069      y: this.adapter.scrollTop()
11070    }
11071    this.waypoints = {
11072      vertical: {},
11073      horizontal: {}
11074    }
11075
11076    element.waypointContextKey = this.key
11077    contexts[element.waypointContextKey] = this
11078    keyCounter += 1
11079    if (!Waypoint.windowContext) {
11080      Waypoint.windowContext = true
11081      Waypoint.windowContext = new Context(window)
11082    }
11083
11084    this.createThrottledScrollHandler()
11085    this.createThrottledResizeHandler()
11086  }
11087
11088  /* Private */
11089  Context.prototype.add = function(waypoint) {
11090    var axis = waypoint.options.horizontal ? 'horizontal' : 'vertical'
11091    this.waypoints[axis][waypoint.key] = waypoint
11092    this.refresh()
11093  }
11094
11095  /* Private */
11096  Context.prototype.checkEmpty = function() {
11097    var horizontalEmpty = this.Adapter.isEmptyObject(this.waypoints.horizontal)
11098    var verticalEmpty = this.Adapter.isEmptyObject(this.waypoints.vertical)
11099    var isWindow = this.element == this.element.window
11100    if (horizontalEmpty && verticalEmpty && !isWindow) {
11101      this.adapter.off('.waypoints')
11102      delete contexts[this.key]
11103    }
11104  }
11105
11106  /* Private */
11107  Context.prototype.createThrottledResizeHandler = function() {
11108    var self = this
11109
11110    function resizeHandler() {
11111      self.handleResize()
11112      self.didResize = false
11113    }
11114
11115    this.adapter.on('resize.waypoints', function() {
11116      if (!self.didResize) {
11117        self.didResize = true
11118        Waypoint.requestAnimationFrame(resizeHandler)
11119      }
11120    })
11121  }
11122
11123  /* Private */
11124  Context.prototype.createThrottledScrollHandler = function() {
11125    var self = this
11126    function scrollHandler() {
11127      self.handleScroll()
11128      self.didScroll = false
11129    }
11130
11131    this.adapter.on('scroll.waypoints', function() {
11132      if (!self.didScroll || Waypoint.isTouch) {
11133        self.didScroll = true
11134        Waypoint.requestAnimationFrame(scrollHandler)
11135      }
11136    })
11137  }
11138
11139  /* Private */
11140  Context.prototype.handleResize = function() {
11141    Waypoint.Context.refreshAll()
11142  }
11143
11144  /* Private */
11145  Context.prototype.handleScroll = function() {
11146    var triggeredGroups = {}
11147    var axes = {
11148      horizontal: {
11149        newScroll: this.adapter.scrollLeft(),
11150        oldScroll: this.oldScroll.x,
11151        forward: 'right',
11152        backward: 'left'
11153      },
11154      vertical: {
11155        newScroll: this.adapter.scrollTop(),
11156        oldScroll: this.oldScroll.y,
11157        forward: 'down',
11158        backward: 'up'
11159      }
11160    }
11161
11162    for (var axisKey in axes) {
11163      var axis = axes[axisKey]
11164      var isForward = axis.newScroll > axis.oldScroll
11165      var direction = isForward ? axis.forward : axis.backward
11166
11167      for (var waypointKey in this.waypoints[axisKey]) {
11168        var waypoint = this.waypoints[axisKey][waypointKey]
11169        if (waypoint.triggerPoint === null) {
11170          continue
11171        }
11172        var wasBeforeTriggerPoint = axis.oldScroll < waypoint.triggerPoint
11173        var nowAfterTriggerPoint = axis.newScroll >= waypoint.triggerPoint
11174        var crossedForward = wasBeforeTriggerPoint && nowAfterTriggerPoint
11175        var crossedBackward = !wasBeforeTriggerPoint && !nowAfterTriggerPoint
11176        if (crossedForward || crossedBackward) {
11177          waypoint.queueTrigger(direction)
11178          triggeredGroups[waypoint.group.id] = waypoint.group
11179        }
11180      }
11181    }
11182
11183    for (var groupKey in triggeredGroups) {
11184      triggeredGroups[groupKey].flushTriggers()
11185    }
11186
11187    this.oldScroll = {
11188      x: axes.horizontal.newScroll,
11189      y: axes.vertical.newScroll
11190    }
11191  }
11192
11193  /* Private */
11194  Context.prototype.innerHeight = function() {
11195    /*eslint-disable eqeqeq */
11196    if (this.element == this.element.window) {
11197      return Waypoint.viewportHeight()
11198    }
11199    /*eslint-enable eqeqeq */
11200    return this.adapter.innerHeight()
11201  }
11202
11203  /* Private */
11204  Context.prototype.remove = function(waypoint) {
11205    delete this.waypoints[waypoint.axis][waypoint.key]
11206    this.checkEmpty()
11207  }
11208
11209  /* Private */
11210  Context.prototype.innerWidth = function() {
11211    /*eslint-disable eqeqeq */
11212    if (this.element == this.element.window) {
11213      return Waypoint.viewportWidth()
11214    }
11215    /*eslint-enable eqeqeq */
11216    return this.adapter.innerWidth()
11217  }
11218
11219  /* Public */
11220  /* http://imakewebthings.com/waypoints/api/context-destroy */
11221  Context.prototype.destroy = function() {
11222    var allWaypoints = []
11223    for (var axis in this.waypoints) {
11224      for (var waypointKey in this.waypoints[axis]) {
11225        allWaypoints.push(this.waypoints[axis][waypointKey])
11226      }
11227    }
11228    for (var i = 0, end = allWaypoints.length; i < end; i++) {
11229      allWaypoints[i].destroy()
11230    }
11231  }
11232
11233  /* Public */
11234  /* http://imakewebthings.com/waypoints/api/context-refresh */
11235  Context.prototype.refresh = function() {
11236    /*eslint-disable eqeqeq */
11237    var isWindow = this.element == this.element.window
11238    /*eslint-enable eqeqeq */
11239    var contextOffset = isWindow ? undefined : this.adapter.offset()
11240    var triggeredGroups = {}
11241    var axes
11242
11243    this.handleScroll()
11244    axes = {
11245      horizontal: {
11246        contextOffset: isWindow ? 0 : contextOffset.left,
11247        contextScroll: isWindow ? 0 : this.oldScroll.x,
11248        contextDimension: this.innerWidth(),
11249        oldScroll: this.oldScroll.x,
11250        forward: 'right',
11251        backward: 'left',
11252        offsetProp: 'left'
11253      },
11254      vertical: {
11255        contextOffset: isWindow ? 0 : contextOffset.top,
11256        contextScroll: isWindow ? 0 : this.oldScroll.y,
11257        contextDimension: this.innerHeight(),
11258        oldScroll: this.oldScroll.y,
11259        forward: 'down',
11260        backward: 'up',
11261        offsetProp: 'top'
11262      }
11263    }
11264
11265    for (var axisKey in axes) {
11266      var axis = axes[axisKey]
11267      for (var waypointKey in this.waypoints[axisKey]) {
11268        var waypoint = this.waypoints[axisKey][waypointKey]
11269        var adjustment = waypoint.options.offset
11270        var oldTriggerPoint = waypoint.triggerPoint
11271        var elementOffset = 0
11272        var freshWaypoint = oldTriggerPoint == null
11273        var contextModifier, wasBeforeScroll, nowAfterScroll
11274        var triggeredBackward, triggeredForward
11275
11276        if (waypoint.element !== waypoint.element.window) {
11277          elementOffset = waypoint.adapter.offset()[axis.offsetProp]
11278        }
11279
11280        if (typeof adjustment === 'function') {
11281          adjustment = adjustment.apply(waypoint)
11282        }
11283        else if (typeof adjustment === 'string') {
11284          adjustment = parseFloat(adjustment)
11285          if (waypoint.options.offset.indexOf('%') > - 1) {
11286            adjustment = Math.ceil(axis.contextDimension * adjustment / 100)
11287          }
11288        }
11289
11290        contextModifier = axis.contextScroll - axis.contextOffset
11291        waypoint.triggerPoint = Math.floor(elementOffset + contextModifier - adjustment)
11292        wasBeforeScroll = oldTriggerPoint < axis.oldScroll
11293        nowAfterScroll = waypoint.triggerPoint >= axis.oldScroll
11294        triggeredBackward = wasBeforeScroll && nowAfterScroll
11295        triggeredForward = !wasBeforeScroll && !nowAfterScroll
11296
11297        if (!freshWaypoint && triggeredBackward) {
11298          waypoint.queueTrigger(axis.backward)
11299          triggeredGroups[waypoint.group.id] = waypoint.group
11300        }
11301        else if (!freshWaypoint && triggeredForward) {
11302          waypoint.queueTrigger(axis.forward)
11303          triggeredGroups[waypoint.group.id] = waypoint.group
11304        }
11305        else if (freshWaypoint && axis.oldScroll >= waypoint.triggerPoint) {
11306          waypoint.queueTrigger(axis.forward)
11307          triggeredGroups[waypoint.group.id] = waypoint.group
11308        }
11309      }
11310    }
11311
11312    Waypoint.requestAnimationFrame(function() {
11313      for (var groupKey in triggeredGroups) {
11314        triggeredGroups[groupKey].flushTriggers()
11315      }
11316    })
11317
11318    return this
11319  }
11320
11321  /* Private */
11322  Context.findOrCreateByElement = function(element) {
11323    return Context.findByElement(element) || new Context(element)
11324  }
11325
11326  /* Private */
11327  Context.refreshAll = function() {
11328    for (var contextId in contexts) {
11329      contexts[contextId].refresh()
11330    }
11331  }
11332
11333  /* Public */
11334  /* http://imakewebthings.com/waypoints/api/context-find-by-element */
11335  Context.findByElement = function(element) {
11336    return contexts[element.waypointContextKey]
11337  }
11338
11339  window.onload = function() {
11340    if (oldWindowLoad) {
11341      oldWindowLoad()
11342    }
11343    Context.refreshAll()
11344  }
11345
11346
11347  Waypoint.requestAnimationFrame = function(callback) {
11348    var requestFn = window.requestAnimationFrame ||
11349      window.mozRequestAnimationFrame ||
11350      window.webkitRequestAnimationFrame ||
11351      requestAnimationFrameShim
11352    requestFn.call(window, callback)
11353  }
11354  Waypoint.Context = Context
11355}())
11356;(function() {
11357  'use strict'
11358
11359  function byTriggerPoint(a, b) {
11360    return a.triggerPoint - b.triggerPoint
11361  }
11362
11363  function byReverseTriggerPoint(a, b) {
11364    return b.triggerPoint - a.triggerPoint
11365  }
11366
11367  var groups = {
11368    vertical: {},
11369    horizontal: {}
11370  }
11371  var Waypoint = window.Waypoint
11372
11373  /* http://imakewebthings.com/waypoints/api/group */
11374  function Group(options) {
11375    this.name = options.name
11376    this.axis = options.axis
11377    this.id = this.name + '-' + this.axis
11378    this.waypoints = []
11379    this.clearTriggerQueues()
11380    groups[this.axis][this.name] = this
11381  }
11382
11383  /* Private */
11384  Group.prototype.add = function(waypoint) {
11385    this.waypoints.push(waypoint)
11386  }
11387
11388  /* Private */
11389  Group.prototype.clearTriggerQueues = function() {
11390    this.triggerQueues = {
11391      up: [],
11392      down: [],
11393      left: [],
11394      right: []
11395    }
11396  }
11397
11398  /* Private */
11399  Group.prototype.flushTriggers = function() {
11400    for (var direction in this.triggerQueues) {
11401      var waypoints = this.triggerQueues[direction]
11402      var reverse = direction === 'up' || direction === 'left'
11403      waypoints.sort(reverse ? byReverseTriggerPoint : byTriggerPoint)
11404      for (var i = 0, end = waypoints.length; i < end; i += 1) {
11405        var waypoint = waypoints[i]
11406        if (waypoint.options.continuous || i === waypoints.length - 1) {
11407          waypoint.trigger([direction])
11408        }
11409      }
11410    }
11411    this.clearTriggerQueues()
11412  }
11413
11414  /* Private */
11415  Group.prototype.next = function(waypoint) {
11416    this.waypoints.sort(byTriggerPoint)
11417    var index = Waypoint.Adapter.inArray(waypoint, this.waypoints)
11418    var isLast = index === this.waypoints.length - 1
11419    return isLast ? null : this.waypoints[index + 1]
11420  }
11421
11422  /* Private */
11423  Group.prototype.previous = function(waypoint) {
11424    this.waypoints.sort(byTriggerPoint)
11425    var index = Waypoint.Adapter.inArray(waypoint, this.waypoints)
11426    return index ? this.waypoints[index - 1] : null
11427  }
11428
11429  /* Private */
11430  Group.prototype.queueTrigger = function(waypoint, direction) {
11431    this.triggerQueues[direction].push(waypoint)
11432  }
11433
11434  /* Private */
11435  Group.prototype.remove = function(waypoint) {
11436    var index = Waypoint.Adapter.inArray(waypoint, this.waypoints)
11437    if (index > -1) {
11438      this.waypoints.splice(index, 1)
11439    }
11440  }
11441
11442  /* Public */
11443  /* http://imakewebthings.com/waypoints/api/first */
11444  Group.prototype.first = function() {
11445    return this.waypoints[0]
11446  }
11447
11448  /* Public */
11449  /* http://imakewebthings.com/waypoints/api/last */
11450  Group.prototype.last = function() {
11451    return this.waypoints[this.waypoints.length - 1]
11452  }
11453
11454  /* Private */
11455  Group.findOrCreate = function(options) {
11456    return groups[options.axis][options.name] || new Group(options)
11457  }
11458
11459  Waypoint.Group = Group
11460}())
11461;(function() {
11462  'use strict'
11463
11464  var $ = window.jQuery
11465  var Waypoint = window.Waypoint
11466
11467  function JQueryAdapter(element) {
11468    this.$element = $(element)
11469  }
11470
11471  $.each([
11472    'innerHeight',
11473    'innerWidth',
11474    'off',
11475    'offset',
11476    'on',
11477    'outerHeight',
11478    'outerWidth',
11479    'scrollLeft',
11480    'scrollTop'
11481  ], function(i, method) {
11482    JQueryAdapter.prototype[method] = function() {
11483      var args = Array.prototype.slice.call(arguments)
11484      return this.$element[method].apply(this.$element, args)
11485    }
11486  })
11487
11488  $.each([
11489    'extend',
11490    'inArray',
11491    'isEmptyObject'
11492  ], function(i, method) {
11493    JQueryAdapter[method] = $[method]
11494  })
11495
11496  Waypoint.adapters.push({
11497    name: 'jquery',
11498    Adapter: JQueryAdapter
11499  })
11500  Waypoint.Adapter = JQueryAdapter
11501}())
11502;(function() {
11503  'use strict'
11504
11505  var Waypoint = window.Waypoint
11506
11507  function createExtension(framework) {
11508    return function() {
11509      var waypoints = []
11510      var overrides = arguments[0]
11511
11512      if (framework.isFunction(arguments[0])) {
11513        overrides = framework.extend({}, arguments[1])
11514        overrides.handler = arguments[0]
11515      }
11516
11517      this.each(function() {
11518        var options = framework.extend({}, overrides, {
11519          element: this
11520        })
11521        if (typeof options.context === 'string') {
11522          options.context = framework(this).closest(options.context)[0]
11523        }
11524        waypoints.push(new Waypoint(options))
11525      })
11526
11527      return waypoints
11528    }
11529  }
11530
11531  if (window.jQuery) {
11532    window.jQuery.fn.waypoint = createExtension(window.jQuery)
11533  }
11534  if (window.Zepto) {
11535    window.Zepto.fn.waypoint = createExtension(window.Zepto)
11536  }
11537}())
11538;
11539/*!
11540Waypoints Inview Shortcut - 4.0.1
11541Copyright © 2011-2016 Caleb Troughton
11542Licensed under the MIT license.
11543https://github.com/imakewebthings/waypoints/blob/master/licenses.txt
11544*/
11545(function() {
11546  'use strict'
11547
11548  function noop() {}
11549
11550  var Waypoint = window.Waypoint
11551
11552  /* http://imakewebthings.com/waypoints/shortcuts/inview */
11553  function Inview(options) {
11554    this.options = Waypoint.Adapter.extend({}, Inview.defaults, options)
11555    this.axis = this.options.horizontal ? 'horizontal' : 'vertical'
11556    this.waypoints = []
11557    this.element = this.options.element
11558    this.createWaypoints()
11559  }
11560
11561  /* Private */
11562  Inview.prototype.createWaypoints = function() {
11563    var configs = {
11564      vertical: [{
11565        down: 'enter',
11566        up: 'exited',
11567        offset: '100%'
11568      }, {
11569        down: 'entered',
11570        up: 'exit',
11571        offset: 'bottom-in-view'
11572      }, {
11573        down: 'exit',
11574        up: 'entered',
11575        offset: 0
11576      }, {
11577        down: 'exited',
11578        up: 'enter',
11579        offset: function() {
11580          return -this.adapter.outerHeight()
11581        }
11582      }],
11583      horizontal: [{
11584        right: 'enter',
11585        left: 'exited',
11586        offset: '100%'
11587      }, {
11588        right: 'entered',
11589        left: 'exit',
11590        offset: 'right-in-view'
11591      }, {
11592        right: 'exit',
11593        left: 'entered',
11594        offset: 0
11595      }, {
11596        right: 'exited',
11597        left: 'enter',
11598        offset: function() {
11599          return -this.adapter.outerWidth()
11600        }
11601      }]
11602    }
11603
11604    for (var i = 0, end = configs[this.axis].length; i < end; i++) {
11605      var config = configs[this.axis][i]
11606      this.createWaypoint(config)
11607    }
11608  }
11609
11610  /* Private */
11611  Inview.prototype.createWaypoint = function(config) {
11612    var self = this
11613    this.waypoints.push(new Waypoint({
11614      context: this.options.context,
11615      element: this.options.element,
11616      enabled: this.options.enabled,
11617      handler: (function(config) {
11618        return function(direction) {
11619          self.options[config[direction]].call(self, direction)
11620        }
11621      }(config)),
11622      offset: config.offset,
11623      horizontal: this.options.horizontal
11624    }))
11625  }
11626
11627  /* Public */
11628  Inview.prototype.destroy = function() {
11629    for (var i = 0, end = this.waypoints.length; i < end; i++) {
11630      this.waypoints[i].destroy()
11631    }
11632    this.waypoints = []
11633  }
11634
11635  Inview.prototype.disable = function() {
11636    for (var i = 0, end = this.waypoints.length; i < end; i++) {
11637      this.waypoints[i].disable()
11638    }
11639  }
11640
11641  Inview.prototype.enable = function() {
11642    for (var i = 0, end = this.waypoints.length; i < end; i++) {
11643      this.waypoints[i].enable()
11644    }
11645  }
11646
11647  Inview.defaults = {
11648    context: window,
11649    enabled: true,
11650    enter: noop,
11651    entered: noop,
11652    exit: noop,
11653    exited: noop
11654  }
11655
11656  Waypoint.Inview = Inview
11657}())
11658;
11659
11660/*
11661 * SmartMenus jQuery v0.9.6
11662 * http://www.smartmenus.org/
11663 *
11664 * Copyright 2014 Vasil Dinkov, Vadikom Web Ltd.
11665 * http://vadikom.com/
11666 *
11667 * Released under the MIT license:
11668 * http://www.opensource.org/licenses/MIT
11669 */
11670
11671(function($) {
11672
11673	var menuTrees = [],
11674		IE = !!window.createPopup, // we need to detect it, unfortunately
11675		IElt9 = IE && !document.defaultView,
11676		IElt8 = IE && !document.querySelector,
11677		IE6 = IE && typeof document.documentElement.currentStyle.minWidth == 'undefined',
11678		mouse = false, // optimize for touch by default - we will detect for mouse input
11679		mouseDetectionEnabled = false;
11680
11681	// Handle detection for mouse input (i.e. desktop browsers, tablets with a mouse, etc.)
11682	function initMouseDetection(disable) {
11683		if (!mouseDetectionEnabled && !disable && !$('body').hasClass('vmenu')) {
11684			// if we get two consecutive mousemoves within 2 pixels from each other and within 300ms, we assume a real mouse/cursor is present
11685			// 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)
11686			var firstTime = true,
11687				lastMove = null;
11688			$(document).bind({
11689				'mousemove.smartmenus_mouse': function(e) {
11690					var thisMove = { x: e.pageX, y: e.pageY, timeStamp: new Date().getTime() };
11691					if (lastMove) {
11692						var deltaX = Math.abs(lastMove.x - thisMove.x),
11693							deltaY = Math.abs(lastMove.y - thisMove.y);
11694	 					if ((deltaX > 0 || deltaY > 0) && deltaX <= 2 && deltaY <= 2 && thisMove.timeStamp - lastMove.timeStamp <= 300) {
11695							mouse = true;
11696							// 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
11697							if (firstTime) {
11698								var $a = $(e.target).closest('a');
11699								if ($a.is('a')) {
11700									$.each(menuTrees, function() {
11701										if ($.contains(this.$root[0], $a[0])) {
11702											this.itemEnter({ currentTarget: $a[0] });
11703											return false;
11704										}
11705									});
11706								}
11707								firstTime = false;
11708							}
11709						}
11710					}
11711					lastMove = thisMove;
11712				},
11713				'touchstart.smartmenus_mouse pointerover.smartmenus_mouse MSPointerOver.smartmenus_mouse': function(e) {
11714					if (!/^(4|mouse|pen)$/.test(e.originalEvent.pointerType)) {
11715						mouse = false;
11716					}
11717				}
11718			});
11719			mouseDetectionEnabled = true;
11720		} else if (mouseDetectionEnabled && disable) {
11721			$(document).unbind('.smartmenus_mouse');
11722			mouseDetectionEnabled = false;
11723		}
11724	};
11725
11726	$.SmartMenus = function(elm, options) {
11727		this.$root = $(elm);
11728		this.opts = options;
11729		this.rootId = ''; // internal
11730		this.$subArrow = null;
11731		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)
11732		this.activatedItems = []; // stores last activated A's for each level
11733		this.visibleSubMenus = []; // stores visible sub menus UL's
11734		this.showTimeout = 0;
11735		this.hideTimeout = 0;
11736		this.scrollTimeout = 0;
11737		this.clickActivated = false;
11738		this.zIndexInc = 0;
11739		this.$firstLink = null; // we'll use these for some tests
11740		this.$firstSub = null; // at runtime so we'll cache them
11741		this.disabled = false;
11742		this.$disableOverlay = null;
11743		this.init();
11744	};
11745
11746	$.extend($.SmartMenus, {
11747		hideAll: function() {
11748			$.each(menuTrees, function() {
11749				this.menuHideAll();
11750			});
11751		},
11752		destroy: function() {
11753			while (menuTrees.length) {
11754				menuTrees[0].destroy();
11755			}
11756			initMouseDetection(true);
11757		},
11758		prototype: {
11759			init: function(refresh) {
11760				var self = this;
11761
11762				if (!refresh) {
11763					menuTrees.push(this);
11764
11765					this.rootId = (new Date().getTime() + Math.random() + '').replace(/\D/g, '');
11766
11767					if (this.$root.hasClass('sm-rtl')) {
11768						this.opts.rightToLeftSubMenus = true;
11769					}
11770
11771					// init root (main menu)
11772					this.$root
11773						.data('smartmenus', this)
11774						.attr('data-smartmenus-id', this.rootId)
11775						.dataSM('level', 1)
11776						.bind({
11777							'mouseover.smartmenus focusin.smartmenus': $.proxy(this.rootOver, this),
11778							'mouseout.smartmenus focusout.smartmenus': $.proxy(this.rootOut, this)
11779						})
11780						.delegate('a, div.logo-container', {
11781							'mouseenter.smartmenus': $.proxy(this.itemEnter, this),
11782							'mouseleave.smartmenus': $.proxy(this.itemLeave, this),
11783							'mousedown.smartmenus': $.proxy(this.itemDown, this),
11784							'focus.smartmenus': $.proxy(this.itemFocus, this),
11785							'blur.smartmenus': $.proxy(this.itemBlur, this),
11786							'click.smartmenus': $.proxy(this.itemClick, this),
11787							'touchend.smartmenus': $.proxy(this.itemTouchEnd, this)
11788						});
11789
11790					var eNamespace = '.smartmenus' + this.rootId;
11791					// hide menus on tap or click outside the root UL
11792					if (this.opts.hideOnClick) {
11793						$(document).bind('touchstart' + eNamespace, $.proxy(this.docTouchStart, this))
11794							.bind('touchmove' + eNamespace, $.proxy(this.docTouchMove, this))
11795							.bind('touchend' + eNamespace, $.proxy(this.docTouchEnd, this))
11796							// for Opera Mobile < 11.5, webOS browser, etc. we'll check click too
11797							.bind('click' + eNamespace, $.proxy(this.docClick, this));
11798					}
11799					// hide sub menus on resize
11800					$(window).bind('resize' + eNamespace + ' orientationchange' + eNamespace, $.proxy(this.winResize, this));
11801					$(window).bind('scroll' + eNamespace + ' orientationchange' + eNamespace, $.proxy(this.winResize, this));
11802
11803					if (this.opts.subIndicators) {
11804						this.$subArrow = $('<span/>').addClass('sub-arrow');
11805						if (this.opts.subIndicatorsText) {
11806							this.$subArrow.html(this.opts.subIndicatorsText);
11807						}
11808					}
11809
11810					// make sure mouse detection is enabled
11811					initMouseDetection();
11812				}
11813
11814				// init sub menus
11815				this.$firstSub = this.$root.find('ul').each(function() { self.menuInit($(this)); }).eq(0);
11816
11817				this.$firstLink = this.$root.find('a').eq(0);
11818
11819				// find current item
11820				if (this.opts.markCurrentItem) {
11821					var reDefaultDoc = /(index|default)\.[^#\?\/]*/i,
11822						reHash = /#.*/,
11823						locHref = window.location.href.replace(reDefaultDoc, ''),
11824						locHrefNoHash = locHref.replace(reHash, '');
11825					this.$root.find('a').each(function() {
11826						var href = this.href.replace(reDefaultDoc, ''),
11827							$this = $(this);
11828						if (href == locHref || href == locHrefNoHash) {
11829							$this.addClass('current');
11830							if (self.opts.markCurrentTree) {
11831								$this.parents('li').each(function() {
11832									var $this = $(this);
11833									if ($this.dataSM('sub')) {
11834										$this.children('a').addClass('current');
11835									}
11836								});
11837							}
11838						}
11839					});
11840				}
11841			},
11842			destroy: function() {
11843				this.menuHideAll();
11844				this.$root
11845					.removeData('smartmenus')
11846					.removeAttr('data-smartmenus-id')
11847					.removeDataSM('level')
11848					.unbind('.smartmenus')
11849					.undelegate('.smartmenus');
11850				var eNamespace = '.smartmenus' + this.rootId;
11851				$(document).unbind(eNamespace);
11852				$(window).unbind(eNamespace);
11853				if (this.opts.subIndicators) {
11854					this.$subArrow = null;
11855				}
11856				var self = this;
11857				$.each(this.subMenus, function() {
11858					if (this.hasClass('mega-menu')) {
11859						this.find('ul').removeDataSM('in-mega');
11860					}
11861					if (this.dataSM('shown-before')) {
11862						if (IElt8) {
11863							this.children().css({ styleFloat: '', width: '' });
11864						}
11865						if (self.opts.subMenusMinWidth || self.opts.subMenusMaxWidth) {
11866							if (!IE6) {
11867								this.css({ width: '', minWidth: '', maxWidth: '' }).removeClass('sm-nowrap');
11868							} else {
11869								this.css({ width: '', overflowX: '', overflowY: '' }).children().children('a').css('white-space', '');
11870							}
11871						}
11872						if (this.dataSM('scroll-arrows')) {
11873							this.dataSM('scroll-arrows').remove();
11874						}
11875						this.css({ zIndex: '', top: '', left: '', marginLeft: '', marginTop: '', display: '' });
11876					}
11877					if (self.opts.subIndicators) {
11878						this.dataSM('parent-a').removeClass('has-submenu').children('span.sub-arrow').remove();
11879					}
11880					this.removeDataSM('shown-before')
11881						.removeDataSM('ie-shim')
11882						.removeDataSM('scroll-arrows')
11883						.removeDataSM('parent-a')
11884						.removeDataSM('level')
11885						.removeDataSM('beforefirstshowfired')
11886						.parent().removeDataSM('sub');
11887				});
11888				if (this.opts.markCurrentItem) {
11889					this.$root.find('a.current').removeClass('current');
11890				}
11891				this.$root = null;
11892				this.$firstLink = null;
11893				this.$firstSub = null;
11894				if (this.$disableOverlay) {
11895					this.$disableOverlay.remove();
11896					this.$disableOverlay = null;
11897				}
11898				menuTrees.splice($.inArray(this, menuTrees), 1);
11899			},
11900			disable: function(noOverlay) {
11901				if (!this.disabled) {
11902					this.menuHideAll();
11903					// display overlay over the menu to prevent interaction
11904					if (!noOverlay && !this.opts.isPopup && this.$root.is(':visible')) {
11905						var pos = this.$root.offset();
11906						this.$disableOverlay = $('<div class="sm-jquery-disable-overlay"/>').css({
11907							position: 'absolute',
11908							top: pos.top,
11909							left: pos.left,
11910							width: this.$root.outerWidth(),
11911							height: this.$root.outerHeight(),
11912							zIndex: this.getStartZIndex() + 1,
11913							opacity: 0
11914						}).appendTo(document.body);
11915					}
11916					this.disabled = true;
11917				}
11918			},
11919			docClick: function(e) {
11920				// hide on any click outside the menu or on a menu link
11921				if (this.visibleSubMenus.length && !$.contains(this.$root[0], e.target) || $(e.target).is('a')) {
11922					this.menuHideAll($(e.target));
11923				}
11924			},
11925			docTouchEnd: function(e) {
11926				if (!this.lastTouch) {
11927					return;
11928				}
11929				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))) {
11930					if (this.hideTimeout) {
11931						clearTimeout(this.hideTimeout);
11932						this.hideTimeout = 0;
11933					}
11934					// hide with a delay to prevent triggering accidental unwanted click on some page element
11935					var self = this;
11936					this.hideTimeout = setTimeout(function() { self.menuHideAll($(e.target)); }, 350);
11937				}
11938				this.lastTouch = null;
11939			},
11940			docTouchMove: function(e) {
11941				if (!this.lastTouch) {
11942					return;
11943				}
11944				var touchPoint = e.originalEvent.touches[0];
11945				this.lastTouch.x2 = touchPoint.pageX;
11946				this.lastTouch.y2 = touchPoint.pageY;
11947			},
11948			docTouchStart: function(e) {
11949				var touchPoint = e.originalEvent.touches[0];
11950				this.lastTouch = { x1: touchPoint.pageX, y1: touchPoint.pageY, target: touchPoint.target };
11951			},
11952			enable: function() {
11953				if (this.disabled) {
11954					if (this.$disableOverlay) {
11955						this.$disableOverlay.remove();
11956						this.$disableOverlay = null;
11957					}
11958					this.disabled = false;
11959				}
11960			},
11961			getHeight: function($elm) {
11962				return this.getOffset($elm, true);
11963			},
11964			// returns precise width/height float values in IE9+, FF4+, recent WebKit
11965			// http://vadikom.com/dailies/offsetwidth-offsetheight-useless-in-ie9-firefox4/
11966			getOffset: function($elm, height) {
11967				var old;
11968				if ($elm.css('display') == 'none') {
11969					old = { position: $elm[0].style.position, visibility: $elm[0].style.visibility };
11970					$elm.css({ position: 'absolute', visibility: 'hidden' }).show();
11971				}
11972				var defaultView = $elm[0].ownerDocument.defaultView,
11973					compStyle = defaultView && defaultView.getComputedStyle && defaultView.getComputedStyle($elm[0], null),
11974					val = compStyle && parseFloat(compStyle[height ? 'height' : 'width']);
11975				if (val) {
11976					val += parseFloat(compStyle[height ? 'paddingTop' : 'paddingLeft'])
11977	 					+ parseFloat(compStyle[height ? 'paddingBottom' : 'paddingRight'])
11978	 					+ parseInt(compStyle[height ? 'borderTopWidth' : 'borderLeftWidth'])
11979	 					+ parseInt(compStyle[height ? 'borderBottomWidth' : 'borderRightWidth']);
11980				} else {
11981					val = height ? $elm[0].offsetHeight : $elm[0].offsetWidth;
11982				}
11983				if (old) {
11984					$elm.hide().css(old);
11985				}
11986				return val;
11987			},
11988			getWidth: function($elm) {
11989				return this.getOffset($elm);
11990			},
11991			getStartZIndex: function() {
11992				var zIndex = parseInt(this.$root.css('z-index'));
11993				return !isNaN(zIndex) ? zIndex : 1;
11994			},
11995			handleEvents: function() {
11996				return !this.disabled && this.isCSSOn();
11997			},
11998			handleItemEvents: function($a) {
11999				return this.handleEvents() && !this.isLinkInMegaMenu($a);
12000			},
12001			isCollapsible: function() {
12002				return this.$firstSub.css('position') == 'static';
12003			},
12004			isCSSOn: function() {
12005				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';
12006			},
12007			isFixed: function() {
12008				return this.$root.css('position') == 'fixed';
12009			},
12010			isLinkInMegaMenu: function($a) {
12011				return !$a.parent().parent().dataSM('level');
12012			},
12013			isTouchMode: function() {
12014				return !mouse || this.isCollapsible();
12015			},
12016			itemActivate: function($a) {
12017				var $li = $a.parent(),
12018					$ul = $li.parent(),
12019					level = $ul.dataSM('level');
12020				// 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
12021				if (level > 1 && (!this.activatedItems[level - 2] || this.activatedItems[level - 2][0] != $ul.dataSM('parent-a')[0])) {
12022					var self = this;
12023					$($ul.parentsUntil('[data-smartmenus-id]', 'ul').get().reverse()).add($ul).each(function() {
12024						self.itemActivate($(this).dataSM('parent-a'));
12025					});
12026				}
12027				// hide any visible deeper level sub menus
12028				if (this.visibleSubMenus.length > level) {
12029					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--) {
12030						this.menuHide(this.visibleSubMenus[i]);
12031					}
12032				}
12033				// save new active item and sub menu for this level
12034				this.activatedItems[level - 1] = $a;
12035				this.visibleSubMenus[level - 1] = $ul;
12036				if (this.$root.triggerHandler('activate.smapi', $a[0]) === false) {
12037					return;
12038				}
12039				// show the sub menu if this item has one
12040				var $sub = $li.dataSM('sub');
12041				if ($sub && (this.isTouchMode() || (!this.opts.showOnClick || this.clickActivated))) {
12042					this.menuShow($sub);
12043				}
12044			},
12045			itemBlur: function(e) {
12046				var $a = $(e.currentTarget);
12047				if (!this.handleItemEvents($a)) {
12048					return;
12049				}
12050				this.$root.triggerHandler('blur.smapi', $a[0]);
12051			},
12052			itemClick: function(e) {
12053				var $a = $(e.currentTarget);
12054
12055				if (!this.handleItemEvents($a)) {
12056					return;
12057				}
12058				$a.removeDataSM('mousedown');
12059				if (this.$root.triggerHandler('click.smapi', $a[0]) === false) {
12060					return false;
12061				}
12062				var $sub = $a.parent().dataSM('sub');
12063				if (this.isTouchMode()) {
12064					// undo fix: prevent the address bar on iPhone from sliding down when expanding a sub menu
12065					if ($a.dataSM('href')) {
12066						$a.attr('href', $a.dataSM('href')).removeDataSM('href');
12067					}
12068					// if the sub is not visible
12069					if ($sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) {
12070						// try to activate the item and show the sub
12071						this.itemActivate($a);
12072						// if "itemActivate" showed the sub, prevent the click so that the link is not loaded
12073						// 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
12074						if ($sub.is(':visible')) {
12075							return false;
12076						}
12077					}
12078				} else if (this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 && $sub) {
12079					this.clickActivated = true;
12080					this.menuShow($sub);
12081					return false;
12082				}
12083				if ($a.hasClass('disabled')) {
12084					return false;
12085				}
12086				if (this.$root.triggerHandler('select.smapi', $a[0]) === false) {
12087					return false;
12088				}
12089			},
12090			itemDown: function(e) {
12091				var $a = $(e.currentTarget);
12092				if (!this.handleItemEvents($a)) {
12093					return;
12094				}
12095				$a.dataSM('mousedown', true);
12096			},
12097			itemEnter: function(e) {
12098				var $a = $(e.currentTarget);
12099				if (!this.handleItemEvents($a)) {
12100					return;
12101				}
12102				if (!this.isTouchMode()) {
12103					if (this.showTimeout) {
12104						clearTimeout(this.showTimeout);
12105						this.showTimeout = 0;
12106					}
12107					var self = this;
12108					this.showTimeout = setTimeout(function() { self.itemActivate($a); }, this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 ? 1 : this.opts.showTimeout);
12109				}
12110				this.$root.triggerHandler('mouseenter.smapi', $a[0]);
12111			},
12112			itemFocus: function(e) {
12113				var $a = $(e.currentTarget);
12114				if (!this.handleItemEvents($a)) {
12115					return;
12116				}
12117				// 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
12118				if ((!this.isTouchMode() || !$a.dataSM('mousedown')) && (!this.activatedItems.length || this.activatedItems[this.activatedItems.length - 1][0] != $a[0])) {
12119					this.itemActivate($a);
12120				}
12121				this.$root.triggerHandler('focus.smapi', $a[0]);
12122			},
12123			itemLeave: function(e) {
12124				var $a = $(e.currentTarget);
12125				if (!this.handleItemEvents($a)) {
12126					return;
12127				}
12128				if (!this.isTouchMode()) {
12129					if ($a[0].blur) {
12130						$a[0].blur();
12131					}
12132					if (this.showTimeout) {
12133						clearTimeout(this.showTimeout);
12134						this.showTimeout = 0;
12135					}
12136				}
12137				$a.removeDataSM('mousedown');
12138				this.$root.triggerHandler('mouseleave.smapi', $a[0]);
12139			},
12140			itemTouchEnd: function(e) {
12141				var $a = $(e.currentTarget);
12142				if (!this.handleItemEvents($a)) {
12143					return;
12144				}
12145				// prevent the address bar on iPhone from sliding down when expanding a sub menu
12146				var $sub = $a.parent().dataSM('sub');
12147				if ($a.attr('href').charAt(0) !== '#' && $sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) {
12148					$a.dataSM('href', $a.attr('href'));
12149					$a.attr('href', '#');
12150				}
12151			},
12152			menuFixLayout: function($ul) {
12153				// fixes a menu that is being shown for the first time
12154				if (!$ul.dataSM('shown-before')) {
12155					$ul.hide().dataSM('shown-before', true);
12156					// fix the layout of the items in IE<8
12157					if (IElt8) {
12158						$ul.children().css({ styleFloat: 'left', width: '100%' });
12159					}
12160				}
12161			},
12162			menuHide: function($sub) {
12163				if (this.$root.triggerHandler('beforehide.smapi', $sub[0]) === false) {
12164					return;
12165				}
12166				$sub.stop(true, true);
12167				if ($sub.is(':visible')) {
12168					var complete = function() {
12169						// unset z-index
12170						if (IElt9) {
12171							$sub.parent().css('z-index', '');
12172						} else {
12173							$sub.css('z-index', '');
12174						}
12175					};
12176					// if sub is collapsible (mobile view)
12177					if (this.isCollapsible()) {
12178						if (this.opts.collapsibleHideFunction) {
12179							this.opts.collapsibleHideFunction.call(this, $sub, complete);
12180						} else {
12181							$sub.hide(this.opts.collapsibleHideDuration, complete);
12182						}
12183					} else {
12184						if (this.opts.hideFunction) {
12185							this.opts.hideFunction.call(this, $sub, complete);
12186						} else {
12187							$sub.hide(this.opts.hideDuration, complete);
12188						}
12189					}
12190					// remove IE iframe shim
12191					if ($sub.dataSM('ie-shim')) {
12192						$sub.dataSM('ie-shim').remove();
12193					}
12194					// deactivate scrolling if it is activated for this sub
12195					if ($sub.dataSM('scroll')) {
12196						$sub.unbind('.smartmenus_scroll').removeDataSM('scroll').dataSM('scroll-arrows').hide();
12197					}
12198					// unhighlight parent item
12199					$sub.dataSM('parent-a').removeClass('highlighted');
12200					var level = $sub.dataSM('level');
12201					this.activatedItems.splice(level - 1, 1);
12202					this.visibleSubMenus.splice(level - 1, 1);
12203					this.$root.triggerHandler('hide.smapi', $sub[0]);
12204				}
12205			},
12206			menuHideAll: function($item) {
12207				if ($item != undefined && $item.parent().hasClass('menu-item') && !$item.parent().hasClass('menu-item-has-children')) return;
12208				var $win = $(window),
12209					winW = $win.width();
12210				if ( $('body').hasClass('vmenu') && winW >= 560 ) {
12211					return;
12212				}
12213				if (this.showTimeout) {
12214					clearTimeout(this.showTimeout);
12215					this.showTimeout = 0;
12216				}
12217				// hide all subs
12218				for (var i = this.visibleSubMenus.length - 1; i > 0; i--) {
12219					this.menuHide(this.visibleSubMenus[i]);
12220				}
12221				// hide root if it's popup
12222				if (this.opts.isPopup) {
12223					this.$root.stop(true, true);
12224					if (this.$root.is(':visible')) {
12225						if (this.opts.hideFunction) {
12226							this.opts.hideFunction.call(this, this.$root);
12227						} else {
12228							this.$root.hide(this.opts.hideDuration);
12229						}
12230						// remove IE iframe shim
12231						if (this.$root.dataSM('ie-shim')) {
12232							this.$root.dataSM('ie-shim').remove();
12233						}
12234					}
12235				}
12236				this.activatedItems = [];
12237				this.visibleSubMenus = [];
12238				this.clickActivated = false;
12239				// reset z-index increment
12240				this.zIndexInc = 0;
12241			},
12242			menuIframeShim: function($ul) {
12243				// create iframe shim for the menu
12244				if (IE && this.opts.overlapControlsInIE && !$ul.dataSM('ie-shim')) {
12245					$ul.dataSM('ie-shim', $('<iframe/>').attr({ src: 'javascript:0', tabindex: -9 })
12246						.css({ position: 'absolute', top: 'auto', left: '0', opacity: 0, border: '0' })
12247					);
12248				}
12249			},
12250			menuInit: function($ul) {
12251				if (!$ul.dataSM('in-mega')) {
12252					this.subMenus.push($ul);
12253					// mark UL's in mega drop downs (if any) so we can neglect them
12254					if ($ul.hasClass('mega-menu')) {
12255						$ul.find('ul').dataSM('in-mega', true);
12256					}
12257					// get level (much faster than, for example, using parentsUntil)
12258					var level = 2,
12259						par = $ul[0];
12260					while (par != null && par.parentNode != null && ( par = par.parentNode.parentNode) != this.$root[0]) {
12261						level++;
12262					}
12263					// cache stuff
12264					$ul.dataSM('parent-a', $ul.prevAll('a').eq(-1))
12265						.dataSM('level', level)
12266						.parent().dataSM('sub', $ul);
12267					// add sub indicator to parent item
12268					if (this.opts.subIndicators) {
12269						$ul.dataSM('parent-a').addClass('has-submenu')[this.opts.subIndicatorsPos](this.$subArrow.clone());
12270					}
12271				}
12272			},
12273			menuPosition: function($sub) {
12274				var fixIE = $('html.ie').length;
12275				// if (fixIE) {
12276				// 	var $rowParent = $($sub).closest('.main-menu-container');
12277				// 	$rowParent.height($rowParent.height());
12278				// }
12279				var $a = $sub.dataSM('parent-a'),
12280					$li = $sub.parent(),
12281					$ul = $sub.parent().parent(),
12282					// $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'),
12283					$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'),
12284					level = $sub.dataSM('level'),
12285					subW = this.getWidth($sub),
12286					subH = this.getHeight($sub),
12287					itemOffset = $a.offset(),
12288					itemX = itemOffset.left,
12289					itemY = itemOffset.top,
12290					itemW = this.getWidth($a),
12291					itemH = this.getHeight($a),
12292					$win = $(window),
12293					winX = $win.scrollLeft(),
12294					winY = $win.scrollTop(),
12295					winW = $win.width(),
12296					winH = $win.height(),
12297					containerW = $container.width(),
12298					containerOffsetX = containerW + ((winW - containerW) / 2),
12299					horizontalParent = $ul.hasClass('sm') && !$ul.hasClass('sm-vertical'),
12300					subOffsetX = level == 2 ? this.opts.mainMenuSubOffsetX : this.opts.subMenusSubOffsetX,
12301					subOffsetY = level == 2 ? this.opts.mainMenuSubOffsetY : this.opts.subMenusSubOffsetY,
12302					x, y, leftPos;
12303
12304				if (horizontalParent) {
12305					x = this.opts.rightToLeftSubMenus ? itemW - subW - subOffsetX : subOffsetX;
12306					y = this.opts.bottomToTopSubMenus ? -subH - subOffsetY : itemH + subOffsetY;
12307				} else {
12308					x = this.opts.rightToLeftSubMenus ? subOffsetX - subW : subW - subOffsetX;
12309					y = this.opts.bottomToTopSubMenus ? itemH - subOffsetY - subH : subOffsetY;
12310				}
12311				if (this.opts.keepInViewport && !this.isCollapsible()) {
12312					if (this.isFixed()) {
12313						itemX -= winX;
12314						itemY -= winY;
12315						winX = winY = 0;
12316					}
12317					var absX = itemX + x,
12318						absY = itemY + y;
12319					if (this.opts.rightToLeftSubMenus && absX < winX) {
12320						x = horizontalParent ? winX - absX + x : itemW - subOffsetX;
12321					} else if (!this.opts.rightToLeftSubMenus && absX + subW > winX + containerOffsetX ) {
12322						x = horizontalParent ? winX + containerOffsetX - subW - absX + x : subOffsetX - subW;
12323					}
12324					if (!horizontalParent) {
12325						if (subH < winH && absY + subH > winY + winH) {
12326							y += winY + winH - subH - absY;
12327						} else if (subH >= winH || absY < winY) {
12328							y += winY - absY;
12329						}
12330					}
12331					// do we need scrolling?
12332					// 0.49 added for the sake of IE9/FF4+ where we might be dealing with float numbers for "subH"
12333					if (mouse && (horizontalParent && (absY + subH > winY + winH + 0.49 || absY < winY) || !horizontalParent && subH > winH + 0.49)) {
12334						var self = this;
12335						if (!$sub.dataSM('scroll-arrows')) {
12336							$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]])
12337								.bind({
12338									mouseenter: function() { self.menuScroll($sub, $(this).hasClass('scroll-up')); },
12339									mouseleave: function(e) {
12340										self.menuScrollStop($sub);
12341										self.menuScrollOut($sub, e);
12342									},
12343									'mousewheel DOMMouseScroll': function(e) { e.preventDefault(); }
12344								})
12345								.insertAfter($sub)
12346							);
12347						}
12348						// bind events to show/hide arrows on hover and save scrolling data for this sub
12349						var vportY = winY - (itemY + itemH);
12350						$sub.dataSM('scroll', {
12351								vportY: vportY,
12352								subH: subH,
12353								winH: winH,
12354								step: 1
12355							})
12356							.bind({
12357								'mouseover.smartmenus_scroll': function(e) { self.menuScrollOver($sub, e); },
12358								'mouseout.smartmenus_scroll': function(e) { self.menuScrollOut($sub, e); },
12359								'mousewheel.smartmenus_scroll DOMMouseScroll.smartmenus_scroll': function(e) { self.menuScrollMousewheel($sub, e); }
12360							})
12361							.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
12361StartZIndex() + this.zIndexInc })
12362							.eq(0).css('margin-top', vportY).end()
12363							.eq(1).css('margin-top', vportY + winH - this.getHeight($sub.dataSM('scroll-arrows').eq(1))).end()
12364							.eq(horizontalParent && this.opts.bottomToTopSubMenus ? 0 : 1).show();
12365					}
12366				}
12367				if ( !$sub.closest('.menu-accordion').length ) {
12368					var rightPos = 'auto';
12369					if ( $sub.closest('.grid-filters').length ) {
12370						if ( $sub.closest('.text-right').length ) {
12371							leftPos = '0px';
12372							rightPos = 'auto';
12373						} else {
12374							leftPos = 'auto';
12375							rightPos = '0px';
12376						}
12377						x = 0;
12378					} else {
12379						if ( $sub.hasClass('mega-menu-inner') ) {
12380							$sub.css({ width: containerW});
12381							leftPos = -1 * (parseFloat($sub.closest('ul.menu-smart').offset().left) - parseFloat($sub.closest('.row-menu').offset().left));
12382							if ( ! $('body').hasClass('megamenu-side-to-side') ) {
12383								leftPos += parseFloat($sub.closest('.row-menu-inner').css('paddingLeft'));
12384							}
12385							x = 0;
12386						} else {
12387							leftPos = (level > 2 ? $li.position().left - parseFloat($li.closest('ul').css('paddingLeft')) : $li.position().left ) + 'px';
12388							x = (level > 2 && x >= 0) ? x + 1 : x - 1;
12389						}
12390					}
12391				}
12392
12393				// $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) });
12394				$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) });
12395				// IE iframe shim
12396				this.menuIframeShim($sub);
12397				if ($sub.dataSM('ie-shim')) {
12398					$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) });
12399				}
12400			},
12401			menuScroll: function($sub, up, wheel) {
12402				var y = parseFloat($sub.css('margin-top')),
12403					scroll = $sub.dataSM('scroll'),
12404					end = scroll.vportY + (up ? 0 : scroll.winH - scroll.subH),
12405					step = wheel || !this.opts.scrollAccelerate ? this.opts.scrollStep : Math.floor($sub.dataSM('scroll').step);
12406				$sub.add($sub.dataSM('ie-shim')).css('margin-top', Math.abs(end - y) > step ? y + (up ? step : -step) : end);
12407				y = parseFloat($sub.css('margin-top'));
12408				// show opposite arrow if appropriate
12409				if (up && y + scroll.subH > scroll.vportY + scroll.winH || !up && y < scroll.vportY) {
12410					$sub.dataSM('scroll-arrows').eq(up ? 1 : 0).show();
12411				}
12412				// accelerate when not using mousewheel to scroll
12413				if (!wheel && this.opts.scrollAccelerate && $sub.dataSM('scroll').step < this.opts.scrollStep) {
12414					$sub.dataSM('scroll').step += 0.5;
12415				}
12416				// "y" and "end" might be float numbers in IE9/FF4+ so this weird way to check is used
12417				if (Math.abs(y - end) < 1) {
12418					$sub.dataSM('scroll-arrows').eq(up ? 0 : 1).hide();
12419					$sub.dataSM('scroll').step = 1;
12420				} else if (!wheel) {
12421					var self = this;
12422					this.scrollTimeout = setTimeout(function() { self.menuScroll($sub, up); }, this.opts.scrollInterval);
12423				}
12424			},
12425			menuScrollMousewheel: function($sub, e) {
12426				var $closestSub = $(e.target).closest('ul');
12427				while ($closestSub.dataSM('in-mega')) {
12428					$closestSub = $closestSub.parent().closest('ul');
12429				}
12430				if ($closestSub[0] == $sub[0]) {
12431					var up = (e.originalEvent.wheelDelta || -e.originalEvent.detail) > 0;
12432					if ($sub.dataSM('scroll-arrows').eq(up ? 0 : 1).is(':visible')) {
12433						this.menuScroll($sub, up, true);
12434					}
12435				}
12436				e.preventDefault();
12437			},
12438			menuScrollOut: function($sub, e) {
12439				var reClass = /^scroll-(up|down)/,
12440					$closestSub = $(e.relatedTarget).closest('ul');
12441				while ($closestSub.dataSM('in-mega')) {
12442					$closestSub = $closestSub.parent().closest('ul');
12443				}
12444				if (!reClass.test((e.relatedTarget || '').className) && ($sub[0] != e.relatedTarget && !$.contains($sub[0], e.relatedTarget) || $closestSub[0] != $sub[0])) {
12445					$sub.dataSM('scroll-arrows').css('visibility', 'hidden');
12446				}
12447			},
12448			menuScrollOver: function($sub, e) {
12449				var reClass = /^scroll-(up|down)/,
12450					$closestSub = $(e.target).closest('ul');
12451				while ($closestSub.dataSM('in-mega')) {
12452					$closestSub = $closestSub.parent().closest('ul');
12453				}
12454				if (!reClass.test(e.target.className) && $closestSub[0] == $sub[0]) {
12455					$sub.dataSM('scroll-arrows').css('visibility', 'visible');
12456				}
12457			},
12458			menuScrollStop: function($sub) {
12459				if (this.scrollTimeout) {
12460					clearTimeout(this.scrollTimeout);
12461					this.scrollTimeout = 0;
12462					$sub.dataSM('scroll').step = 1;
12463				}
12464			},
12465			menuShow: function($sub) {
12466				if (!$sub.dataSM('beforefirstshowfired')) {
12467					$sub.dataSM('beforefirstshowfired', true);
12468					if (this.$root.triggerHandler('beforefirstshow.smapi', $sub[0]) === false) {
12469						return;
12470					}
12471				}
12472				if (this.$root.triggerHandler('beforeshow.smapi', $sub[0]) === false) {
12473					return;
12474				}
12475				this.menuFixLayout($sub);
12476				$sub.stop(true, true);
12477				if (!$sub.is(':visible')) {
12478					$sub.css({
12479						'visibility': 'visible',
12480						'pointer-events': 'auto',
12481					});
12482					// set z-index - for IE < 9 set it to the parent LI
12483					var zIndex = this.getStartZIndex() + (++this.zIndexInc);
12484					if (IElt9) {
12485						$sub.parent().css('z-index', zIndex);
12486					} else {
12487						$sub.css('z-index', zIndex);
12488					}
12489					// highlight parent item
12490					if (this.opts.keepHighlighted || this.isCollapsible()) {
12491						if ($sub.dataSM('parent-a').attr('data-type') != 'title')
12492							$sub.dataSM('parent-a').addClass('highlighted');
12493					}
12494					// min/max-width fix - no way to rely purely on CSS as all UL's are nested
12495					if (this.opts.subMenusMinWidth || this.opts.subMenusMaxWidth) {
12496						if (!IElt8) {
12497							$sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap');
12498							if (this.opts.subMenusMinWidth) {
12499							 	$sub.css('min-width', this.opts.subMenusMinWidth);
12500							}
12501							if (this.opts.subMenusMaxWidth) {
12502							 	var noMaxWidth = this.getWidth($sub);
12503							 	if ( ! $sub.hasClass('mega-menu-inner') ) {
12504								 	$sub.css('max-width', this.opts.subMenusMaxWidth);
12505							 	}
12506								if (noMaxWidth > this.getWidth($sub)) {
12507									$sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth);
12508								}
12509							}
12510						// IE6,7
12511 						} else {
12512							$sub.children().css('styleFloat', 'none');
12513							if (IE6) {
12514								$sub.width(this.opts.subMenusMinWidth ? this.opts.subMenusMinWidth : 1)
12515									.children().children('a').css('white-space', 'nowrap');
12516							} else { // IE7
12517								$sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap');
12518								if (this.opts.subMenusMinWidth) {
12519									$sub.css('min-width', this.opts.subMenusMinWidth);
12520								}
12521							}
12522							if (this.opts.subMenusMaxWidth) {
12523								var noMaxWidth = $sub.width();
12524								if (IE6) {
12525							 		var maxWidth = $sub.css({ width: this.opts.subMenusMaxWidth, overflowX: 'hidden', overflowY: 'hidden' }).width();
12526									if (noMaxWidth > maxWidth) {
12527										$sub.css({ width: maxWidth, overflowX: 'visible', overflowY: 'visible' }).children().children('a').css('white-space', '');
12528									} else {
12529										$sub.css({ width: noMaxWidth, overflowX: 'visible', overflowY: 'visible' });
12530									}
12531								} else { // IE7
12532								 	if ( ! $sub.hasClass('mega-menu-inner') ) {
12533									 	$sub.css('max-width', this.opts.subMenusMaxWidth);
12534								 	}
12535									if (noMaxWidth > $sub.width()) {
12536										$sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth);
12537									} else {
12538										$sub.width(noMaxWidth);
12539									}
12540								}
12541							} else {
12542							 	$sub.width($sub.width());
12543							}
12544							$sub.children().css('styleFloat', 'left');
12545						}
12546					}
12547					this.menuPosition($sub);
12548					// insert IE iframe shim
12549					if ($sub.dataSM('ie-shim')) {
12550						$sub.dataSM('ie-shim').insertBefore($sub);
12551					}
12552					var complete = function() {
12553						// fix: "overflow: hidden;" is not reset on animation complete in jQuery < 1.9.0 in Chrome when global "box-sizing: border-box;" is used
12554						$sub.css('overflow', '');
12555					};
12556					// if sub is collapsible (mobile view)
12557					if (this.isCollapsible()) {
12558						if (this.opts.collapsibleShowFunction) {
12559							this.opts.collapsibleShowFunction.call(this, $sub, complete);
12560						} else {
12561							$sub.show(this.opts.collapsibleShowDuration, complete);
12562						}
12563					} else {
12564						if (this.opts.showFunction) {
12565							this.opts.showFunction.call(this, $sub, complete);
12566						} else {
12567							$sub.show(this.opts.showDuration, complete);
12568						}
12569					}
12570					// save new sub menu for this level
12571					this.visibleSubMenus[$sub.dataSM('level') - 1] = $sub;
12572					this.$root.triggerHandler('show.smapi', $sub[0]);
12573				}
12574			},
12575			popupHide: function(noHideTimeout) {
12576				if (this.hideTimeout) {
12577					clearTimeout(this.hideTimeout);
12578					this.hideTimeout = 0;
12579				}
12580				var self = this;
12581				this.hideTimeout = setTimeout(function() {
12582					self.menuHideAll();
12583				}, noHideTimeout ? 1 : this.opts.hideTimeout);
12584			},
12585			popupShow: function(left, top) {
12586				if (!this.opts.isPopup) {
12587					alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.');
12588					return;
12589				}
12590				if (this.hideTimeout) {
12591					clearTimeout(this.hideTimeout);
12592					this.hideTimeout = 0;
12593				}
12594				this.menuFixLayout(this.$root);
12595				this.$root.stop(true, true);
12596				if (!this.$root.is(':visible')) {
12597					this.$root.css({ left: left, top: top });
12598					// IE iframe shim
12599					this.menuIframeShim(this.$root);
12600					if (this.$root.dataSM('ie-shim')) {
12601						this.$root.dataSM('ie-shim').css({ zIndex: this.$root.css('z-index'), width: this.getWidth(this.$root), height: this.getHeight(this.$root), left
12601: left, top: top }).insertBefore(this.$root);
12602					}
12603					// show menu
12604					if (this.opts.showFunction) {
12605						this.opts.showFunction.call(this, this.$root);
12606					} else {
12607						this.$root.show(this.opts.showDuration);
12608					}
12609					this.visibleSubMenus[0] = this.$root;
12610				}
12611			},
12612			refresh: function() {
12613				this.menuHideAll();
12614				this.$root.find('ul').each(function() {
12615						var $this = $(this);
12616						if ($this.dataSM('scroll-arrows')) {
12617							$this.dataSM('scroll-arrows').remove();
12618						}
12619					})
12620					.removeDataSM('in-mega')
12621					.removeDataSM('shown-before')
12622					.removeDataSM('ie-shim')
12623					.removeDataSM('scroll-arrows')
12624					.removeDataSM('parent-a')
12625					.removeDataSM('level')
12626					.removeDataSM('beforefirstshowfired');
12627				this.$root.find('a.has-submenu').removeClass('has-submenu')
12628					.parent().removeDataSM('sub');
12629				if (this.opts.subIndicators) {
12630					this.$root.find('span.sub-arrow').remove();
12631				}
12632				if (this.opts.markCurrentItem) {
12633					this.$root.find('a.current').removeClass('current');
12634				}
12635				this.subMenus = [];
12636				this.init(true);
12637			},
12638			rootOut: function(e) {
12639				if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) {
12640					return;
12641				}
12642				if (this.hideTimeout) {
12643					clearTimeout(this.hideTimeout);
12644					this.hideTimeout = 0;
12645				}
12646				if (!this.opts.showOnClick || !this.opts.hideOnClick) {
12647					var self = this;
12648					this.hideTimeout = setTimeout(function() { self.menuHideAll(); }, this.opts.hideTimeout);
12649				}
12650			},
12651			rootOver: function(e) {
12652				if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) {
12653					return;
12654				}
12655				if (this.hideTimeout) {
12656					clearTimeout(this.hideTimeout);
12657					this.hideTimeout = 0;
12658				}
12659			},
12660			winResize: function(e) {
12661				if (!this.handleEvents()) {
12662					// we still need to resize the disable overlay if it's visible
12663					if (this.$disableOverlay) {
12664						var pos = this.$root.offset();
12665	 					this.$disableOverlay.css({
12666							top: pos.top,
12667							left: pos.left,
12668							width: this.$root.outerWidth(),
12669							height: this.$root.outerHeight()
12670						});
12671					}
12672					return;
12673				}
12674				// hide sub menus on resize - on mobile do it only on orientation change
12675				if (!this.isCollapsible() && (!('onorientationchange' in window) || e.type == 'orientationchange')) {
12676					if (this.activatedItems.length) {
12677						this.activatedItems[this.activatedItems.length - 1][0].blur();
12678					}
12679					this.menuHideAll();
12680				}
12681			}
12682		}
12683	});
12684
12685	$.fn.dataSM = function(key, val) {
12686		if (val) {
12687			return this.data(key + '_smartmenus', val);
12688		}
12689		return this.data(key + '_smartmenus');
12690	}
12691
12692	$.fn.removeDataSM = function(key) {
12693		return this.removeData(key + '_smartmenus');
12694	}
12695
12696	$.fn.smartmenus = function(options) {
12697		if (typeof options == 'string') {
12698			var args = arguments,
12699				method = options;
12700			Array.prototype.shift.call(args);
12701			return this.each(function() {
12702				var smartmenus = $(this).data('smartmenus');
12703				if (smartmenus && smartmenus[method]) {
12704					smartmenus[method].apply(smartmenus, args);
12705				}
12706			});
12707		}
12708		var opts = $.extend({}, $.fn.smartmenus.defaults, options);
12709		return this.each(function() {
12710			new $.SmartMenus(this, opts);
12711		});
12712	}
12713
12714	// default settings
12715	$.fn.smartmenus.defaults = {
12716		isPopup:		false,		// is this a popup menu (can be shown via the popupShow/popupHide methods) or a permanent menu bar
12717		mainMenuSubOffsetX:	0,		// pixels offset from default position
12718		mainMenuSubOffsetY:	0,		// pixels offset from default position
12719		subMenusSubOffsetX:	0,		// pixels offset from default position
12720		subMenusSubOffsetY:	0,		// pixels offset from default position
12721		subMenusMinWidth:	false, //'10em',		// min-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored
12722		subMenusMaxWidth:	false, //'20em',		// max-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored
12723		subIndicators: 		true,		// create sub menu indicators - creates a SPAN and inserts it in the A
12724		subIndicatorsPos: 	'prepend',	// position of the SPAN relative to the menu item content ('prepend', 'append')
12725		subIndicatorsText:	'+',		// [optionally] add text in the SPAN (e.g. '+') (you may want to check the CSS for the sub indicators too)
12726		scrollStep: 		30,		// pixels step when scrolling long sub menus that do not fit in the viewport height
12727		scrollInterval:		30,		// interval between each scrolling step
12728		scrollAccelerate:	true,		// accelerate scrolling or use a fixed step
12729		showTimeout:		250,		// timeout before showing the sub menus
12730		hideTimeout:		500,		// timeout before hiding the sub menus
12731		showDuration:		0,		// duration for show animation - set to 0 for no animation - matters only if showFunction:null
12732		showFunction:		null,		// custom function to use when showing a sub menu (the default is the jQuery 'show')
12733							// don't forget to call complete() at the end of whatever you do
12734							// e.g.: function($ul, complete) { $ul.fadeIn(250, complete); }
12735		hideDuration:		0,		// duration for hide animation - set to 0 for no animation - matters only if hideFunction:null
12736		hideFunction:		function($ul, complete) { $ul.fadeOut(200, complete); },	// custom function to use when hiding a sub menu (the default is the jQuery 'hide')
12737							// don't forget to call complete() at the end of whatever you do
12738							// e.g.: function($ul, complete) { $ul.fadeOut(250, complete); }
12739		collapsibleShowDuration:0,		// duration for show animation for collapsible sub menus - matters only if collapsibleShowFunction:null
12740		collapsibleShowFunction:function($ul, complete) { $ul.slideDown(200, complete); },	// custom function to use when showing a collapsible sub menu
12741							// (i.e. when mobile styles are used to make the sub menus collapsible)
12742		collapsibleHideDuration:0,		// duration for hide animation for collapsible sub menus - matters only if collapsibleHideFunction:null
12743		collapsibleHideFunction:function($ul, complete) { $ul.slideUp(200, complete); },	// custom function to use when hiding a collapsible sub menu
12744							// (i.e. when mobile styles are used to make the sub menus collapsible)
12745		showOnClick:		false,		// show the first-level sub menus onclick instead of onmouseover (matters only for mouse input)
12746		hideOnClick:		true,		// hide the sub menus on click/tap anywhere on the page
12747		keepInViewport:		true,		// reposition the sub menus if needed to make sure they always appear inside the viewport
12748		keepHighlighted:	true,		// keep all ancestor items of the current sub menu highlighted (adds the 'highlighted' class to the A's)
12749		markCurrentItem:	false,		// automatically add the 'current' class to the A element of the item linking to the current URL
12750		markCurrentTree:	true,		// add the 'current' class also to the A elements of all ancestor items of the current item
12751		rightToLeftSubMenus:	false,		// right to left display of the sub menus (check the CSS for the sub indicators' position)
12752		bottomToTopSubMenus:	false,		// bottom to top display of the sub menus
12753		overlapControlsInIE:	true		// make sure sub menus appear on top of special OS controls in IE (i.e. SELECT, OBJECT, EMBED, etc.)
12754	};
12755
12756})(jQuery);
12757
12758/*
12759 * jQuery Easing v1.4.1 - http://gsgd.co.uk/sandbox/jquery/easing/
12760 * Open source under the BSD License.
12761 * Copyright © 2008 George McGinley Smith
12762 * All rights reserved.
12763 * https://raw.github.com/gdsmith/jquery.easing/master/LICENSE
12764*/
12765
12766/* globals jQuery, define, module, require */
12767(function (factory) {
12768	if (typeof define === "function" && define.amd) {
12769		define(['jquery'], function ($) {
12770			return factory($);
12771		});
12772	} else if (typeof module === "object" && typeof module.exports === "object") {
12773		module.exports = factory(require('jquery'));
12774	} else {
12775		factory(jQuery);
12776	}
12777})(function($){
12778
12779	// Preserve the original jQuery "swing" easing as "jswing"
12780	if (typeof $.easing !== 'undefined') {
12781		$.easing['jswing'] = $.easing['swing'];
12782	}
12783
12784	var pow = Math.pow,
12785		sqrt = Math.sqrt,
12786		sin = Math.sin,
12787		cos = Math.cos,
12788		PI = Math.PI,
12789		c1 = 1.70158,
12790		c2 = c1 * 1.525,
12791		c3 = c1 + 1,
12792		c4 = ( 2 * PI ) / 3,
12793		c5 = ( 2 * PI ) / 4.5;
12794
12795	// x is the fraction of animation progress, in the range 0..1
12796	function bounceOut(x) {
12797		var n1 = 7.5625,
12798			d1 = 2.75;
12799		if ( x < 1/d1 ) {
12800			return n1*x*x;
12801		} else if ( x < 2/d1 ) {
12802			return n1*(x-=(1.5/d1))*x + .75;
12803		} else if ( x < 2.5/d1 ) {
12804			return n1*(x-=(2.25/d1))*x + .9375;
12805		} else {
12806			return n1*(x-=(2.625/d1))*x + .984375;
12807		}
12808	}
12809
12810	$.extend( $.easing, {
12811		def: 'easeOutQuad',
12812		swing: function (x) {
12813			return $.easing[$.easing.def](x);
12814		},
12815		easeInQuad: function (x) {
12816			return x * x;
12817		},
12818		easeOutQuad: function (x) {
12819			return 1 - ( 1 - x ) * ( 1 - x );
12820		},
12821		easeInOutQuad: function (x) {
12822			return x < 0.5 ?
12823				2 * x * x :
12824				1 - pow( -2 * x + 2, 2 ) / 2;
12825		},
12826		easeInCubic: function (x) {
12827			return x * x * x;
12828		},
12829		easeOutCubic: function (x) {
12830			return 1 - pow( 1 - x, 3 );
12831		},
12832		easeInOutCubic: function (x) {
12833			return x < 0.5 ?
12834				4 * x * x * x :
12835				1 - pow( -2 * x + 2, 3 ) / 2;
12836		},
12837		easeInQuart: function (x) {
12838			return x * x * x * x;
12839		},
12840		easeOutQuart: function (x) {
12841			return 1 - pow( 1 - x, 4 );
12842		},
12843		easeInOutQuart: function (x) {
12844			return x < 0.5 ?
12845				8 * x * x * x * x :
12846				1 - pow( -2 * x + 2, 4 ) / 2;
12847		},
12848		easeInQuint: function (x) {
12849			return x * x * x * x * x;
12850		},
12851		easeOutQuint: function (x) {
12852			return 1 - pow( 1 - x, 5 );
12853		},
12854		easeInOutQuint: function (x) {
12855			return x < 0.5 ?
12856				16 * x * x * x * x * x :
12857				1 - pow( -2 * x + 2, 5 ) / 2;
12858		},
12859		easeInSine: function (x) {
12860			return 1 - cos( x * PI/2 );
12861		},
12862		easeOutSine: function (x) {
12863			return sin( x * PI/2 );
12864		},
12865		easeInOutSine: function (x) {
12866			return -( cos( PI * x ) - 1 ) / 2;
12867		},
12868		easeInExpo: function (x) {
12869			return x === 0 ? 0 : pow( 2, 10 * x - 10 );
12870		},
12871		easeOutExpo: function (x) {
12872			return x === 1 ? 1 : 1 - pow( 2, -10 * x );
12873		},
12874		easeInOutExpo: function (x) {
12875			return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ?
12876				pow( 2, 20 * x - 10 ) / 2 :
12877				( 2 - pow( 2, -20 * x + 10 ) ) / 2;
12878		},
12879		easeInCirc: function (x) {
12880			return 1 - sqrt( 1 - pow( x, 2 ) );
12881		},
12882		easeOutCirc: function (x) {
12883			return sqrt( 1 - pow( x - 1, 2 ) );
12884		},
12885		easeInOutCirc: function (x) {
12886			return x < 0.5 ?
12887				( 1 - sqrt( 1 - pow( 2 * x, 2 ) ) ) / 2 :
12888				( sqrt( 1 - pow( -2 * x + 2, 2 ) ) + 1 ) / 2;
12889		},
12890		easeInElastic: function (x) {
12891			return x === 0 ? 0 : x === 1 ? 1 :
12892				-pow( 2, 10 * x - 10 ) * sin( ( x * 10 - 10.75 ) * c4 );
12893		},
12894		easeOutElastic: function (x) {
12895			return x === 0 ? 0 : x === 1 ? 1 :
12896				pow( 2, -10 * x ) * sin( ( x * 10 - 0.75 ) * c4 ) + 1;
12897		},
12898		easeInOutElastic: function (x) {
12899			return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ?
12900				-( pow( 2, 20 * x - 10 ) * sin( ( 20 * x - 11.125 ) * c5 )) / 2 :
12901				pow( 2, -20 * x + 10 ) * sin( ( 20 * x - 11.125 ) * c5 ) / 2 + 1;
12902		},
12903		easeInBack: function (x) {
12904			return c3 * x * x * x - c1 * x * x;
12905		},
12906		easeOutBack: function (x) {
12907			return 1 + c3 * pow( x - 1, 3 ) + c1 * pow( x - 1, 2 );
12908		},
12909		easeInOutBack: function (x) {
12910			return x < 0.5 ?
12911				( pow( 2 * x, 2 ) * ( ( c2 + 1 ) * 2 * x - c2 ) ) / 2 :
12912				( pow( 2 * x - 2, 2 ) *( ( c2 + 1 ) * ( x * 2 - 2 ) + c2 ) + 2 ) / 2;
12913		},
12914		easeInBounce: function (x) {
12915			return 1 - bounceOut( 1 - x );
12916		},
12917		easeOutBounce: bounceOut,
12918		easeInOutBounce: function (x) {
12919			return x < 0.5 ?
12920				( 1 - bounceOut( 1 - 2 * x ) ) / 2 :
12921				( 1 + bounceOut( 2 * x - 1 ) ) / 2;
12922		}
12923	});
12924	return $;
12925});
12926
12927/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net)
12928 * Licensed under the MIT License (LICENSE.txt).
12929 *
12930 * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
12931 * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
12932 * Thanks to: Seamus Leahy for adding deltaX and deltaY
12933 *
12934 * Version: 3.0.6
12935 *
12936 * Requires: 1.2.2+
12937 */
12938(function($) {
12939    var types = ['DOMMouseScroll', 'mousewheel'];
12940    if ($.event.fixHooks) {
12941        for (var i = types.length; i;) {
12942            $.event.fixHooks[types[--i]] = $.event.mouseHooks;
12943        }
12944    }
12945    $.event.special.mousewheel = {
12946        setup: function() {
12947            if (this.addEventListener) {
12948                for (var i = types.length; i;) {
12949                    this.addEventListener(types[--i], handler, false);
12950                }
12951            } else {
12952                this.onmousewheel = handler;
12953            }
12954        },
12955        teardown: function() {
12956            if (this.removeEventListener) {
12957                for (var i = types.length; i;) {
12958                    this.removeEventListener(types[--i], handler, false);
12959                }
12960            } else {
12961                this.onmousewheel = null;
12962            }
12963        }
12964    };
12965    $.fn.extend({
12966        mousewheel: function(fn) {
12967            return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");
12968        },
12969        unmousewheel: function(fn) {
12970            return this.unbind("mousewheel", fn);
12971        }
12972    });
12973
12974    function handler(event) {
12975        var orgEvent = event || window.event,
12976            args = [].slice.call(arguments, 1),
12977            delta = 0,
12978            returnValue = true,
12979            deltaX = 0,
12980            deltaY = 0;
12981        event = $.event.fix(orgEvent);
12982        event.type = "mousewheel";
12983        // Old school scrollwheel delta
12984        if (orgEvent.wheelDelta) {
12985            delta = orgEvent.wheelDelta / 120;
12986        }
12987        if (orgEvent.detail) {
12988            delta = -orgEvent.detail / 3;
12989        }
12990        // New school multidimensional scroll (touchpads) deltas
12991        deltaY = delta;
12992        // Gecko
12993        if (orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS) {
12994            deltaY = 0;
12995            deltaX = -1 * delta;
12996        }
12997        // Webkit
12998        if (orgEvent.wheelDeltaY !== undefined) {
12999            deltaY = orgEvent.wheelDeltaY / 120;
13000        }
13001        if (orgEvent.wheelDeltaX !== undefined) {
13002            deltaX = -1 * orgEvent.wheelDeltaX / 120;
13003        }
13004        // Add event and delta to the front of the arguments
13005        args.unshift(event, delta, deltaX, deltaY);
13006        return ($.event.dispatch || $.event.handle).apply(this, args);
13007    }
13008})(jQuery);
13009/**
13010 * jQuery iLightBox - Revolutionary Lightbox Plugin
13011 * http://www.ilightbox.net/
13012 *
13013 * @version: 2.2.4 - October 14, 2017
13014 *
13015 * @author: iProDev (Hemn Chawroka)
13016 *          http://www.iprodev.com/
13017 *
13018 */
13019(function($, window, undefined) {
13020
13021	var extensions = {
13022			flash: ['swf'],
13023			image: ['bmp', 'gif', 'jpeg', 'jpg', 'png', 'tiff', 'tif', 'jfif', 'jpe', 'webp'],
13024			iframe: ['asp', 'aspx', 'cgi', 'cfm', 'htm', 'html', 'jsp', 'php', 'pl', 'php3', 'php4', 'php5', 'phtml', 'rb', 'rhtml', 'shtml', 'txt'],
13025			video: ['avi', 'mov', 'mpg', 'mpeg', 'movie', 'mp4', 'webm', 'ogv', 'ogg', '3gp', 'm4v']
13026		},
13027
13028		// Global DOM elements
13029		$win = $(window),
13030		$doc = $(document),
13031
13032		// Support indicators
13033		browser,
13034		transform,
13035		gpuAcceleration,
13036		fullScreenApi = '',
13037		userAgent = navigator.userAgent || navigator.vendor || window.opera,
13038        supportTouch = "ontouchstart" in window || navigator.msMaxTouchPoints || (navigator.maxTouchPoints && navigator.userAgent.indexOf('Windows') > -1),
13039        ishybrid = navigator.maxTouchPoints && navigator.userAgent.indexOf('Windows') > -1,
13040        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)),
13041
13042		// Events
13043		clickEvent = ishybrid ? "itap.iLightBox click.iLightBox" : supportTouch ? "itap.iLightBox" : "click.iLightBox",
13044		touchStartEvent = ishybrid ? "touchstart.iLightBox mousedown.iLightBox" : supportTouch ? "touchstart.iLightBox" : "mousedown.iLightBox",
13045		touchStopEvent = ishybrid ? "touchend.iLightBox mouseup.iLightBox" : supportTouch ? "touchend.iLightBox" : "mouseup.iLightBox",
13046		touchMoveEvent = ishybrid ? "touchmove.iLightBox mousemove.iLightBox" : supportTouch ? "touchmove.iLightBox" : "mousemove.iLightBox",
13047
13048		// Math shorthands
13049		abs = Math.abs,
13050		sqrt = Math.sqrt,
13051		round = Math.round,
13052		max = Math.max,
13053		min = Math.min,
13054		floor = Math.floor,
13055		random = Math.random,
13056
13057		pluginspages = {
13058			quicktime: 'http://www.apple.com/quicktime/download',
13059			flash: 'http://www.adobe.com/go/getflash'
13060		},
13061
13062		iLightBox = function(el, options, items, instant) {
13063			var iL = this;
13064
13065			iL.options = options,
13066				iL.selector = options.selector || el,
13067				iL.context = document,
13068				iL.instant = instant;
13069
13070			if (items.length < 1) iL.attachItems();
13071			else iL.items = items;
13072
13073			iL.vars = {
13074				total: iL.items.length,
13075				start: 0,
13076				current: null,
13077				next: null,
13078				prev: null,
13079				BODY: $('body'),
13080				loadRequests: 0,
13081				overlay: $('<div class="ilightbox-overlay"></div>'),
13082				loader: $('<div class="ilightbox-loader"><div></div></div>'),
13083				toolbar: $('<div class="ilightbox-toolbar"></div>'),
13084				innerToolbar: $('<div class="ilightbox-inner-toolbar"></div>'),
13085				title: $('<div class="ilightbox-title"></div>'),
13086				closeButton: $('<a class="ilightbox-close" title="' + iL.options.text.close + '"></a>'),
13087				fullScreenButton: $('<a class="ilightbox-fullscreen" title="' + iL.options.text.enterFullscreen + '"></a>'),
13088				innerPlayButton: $('<a class="ilightbox-play" title="' + iL.options.text.slideShow + '"></a>'),
13089				innerNextButton: $('<a class="ilightbox-next-button" title="' + iL.options.text.next + '"></a>'),
13090				innerPrevButton: $('<a class="ilightbox-prev-button" title="' + iL.options.text.previous + '"></a>'),
13091				holder: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + '" ondragstart="return false;"><div class="ilightbox-container"></div></div>'),
13092				nextPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-next" ondragstart="return false;"><div class="ilightbox-container"></div></div>'),
13093				prevPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-prev" ondragstart="return false;"><div class="ilightbox-container"></div></div>'),
13094				nextButton: $('<a class="ilightbox-button ilightbox-next-button" ondragstart="return false;" title="' + iL.options.text.next + '"><span></span></a>'),
13095				prevButton: $('<a class="ilightbox-button ilightbox-prev-button" ondragstart="return false;" title="' + iL.options.text.previous + '"><span></span></a>'),
13096				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>'),
13097				thumbs: false,
13098				nextLock: false,
13099				prevLock: false,
13100				hashLock: false,
13101				isMobile: false,
13102				mobileMaxWidth: 980,
13103				isInFullScreen: false,
13104				isSwipe: false,
13105				mouseID: 0,
13106				cycleID: 0,
13107				isPaused: 0,
13108				captionHeight: 39,
13109			};
13110
13111			// Hideable elements with mousemove event
13112			iL.vars.hideableElements = iL.vars.nextButton.add(iL.vars.prevButton);
13113
13114			iL.normalizeItems();
13115
13116			//Check necessary plugins
13117			iL.availPlugins();
13118
13119			//Set startFrom
13120			iL.options.startFrom = (iL.options.startFrom > 0 && iL.options.startFrom >= iL.vars.total) ? iL.vars.total - 1 : iL.options.startFrom;
13121
13122			//If randomStart
13123			iL.options.startFrom = (iL.options.randomStart) ? floor(random() * iL.vars.total) : iL.options.startFrom;
13124			iL.vars.start = iL.options.startFrom;
13125
13126			if (instant) iL.instantCall();
13127			else iL.patchItemsEvents();
13128
13129			if (iL.options.linkId) {
13130				iL.hashChangeHandler();
13131				$win.iLightBoxHashChange(function() {
13132					iL.hashChangeHandler();
13133				});
13134			}
13135
13136			if (supportTouch) {
13137				var RegExp = /(click|mouseenter|mouseleave|mouseover|mouseout)/ig,
13138					replace = "itap";
13139				iL.options.caption.show = iL.options.caption.show.replace(RegExp, replace),
13140					iL.options.caption.hide = iL.options.caption.hide.replace(RegExp, replace),
13141					iL.options.social.show = iL.options.social.show.replace(RegExp, replace),
13142					iL.options.social.hide = iL.options.social.hide.replace(RegExp, replace);
13143			}
13144
13145			if (iL.options.controls.arrows || $(window).width() < UNCODE.mediaQuery) {
13146				$.extend(iL.options.styles, {
13147					nextOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4,
13148					prevOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4,
13149					nextOpacity: 0,
13150					prevOpacity: 0
13151				});
13152			}
13153		};
13154
13155	//iLightBox helpers
13156	iLightBox.prototype = {
13157		showLoader: function() {
13158			var iL = this;
13159			iL.vars.loadRequests += 1;
13160			if (iL.options.path.toLowerCase() == "horizontal") iL.vars.loader.addClass('ilightbox-show').stop().animate({
13161				//top: '-30px'
13162				opacity: '1'
13163			}, iL.options.show.speed, 'easeOutCirc');
13164			else iL.vars.loader.addClass('ilightbox-show').stop().animate({
13165				//left: '-30px'
13166				opacity: '1'
13167			}, iL.options.show.speed, 'easeOutCirc');
13168		},
13169
13170		hideLoader: function() {
13171			var iL = this;
13172			iL.vars.loadRequests -= 1;
13173			iL.vars.loadRequests = (iL.vars.loadRequests < 0) ? 0 : iL.vars.loadRequests;
13174			if (iL.options.path.toLowerCase() == "horizontal") {
13175				if (iL.vars.loadRequests <= 0) iL.vars.loader.removeClass('ilightbox-show').stop().animate({
13176					//top: '-192px'
13177					opacity: '0'
13178				}, iL.options.show.speed, 'easeInCirc');
13179			} else {
13180				if (iL.vars.loadRequests <= 0) iL.vars.loader.removeClass('ilightbox-show').stop().animate({
13181					//left: '-192px'
13182					opacity: '0'
13183				}, iL.options.show.speed, 'easeInCirc');
13184			}
13185		},
13186
13187		createUI: function() {
13188			var iL = this;
13189
13190			iL.ui = {
13191				currentElement: iL.vars.holder,
13192				nextElement: iL.vars.nextPhoto,
13193				prevElement: iL.vars.prevPhoto,
13194				currentItem: iL.vars.current,
13195				nextItem: iL.vars.next,
13196				prevItem: iL.vars.prev,
13197				hide: function() {
13198					iL.closeAction();
13199				},
13200				refresh: function() {
13201					(arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto();
13202				},
13203				fullscreen: function() {
13204					iL.fullScreenAction();
13205				}
13206			};
13207		},
13208
13209		attachItems: function() {
13210			var iL = this,
13211				itemsObject = new Array(),
13212				items = new Array();
13213
13214			$(iL.selector, iL.context).each(function() {
13215				var t = $(this),
13216					URL = t.attr(iL.options.attr) || null,
13217					options = t.data("options") && eval("({" + t.data("options") + "})") || {},
13218					caption = t.data('caption'),
13219					title = t.data('title'),
13220					type = t.data('type') || getTypeByExtension(URL),
13221					clone = t.data('lbox-clone') || false;
13222
13223				//Uncode addition ##START##
13224				if (type === false) {
13225					return;
13226				}
13227				//Uncode addition ##END##
13228
13229				if (t.data('lbox-clone') != undefined) return;
13230
13231				//Uncode addition ##START##
13232				if ( typeof t.attr('data-album') != 'undefined' && t.attr('data-album') != '' ) {
13233					var ALBUM_URLS = JSON.parse(t.attr('data-album')),
13234						URL_i,
13235						URLS_LENGHT = ALBUM_URLS.length;
13236
13237					for (URL_i = 0; URL_i < URLS_LENGHT; URL_i++) {
13238						if ( typeof ALBUM_URLS[URL_i].url !== 'undefined' && ALBUM_URLS[URL_i].url != '' ) {
13239							var item_opts = 'width:' + ALBUM_URLS[URL_i].width + ',height:' + ALBUM_URLS[URL_i].height + ',thumbnail: \'' + ALBUM_URLS[URL_i].thumbnail + '\'';
13240							item_opts = item_opts && eval("({" + item_opts + "})") || {},
13241							items.push({
13242								URL: ALBUM_URLS[URL_i].url,
13243								caption: ALBUM_URLS[URL_i].caption,
13244								title: ALBUM_URLS[URL_i].title,
13245								type: getTypeByExtension(ALBUM_URLS[URL_i].url),
13246								options: item_opts,
13247								clone: clone
13248							});
13249							var newT = t;
13250							newT.attr('href',ALBUM_URLS[URL_i].url);
13251							if (!iL.instant) itemsObject.push(newT);
13252						}
13253					}
13254				} else {
13255				//Uncode addition ##END##
13256					items.push({
13257						URL: URL,
13258						caption: caption,
13259						title: title,
13260						type: type,
13261						options: options,
13262						clone: clone
13263					});
13264				}
13265
13266
13267				if (iL.vars != undefined) iL.vars.total = items.length;
13268
13269				if (!iL.instant) itemsObject.push(t);
13270			});
13271
13272			iL.items = items,
13273				iL.itemsObject = itemsObject;
13274
13275		},
13276
13277		normalizeItems: function() {
13278			var iL = this,
13279				newItems = new Array();
13280
13281			$.each(iL.items, function(key, val) {
13282
13283				if (typeof val == "string") val = {
13284					url: val
13285				};
13286
13287				var URL = val.url || val.URL || null,
13288					options = val.options || {},
13289					caption = val.caption || null,
13290					title = val.title || null,
13291					type = (val.type) ? val.type.toLowerCase() : getTypeByExtension(URL),
13292					ext = (typeof URL != 'object') ? getExtension(URL) : '';
13293
13294				options.thumbnail = options.thumbnail || ((type == "image") ? URL : null),
13295				options.videoType = options.videoType || null,
13296				options.skin = options.skin || iL.options.skin,
13297				options.width = options.width || null,
13298				options.height = options.height || null,
13299				options.mousewheel = (typeof options.mousewheel != 'undefined') ? options.mousewheel : true,
13300				options.swipe = (typeof options.swipe != 'undefined') ? options.swipe : true,
13301				options.social = (typeof options.social != 'undefined') ? options.social : iL.options.social.buttons && $.extend({}, {}, iL.options.social.buttons);
13302
13303				if (type == "video") {
13304					options.html5video = (typeof options.html5video != 'undefined') ? options.html5video : {};
13305
13306					options.html5video.webm = options.html5video.webm || options.html5video.WEBM || null;
13307					options.html5video.controls = (typeof options.html5video.controls != 'undefined') ? options.html5video.controls : "controls";
13308					options.html5video.preload = options.html5video.preload || "metadata";
13309					options.html5video.autoplay = (typeof options.html5video.autoplay != 'undefined') ? options.html5video.autoplay : false;
13310					//UNCODE addition
13311					options.html5video.loop = (typeof options.html5video.loop != 'undefined') ? options.html5video.loop : false;
13312				}
13313
13314				if (!options.width || !options.height) {
13315					if (type == "video") options.width = 1280, options.height = 720;
13316					else if (type == "iframe") options.width = '100%', options.height = '90%';
13317					else if (type == "flash") options.width = 1280, options.height = 720;
13318				}
13319
13320				delete val.url;
13321				val.index = key;
13322				val.URL = URL;
13323				val.caption = caption;
13324				val.title = title;
13325				val.type = type;
13326				val.options = options;
13327				val.ext = ext;
13328
13329				newItems.push(val);
13330			});
13331
13332			iL.items = newItems;
13333		},
13334
13335		instantCall: function() {
13336			var iL = this,
13337				key = iL.vars.start;
13338
13339			iL.vars.current = key;
13340			iL.vars.next = (iL.items[key + 1]) ? key + 1 : null;
13341			iL.vars.prev = (iL.items[key - 1]) ? key - 1 : null;
13342
13343			iL.addContents();
13344			iL.patchEvents();
13345		},
13346
13347		addContents: function() {
13348			var iL = this,
13349				vars = iL.vars,
13350				opts = iL.options,
13351				viewport = getViewport(),
13352				path = opts.path.toLowerCase(),
13353				recognizingItems = vars.total > 0 && iL.items.filter(function(e, i, arr) {
13354					return ['image', 'flash', 'video'].indexOf(e.type) === -1 && typeof e.recognized === 'undefined' && (opts.smartRecognition || e.options.smartRecognition);
13355				}),
13356				needRecognition = recognizingItems.length > 0;
13357
13358			if (opts.mobileOptimizer && !opts.innerToolbar)
13359				vars.isMobile = viewport.width <= vars.mobileMaxWidth;
13360
13361			vars.overlay.addClass(opts.skin).hide().css('opacity', opts.overlay.opacity);
13362
13363			if (opts.linkId)
13364				vars.overlay[0].setAttribute('linkid', opts.linkId);
13365
13366			//Add Toolbar Buttons
13367			if (opts.controls.toolbar) {
13368				vars.toolbar.addClass(opts.skin).append(vars.closeButton);
13369				if (opts.controls.fullscreen)
13370					vars.toolbar.append(vars.fullScreenButton);
13371				if (opts.controls.slideshow)
13372					vars.toolbar.append(vars.innerPlayButton);
13373				if (vars.total > 1)
13374					vars.toolbar.append(vars.innerPrevButton).append(vars.innerNextButton);
13375			}
13376
13377			//Append elements to body
13378			vars.BODY.addClass('ilightbox-noscroll').append(vars.overlay).append(vars.loader).append(vars.holder).append(vars.nextPhoto).append(vars.prevPhoto);
13379
13380			if (!opts.innerToolbar)
13381				vars.BODY.append(vars.toolbar);
13382			if (opts.controls.arrows)
13383				vars.BODY.append(vars.nextButton).append(vars.prevButton);
13384
13385			if (opts.controls.thumbnail && vars.total > 1) {
13386				vars.BODY.append(vars.thumbnails);
13387				vars.thumbnails.addClass(opts.skin).addClass('ilightbox-' + path);
13388				$('div.ilightbox-thumbnails-grid', vars.thumbnails).empty();
13389				vars.thumbs = true;
13390			}
13391
13392			//Configure loader and arrows
13393			var loaderCss = (opts.path.toLowerCase() == "horizontal") ? {
13394				left: parseInt((viewport.width / 2) - (vars.loader.outerWidth() / 2))
13395			} : {
13396				top: parseInt((viewport.height / 2) - (vars.loader.outerHeight() / 2))
13397			};
13398			vars.loader.addClass(opts.skin).css(loaderCss);
13399			vars.nextButton.add(vars.prevButton).addClass(opts.skin);
13400			if (path == "horizontal")
13401				vars.loader.add(vars.nextButton).add(vars.prevButton).addClass('horizontal');
13402
13403			// Configure arrow buttons
13404			vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile');
13405
13406			if (!opts.infinite) {
13407				vars.prevButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
13408
13409				if (vars.current == 0)
13410					vars.prevButton.add(vars.innerPrevButton).addClass('disabled');
13411				if (vars.current >= vars.total - 1)
13412					vars.nextButton.add(vars.innerNextButton).addClass('disabled');
13413			}
13414
13415			if (opts.show.effect) {
13416				vars.overlay.stop().fadeIn(opts.show.speed);
13417				vars.toolbar.stop().fadeIn(opts.show.speed);
13418			} else {
13419				vars.overlay.show();
13420				vars.toolbar.show();
13421			}
13422
13423			var length = recognizingItems.length;
13424			if (needRecognition) {
13425				iL.showLoader();
13426
13427				$.each(recognizingItems, function(key, val) {
13428					var resultFnc = function(result) {
13429							var key = -1,
13430								filter = iL.items.filter(function(e, i, arr) {
13431									if (e.URL == result.url)
13432										key = i;
13433
13434									return e.URL == result.url;
13435								}),
13436								self = iL.items[key];
13437
13438							if (result)
13439								$.extend(true, self, {
13440									URL: result.source,
13441									type: result.type,
13442									recognized: true,
13443									options: {
13444										html5video: result.html5video,
13445										width: (result.type == "image") ? 0 : (result.width || self.width),
13446										height: (result.type == "image") ? 0 : (result.height || self.height),
13447										thumbnail: self.options.thumbnail || result.thumbnail
13448									}
13449								});
13450
13451							length--;
13452
13453							if (length == 0) {
13454								iL.hideLoader();
13455
13456								vars.dontGenerateThumbs = false;
13457								iL.generateThumbnails();
13458
13459								if (opts.show.effect)
13460									setTimeout(function() {
13461										iL.generateBoxes();
13462									}, opts.show.speed);
13463								else
13464									iL.generateBoxes();
13465							}
13466						};
13467
13468					iL.ogpRecognition(this, resultFnc);
13469				});
13470			}
13471			else {
13472				if (opts.show.effect)
13473					setTimeout(function() {
13474						iL.generateBoxes();
13475					}, opts.show.speed);
13476				else
13477					iL.generateBoxes();
13478			}
13479
13480			iL.createUI();
13481
13482			window.iLightBox = {
13483				close: function() {
13484					iL.closeAction();
13485				},
13486				fullscreen: function() {
13487					iL.fullScreenAction();
13488				},
13489				moveNext: function() {
13490					iL.moveTo('next');
13491				},
13492				movePrev: function() {
13493					iL.moveTo('prev');
13494				},
13495				goTo: function(index) {
13496					iL.goTo(index);
13497				},
13498				refresh: function() {
13499					iL.refresh();
13500				},
13501				reposition: function() {
13502					(arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto();
13503				},
13504				setOption: function(options) {
13505					iL.setOption(options);
13506				},
13507				destroy: function() {
13508					iL.closeAction();
13509					iL.dispatchItemsEvents();
13510				}
13511			};
13512
13513			if (opts.linkId) {
13514				vars.hashLock = true;
13515				window.location.hash = opts.linkId + '/' + vars.current;
13516				setTimeout(function() {
13517					vars.hashLock = false;
13518				}, 55);
13519			}
13520
13521			if (!opts.slideshow.startPaused) {
13522				iL.resume();
13523				vars.innerPlayButton.removeClass('ilightbox-play').addClass('ilightbox-pause');
13524			}
13525
13526			//Trigger the onOpen callback
13527			if (typeof iL.options.callback.onOpen == 'function') iL.options.callback.onOpen.call(iL);
13528		},
13529
13530		loadContent: function(obj, opt, speed) {
13531			var iL = this,
13532				holder, item;
13533
13534			iL.createUI();
13535
13536			obj.speed = speed || iL.options.effects.loadedFadeSpeed;
13537
13538			if (opt == 'current') {
13539				if (!obj.options.mousewheel) iL.vars.lockWheel = true;
13540				else iL.vars.lockWheel = false;
13541
13542				if (!obj.options.swipe) iL.vars.lockSwipe = true;
13543				else iL.vars.lockSwipe = false;
13544			}
13545
13546			switch (opt) {
13547				case 'current':
13548					holder = iL.vars.holder, item = iL.vars.current;
13549					break;
13550				case 'next':
13551					holder = iL.vars.nextPhoto, item = iL.vars.next;
13552					break;
13553				case 'prev':
13554					holder = iL.vars.prevPhoto, item = iL.vars.prev;
13555					break;
13556			}
13557
13558			holder.removeAttr('style class').addClass('ilightbox-holder' + (supportTouch ? ' supportTouch' : '')).addClass(obj.options.skin);
13559			$('div.ilightbox-inner-toolbar', holder).remove();
13560
13561			if (obj.title || iL.options.innerToolbar) {
13562				var innerToolbar = iL.vars.innerToolbar.clone();
13563				if (obj.title && iL.options.show.title) {
13564					var title = iL.vars.title.clone();
13565					title.empty().html(obj.title);
13566					innerToolbar.append(title);
13567				}
13568				if (iL.options.innerToolbar) {
13569					innerToolbar.append((iL.vars.total > 1) ? iL.vars.toolbar.clone() : iL.vars.toolbar);
13570				}
13571				holder.prepend(innerToolbar);
13572			}
13573
13574			//console.warn('loadContent', arguments);
13575
13576			iL.loadSwitcher(obj, holder, item, opt);
13577		},
13578
13579		loadSwitcher: function(obj, holder, item, opt) {
13580			var iL = this,
13581				opts = iL.options,
13582				api = {
13583					element: holder,
13584					position: item
13585				};
13586
13587			switch (obj.type) {
13588				case 'image':
13589					//Trigger the onBeforeLoad callback
13590					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
13591					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
13592
13593					iL.loadImage(obj.URL, function(img) {
13594						//Trigger the onAfterLoad callback
13595						if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
13596						if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
13597
13598						var width = (img) ? img.width : 400,
13599							height = (img) ? img.height : 200;
13600
13601						holder.data({
13602							naturalWidth: width,
13603							naturalHeight: height
13604						});
13605
13606						$('div.ilightbox-container', holder).empty().append((img) ? '<img src="' + obj.URL + '" class="ilightbox-image" />' : '<span class="ilightbox-alert">' + opts.errors.loadImage + '</span>');
13607
13608						//Trigger the onRender callback
13609						if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
13610						if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
13611
13612						iL.configureHolder(obj, opt, holder);
13613					});
13614
13615					break;
13616
13617				case 'video':
13618					holder.data({
13619						naturalWidth: obj.options.width,
13620						naturalHeight: obj.options.height
13621					});
13622
13623					if (opt === 'current') {
13624						iL.addContent(holder, obj);
13625
13626						//Trigger the onRender callback
13627						if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
13628						if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
13629					} else {
13630						$('div.ilightbox-container', holder).empty();
13631					}
13632
13633					iL.configureHolder(obj, opt, holder);
13634
13635					break;
13636
13637				case 'iframe':
13638					//iL.showLoader();
13639					holder.data({
13640						naturalWidth: obj.options.width,
13641						naturalHeight: obj.options.height
13642					});
13643
13644					iL.configureHolder(obj, opt, holder);
13645
13646					if (opt === 'current') {
13647						var el = iL.addContent(holder, obj);
13648
13649						//Trigger the onRender callback
13650						if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
13651						if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
13652
13653						//Trigger the onBeforeLoad callback
13654						if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
13655						if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
13656
13657						el.bind('load', function() {
13658							//Trigger the onAfterLoad callback
13659							if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
13660							if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
13661
13662							//iL.hideLoader();
13663							el.unbind('load');
13664						});
13665					} else {
13666						$('div.ilightbox-container', holder).empty();
13667					}
13668
13669					break;
13670
13671				case 'inline':
13672					var el = $(obj.URL),
13673						content = iL.addContent(holder, obj),
13674						images = findImageInElement(holder);
13675
13676					holder.data({
13677						naturalWidth: (iL.items[item].options.width || el.outerWidth()),
13678						naturalHeight: (iL.items[item].options.height || el.outerHeight())
13679					});
13680					content.children().eq(0).show();
13681
13682					//Trigger the onRender callback
13683					if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
13684					if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
13685
13686					//Trigger the onBeforeLoad callback
13687					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
13688					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
13689
13690					iL.loadImage(images, function() {
13691						//Trigger the onAfterLoad callback
13692						if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
13693						if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
13694
13695						iL.configureHolder(obj, opt, holder);
13696					});
13697
13698					break;
13699
13700				case 'flash':
13701					var el = iL.addContent(holder, obj);
13702
13703					holder.data({
13704						naturalWidth: (iL.items[item].options.width || el.outerWidth()),
13705						naturalHeight: (iL.items[item].options.height || el.outerHeight())
13706					});
13707
13708					//Trigger the onRender callback
13709					if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
13710					if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
13711
13712					iL.configureHolder(obj, opt, holder);
13713
13714					break;
13715
13716				case 'ajax':
13717					var ajax = obj.options.ajax || {};
13718					//Trigger the onBeforeLoad callback
13719					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
13720					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
13721
13722					iL.showLoader();
13723					$.ajax({
13724						url: obj.URL || opts.ajaxSetup.url,
13725						data: ajax.data || null,
13726						dataType: ajax.dataType || "html",
13727						type: ajax.type || opts.ajaxSetup.type,
13728						cache: ajax.cache || opts.ajaxSetup.cache,
13729						crossDomain: ajax.crossDomain || opts.ajaxSetup.crossDomain,
13730						global: ajax.global || opts.ajaxSetup.global,
13731						ifModified: ajax.ifModified || opts.ajaxSetup.ifModified,
13732						username: ajax.username || opts.ajaxSetup.username,
13733						password: ajax.password || opts.ajaxSetup.password,
13734						beforeSend: ajax.beforeSend || opts.ajaxSetup.beforeSend,
13735						complete: ajax.complete || opts.ajaxSetup.complete,
13736						success: function(data, textStatus, jqXHR) {
13737							iL.hideLoader();
13738
13739							var el = $(data),
13740								container = $('div.ilightbox-container', holder),
13741								elWidth = iL.items[item].options.width || parseInt(el[0].getAttribute('width')),
13742								elHeight = iL.items[item].options.height || parseInt(el[0].getAttribute('height')),
13743								css = (el[0].getAttribute('width') && el[0].getAttribute('height')) ? {
13744									'overflow': 'hidden'
13745								} : {};
13746
13747							container.empty().append($('<div class="ilightbox-wrapper"></div>').css(css).html(el));
13748							holder.show().data({
13749								naturalWidth: (elWidth || container.outerWidth()),
13750								naturalHeight: (elHeight || container.outerHeight())
13751							}).hide();
13752
13753							//Trigger the onRender callback
13754							if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
13755							if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
13756
13757							var images = findImageInElement(holder);
13758							iL.loadImage(images, function() {
13759								//Trigger the onAfterLoad callback
13760								if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
13761								if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
13762
13763								iL.configureHolder(obj, opt, holder);
13764							});
13765
13766							opts.ajaxSetup.success(data, textStatus, jqXHR);
13767							if (typeof ajax.success == 'function') ajax.success(data, textStatus, jqXHR);
13768						},
13769						error: function(jqXHR, textStatus, errorThrown) {
13770							//Trigger the onAfterLoad callback
13771							if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
13772							if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
13773
13774							iL.hideLoader();
13775							$('div.ilightbox-container', holder).empty().append('<span class="ilightbox-alert">' + opts.errors.loadContents + '</span>');
13776							iL.configureHolder(obj, opt, holder);
13777
13778							opts.ajaxSetup.error(jqXHR, textStatus, errorThrown);
13779							if (typeof ajax.error == 'function') ajax.error(jqXHR, textStatus, errorThrown);
13780						}
13781					});
13782
13783					break;
13784
13785				case 'html':
13786					var object = obj.URL,
13787						el
13788					container = $('div.ilightbox-container', holder);
13789
13790					if (object[0].nodeName) el = object.clone();
13791					else {
13792						var dom = $(object);
13793						if (dom.selector) el = $('<div>' + dom + '</div>');
13794						else el = dom;
13795					}
13796
13797					var elWidth = iL.items[item].options.width || parseInt(el.attr('width')),
13798						elHeight = iL.items[item].options.height || parseInt(el.attr('height'));
13799
13800					iL.addContent(holder, obj);
13801
13802					el.appendTo(document.documentElement).hide();
13803
13804					//Trigger the onRender callback
13805					if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
13806					if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
13807
13808					var images = findImageInElement(holder);
13809
13810					//Trigger the onBeforeLoad callback
13811					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
13812					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
13813
13814					iL.loadImage(images, function() {
13815						//Trigger the onAfterLoad callback
13816						if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
13817						if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
13818
13819						holder.show().data({
13820							naturalWidth: (elWidth || container.outerWidth()),
13821							naturalHeight: (elHeight || container.outerHeight())
13822						}).hide();
13823						el.remove();
13824
13825						iL.configureHolder(obj, opt, holder);
13826					});
13827
13828					break;
13829			}
13830		},
13831
13832		configureHolder: function(obj, opt, holder) {
13833			var iL = this,
13834				vars = iL.vars,
13835				opts = iL.options;
13836
13837			if (opt != "current")(opt == "next") ? holder.addClass('ilightbox-next') : holder.addClass('ilightbox-prev');
13838
13839			if (opt == "current")
13840				var item = vars.current;
13841			else if (opt == "next")
13842				var opacity = opts.styles.nextOpacity,
13843					item = vars.next;
13844			else
13845				var opacity = opts.styles.prevOpacity,
13846					item = vars.prev;
13847
13848			var api = {
13849				element: holder,
13850				position: item
13851			};
13852
13853			iL.items[item].options.width = iL.items[item].options.width || 0,
13854			iL.items[item].options.height = iL.items[item].options.height || 0;
13855
13856			if (opt == "current") {
13857				if (opts.show.effect) holder.css(transform, gpuAcceleration).fadeIn(obj.speed, function() {
13858					holder.css(transform, '');
13859					if (obj.caption) {
13860						iL.setCaption(obj, holder);
13861						var caption = $('div.ilightbox-caption', holder),
13862							percent = parseInt((caption.outerHeight() / holder.outerHeight()) * 100);
13863						if (opts.caption.start & percent <= 50) caption.fadeIn(opts.effects.fade
13863Speed);
13864					}
13865
13866					var social = obj.options.social;
13867					if (social) {
13868						iL.setSocial(social, obj.URL, holder);
13869						if (opts.social.start) $('div.ilightbox-social', holder).fadeIn(opts.effects.fadeSpeed);
13870					}
13871
13872					//Generate thumbnails
13873					iL.generateThumbnails();
13874
13875					//Trigger the onShow callback
13876					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
13877					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
13878				});
13879				else {
13880					holder.show();
13881
13882					//Generate thumbnails
13883					iL.generateThumbnails();
13884
13885					//Trigger the onShow callback
13886					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
13887					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
13888				}
13889			} else {
13890				if (opts.show.effect) holder.fadeTo(obj.speed, opacity, function() {
13891					if (opt == "next") vars.nextLock = false;
13892					else vars.prevLock = false;
13893
13894					//Generate thumbnails
13895					iL.generateThumbnails();
13896
13897					//Trigger the onShow callback
13898					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
13899					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
13900				});
13901				else {
13902					holder.css({
13903						opacity: opacity
13904					}).show();
13905					if (opt == "next") vars.nextLock = false;
13906					else vars.prevLock = false;
13907
13908					//Generate thumbnails
13909					iL.generateThumbnails();
13910
13911					//Trigger the onShow callback
13912					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
13913					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
13914				}
13915			}
13916
13917			setTimeout(function() {
13918				iL.repositionPhoto();
13919			}, 0);
13920		},
13921
13922		generateBoxes: function() {
13923			var iL = this,
13924				vars = iL.vars,
13925				opts = iL.options;
13926
13927			if (opts.infinite && vars.total >= 3) {
13928				if (vars.current == vars.total - 1) vars.next = 0;
13929				if (vars.current == 0) vars.prev = vars.total - 1;
13930			} else opts.infinite = false;
13931
13932			//UNCODE addition
13933			if ( typeof iL.items[vars.current] == 'undefined' )
13934				vars.current = 0;
13935
13936			iL.loadContent(iL.items[vars.current], 'current', opts.show.speed);
13937
13938			if (iL.items[vars.next]) iL.loadContent(iL.items[vars.next], 'next', opts.show.speed);
13939			if (iL.items[vars.prev]) iL.loadContent(iL.items[vars.prev], 'prev', opts.show.speed);
13940		},
13941
13942		generateThumbnails: function() {
13943			var iL = this,
13944				vars = iL.vars,
13945				opts = iL.options,
13946				timeOut = null;
13947
13948			if (vars.thumbs && !iL.vars.dontGenerateThumbs) {
13949				var thumbnails = vars.thumbnails,
13950					container = $('div.ilightbox-thumbnails-container', thumbnails),
13951					grid = $('div.ilightbox-thumbnails-grid', container),
13952					i = 0;
13953
13954				grid.removeAttr('style').empty();
13955
13956				$.each(iL.items, function(key, val) {
13957					var isActive = (vars.current == key) ? 'ilightbox-active' : '',
13958						opacity = (vars.current == key) ? opts.thumbnails.activeOpacity : opts.thumbnails.normalOpacity,
13959						thumb = val.options.thumbnail,
13960						thumbnail = $('<div class="ilightbox-thumbnail"></div>'),
13961						icon = $('<div class="ilightbox-thumbnail-icon"></div>');
13962
13963					thumbnail.css({
13964						opacity: 0
13965					}).addClass(isActive);
13966
13967					if ((val.type == "video" || val.type == "flash") && typeof val.options.icon == 'undefined') {
13968						icon.addClass('ilightbox-thumbnail-video');
13969						thumbnail.append(icon);
13970					} else if (val.options.icon) {
13971						icon.addClass('ilightbox-thumbnail-' + val.options.icon);
13972						thumbnail.append(icon);
13973					}
13974
13975					if (thumb) iL.loadImage(thumb, function(img) {
13976						i++;
13977						if (img) thumbnail.data({
13978							naturalWidth: img.width,
13979							naturalHeight: img.height
13980						}).append('<img src="' + thumb + '" border="0" />');
13981						else thumbnail.data({
13982							naturalWidth: opts.thumbnails.maxWidth,
13983							naturalHeight: opts.thumbnails.maxHeight
13984						});
13985
13986						clearTimeout(timeOut);
13987						timeOut = setTimeout(function() {
13988							iL.positionThumbnails(thumbnails, container, grid);
13989						}, 20);
13990						setTimeout(function() {
13991							thumbnail.fadeTo(opts.effects.loadedFadeSpeed, opacity);
13992						}, i * 20);
13993					});
13994
13995					grid.append(thumbnail);
13996				});
13997				iL.vars.dontGenerateThumbs = true;
13998			}
13999		},
14000
14001		positionThumbnails: function(thumbnails, container, grid) {
14002			var iL = this,
14003				vars = iL.vars,
14004				opts = iL.options,
14005				viewport = getViewport(),
14006				path = opts.path.toLowerCase();
14007
14008			if (!thumbnails) thumbnails = vars.thumbnails;
14009			if (!container) container = $('div.ilightbox-thumbnails-container', thumbnails);
14010			if (!grid) grid = $('div.ilightbox-thumbnails-grid', container);
14011
14012			var thumbs = $('.ilightbox-thumbnail', grid),
14013				widthAvail = (path == 'horizontal') ? viewport.width - opts.styles.pageOffsetX : thumbs.eq(0).outerWidth() - opts.styles.pageOffsetX,
14014				heightAvail = (path == 'horizontal') ? thumbs.eq(0).outerHeight() - opts.styles.pageOffsetY : viewport.height - opts.styles.pageOffsetY,
14015				gridWidth = (path == 'horizontal') ? 0 : widthAvail,
14016				gridHeight = (path == 'horizontal') ? heightAvail : 0,
14017				active = $('.ilightbox-active', grid),
14018				gridCss = {},
14019				css = {};
14020
14021			if (arguments.length < 3) {
14022				thumbs.css({
14023					opacity: opts.thumbnails.normalOpacity
14024				});
14025				active.css({
14026					opacity: opts.thumbnails.activeOpacity
14027				});
14028			}
14029
14030			thumbs.each(function(i) {
14031				var t = $(this),
14032					data = t.data(),
14033					width = (path == 'horizontal') ? 0 : opts.thumbnails.maxWidth;
14034				height = (path == 'horizontal') ? opts.thumbnails.maxHeight : 0;
14035				dims = iL.getNewDimenstions(width, height, data.naturalWidth, data.naturalHeight, true);
14036
14037				t.css({
14038					width: dims.width,
14039					height: dims.height
14040				});
14041				if (path == 'horizontal') t.css({
14042					'float': 'left'
14043				});
14044
14045				(path == 'horizontal') ? (
14046					gridWidth += t.outerWidth()
14047				) : (
14048					gridHeight += t.outerHeight()
14049				);
14050			});
14051
14052			gridCss = {
14053				width: gridWidth,
14054				height: gridHeight
14055			};
14056
14057			grid.css(gridCss);
14058
14059			gridCss = {};
14060
14061			var gridOffset = grid.offset(),
14062				activeOffset = (active.length) ? active.offset() : {
14063					top: parseInt(heightAvail / 2),
14064					left: parseInt(widthAvail / 2)
14065				};
14066
14067			gridOffset.top = (gridOffset.top - $doc.scrollTop()),
14068				gridOffset.left = (gridOffset.left - $doc.scrollLeft()),
14069				activeOffset.top = (activeOffset.top - gridOffset.top - $doc.scrollTop()),
14070				activeOffset.left = (activeOffset.left - gridOffset.left - $doc.scrollLeft());
14071
14072			(path == 'horizontal') ? (
14073				gridCss.top = 0,
14074				gridCss.left = parseInt((widthAvail / 2) - activeOffset.left - (active.outerWidth() / 2))
14075			) : (
14076				gridCss.top = parseInt(((heightAvail / 2) - activeOffset.top - (active.outerHeight() / 2))),
14077				gridCss.left = 0
14078			);
14079
14080			if (arguments.length < 3) grid.stop().animate(gridCss, opts.effects.repositionSpeed, 'easeOutCirc');
14081			else grid.css(gridCss);
14082		},
14083
14084		loadImage: function(image, callback) {
14085			if (!$.isArray(image)) image = [image];
14086
14087			var iL = this,
14088				length = image.length;
14089
14090			if (length > 0) {
14091				iL.showLoader();
14092				$.each(image, function(index, value) {
14093					var img = new Image();
14094					img.onload = function() {
14095						length -= 1;
14096						if (length == 0) {
14097							iL.hideLoader();
14098							callback(img);
14099						}
14100					};
14101					img.onerror = img.onabort = function() {
14102						length -= 1;
14103						if (length == 0) {
14104							iL.hideLoader();
14105							callback(false);
14106						}
14107					};
14108					img.src = image[index];
14109				});
14110			} else callback(false);
14111		},
14112
14113		patchItemsEvents: function() {
14114			var iL = this,
14115				vars = iL.vars,
14116				clickEvent = ishybrid ? "itap.iL click.iL" : supportTouch ? "itap.iL" : "click.iL",
14117				vEvent = ishybrid ? "click.iL itap.iL" : supportTouch ? "click.iL" : "itap.iL";
14118
14119			if (iL.context && iL.selector) {
14120				var $items = $(iL.selector, iL.context);
14121
14122				$(iL.context).on(clickEvent, iL.selector, function() {
14123					var $this = $(this),
14124						//UNCODE addition
14125						key = typeof $(this).data('lb-index') !== '' && $(this).closest('.owl-item').length ? $(this).data('lb-index') : $items.index($this);
14126					if (UNCODE.isMobile) {
14127						var isCarousel = $this.closest('.owl-carousel');
14128						if (isCarousel.length) {
14129							if (isCarousel.hasClass('owl-translating')) return false;
14130						}
14131					}
14132
14133					vars.current = key;
14134					vars.next = iL.items[key + 1] ? key + 1 : null;
14135					vars.prev = iL.items[key - 1] ? key - 1 : null;
14136
14137					//UNCODE addition
14138					if ( vars.BODY.hasClass('fp-slide-scrolling') )
14139						return false;
14140
14141					iL.addContents();
14142					iL.patchEvents();
14143
14144					return false;
14145				}).on(vEvent, iL.selector, function() {
14146					return false;
14147				});
14148			} else
14149				$.each(iL.itemsObject, function(key, val) {
14150					val.on(clickEvent, function() {
14151						vars.current = key;
14152						vars.next = iL.items[key + 1] ? key + 1 : null;
14153						vars.prev = iL.items[key - 1] ? key - 1 : null;
14154
14155						iL.addContents();
14156						iL.patchEvents();
14157
14158						return false;
14159					}).on(vEvent, function() {
14160						return false;
14161					});
14162				});
14163		},
14164
14165		dispatchItemsEvents: function() {
14166			var iL = this,
14167				vars = iL.vars,
14168				opts = iL.options;
14169
14170			if (iL.context && iL.selector)
14171				$(iL.context).off('.iL', iL.selector);
14172			else
14173				$.each(iL.itemsObject, function(key, val) {
14174					val.off('.iL');
14175				});
14176		},
14177
14178		refresh: function() {
14179			var iL = this;
14180
14181			iL.dispatchItemsEvents();
14182			iL.attachItems();
14183			iL.normalizeItems();
14184			iL.patchItemsEvents();
14185		},
14186
14187		patchEvents: function() {
14188			var iL = this,
14189				vars = iL.vars,
14190				opts = iL.options,
14191				path = opts.path.toLowerCase(),
14192				holders = $('.ilightbox-holder'),
14193				fullscreenEvent = fullScreenApi.fullScreenEventName + '.iLightBox',
14194				durationThreshold = 1000,
14195				horizontalDistanceThreshold =
14196				verticalDistanceThreshold = 100,
14197				buttonsArray = [vars.nextButton[0], vars.prevButton[0], vars.nextButton[0].firstChild, vars.prevButton[0].firstChild];
14198
14199			$win.bind('resize.iLightBox', function() {
14200				var viewport = getViewport();
14201
14202				if (opts.mobileOptimizer && !opts.innerToolbar) vars.isMobile = viewport.width <= vars.mobileMaxWidth;
14203				vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile');
14204
14205				iL.repositionPhoto(null);
14206				if (supportTouch) {
14207					clearTimeout(vars.setTime);
14208					vars.setTime = setTimeout(function() {
14209						var scrollTop = getScrollXY().y;
14210						window.scrollTo(0, scrollTop - 30);
14211						window.scrollTo(0, scrollTop + 30);
14212						window.scrollTo(0, scrollTop);
14213					}, 2000);
14214				}
14215				if (vars.thumbs) iL.positionThumbnails();
14216			}).bind('keydown.iLightBox', function(event) {
14217				if (opts.controls.keyboard) {
14218					switch (event.keyCode) {
14219						case 13:
14220							if (event.shiftKey && opts.keyboard.shift_enter) iL.fullScreenAction();
14221							break;
14222						case 27:
14223							if (opts.keyboard.esc) iL.closeAction();
14224							break;
14225						case 37:
14226							if (opts.keyboard.left && !vars.lockKey) iL.moveTo('prev');
14227							break;
14228						case 38:
14229							if (opts.keyboard.up && !vars.lockKey) iL.moveTo('prev');
14230							break;
14231						case 39:
14232							if (opts.keyboard.right && !vars.lockKey) iL.moveTo('next');
14233							break;
14234						case 40:
14235							if (opts.keyboard.down && !vars.lockKey) iL.moveTo('next');
14236							break;
14237					}
14238				}
14239			});
14240
14241			if (fullScreenApi.supportsFullScreen) $win.bind(fullscreenEvent, function() {
14242				iL.doFullscreen();
14243			});
14244
14245			var holderEventsArr = [opts.caption.show + '.iLightBox', opts.caption.hide + '.iLightBox', opts.social.show + '.iLightBox', opts.social.hide + '.iLightBox'].filter(function(e, i, arr) {
14246					return arr.lastIndexOf(e) === i;
14247				}),
14248				holderEvents = "";
14249
14250			$.each(holderEventsArr, function(key, val) {
14251				if (key != 0) holderEvents += ' ';
14252				holderEvents += val;
14253			});
14254
14255			$doc.on(clickEvent, '.ilightbox-overlay', function() {
14256				if (opts.overlay.blur) iL.closeAction();
14257			}).on(clickEvent, '.ilightbox-next, .ilightbox-next-button', function() {
14258				iL.moveTo('next');
14259			}).on(clickEvent, '.ilightbox-prev, .ilightbox-prev-button', function() {
14260				iL.moveTo('prev');
14261			}).on(clickEvent, '.ilightbox-thumbnail', function() {
14262				var t = $(this),
14263					thumbs = $('.ilightbox-thumbnail', vars.thumbnails),
14264					index = thumbs.index(t);
14265
14266				if (index != vars.current) iL.goTo(index);
14267			}).on(holderEvents, '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) {
14268				var caption = $('div.ilightbox-caption', vars.holder),
14269					social = $('div.ilightbox-social', vars.holder),
14270					fadeSpeed = opts.effects.fadeSpeed;
14271
14272				if (vars.nextLock || vars.prevLock) {
14273					if (e.type == opts.caption.show && !caption.is(':visible')) caption.fadeIn(fadeSpeed);
14274					else if (e.type == opts.caption.hide && caption.is(':visible')) caption.fadeOut(fadeSpeed);
14275
14276					if (e.type == opts.social.show && !social.is(':visible')) social.fadeIn(fadeSpeed);
14277					else if (e.type == opts.social.hide && social.is(':visible')) social.fadeOut(fadeSpeed);
14278				} else {
14279					if (e.type == opts.caption.show && !caption.is(':visible')) caption.stop().fadeIn(fadeSpeed);
14280					else if (e.type == opts.caption.hide && caption.is(':visible')) caption.stop().fadeOut(fadeSpeed);
14281
14282					if (e.type == opts.social.show && !social.is(':visible')) social.stop().fadeIn(fadeSpeed);
14283					else if (e.type == opts.social.hide && social.is(':visible')) social.stop().fadeOut(fadeSpeed);
14284				}
14285			}).on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-wrapper', function(e) {
14286				if (e.type == 'mouseenter') vars.lockWheel = true;
14287				else vars.lockWheel = false;
14288			}).on(clickEvent, '.ilightbox-toolbar a.ilightbox-close, .ilightbox-toolbar a.ilightbox-fullscreen, .ilightbox-toolbar a.ilightbox-play, .ilightbox-toolbar a.ilightbox-pause', function() {
14289				var t = $(this);
14290
14291				if (t.hasClass('ilightbox-fullscreen')) iL.fullScreenAction();
14292				else if (t.hasClass('ilightbox-play')) {
14293					iL.resume();
14294					t.addClass('ilightbox-pause').removeClass('ilightbox-play');
14295				} else if (t.hasClass('ilightbox-pause')) {
14296					iL.pause();
14297					t.addClass('ilightbox-play').removeClass('ilightbox-pause');
14298				} else iL.closeAction();
14299			}).on(touchMoveEvent, '.ilightbox-overlay, .ilightbox-thumbnails-container', function(e) {
14300				// prevent scrolling
14301				e.preventDefault();
14302			});
14303
14304			function mouseMoveHandler(e) {
14305				if (!vars.isMobile) {
14306					if (!vars.mouseID) {
14307						vars.hideableElements.show();
14308					}
14309
14310					vars.mouseID = clearTimeout(vars.mouseID);
14311
14312					if (buttonsArray.indexOf(e.target) === -1)
14313						vars.mouseID = setTimeout(function() {
14314							vars.hideableElements.hide();
14315							vars.mouseID = clearTimeout(vars.mouseID);
14316						}, 3000);
14317				}
14318			}
14319
14320			if (opts.controls.arrows && !supportTouch) $doc.on('mousemove.iLightBox', mouseMoveHandler);
14321
14322			if (opts.controls.slideshow && opts.slideshow.pauseOnHover) $doc.on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) {
14323				if (e.type == 'mouseenter' && vars.cycleID) iL.pause();
14324				else if (e.type == 'mouseleave' && vars.isPaused) iL.resume();
14325			});
14326
14327			var switchers = $('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails'),
14328				delay = false;
14329
14330			if (opts.controls.mousewheel) switchers.on('mousewheel.iLightBox', function(event, delta) {
14331				event.preventDefault();
14332				if (delay) return;
14333				delay = true;
14334				if (!vars.lockWheel) {
14335					event.preventDefault();
14336					if (delta < 0) {
14337						iL.moveTo('next');
14338					} else if (delta > 0) {
14339						iL.moveTo('prev');
14340					}
14341				}
14342				setTimeout(function(){
14343					delay = false;
14344				}, 2000);
14345			});
14346
14347			if (opts.controls.swipe) holders.on(touchStartEvent, function(event) {
14348				if (vars.nextLock || vars.prevLock || vars.total == 1 || vars.lockSwipe) return;
14349
14350				vars.BODY.addClass('ilightbox-closedhand');
14351
14352				var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event,
14353					scrollTop = $doc.scrollTop(),
14354					scrollLeft = $doc.scrollLeft(),
14355					offsets = [
14356						holders.eq(0).offset(),
14357						holders.eq(1).offset(),
14358						holders.eq(2).offset()
14359					],
14360					offSet = [{
14361						top: offsets[0].top - scrollTop,
14362						left: offsets[0].left - scrollLeft
14363					}, {
14364						top: offsets[1].top - scrollTop,
14365						left: offsets[1].left - scrollLeft
14366					}, {
14367						top: offsets[2].top - scrollTop,
14368						left: offsets[2].left - scrollLeft
14369					}],
14370					start = {
14371						time: (new Date()).getTime(),
14372						coords: [data.pageX - scrollLeft, data.pageY - scrollTop]
14373					},
14374					stop;
14375
14376				function moveEachHandler(i) {
14377					var t = $(this),
14378						offset = offSet[i],
14379						scroll = [(start.coords[0] - stop.coords[0]), (start.coords[1] - stop.coords[1])];
14380
14381					t[0].style[path == "horizontal" ? 'left' : 'top'] = (path == "horizontal" ? offset.left - scroll[0] : offset.top - scroll[1]) + 'px';
14382				}
14383
14384				function moveHandler(event) {
14385
14386					if (!start) return;
14387
14388					var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event;
14389
14390					stop = {
14391						time: (new Date()).getTime(),
14392						coords: [data.pageX - scrollLeft, data.pageY - scrollTop]
14393					};
14394
14395					holders.each(moveEachHandler);
14396
14397					// prevent scrolling
14398					event.preventDefault();
14399				}
14400
14401				function repositionHolders() {
14402					holders.each(function() {
14403						var t = $(this),
14404							offset = t.data('offset') || {
14405								top: t.offset().top - scrollTop,
14406								left: t.offset().left - scrollLeft
14407							},
14408							top = offset.top,
14409							left = offset.left;
14410
14411						t.css(transform, gpuAcceleration).stop().animate({
14412							top: top,
14413							left: left
14414						}, 500, 'easeOutCirc', function() {
14415							t.css(transform, '');
14416						});
14417					});
14418				}
14419
14420				holders.bind(touchMoveEvent, moveHandler);
14421				$doc.one(touchStopEvent, function(event) {
14422					holders.unbind(touchMoveEvent, moveHandler);
14423
14424					vars.BODY.removeClass('ilightbox-closedhand');
14425
14426					if (start && stop) {
14427						if (path == "horizontal" && stop.time - start.time < durationThreshold && abs(start.coords[0] - stop.coords[0]) > horizontalDistanceThreshold && abs(start.coords[1] - stop.coords[1]) < verticalDistanceThreshold) {
14428							if (start.coords[0] > stop.coords[0]) {
14429								if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders();
14430								else {
14431									vars.isSwipe = true;
14432									iL.moveTo('next');
14433								}
14434							} else {
14435								if (vars.current == 0 && !opts.infinite) repositionHolders();
14436								else {
14437									vars.isSwipe = true;
14438									iL.moveTo('prev');
14439								}
14440							}
14441						} 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) {
14442							if (start.coords[1] > stop.coords[1]) {
14443								if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders();
14444								else {
14445									vars.isSwipe = true;
14446									iL.moveTo('next');
14447								}
14448							} else {
14449								if (vars.current == 0 && !opts.infinite) repositionHolders();
14450								else {
14451									vars.isSwipe = true;
14452									iL.moveTo('prev');
14453								}
14454							}
14455						} else repositionHolders();
14456					}
14457					start = stop = undefined;
14458				});
14459			});
14460
14461		},
14462
14463		goTo: function(index) {
14464			var iL = this,
14465				vars = iL.vars,
14466				opts = iL.options,
14467				diff = (index - vars.current);
14468
14469			if (opts.infinite) {
14470				if (index == vars.total - 1 && vars.current == 0) diff = -1;
14471				if (vars.current == vars.total - 1 && index == 0) diff = 1;
14472			}
14473
14474			if (diff == 1) iL.moveTo('next');
14475			else if (diff == -1) iL.moveTo('prev');
14476			else {
14477
14478				if (vars.nextLock || vars.prevLock) return false;
14479
14480				//Trigger the onBeforeChange callback
14481				if (typeof opts.callback.onBeforeChange == 'function') opts.callback.onBeforeChange.call(iL, iL.ui);
14482
14483				if (opts.linkId) {
14484					vars.hashLock = true;
14485					window.location.hash = opts.linkId + '/' + index;
14486				}
14487
14488				if (iL.items[index]) {
14489					if (!iL.items[index].options.mousewheel) vars.lockWheel = true;
14490					else iL.vars.lockWheel = false;
14491
14492					if (!iL.items[index].options.swipe) vars.lockSwipe = true;
14493					else vars.lockSwipe = false;
14494				}
14495
14496				$.each([vars.holder, vars.nextPhoto, vars.prevPhoto], function(key, val) {
14497					val.css(transform, gpuAcceleration).fadeOut(opts.effects.loadedFadeSpeed);
14498				});
14499
14500				vars.current = index;
14501				vars.next = index + 1;
14502				vars.prev = index - 1;
14503
14504				iL.createUI();
14505
14506				setTimeout(function() {
14507					iL.generateBoxes();
14508				}, opts.effects.loadedFadeSpeed + 50);
14509
14510				$('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(index).addClass('ilightbox-active');
14511				iL.positionThumbnails();
14512
14513				if (opts.linkId) setTimeout(function() {
14514					vars.hashLock = false;
14515				}, 55);
14516
14517				// Configure arrow buttons
14518				if (!opts.infinite) {
14519					vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
14520
14521					if (vars.current == 0) {
14522						vars.prevButton.add(vars.innerPrevButton).addClass('disabled');
14523					}
14524					if (vars.current >= vars.total - 1) {
14525						vars.nextButton.add(vars.innerNextButton).addClass('disabled');
14526					}
14527				}
14528
14529				// Reset next cycle timeout
14530				iL.resetCycle();
14531
14532				//Trigger the onAfterChange callback
14533				if (typeof opts.callback.onAfterChange == 'function') opts.callback.onAfterChange.call(iL, iL.ui);
14534			}
14535		},
14536
14537		moveTo: function(side) {
14538			var iL = this,
14539				vars = iL.vars,
14540				opts = iL.options,
14541				path = opts.path.toLowerCase(),
14542				viewport = getViewport(),
14543				switchSpeed = opts.effects.switchSpeed;
14544
14545			if (vars.nextLock || vars.prevLock) return false;
14546			else {
14547
14548				var item = (side == "next") ? vars.next : vars.prev;
14549
14550				if (opts.linkId) {
14551					vars.hashLock = true;
14552					window.location.hash = opts.linkId + '/' + item;
14553				}
14554
14555				if (side == "next") {
14556					if (!iL.items[item]) return false;
14557					var firstHolder = vars.nextPhoto,
14558						secondHolder = vars.holder,
14559						lastHolder = vars.prevPhoto,
14560						firstClass = 'ilightbox-prev',
14561						secondClass = 'ilightbox-next';
14562				} else if (side == "prev") {
14563					if (!iL.items[item]) return false;
14564					var firstHolder = vars.prevPhoto,
14565						secondHolder = vars.holder,
14566						lastHolder = vars.nextPhoto,
14567						firstClass = 'ilightbox-next',
14568						secondClass = 'ilightbox-prev';
14569				}
14570
14571				//Trigger the onBeforeChange callback
14572				if (typeof opts.callback.onBeforeChange == 'function')
14573					opts.callback.onBeforeChange.call(iL, iL.ui);
14574
14575				(side == "next") ? vars.nextLock = true: vars.prevLock = true;
14576
14577				var captionFirst = $('div.ilightbox-caption', secondHolder),
14578					socialFirst = $('div.ilightbox-social', secondHolder);
14579
14580				if (captionFirst.length)
14581					captionFirst.stop().fadeOut(switchSpeed, function() {
14582						$(this).remove();
14583					});
14584				if (socialFirst.length)
14585					socialFirst.stop().fadeOut(switchSpeed, function() {
14586						$(this).remove();
14587					});
14588
14589				if (iL.items[item].caption) {
14590					iL.setCaption(iL.items[item], firstHolder);
14591					var caption = $('div.ilightbox-caption', firstHolder),
14592						percent = parseInt((caption.outerHeight() / firstHolder.outerHeight()) * 100);
14593					if (opts.caption.start && percent <= 50) caption.fadeIn(switchSpeed);
14594				}
14595
14596				var social = iL.items[item].options.social;
14597				if (social) {
14598					iL.setSocial(social, iL.items[item].URL, firstHolder);
14599					if (opts.social.start) $('div.ilightbox-social', firstHolder).fadeIn(opts.effects.fadeSpeed);
14600				}
14601
14602				$.each([firstHolder, secondHolder, lastHolder], function(key, val) {
14603					val.removeClass('ilightbox-next ilightbox-prev');
14604				});
14605
14606				var firstOffset = firstHolder.data('offset'),
14607					winW = (viewport.width - (opts.styles.pageOffsetX)),
14608					winH = (viewport.height - (opts.styles.pageOffsetY)),
14609					width = firstOffset.newDims.width,
14610					height = firstOffset.newDims.height,
14611					thumbsOffset = firstOffset.thumbsOffset,
14612					diff = firstOffset.diff,
14613					top = parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)),
14614					left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2));
14615
14616				var secondOffset = secondHolder.data('offset'),
14617					object = secondOffset.object;
14618
14619				/*if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) {
14620					var objRatio = width / height;
14621					height = height - vars.captionHeight;
14622					width = height * objRatio;
14623					top = path == 'horizontal' ? parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)) : top,
14624					left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2));
14625				}*/
14626
14627				firstHolder.show().css(transform, gpuAcceleration).animate({
14628					top: top,
14629					left: left,
14630					opacity: 1
14631				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() {
14632					firstHolder.css(transform, '');
14633				});
14634
14635				$('div.ilightbox-container', firstHolder).animate({
14636					width: width,
14637					height: height
14638				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc');
14639
14640				diff = secondOffset.diff;
14641
14642				width = secondOffset.newDims.width,
14643					height = secondOffset.newDims.height;
14644
14645				width = parseInt(width * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']),
14646					height = parseInt(height * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']),
14647					top = (path == 'horizontal') ? parseInt((winH / 2) - object.offsetY - (height / 2) - diff.H - (thumbsOffset.H / 2)) : parseInt(winH - object.offsetX - diff.H - (thumbsOffset.H / 2));
14648
14649				if (side == 'prev')
14650					left = (path == 'horizontal') ? parseInt(winW - object.offsetX - diff.W - (thumbsOffset.W / 2)) : parseInt((winW / 2) - (width / 2) - diff.W - object.offsetY - (thumbsOffset.W / 2));
14651				else {
14652					top = (path == 'horizontal') ? top : parseInt(object.offsetX - diff.H - height - (thumbsOffset.H / 2)),
14653					left = (path == 'horizontal') ? parseInt(object.offsetX - diff.W - width - (thumbsOffset.W / 2)) : parseInt((winW / 2) - object.offsetY - (width / 2) - diff.W - (thumbsOffset.W / 2));
14654				}
14655
14656				/*if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) {
14657					var objRatio = width / height;
14658					height = height - vars.captionHeight;
14659					width = height * objRatio;
14660					top = path == 'horizontal' ? parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)) : top;
14661				}*/
14662
14663				$('div.ilightbox-container', secondHolder).animate({
14664					width: width,
14665					height: height
14666				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc');
14667
14668				secondHolder.addClass(firstClass).css(transform, gpuAcceleration).animate({
14669					top: top,
14670					left: left,
14671					opacity: opts.styles.prevOpacity,
14672				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() {
14673					secondHolder.css(transform, '');
14674
14675					$('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(item).addClass('ilightbox-active');
14676					iL.positionThumbnails();
14677
14678					if (iL.items[item]) {
14679						if (!iL.items[item].options.mousewheel) vars.lockWheel = true;
14680						else vars.lockWheel = false;
14681
14682						if (!iL.items[item].options.swipe) vars.lockSwipe = true;
14683						else vars.lockSwipe = false;
14684					}
14685
14686					vars.isSwipe = false;
14687
14688					// Remove iframe & video from previous slide
14689					if (['iframe', 'video'].indexOf(iL.items[vars.current].type) !== -1) {
14690						$('div.ilightbox-container', secondHolder).empty();
14691					}
14692
14693					if (side == "next") {
14694						vars.nextPhoto = lastHolder,
14695							vars.prevPhoto = secondHolder,
14696							vars.holder = firstHolder;
14697
14698						vars.nextPhoto.hide();
14699
14700						vars.next = vars.next + 1,
14701							vars.prev = vars.current,
14702							vars.current = vars.current + 1;
14703
14704						if (opts.infinite) {
14705							if (vars.current > vars.total - 1) vars.current = 0;
14706							if (vars.current == vars.total - 1) vars.next = 0;
14707							if (vars.current == 0) vars.prev = vars.total - 1;
14708						}
14709
14710						iL.createUI();
14711
14712						if (!iL.items[vars.next])
14713							vars.nextLock = false;
14714						else
14715							iL.loadContent(iL.items[vars.next], 'next');
14716					} else {
14717						vars.prevPhoto = lastHolder;
14718						vars.nextPhoto = secondHolder;
14719						vars.holder = firstHolder;
14720
14721						vars.prevPhoto.hide();
14722
14723						vars.next = vars.current;
14724						vars.current = vars.prev;
14725						vars.prev = vars.current - 1;
14726
14727						if (opts.infinite) {
14728							if (vars.current == vars.total - 1) vars.next = 0;
14729							if (vars.current == 0) vars.prev = vars.total - 1;
14730						}
14731
14732						iL.createUI();
14733
14734						if (!iL.items[vars.prev])
14735							vars.prevLock = false;
14736						else
14737							iL.loadContent(iL.items[vars.prev], 'prev');
14738					}
14739
14740					// Add iframe & video content for current slide
14741					if (['iframe', 'video'].indexOf(iL.items[vars.current].type) !== -1) {
14742						iL.loadContent(iL.items[vars.current], 'current');
14743					}
14744
14745					if (opts.linkId) setTimeout(function() {
14746						vars.hashLock = false;
14747					}, 55);
14748
14749					// Configure arrow buttons
14750					if (!opts.infinite) {
14751						vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
14752
14753						if (vars.current == 0)
14754							vars.prevButton.add(vars.innerPrevButton).addClass('disabled');
14755						if (vars.current >= vars.total - 1)
14756							vars.nextButton.add(vars.innerNextButton).addClass('disabled');
14757					}
14758
14759					iL.repositionPhoto();
14760
14761					// Reset next cycle timeout
14762					iL.resetCycle();
14763
14764					//Trigger the onAfterChange callback
14765					if (typeof opts.callback.onAfterChange == 'function')
14766						opts.callback.onAfterChange.call(iL, iL.ui);
14767				});
14768
14769				top = (path == 'horizontal') ? getPixel(lastHolder, 'top') : ((side == "next") ? parseInt(-(winH / 2) - lastHolder.outerHeight()) : parseInt(top * 2)),
14770					left = (path == 'horizontal') ? ((side == "next") ? parseInt(-(winW / 2) - lastHolder.outerWidth()) : parseInt(left * 2)) : getPixel(lastHolder, 'left');
14771
14772				lastHolder.css(transform, gpuAcceleration).animate({
14773					top: top,
14774					left: left,
14775					opacity: opts.styles.nextOpacity
14776				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() {
14777					lastHolder.css(transform, '');
14778				}).addClass(secondClass);
14779			}
14780		},
14781
14782		setCaption: function(obj, target) {
14783			var iL = this,
14784				caption = $('<div class="ilightbox-caption"></div>');
14785
14786			if (obj.caption) {
14787				caption.html(obj.caption);
14788				$('div.ilightbox-container', target).append(caption);
14789			}
14790		},
14791
14792		normalizeSocial: function(obj, url) {
14793			var iL = this,
14794				vars = iL.vars,
14795				opts = iL.options,
14796				baseURL = window.location.href;
14797
14798			$.each(obj, function(key, value) {
14799				if (!value)
14800					return true;
14801
14802				var item = key.toLowerCase(),
14803					source, text;
14804
14805				switch (item) {
14806					case 'facebook':
14807						source = "http://www.facebook.com/share.php?v=4&src=bm&u={URL}",
14808							text = "Share on Facebook";
14809						break;
14810					case 'twitter':
14811						source = "http://twitter.com/home?status={URL}",
14812							text = "Share on Twitter";
14813						break;
14814					case 'digg':
14815						source = "http://digg.com/submit?phase=2&url={URL}",
14816							text = "Share on Digg";
14817						break;
14818					case 'reddit':
14819						source = "http://reddit.com/submit?url={URL}",
14820							text = "Share on reddit";
14821						break;
14822				}
14823
14824				obj[key] = {
14825					URL: value.URL && absolutizeURI(baseURL, value.URL) || opts.linkId && window.location.href || typeof url !== 'string' && baseURL || url && absolutizeURI(baseURL, url) || baseURL,
14826					source: value.source || source || value.URL && absolutizeURI(baseURL, value.URL) || url && absolutizeURI(baseURL, url),
14827					text: value.text || text || "Share on " + key,
14828					width: (typeof(value.width) != 'undefined' && !isNaN(value.width)) ? parseInt(value.width) : 640,
14829					height: value.height || 360
14830				};
14831
14832			});
14833
14834			return obj;
14835		},
14836
14837		setSocial: function(obj, url, target) {
14838			var iL = this,
14839				socialBar = $('<div class="ilightbox-social"></div>'),
14840				buttons = '<ul>';
14841
14842			obj = iL.normalizeSocial(obj, url);
14843
14844			$.each(obj, function(key, value) {
14845				var item = key.toLowerCase(),
14846					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, '+'));
14847				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>';
14848			});
14849
14850			buttons += '</ul>';
14851
14852			socialBar.html(buttons);
14853			$('div.ilightbox-container', target).append(socialBar);
14854		},
14855
14856		fullScreenAction: function() {
14857			var iL = this,
14858				vars = iL.vars;
14859
14860			if (fullScreenApi.supportsFullScreen) {
14861				if (fullScreenApi.isFullScreen()) fullScreenApi.cancelFullScreen(document.documentElement);
14862				else fullScreenApi.requestFullScreen(document.documentElement);
14863			} else {
14864				iL.doFullscreen();
14865			}
14866		},
14867
14868		doFullscreen: function() {
14869			var iL = this,
14870				vars = iL.vars,
14871				viewport = getViewport(),
14872				opts = iL.options;
14873
14874			if (opts.fullAlone) {
14875				var currentHolder = vars.holder,
14876					current = iL.items[vars.current],
14877					windowWidth = viewport.width,
14878					windowHeight = viewport.height,
14879					elements = [currentHolder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.overlay, vars.toolbar, vars.thumbnails, vars.loader],
14880					hideElements = [vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails];
14881
14882				if (!vars.isInFullScreen) {
14883					vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = true;
14884					vars.overlay.css({
14885						opacity: 1
14886					});
14887
14888					$.each(hideElements, function(i, element) {
14889						element.hide();
14890					});
14891
14892					vars.fullScreenButton.attr('title', opts.text.exitFullscreen);
14893
14894					if (opts.fullStretchTypes.indexOf(current.type) != -1) currentHolder.data({
14895						naturalWidthOld: currentHolder.data('naturalWidth'),
14896						naturalHeightOld: currentHolder.data('naturalHeight'),
14897						naturalWidth: windowWidth,
14898						naturalHeight: windowHeight
14899					});
14900					else {
14901						var viewport = current.options.fullViewPort || opts.fullViewPort || '',
14902							newWidth = windowWidth,
14903							newHeight = windowHeight,
14904							width = currentHolder.data('naturalWidth'),
14905							height = currentHolder.data('naturalHeight');
14906
14907						if (viewport.toLowerCase() == 'fill') {
14908							newHeight = (newWidth / width) * height;
14909
14910							if (newHeight < windowHeight) {
14911								newWidth = (windowHeight / height) * width,
14912									newHeight = windowHeight;
14913							}
14914						} else if (viewport.toLowerCase() == 'fit') {
14915							var dims = iL.getNewDimenstions(newWidth, newHeight, width, height, true);
14916
14917							newWidth = dims.width,
14918								newHeight = dims.height;
14919						} else if (viewport.toLowerCase() == 'stretch') {
14920							newWidth = newWidth,
14921								newHeight = newHeight;
14922						} else {
14923							var scale = (width > newWidth || height > newHeight) ? true : false,
14924								dims = iL.getNewDimenstions(newWidth, newHeight, width, height, scale);
14925							newWidth = dims.width,
14926								newHeight = dims.height;
14927						}
14928
14929						currentHolder.data({
14930							naturalWidthOld: currentHolder.data('naturalWidth'),
14931							naturalHeightOld: currentHolder.data('naturalHeight'),
14932							naturalWidth: newWidth,
14933							naturalHeight: newHeight
14934						});
14935					}
14936
14937					$.each(elements, function(key, val) {
14938						val.addClass('ilightbox-fullscreen');
14939					});
14940
14941					//Trigger the onEnterFullScreen callback
14942					if (typeof opts.callback.onEnterFullScreen == 'function') opts.callback.onEnterFullScreen.call(iL, iL.ui);
14943				} else {
14944					vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = false;
14945					vars.overlay.css({
14946						opacity: iL.options.overlay.opacity
14947					});
14948
14949					$.each(hideElements, function(i, element) {
14950						element.show();
14951					});
14952
14953					vars.fullScreenButton.attr('title', opts.text.enterFullscreen);
14954
14955					currentHolder.data({
14956						naturalWidth: currentHolder.data('naturalWidthOld'),
14957						naturalHeight: currentHolder.data('naturalHeightOld'),
14958						naturalWidthOld: null,
14959						naturalHeightOld: null
14960					});
14961
14962					$.each(elements, function(key, val) {
14963						val.removeClass('ilightbox-fullscreen');
14964					});
14965
14966					//Trigger the onExitFullScreen callback
14967					if (typeof opts.callback.onExitFullScreen == 'function') opts.callback.onExitFullScreen.call(iL, iL.ui);
14968				}
14969			} else {
14970				if (!vars.isInFullScreen) vars.isInFullScreen = true;
14971				else vars.isInFullScreen = false;
14972			}
14973			iL.repositionPhoto(true);
14974		},
14975
14976		closeAction: function() {
14977			var iL = this,
14978				vars = iL.vars,
14979				opts = iL.options;
14980
14981			$win.unbind('.iLightBox');
14982			$doc.off('.iLightBox');
14983
14984			if (vars.isInFullScreen) fullScreenApi.cancelFullScreen(document.documentElement);
14985
14986			$('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails').off('.iLightBox');
14987
14988			if (opts.hide.effect) vars.overlay.stop().fadeOut(opts.hide.speed, function() {
14989				vars.overlay.remove();
14990				vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox');
14991			});
14992			else {
14993				vars.overlay.remove();
14994				vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox');
14995			}
14996
14997			var fadeOuts = [vars.toolbar, vars.holder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails];
14998
14999			$.each(fadeOuts, function(i, element) {
15000				element.removeAttr('style').remove();
15001			});
15002
15003			vars.dontGenerateThumbs = vars.isInFullScreen = false;
15004
15005			window.iLightBox = null;
15006
15007			if (opts.linkId) {
15008				vars.hashLock = true;
15009				removeHash();
15010				setTimeout(function() {
15011					vars.hashLock = false;
15012				}, 55);
15013			}
15014
15015			vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
15016
15017			//Trigger the onHide callback
15018			if (typeof opts.callback.onHide == 'function') opts.callback.onHide.call(iL, iL.ui);
15019		},
15020
15021		repositionPhoto: function() {
15022			var iL = this,
15023				vars = iL.vars,
15024				opts = iL.options,
15025				path = opts.path.toLowerCase(),
15026				viewport = getViewport(),
15027				winWidth = viewport.width,
15028				winHeight = viewport.height;
15029
15030			if (viewport.width < UNCODE.mediaQuery) opts.styles.nextOffsetX = 0;
15031
15032			var thumbsOffsetW = (vars.isInFullScreen && opts.fullAlone || vars.isMobile) ? 0 : ((path == 'horizontal') ? 0 : vars.thumbnails.outerWidth()),
15033				thumbsOffsetH = vars.isMobile ? vars.toolbar.outerHeight() : ((vars.isInFullScreen && opts.fullAlone) ? 0 : ((path == 'horizontal') ? vars.thumbnails.outerHeight() : 0)),
15034				width = (vars.isInFullScreen && opts.fullAlone) ? winWidth : (winWidth - (opts.styles.pageOffsetX)),
15035				height = (vars.isInFullScreen && opts.fullAlone) ? winHeight : (winHeight - (opts.styles.pageOffsetY)),
15036				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,
15037				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)));
15038
15039			var elObject = {
15040				type: 'current',
15041				width: width,
15042				height: height,
15043				item: iL.items[vars.current],
15044				offsetW: offsetW,
15045				offsetH: offsetH,
15046				thumbsOffsetW: thumbsOffsetW,
15047				thumbsOffsetH: thumbsOffsetH,
15048				animate: arguments.length,
15049				holder: vars.holder
15050			};
15051
15052			iL.repositionEl(elObject);
15053
15054			if (iL.items[vars.next]) {
15055				elObject = $.extend(elObject, {
15056					type: 'next',
15057					item: iL.items[vars.next],
15058					offsetX: opts.styles.nextOffsetX,
15059					offsetY: opts.styles.nextOffsetY,
15060					holder: vars.nextPhoto
15061				});
15062
15063				iL.repositionEl(elObject);
15064			}
15065
15066			if (iL.items[vars.prev]) {
15067				elObject = $.extend(elObject, {
15068					type: 'prev',
15069					item: iL.items[vars.prev],
15070					offsetX: opts.styles.nextOffsetX,
15071					offsetY: opts.styles.prevOffsetY,
15072					holder: vars.prevPhoto
15073				});
15074
15075				iL.repositionEl(elObject);
15076			}
15077
15078			var loaderCss = (path == "horizontal") ? {
15079				left: parseInt((width / 2) - (vars.loader.outerWidth() / 2))
15080			} : {
15081				top: parseInt((height / 2) - (vars.loader.outerHeight() / 2))
15082			};
15083			vars.loader.css(loaderCss);
15084		},
15085
15086		repositionEl: function(obj) {
15087			var iL = this,
15088				vars = iL.vars,
15089				opts = iL.options,
15090				path = opts.path.toLowerCase(),
15091				widthAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.width : (obj.width - obj.offsetW)) : (obj.width - obj.offsetW),
15092				heightAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.height : (obj.height - obj.offsetH)) : (obj.height - obj.offsetH),
15093				itemParent = obj.item,
15094				item = obj.item.options,
15095				holder = obj.holder,
15096				offsetX = obj.offsetX || 0,
15097				offsetY = obj.offsetY || 0,
15098				//Uncode change ##START##
15099				toolbarHeight = $('.ilightbox-inner-toolbar', holder).length ? parseInt( $('.ilightbox-inner-toolbar', holder).outerHeight() ) : 0,
15100				//Uncode change ##END##
15101				thumbsOffsetW = obj.thumbsOffsetW,
15102				thumbsOffsetH = obj.thumbsOffsetH;
15103
15104			if (obj.type == 'current') {
15105				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);
15106				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);
15107			} else {
15108				if (typeof item.width == 'number' && item.width) widthAvail = (item.width > widthAvail) ? widthAvail : item.width;
15109				if (typeof item.height == 'number' && item.height) heightAvail = (item.height > heightAvail) ? heightAvail : item.height;
15110			}
15111
15112
15113			//Uncode change ##START##
15114			heightAvail = parseInt(heightAvail - toolbarHeight);
15115			// heightAvail = parseInt(heightAvail - $('.ilightbox-inner-toolbar', holder).outerHeight());
15116			//Uncode change ##END##
15117
15118			var width = (typeof item.width == 'string' && item.width.indexOf('%') != -1) ? percentToValue(parseInt(item.width.replace('%', '')), obj.width) : holder.data('naturalWidth'),
15119				height = (typeof item.height == 'string' && item.height.indexOf('%') != -1) ? percentToValue(parseInt(item.height.replace('%', '')), obj.height) : holder.data('naturalHeight');
15120
15121			var dims = ((typeof item.width == 'string' && item.width.indexOf('%') != -1 || typeof item.height == 'string' && item.height.indexOf('%') != -1) ? {
15122					width: width,
15123					height: height
15124				} : iL.getNewDimenstions(widthAvail, heightAvail, width, height)),
15125				newDims = $.extend({}, dims, {});
15126
15127			if (obj.type == 'prev' || obj.type == 'next')
15128				width = parseInt(dims.width * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale)),
15129				height = parseInt(dims.height * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale));
15130			else
15131				width = dims.width,
15132				height = dims.height;
15133
15134			var widthDiff = parseInt((getPixel(holder, 'padding-left') + getPixel(holder, 'padding-right') + getPixel(holder, 'border-left-width') + getPixel(holder, 'border-right-width')) / 2),
15135				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);
15136
15137			switch (obj.type) {
15138				case 'current':
15139					var top = parseInt((obj.height / 2) - (height / 2) - heightDiff - (thumbsOffsetH / 2)),
15140						left = parseInt((obj.width / 2) - (width / 2) - widthDiff - (thumbsOffsetW / 2));
15141					break;
15142
15143				case 'next':
15144					var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(obj.height - offsetX - heightDiff - (thumbsOffsetH / 2)),
15145						left = (path == 'horizontal') ? parseInt(obj.width - offsetX - widthDiff - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - (width / 2) - widthDiff - offsetY - (thumbsOffsetW / 2));
15146					break;
15147
15148				case 'prev':
15149					var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(offsetX - heightDiff - height - (thumbsOffsetH / 2)),
15150						left = (path == 'horizontal') ? parseInt(offsetX - widthDiff - width - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - offsetY - (width / 2) - widthDiff - (thumbsOffsetW / 2));
15151					break;
15152			}
15153
15154			holder.data('offset', {
15155				top: top,
15156				left: left,
15157				newDims: newDims,
15158				diff: {
15159					W: widthDiff,
15160					H: heightDiff
15161				},
15162				thumbsOffset: {
15163					W: thumbsOffsetW,
15164					H: thumbsOffsetH
15165				},
15166				object: obj
15167			});
15168
15169			var opacityMobile;
15170			if ( isMobile ) {
15171				opacityMobile = {
15172					opacity: 1,
15173					top: top,
15174					left: left
15175				};
15176			} else {
15177				opacityMobile = {
15178					top: top,
15179					left: left
15180				};
15181			}
15182
15183			if (obj.animate > 0 && opts.effects.reposition) {
15184				holder.css(transform, gpuAcceleration).stop().animate(
15185					opacityMobile,
15186					opts.effects.repositionSpeed, 'easeOutCirc', function() {
15187					holder.css(transform, '');
15188				});
15189				$('div.ilightbox-container', holder).stop().animate({
15190					width: width,
15191					height: height
15192				}, opts.effects.repositionSpeed, 'easeOutCirc');
15193				$('div.ilightbox-inner-toolbar', holder).stop().animate({
15194					width: width
15195				}, opts.effects.repositionSpeed, 'easeOutCirc', function() {
15196					$(this).css('overflow', 'visible');
15197				});
15198			} else {
15199				holder.css(opacityMobile);
15200				$('div.ilightbox-container', holder).css({
15201					width: width,
15202					height: height
15203				});
15204				$('div.ilightbox-inner-toolbar', holder).css({
15205					width: width
15206				});
15207			}
15208		},
15209
15210
15211		resume: function(priority) {
15212			var iL = this,
15213				vars = iL.vars,
15214				opts = iL.options;
15215
15216			if (!opts.slideshow.pauseTime || opts.controls.slideshow && vars.total <= 1 || priority < vars.isPaused) {
15217				return;
15218			}
15219
15220			vars.isPaused = 0;
15221
15222			if (vars.cycleID) {
15223				vars.cycleID = clearTimeout(vars.cycleID);
15224			}
15225
15226			vars.cycleID = setTimeout(function() {
15227				if (vars.current == vars.total - 1) iL.goTo(0);
15228				else iL.moveTo('next');
15229			}, opts.slideshow.pauseTime);
15230		},
15231
15232		pause: function(priority) {
15233			var iL = this,
15234				vars = iL.vars,
15235				opts = iL.options;
15236
15237			if (priority < vars.isPaused) {
15238				return;
15239			}
15240
15241			vars.isPaused = priority || 100;
15242
15243			if (vars.cycleID) {
15244				vars.cycleID = clearTimeout(vars.cycleID);
15245			}
15246		},
15247
15248		resetCycle: function() {
15249			var iL = this,
15250				vars = iL.vars,
15251				opts = iL.options;
15252
15253			if (opts.controls.slideshow && vars.cycleID && !vars.isPaused) {
15254				iL.resume();
15255			}
15256		},
15257
15258		getNewDimenstions: function(width, height, width_old, height_old, thumb) {
15259			var iL = this;
15260
15261			if (!width) factor = height / height_old;
15262			else if (!height) factor = width / width_old;
15263			else factor = min(width / width_old, height / height_old);
15264
15265			if (!thumb) {
15266				if (factor > iL.options.maxScale) factor = iL.options.maxScale;
15267				else if (factor < iL.options.minScale) factor = iL.options.minScale;
15268			}
15269
15270			var final_width = (iL.options.keepAspectRatio) ? round(width_old * factor) : width,
15271				final_height = (iL.options.keepAspectRatio) ? round(height_old * factor) : height;
15272
15273			return {
15274				width: final_width,
15275				height: final_height,
15276				ratio: factor
15277			};
15278		},
15279
15280		setOption: function(options) {
15281			var iL = this;
15282
15283			iL.options = $.extend(true, iL.options, options || {});
15284			iL.refresh();
15285		},
15286
15287		availPlugins: function() {
15288			var iL = this,
15289				testEl = document.createElement("video");
15290
15291			iL.plugins = {
15292				flash: !isMobile,
15293				quicktime: (parseInt(PluginDetect.getVersion("QuickTime")) >= 0) ? true : false,
15294				html5H264: !!(testEl.canPlayType && testEl.canPlayType('video/mp4').replace(/no/, '')),
15295				html5WebM: !!(testEl.canPlayType && testEl.canPlayType('video/webm').replace(/no/, '')),
15296				html5Vorbis: !!(testEl.canPlayType && testEl.canPlayType('video/ogg').replace(/no/, '')),
15297				html5QuickTime: !!(testEl.canPlayType && testEl.canPlayType('video/quicktime').replace(/no/, ''))
15298			};
15299		},
15300
15301		addContent: function(element, obj) {
15302			var iL = this,
15303				el;
15304
15305			switch (obj.type) {
15306				case 'video':
15307					var HTML5 = false,
15308						videoType = obj.videoType,
15309						html5video = obj.options.html5video;
15310
15311					if (((videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v') || html5video.h264) && iL.plugins.html5H264)
15312						obj.ext = 'mp4',
15313						obj.URL = html5video.h264 || obj.URL;
15314					else if (html5video.webm && iL.plugins.html5WebM)
15315						obj.ext = 'webm',
15316						obj.URL = html5video.webm || obj.URL;
15317					else if (html5video.ogg && iL.plugins.html5Vorbis)
15318						obj.ext = 'ogv',
15319						obj.URL = html5video.ogg || obj.URL;
15320
15321					if (iL.plugins.html5H264 && (videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v')) HTML5 = true, videoType = "video/mp4";
15322					else if (iL.plugins.html5WebM && (videoType == 'video/webm' || obj.ext == 'webm')) HTML5 = true, videoType = "video/webm";
15323					else if (iL.plugins.html5Vorbis && (videoType == 'video/ogg' || obj.ext == 'ogv')) HTML5 = true, videoType = "video/ogg";
15324					else if (iL.plugins.html5QuickTime && (videoType == 'video/quicktime' || obj.ext == 'mov' || obj.ext == 'qt')) HTML5 = true, videoType = "video/quicktime";
15325
15326					if (HTML5) {
15327						el = $('<video />
15327', {
15328							"width": "100%",
15329							"height": "100%",
15330							"preload": html5video.preload,
15331							"autoplay": html5video.autoplay,
15332							"loop": html5video.loop,
15333							"poster": html5video.poster,
15334							"controls": html5video.controls,
15335							"controlslist": "nodownload"
15336						}).append($('<source />', {
15337							"src": obj.URL,
15338							"type": videoType
15339						}));
15340					} else {
15341						if (!iL.plugins.quicktime) el = $('<span />', {
15342							"class": "ilightbox-alert",
15343							html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.quicktime).replace('{type}', 'QuickTime')
15344						});
15345						else {
15346
15347							el = $('<object />', {
15348								"type": "video/quicktime",
15349								"pluginspage": pluginspages.quicktime
15350							}).attr({
15351								"data": obj.URL,
15352								"width": "100%",
15353								"height": "100%"
15354							}).append($('<param />', {
15355								"name": "src",
15356								"value": obj.URL
15357							})).append($('<param />', {
15358								"name": "autoplay",
15359								"value": "false"
15360							})).append($('<param />', {
15361								"name": "loop",
15362								"value": "false"
15363							})).append($('<param />', {
15364								"name": "scale",
15365								"value": "tofit"
15366							}));
15367
15368							if (browser.msie) el = QT_GenerateOBJECTText(obj.URL, '100%', '100%', '', 'SCALE', 'tofit', 'AUTOPLAY', 'false', 'LOOP', 'false');
15369						}
15370					}
15371
15372					break;
15373
15374				case 'flash':
15375					if (!iL.plugins.flash) el = $('<span />', {
15376						"class": "ilightbox-alert",
15377						html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.flash).replace('{type}', 'Adobe Flash player')
15378					});
15379					else {
15380						var flashvars = "",
15381							i = 0;
15382
15383						if (obj.options.flashvars) $.each(obj.options.flashvars, function(k, v) {
15384							if (i != 0) flashvars += "&";
15385							flashvars += k + "=" + encodeURIComponent(v);
15386							i++;
15387						});
15388						else flashvars = null;
15389
15390						el = $('<embed />').attr({
15391							"type": "application/x-shockwave-flash",
15392							"src": obj.URL,
15393							"width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%",
15394							"height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%",
15395							"quality": "high",
15396							"bgcolor": "#000000",
15397							"play": "true",
15398							"loop": "true",
15399							"menu": "true",
15400							"wmode": "transparent",
15401							"scale": "showall",
15402							"allowScriptAccess": "always",
15403							"allowFullScreen": "true",
15404							"flashvars": flashvars,
15405							"fullscreen": "yes"
15406						});
15407					}
15408
15409					break;
15410
15411				case 'iframe':
15412					el = $('<iframe />').attr({
15413						"width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%",
15414						"height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%",
15415						src: obj.URL,
15416						frameborder: 0,
15417						'hspace': 0,
15418						'vspace': 0,
15419						'scrolling': supportTouch ? 'auto' : 'scroll',
15420						'webkitAllowFullScreen': '',
15421						'mozallowfullscreen': '',
15422						'allowFullScreen': ''
15423					});
15424
15425					break;
15426
15427				case 'inline':
15428					el = $('<div class="ilightbox-wrapper"></div>').html($(obj.URL).clone(true));
15429
15430					break;
15431
15432				case 'html':
15433					var object = obj.URL,
15434						el;
15435
15436					if (object[0].nodeName) {
15437						el = $('<div class="ilightbox-wrapper"></div>').html(object);
15438					} else {
15439						var dom = $(obj.URL),
15440							html = (dom.selector) ? $('<div>' + dom + '</div>') : dom;
15441						el = $('<div class="ilightbox-wrapper"></div>').html(html);
15442					}
15443
15444					break;
15445			}
15446
15447			$('div.ilightbox-container', element).empty().html(el);
15448
15449			// For fixing Chrome about just playing the video for first time
15450			if (el[0].tagName.toLowerCase() === 'video' && browser.webkit) setTimeout(function() {
15451				var src = el[0].currentSrc + '?' + floor(random() * 30000);
15452				el[0].currentSrc = src;
15453				el[0].src = src;
15454			});
15455
15456			return el;
15457		},
15458
15459		ogpRecognition: function(obj, callback) {
15460			var iL = this,
15461				url = obj.URL;
15462
15463			iL.showLoader();
15464			doAjax(url, function(data) {
15465				iL.hideLoader();
15466				if (data) {
15467					var object = new Object();
15468
15469					object.length = false,
15470					object.url = data.url;
15471
15472					if (data.status == 200) {
15473						var result = data.results,
15474							type = result.type,
15475							source = result.source;
15476
15477						object.source = source.src,
15478						object.width = source.width && parseInt(source.width) || 0,
15479						object.height = source.height && parseInt(source.height) || 0,
15480						object.type = type,
15481						object.thumbnail = source.thumbnail || result.images && result.images[0],
15482						object.html5video = result.html5video || {},
15483						object.length = true;
15484
15485						if (source.type == 'application/x-shockwave-flash') object.type = "flash";
15486						else if (source.type.indexOf("video/") != -1) object.type = "video";
15487						else if (source.type.indexOf("/html") != -1) object.type = "iframe";
15488						else if (source.type.indexOf("image/") != -1) object.type = "image";
15489
15490					} else if (typeof data.response != 'undefined')
15491						throw data.response;
15492
15493					callback.call(this, object.length ? object : false);
15494				}
15495			});
15496		},
15497
15498		hashChangeHandler: function(url) {
15499			var iL = this,
15500				vars = iL.vars,
15501				opts = iL.options,
15502				URL = url || window.location.href,
15503				hash = parseURI(URL).hash,
15504				split = hash.split('/'),
15505				index = split[1];
15506
15507			if (vars.hashLock || ('#' + opts.linkId != split[0] && hash.length > 1)) return;
15508
15509			if (index) {
15510				var target = split[1] || 0;
15511				if (iL.items[target]) {
15512					var overlay = $('.ilightbox-overlay');
15513					if (overlay.length && overlay.attr('linkid') == opts.linkId) {
15514						iL.goTo(target);
15515					} else {
15516						iL.itemsObject[target].trigger(ishybrid ? "itap click" : supportTouch ? 'itap' : 'click');
15517						//iL.goTo(target);
15518					}
15519				} else {
15520					var overlay = $('.ilightbox-overlay');
15521					if (overlay.length) iL.closeAction();
15522				}
15523			} else {
15524				var overlay = $('.ilightbox-overlay');
15525				if (overlay.length) iL.closeAction();
15526			}
15527		}
15528	};
15529
15530	/**
15531	 * Parse style to pixels.
15532	 *
15533	 * @param {Object}   $element   jQuery object with element.
15534	 * @param {Property} property   CSS property to get the pixels from.
15535	 *
15536	 * @return {Int}
15537	 */
15538	function getPixel($element, property) {
15539		return parseInt($element.css(property), 10) || 0;
15540	}
15541
15542	/**
15543	 * Make sure that number is within the limits.
15544	 *
15545	 * @param {Number} number
15546	 * @param {Number} min
15547	 * @param {Number} max
15548	 *
15549	 * @return {Number}
15550	 */
15551	function within(number, min, max) {
15552		return number < min ? min : number > max ? max : number;
15553	}
15554
15555	/**
15556	 * Get viewport/window size (width and height).
15557	 *
15558	 * @return {Object}
15559	 */
15560	function getViewport() {
15561		var e = window,
15562			a = 'inner';
15563		if (!('innerWidth' in window)) {
15564			a = 'client';
15565			e = document.documentElement || document.body;
15566		}
15567		return {
15568			width: e[a + 'Width'],
15569			height: e[a + 'Height']
15570		}
15571	}
15572
15573	/**
15574	 * Remove hash tag from the URL
15575	 *
15576	 * @return {Void}
15577	 */
15578	function removeHash() {
15579		var scroll = getScrollXY();
15580
15581		//UNCODE change
15582		// window.location.hash = "";
15583		// history.pushState("", document.title, window.location.pathname + window.location.search);
15584		history.replaceState({}, document.title, window.location.pathname + window.location.search);
15585
15586		// Restore the scroll offset, should be flicker free
15587		window.scrollTo(scroll.x, scroll.y);
15588	}
15589
15590	/**
15591	 * Do the ajax requests with callback.
15592	 *
15593	 * @param {String}   url
15594	 * @param {Function} callback
15595	 *
15596	 * @return {Void}
15597	 */
15598	function doAjax(url, callback) {
15599		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');
15600		$.ajax({
15601			url: url,
15602			dataType: 'jsonp'
15603		});
15604
15605		iLCallback = function(data) {
15606			callback.call(this, data);
15607		};
15608	}
15609
15610	/**
15611	 * Find image from DOM elements
15612	 *
15613	 * @param {Element} element
15614	 *
15615	 * @return {Void}
15616	 */
15617	function findImageInElement(element) {
15618		var elements = $('*', element),
15619			imagesArr = new Array();
15620
15621		elements.each(function() {
15622			var url = "",
15623				element = this;
15624
15625			if ($(element).css("background-image") != "none") {
15626				url = $(element).css("background-image");
15627			} else if (typeof($(element).attr("src")) != "undefined" && element.nodeName.toLowerCase() == "img") {
15628				url = $(element).attr("src");
15629			}
15630
15631			if (url.indexOf("gradient") == -1) {
15632				url = url.replace(/url\(\"/g, "");
15633				url = url.replace(/url\(/g, "");
15634				url = url.replace(/\"\)/g, "");
15635				url = url.replace(/\)/g, "");
15636
15637				var urls = url.split(",");
15638
15639				for (var i = 0; i < urls.length; i++) {
15640					if (urls[i].length > 0 && $.inArray(urls[i], imagesArr) == -1) {
15641						var extra = "";
15642						if (browser.msie && browser.version < 9) {
15643							extra = "?" + floor(random() * 3000);
15644						}
15645						imagesArr.push(urls[i] + extra);
15646					}
15647				}
15648			}
15649		});
15650
15651		return imagesArr;
15652	}
15653
15654	/**
15655	 * Get file extension.
15656	 *
15657	 * @param {String} URL
15658	 *
15659	 * @return {String}
15660	 */
15661	function getExtension(URL) {
15662		if (URL !== null) {
15663			//UNCODE: fix issue to detect media type with query strings
15664			var ext = URL.indexOf('?') !== -1 ? URL.split('?')[0] : URL;
15665			ext = ext.split('.').pop().toLowerCase();
15666
15667			return ext;
15668		}
15669	}
15670
15671	/**
15672	 * Get type via extension.
15673	 *
15674	 * @param {String} URL
15675	 *
15676	 * @return {String}
15677	 */
15678	function getTypeByExtension(URL) {
15679		var type,
15680			ext = getExtension(URL);
15681
15682		//Uncode addition ##START##
15683		if (URL == undefined) {
15684			return false;
15685		}
15686		//Uncode addition ##END##
15687
15688		if (extensions.image.indexOf(ext) !== -1) type = 'image';
15689		else if (extensions.flash.indexOf(ext) !== -1) type = 'flash';
15690		else if (extensions.video.indexOf(ext) !== -1) type = 'video';
15691		else if (ext.substring(0, 1) == "#") type = 'inline'; //Uncode addition
15692		else type = 'iframe';
15693
15694		return type;
15695	}
15696
15697	/**
15698	 * Return value from percent of a number.
15699	 *
15700	 * @param {Number} percent
15701	 * @param {Number} total
15702	 *
15703	 * @return {Number}
15704	 */
15705	function percentToValue(percent, total) {
15706		return parseInt((total / 100) * percent);
15707	}
15708
15709	/**
15710	 * A JavaScript equivalent of PHP’s parse_url.
15711	 *
15712	 * @param {String} url           The URL to parse.
15713	 *
15714	 * @return {Mixed}
15715	 */
15716	function parseURI(url) {
15717		var m = String(url).replace(/^\s+|\s+$/g, '').match(/^([^:\/?#]+:)?(\/\/(?:[^:@]*(?::[^:@]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/);
15718		// authority = '//' + user + ':' + pass '@' + hostname + ':' port
15719		return (m ? {
15720			href: m[0] || '',
15721			protocol: m[1] || '',
15722			authority: m[2] || '',
15723			host: m[3] || '',
15724			hostname: m[4] || '',
15725			port: m[5] || '',
15726			pathname: m[6] || '',
15727			search: m[7] || '',
15728			hash: m[8] || ''
15729		} : null);
15730	}
15731
15732	/**
15733	 * Gets the absolute URI.
15734	 *
15735	 * @param {String} href     The relative URL.
15736	 * @param {String} base     The base URL.
15737	 *
15738	 * @return {String}         The absolute URL.
15739	 */
15740	function absolutizeURI(base, href) { // RFC 3986
15741		var iL = this;
15742
15743		function removeDotSegments(input) {
15744			var output = [];
15745			input.replace(/^(\.\.?(\/|$))+/, '')
15746				.replace(/\/(\.(\/|$))+/g, '/')
15747				.replace(/\/\.\.$/, '/../')
15748				.replace(/\/?[^\/]*/g, function(p) {
15749					if (p === '/..') {
15750						output.pop();
15751					} else {
15752						output.push(p);
15753					}
15754				});
15755			return output.join('').replace(/^\//, input.charAt(0) === '/' ? '/' : '');
15756		}
15757
15758		href = parseURI(href || '');
15759		base = parseURI(base || '');
15760
15761		return !href || !base ? null : (href.protocol || base.protocol) +
15762			(href.protocol || href.authority ? href.authority : base.authority) +
15763			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)) +
15764			(href.protocol || href.authority || href.pathname ? href.search : (href.search || base.search)) +
15765			href.hash;
15766	}
15767
15768	/**
15769	 * A JavaScript equivalent of PHP’s version_compare.
15770	 *
15771	 * @param {String} v1
15772	 * @param {String} v2
15773	 * @param {String} operator
15774	 *
15775	 * @return {Boolean}
15776	 */
15777	function version_compare(v1, v2, operator) {
15778		this.php_js = this.php_js || {};
15779		this.php_js.ENV = this.php_js.ENV || {};
15780		var i = 0,
15781			x = 0,
15782			compare = 0,
15783			vm = {
15784				'dev': -6,
15785				'alpha': -5,
15786				'a': -5,
15787				'beta': -4,
15788				'b': -4,
15789				'RC': -3,
15790				'rc': -3,
15791				'#': -2,
15792				'p': 1,
15793				'pl': 1
15794			},
15795			prepVersion = function(v) {
15796				v = ('' + v).replace(/[_\-+]/g, '.');
15797				v = v.replace(/([^.\d]+)/g, '.$1.').replace(/\.{2,}/g, '.');
15798				return (!v.length ? [-8] : v.split('.'));
15799			},
15800			numVersion = function(v) {
15801				return !v ? 0 : (isNaN(v) ? vm[v] || -7 : parseInt(v, 10));
15802			};
15803		v1 = prepVersion(v1);
15804		v2 = prepVersion(v2);
15805		x = max(v1.length, v2.length);
15806		for (i = 0; i < x; i++) {
15807			if (v1[i] == v2[i]) {
15808				continue;
15809			}
15810			v1[i] = numVersion(v1[i]);
15811			v2[i] = numVersion(v2[i]);
15812			if (v1[i] < v2[i]) {
15813				compare = -1;
15814				break;
15815			} else if (v1[i] > v2[i]) {
15816				compare = 1;
15817				break;
15818			}
15819		}
15820		if (!operator) {
15821			return compare;
15822		}
15823
15824		switch (operator) {
15825			case '>':
15826			case 'gt':
15827				return (compare > 0);
15828			case '>=':
15829			case 'ge':
15830				return (compare >= 0);
15831			case '<=':
15832			case 'le':
15833				return (compare <= 0);
15834			case '==':
15835			case '=':
15836			case 'eq':
15837				return (compare === 0);
15838			case '<>':
15839			case '!=':
15840			case 'ne':
15841				return (compare !== 0);
15842			case '':
15843			case '<':
15844			case 'lt':
15845				return (compare < 0);
15846			default:
15847				return null;
15848		}
15849	}
15850
15851
15852	// Begin the iLightBox plugin
15853	$.fn.iLightBox = function() {
15854
15855		var args = arguments,
15856			opt = ($.isPlainObject(args[0])) ? args[0] : args[1],
15857			items = ($.isArray(args[0]) || typeof args[0] == 'string') ? args[0] : args[1];
15858
15859		if (!opt) opt = {};
15860
15861		// Default options. Play carefully.
15862		var options = $.extend(true, {
15863			attr: 'href',
15864			path: 'vertical',
15865			skin: 'dark',
15866			linkId: false,
15867			infinite: false,
15868			startFrom: 0,
15869			randomStart: false,
15870			keepAspectRatio: true,
15871			maxScale: 1,
15872			minScale: .2,
15873			innerToolbar: false,
15874			smartRecognition: false,
15875			mobileOptimizer: true,
15876			fullAlone: true,
15877			fullViewPort: null,
15878			fullStretchTypes: 'flash, video',
15879			overlay: {
15880				blur: true,
15881				opacity: .85
15882			},
15883			controls: {
15884				arrows: false,
15885				slideshow: false,
15886				toolbar: true,
15887				fullscreen: true,
15888				thumbnail: true,
15889				keyboard: true,
15890				mousewheel: true,
15891				swipe: true
15892			},
15893			keyboard: {
15894				left: true, // previous
15895				right: true, // next
15896				up: true, // previous
15897				down: true, // next
15898				esc: true, // close
15899				shift_enter: true // fullscreen
15900			},
15901			show: {
15902				effect: true,
15903				speed: 300,
15904				title: true
15905			},
15906			hide: {
15907				effect: true,
15908				speed: 300
15909			},
15910			caption: {
15911				start: true,
15912				show: 'mouseenter',
15913				hide: 'mouseleave'
15914			},
15915			social: {
15916				start: true,
15917				show: 'mouseenter',
15918				hide: 'mouseleave',
15919				buttons: false
15920			},
15921			styles: {
15922				pageOffsetX: 0,
15923				pageOffsetY: 0,
15924				nextOffsetX: 45,
15925				nextOffsetY: 0,
15926				nextOpacity: 1,
15927				nextScale: 1,
15928				prevOffsetX: 45,
15929				prevOffsetY: 0,
15930				prevOpacity: 1,
15931				prevScale: 1
15932			},
15933			thumbnails: {
15934				maxWidth: 120,
15935				maxHeight: 80,
15936				normalOpacity: 1,
15937				activeOpacity: .6
15938			},
15939			effects: {
15940				reposition: true,
15941				repositionSpeed: 200,
15942				switchSpeed: 500,
15943				loadedFadeSpeed: 180,
15944				fadeSpeed: 200
15945			},
15946			slideshow: {
15947				pauseTime: 5000,
15948				pauseOnHover: false,
15949				startPaused: true
15950			},
15951			text: {
15952				close: "Press Esc to close",
15953				enterFullscreen: "Enter Fullscreen (Shift+Enter)",
15954				exitFullscreen: "Exit Fullscreen (Shift+Enter)",
15955				slideShow: "Slideshow",
15956				next: "Next",
15957				previous: "Previous"
15958			},
15959			errors: {
15960				loadImage: "An error occurred when trying to load photo.",
15961				loadContents: "An error occurred when trying to load contents.",
15962				missingPlugin: "The content your are attempting to view requires the <a href='{pluginspage}' target='_blank'>{type} plugin<\/a>."
15963			},
15964			ajaxSetup: {
15965				url: '',
15966				beforeSend: function(jqXHR, settings) {},
15967				cache: false,
15968				complete: function(jqXHR, textStatus) {},
15969				crossDomain: false,
15970				error: function(jqXHR, textStatus, errorThrown) {},
15971				success: function(data, textStatus, jqXHR) {},
15972				global: true,
15973				ifModified: false,
15974				username: null,
15975				password: null,
15976				type: 'GET'
15977			},
15978			callback: {}
15979		}, opt);
15980
15981		var instant = ($.isArray(items) || typeof items == 'string') ? true : false;
15982
15983		items = $.isArray(items) ? items : new Array();
15984
15985		if (typeof args[0] == 'string') items[0] = args[0];
15986
15987		if (version_compare($.fn.jquery, '1.8', '>=')) {
15988			var iLB = new iLightBox($(this), options, items, instant);
15989			return {
15990				close: function() {
15991					iLB.closeAction();
15992				},
15993				fullscreen: function() {
15994					iLB.fullScreenAction();
15995				},
15996				moveNext: function() {
15997					iLB.moveTo('next');
15998				},
15999				movePrev: function() {
16000					iLB.moveTo('prev');
16001				},
16002				goTo: function(index) {
16003					iLB.goTo(index);
16004				},
16005				refresh: function() {
16006					iLB.refresh();
16007				},
16008				reposition: function() {
16009					(arguments.length > 0) ? iLB.repositionPhoto(true): iLB.repositionPhoto();
16010				},
16011				setOption: function(options) {
16012					iLB.setOption(options);
16013				},
16014				destroy: function() {
16015					iLB.closeAction();
16016					iLB.dispatchItemsEvents();
16017				}
16018			};
16019		} else {
16020			throw "The jQuery version that was loaded is too old. iLightBox requires jQuery 1.8+";
16021		}
16022
16023	};
16024
16025
16026	$.iLightBox = function() {
16027		return $.fn.iLightBox(arguments[0], arguments[1]);
16028	};
16029
16030	function getScrollXY() {
16031		var scrOfX = 0,
16032			scrOfY = 0;
16033		if (typeof(window.pageYOffset) == 'number') {
16034			//Netscape compliant
16035			scrOfY = window.pageYOffset;
16036			scrOfX = window.pageXOffset;
16037		} else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) {
16038			//DOM compliant
16039			scrOfY = document.body.scrollTop;
16040			scrOfX = document.body.scrollLeft;
16041		} else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
16042			//IE6 standards compliant mode
16043			scrOfY = document.documentElement.scrollTop;
16044			scrOfX = document.documentElement.scrollLeft;
16045		}
16046		return {
16047			x: scrOfX,
16048			y: scrOfY
16049		};
16050	}
16051
16052	(function() {
16053		// add new event shortcuts
16054		$.each(("touchstart touchmove touchend " +
16055			"tap taphold " +
16056			"swipe swipeleft swiperight " +
16057			"scrollstart scrollstop").split(" "), function(i, name) {
16058
16059			$.fn[name] = function(fn) {
16060				return fn ? this.bind(name, fn) : this.trigger(name);
16061			};
16062
16063			// jQuery < 1.8
16064			// if ($.attrFn) {
16065			// 	$.attrFn[name] = true;
16066			// }
16067		});
16068
16069		var tapSettings = {
16070			startEvent: 'touchstart.iTap',
16071			endEvent: 'touchend.iTap'
16072		};
16073
16074		// tap Event:
16075		$.event.special.itap = {
16076			setup: function() {
16077
16078				var self = this,
16079					$self = $(this),
16080					start, stop;
16081
16082				$self.bind(tapSettings.startEvent, function(event) {
16083					start = getScrollXY();
16084
16085					$self.one(tapSettings.endEvent, function(event) {
16086						stop = getScrollXY();
16087
16088						var orgEvent = event || window.event;
16089						event = $.event.fix(orgEvent);
16090						event.type = "itap";
16091
16092						if ((start && stop) && (start.x == stop.x && start.y == stop.y))($.event.dispatch || $.event.handle).call(self, event);
16093
16094						start = stop = undefined;
16095					});
16096				});
16097			},
16098
16099			teardown: function() {
16100				$(this).unbind(tapSettings.startEvent);
16101			}
16102		};
16103	}());
16104
16105
16106	//Fullscreen API
16107	(function() {
16108		fullScreenApi = {
16109				supportsFullScreen: false,
16110				isFullScreen: function() {
16111					return false;
16112				},
16113				requestFullScreen: function() {},
16114				cancelFullScreen: function() {},
16115				fullScreenEventName: '',
16116				prefix: ''
16117			},
16118			browserPrefixes = 'webkit moz o ms khtml'.split(' ');
16119
16120		// check for native support
16121		if (typeof document.cancelFullScreen != 'undefined') {
16122			fullScreenApi.supportsFullScreen = true;
16123		} else {
16124			// check for fullscreen support by vendor prefix
16125			for (var i = 0, il = browserPrefixes.length; i < il; i++) {
16126				fullScreenApi.prefix = browserPrefixes[i];
16127
16128				if (typeof document[fullScreenApi.prefix + 'CancelFullScreen'] != 'undefined') {
16129					fullScreenApi.supportsFullScreen = true;
16130
16131					break;
16132				}
16133			}
16134		}
16135
16136		// update methods to do something useful
16137		if (fullScreenApi.supportsFullScreen) {
16138			fullScreenApi.fullScreenEventName = fullScreenApi.prefix + 'fullscreenchange';
16139
16140			fullScreenApi.isFullScreen = function() {
16141				switch (this.prefix) {
16142					case '':
16143						return document.fullScreen;
16144					case 'webkit':
16145						return document.webkitIsFullScreen;
16146					default:
16147						return document[this.prefix + 'FullScreen'];
16148				}
16149			}
16150			fullScreenApi.requestFullScreen = function(el) {
16151				return (this.prefix === '') ? el.requestFullScreen() : el[this.prefix + 'RequestFullScreen']();
16152			}
16153			fullScreenApi.cancelFullScreen = function(el) {
16154				return (this.prefix === '') ? document.cancelFullScreen() : document[this.prefix + 'CancelFullScreen']();
16155			}
16156		}
16157	}());
16158
16159	// Browser detect
16160	(function() {
16161		function uaMatch(ua) {
16162			ua = ua.toLowerCase();
16163
16164			var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
16165				/(webkit)[ \/]([\w.]+)/.exec(ua) ||
16166				/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
16167				/(msie) ([\w.]+)/.exec(ua) ||
16168				ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || [];
16169
16170			return {
16171				browser: match[1] || "",
16172				version: match[2] || "0"
16173			};
16174		}
16175
16176		var matched = uaMatch(navigator.userAgent);
16177		browser = {};
16178
16179		if (matched.browser) {
16180			browser[matched.browser] = true;
16181			browser.version = matched.version;
16182		}
16183
16184		// Chrome is Webkit, but Webkit is also Safari.
16185		if (browser.chrome) {
16186			browser.webkit = true;
16187		} else if (browser.webkit) {
16188			browser.safari = true;
16189		}
16190	}());
16191
16192	// Feature detects
16193	(function() {
16194		var prefixes = ['', 'webkit', 'moz', 'ms', 'o'];
16195		var el = document.createElement('div');
16196
16197		function testProp(prop) {
16198			for (var p = 0, pl = prefixes.length; p < pl; p++) {
16199				var prefixedProp = prefixes[p] ? prefixes[p] + prop.charAt(0).toUpperCase() + prop.slice(1) : prop;
16200				if (el.style[prefixedProp] !== undefined) {
16201					return prefixedProp;
16202				}
16203			}
16204		}
16205
16206		// Global support indicators
16207		transform = testProp('transform') || '';
16208		gpuAcceleration = testProp('perspective') ? 'translateZ(0) ' : '';
16209	}());
16210
16211
16212	/*
16213		PluginDetect v0.7.9
16214		www.pinlady.net/PluginDetect/license/
16215		[ getVersion onWindowLoaded BetterIE ]
16216		[ Flash QuickTime Shockwave ]
16217	*/
16218	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;
16218d++){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);
16218d.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)}
16218c.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;
16218if(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();
16219
16220	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)};
16221
16222
16223	/*
16224		jQuery hashchange event v1.3
16225		https://github.com/cowboy/jquery-hashchange
16226		Copyright (c) 2010 "Cowboy" Ben Alman
16227		Dual licensed under the MIT and GPL licenses.
16228	*/
16229	(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=
16230	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||
16231	"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;
16231a!==d&&(b.title=k.title,b.open(),e&&b.write('<script>document.domain="'+e+'"\x3c/script>'),b.close(),c.location.hash=a)}}();return h}()})();
16232
16233	if (!Array.prototype.filter) {
16234		Array.prototype.filter = function(fun /*, thisp */ ) {
16235			"use strict";
16236
16237			if (this == null)
16238				throw new TypeError();
16239
16240			var t = Object(this);
16241			var len = t.length >>> 0;
16242			if (typeof fun != "function")
16243				throw new TypeError();
16244
16245			var res = [];
16246			var thisp = arguments[1];
16247			for (var i = 0; i < len; i++) {
16248				if (i in t) {
16249					var val = t[i]; // in case fun mutates this
16250					if (fun.call(thisp, val, i, t))
16251						res.push(val);
16252				}
16253			}
16254
16255			return res;
16256		};
16257	}
16258
16259	if (!Array.prototype.indexOf) {
16260		Array.prototype.indexOf = function(searchElement, fromIndex) {
16261			var k;
16262
16263			if (this == null) {
16264				throw new TypeError('"this" is null or not defined');
16265			}
16266
16267			var O = Object(this);
16268
16269			var len = O.length >>> 0;
16270
16271			if (len === 0) {
16272				return -1;
16273			}
16274
16275			var n = +fromIndex || 0;
16276
16277			if (abs(n) === Infinity) {
16278				n = 0;
16279			}
16280
16281			if (n >= len) {
16282				return -1;
16283			}
16284
16285			k = max(n >= 0 ? n : len - abs(n), 0);
16286
16287			while (k < len) {
16288				var kValue;
16289				if (k in O && O[k] === searchElement) {
16290					return k;
16291				}
16292				k++;
16293			}
16294			return -1;
16295		};
16296	}
16297
16298	if (!Array.prototype.lastIndexOf) {
16299		Array.prototype.lastIndexOf = function(searchElement /*, fromIndex*/ ) {
16300			"use strict";
16301
16302			if (this == null)
16303				throw new TypeError();
16304
16305			var t = Object(this);
16306			var len = t.length >>> 0;
16307			if (len === 0)
16308				return -1;
16309
16310			var n = len;
16311			if (arguments.length > 1) {
16312				n = Number(arguments[1]);
16313				if (n != n)
16314					n = 0;
16315				else if (n != 0 && n != (1 / 0) && n != -(1 / 0))
16316					n = (n > 0 || -1) * floor(abs(n));
16317			}
16318
16319			var k = n >= 0 ? min(n, len - 1) : len - abs(n);
16320
16321			for (; k >= 0; k--) {
16322				if (k in t && t[k] === searchElement)
16323					return k;
16324			}
16325			return -1;
16326		};
16327	}
16328})(jQuery, this);
16329
16330/*!
16331 * lightgallery | 2.5.0 | June 13th 2022
16332 * http://www.lightgalleryjs.com/
16333 * Copyright (c) 2020 Sachin Neravath;
16334 * @license GPLv3
16335 */
16336
16337(function (global, factory) {
16338	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
16339	typeof define === 'function' && define.amd ? define(factory) :
16340	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lightGallery = factory());
16341}(this, (function () { 'use strict';
16342
16343	/*! *****************************************************************************
16344	Copyright (c) Microsoft Corporation.
16345
16346	Permission to use, copy, modify, and/or distribute this software for any
16347	purpose with or without fee is hereby granted.
16348
16349	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
16350	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
16351	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
16352	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
16353	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16354	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16355	PERFORMANCE OF THIS SOFTWARE.
16356	***************************************************************************** */
16357
16358	var __assign = function() {
16359		__assign = Object.assign || function __assign(t) {
16360			for (var s, i = 1, n = arguments.length; i < n; i++) {
16361				s = arguments[i];
16362				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
16363			}
16364			return t;
16365		};
16366		return __assign.apply(this, arguments);
16367	};
16368
16369	function __spreadArrays() {
16370		for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
16371		for (var r = Array(s), k = 0, i = 0; i < il; i++)
16372			for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
16373				r[k] = a[j];
16374		return r;
16375	}
16376
16377	/**
16378	 * List of lightGallery events
16379	 * All events should be documented here
16380	 * Below interfaces are used to build the website documentations
16381	 * */
16382	var lGEvents = {
16383		afterAppendSlide: 'lgAfterAppendSlide',
16384		init: 'lgInit',
16385		hasVideo: 'lgHasVideo',
16386		containerResize: 'lgContainerResize',
16387		updateSlides: 'lgUpdateSlides',
16388		afterAppendSubHtml: 'lgAfterAppendSubHtml',
16389		beforeOpen: 'lgBeforeOpen',
16390		afterOpen: 'lgAfterOpen',
16391		slideItemLoad: 'lgSlideItemLoad',
16392		beforeSlide: 'lgBeforeSlide',
16393		afterSlide: 'lgAfterSlide',
16394		posterClick: 'lgPosterClick',
16395		dragStart: 'lgDragStart',
16396		dragMove: 'lgDragMove',
16397		dragEnd: 'lgDragEnd',
16398		beforeNextSlide: 'lgBeforeNextSlide',
16399		beforePrevSlide: 'lgBeforePrevSlide',
16400		beforeClose: 'lgBeforeClose',
16401		afterClose: 'lgAfterClose',
16402		rotateLeft: 'lgRotateLeft',
16403		rotateRight: 'lgRotateRight',
16404		flipHorizontal: 'lgFlipHorizontal',
16405		flipVertical: 'lgFlipVertical',
16406		autoplay: 'lgAutoplay',
16407		autoplayStart: 'lgAutoplayStart',
16408		autoplayStop: 'lgAutoplayStop',
16409	};
16410
16411	var lightGalleryCoreSettings = {
16412		mode: 'lg-slide',
16413		easing: 'ease',
16414		speed: 400,
16415		licenseKey: '0000-0000-000-0000',
16416		height: '100%',
16417		width: '100%',
16418		addClass: '',
16419		startClass: 'lg-start-zoom',
16420		backdropDuration: 300,
16421		container: '',
16422		startAnimationDuration: 400,
16423		zoomFromOrigin: true,
16424		hideBarsDelay: 0,
16425		showBarsAfter: 10000,
16426		slideDelay: 0,
16427		supportLegacyBrowser: true,
16428		allowMediaOverlap: false,
16429		videoMaxSize: '1280-720',
16430		loadYouTubePoster: true,
16431		defaultCaptionHeight: 0,
16432		ariaLabelledby: '',
16433		ariaDescribedby: '',
16434		resetScrollPosition: true,
16435		hideScrollbar: false,
16436		closable: true,
16437		swipeToClose: true,
16438		closeOnTap: true,
16439		showCloseIcon: true,
16440		showMaximizeIcon: false,
16441		loop: true,
16442		escKey: true,
16443		keyPress: true,
16444		trapFocus: true,
16445		controls: true,
16446		slideEndAnimation: true,
16447		hideControlOnEnd: false,
vendor: 15,066 bytes, lines 16448-16995
16448		mousewheel: false,
16449		getCaptionFromTitleOrAlt: true,
16450		appendSubHtmlTo: '.lg-sub-html',
16451		subHtmlSelectorRelative: false,
16452		preload: 2,
16453		numberOfSlideItemsInDom: 10,
16454		selector: '',
16455		selectWithin: '',
16456		nextHtml: '',
16457		prevHtml: '',
16458		index: 0,
16459		iframeWidth: '100%',
16460		iframeHeight: '100%',
16461		iframeMaxWidth: '100%',
16462		iframeMaxHeight: '100%',
16463		download: true,
16464		counter: true,
16465		appendCounterTo: '.lg-toolbar',
16466		swipeThreshold: 50,
16467		enableSwipe: true,
16468		enableDrag: true,
16469		dynamic: false,
16470		dynamicEl: [],
16471		extraProps: [],
16472		exThumbImage: '',
16473		isMobile: undefined,
16474		mobileSettings: {
16475			controls: false,
16476			showCloseIcon: false,
16477			download: false,
16478		},
16479		plugins: [],
16480		strings: {
16481			closeGallery: 'Close gallery',
16482			toggleMaximize: 'Toggle maximize',
16483			previousSlide: 'Previous slide',
16484			nextSlide: 'Next slide',
16485			download: 'Download',
16486			playVideo: 'Play video',
16487		},
16488	};
16489
16490	function initLgPolyfills() {
16491		(function () {
16492			if (typeof window.CustomEvent === 'function')
16493				return false;
16494			function CustomEvent(event, params) {
16495				params = params || {
16496					bubbles: false,
16497					cancelable: false,
16498					detail: null,
16499				};
16500				var evt = document.createEvent('CustomEvent');
16501				evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
16502				return evt;
16503			}
16504			window.CustomEvent = CustomEvent;
16505		})();
16506		(function () {
16507			if (!Element.prototype.matches) {
16508				Element.prototype.matches =
16509					Element.prototype.msMatchesSelector ||
16510						Element.prototype.webkitMatchesSelector;
16511			}
16512		})();
16513	}
16514	var lgQuery = /** @class */ (function () {
16515		function lgQuery(selector) {
16516			this.cssVenderPrefixes = [
16517				'TransitionDuration',
16518				'TransitionTimingFunction',
16519				'Transform',
16520				'Transition',
16521			];
16522			this.selector = this._getSelector(selector);
16523			this.firstElement = this._getFirstEl();
16524			return this;
16525		}
16526		lgQuery.generateUUID = function () {
16527			return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
16528				var r = (Math.random() * 16) | 0, v = c == 'x' ? r : (r & 0x3) | 0x8;
16529				return v.toString(16);
16530			});
16531		};
16532		lgQuery.prototype._getSelector = function (selector, context) {
16533			if (context === void 0) { context = document; }
16534			if (typeof selector !== 'string') {
16535				return selector;
16536			}
16537			context = context || document;
16538			var fl = selector.substring(0, 1);
16539			if (fl === '#') {
16540				return context.querySelector(selector);
16541			}
16542			else {
16543				return context.querySelectorAll(selector);
16544			}
16545		};
16546		lgQuery.prototype._each = function (func) {
16547			if (!this.selector) {
16548				return this;
16549			}
16550			if (this.selector.length !== undefined) {
16551				[].forEach.call(this.selector, func);
16552			}
16553			else {
16554				func(this.selector, 0);
16555			}
16556			return this;
16557		};
16558		lgQuery.prototype._setCssVendorPrefix = function (el, cssProperty, value) {
16559			// prettier-ignore
16560			var property = cssProperty.replace(/-([a-z])/gi, function (s, group1) {
16561				return group1.toUpperCase();
16562			});
16563			if (this.cssVenderPrefixes.indexOf(property) !== -1) {
16564				el.style[property.charAt(0).toLowerCase() + property.slice(1)] = value;
16565				el.style['webkit' + property] = value;
16566				el.style['moz' + property] = value;
16567				el.style['ms' + property] = value;
16568				el.style['o' + property] = value;
16569			}
16570			else {
16571				el.style[property] = value;
16572			}
16573		};
16574		lgQuery.prototype._getFirstEl = function () {
16575			if (this.selector && this.selector.length !== undefined) {
16576				return this.selector[0];
16577			}
16578			else {
16579				return this.selector;
16580			}
16581		};
16582		lgQuery.prototype.isEventMatched = function (event, eventName) {
16583			var eventNamespace = eventName.split('.');
16584			return event
16585				.split('.')
16586				.filter(function (e) { return e; })
16587				.every(function (e) {
16588				return eventNamespace.indexOf(e) !== -1;
16589			});
16590		};
16591		lgQuery.prototype.attr = function (attr, value) {
16592			if (value === undefined) {
16593				if (!this.firstElement) {
16594					return '';
16595				}
16596				return this.firstElement.getAttribute(attr);
16597			}
16598			this._each(function (el) {
16599				el.setAttribute(attr, value);
16600			});
16601			return this;
16602		};
16603		lgQuery.prototype.find = function (selector) {
16604			return $LG(this._getSelector(selector, this.selector));
16605		};
16606		lgQuery.prototype.first = function () {
16607			if (this.selector && this.selector.length !== undefined) {
16608				return $LG(this.selector[0]);
16609			}
16610			else {
16611				return $LG(this.selector);
16612			}
16613		};
16614		lgQuery.prototype.eq = function (index) {
16615			return $LG(this.selector[index]);
16616		};
16617		lgQuery.prototype.parent = function () {
16618			return $LG(this.selector.parentElement);
16619		};
16620		lgQuery.prototype.get = function () {
16621			return this._getFirstEl();
16622		};
16623		lgQuery.prototype.removeAttr = function (attributes) {
16624			var attrs = attributes.split(' ');
16625			this._each(function (el) {
16626				attrs.forEach(function (attr) { return el.removeAttribute(attr); });
16627			});
16628			return this;
16629		};
16630		lgQuery.prototype.wrap = function (className) {
16631			if (!this.firstElement) {
16632				return this;
16633			}
16634			var wrapper = document.createElement('div');
16635			wrapper.className = className;
16636			this.firstElement.parentNode.insertBefore(wrapper, this.firstElement);
16637			this.firstElement.parentNode.removeChild(this.firstElement);
16638			wrapper.appendChild(this.firstElement);
16639			return this;
16640		};
16641		lgQuery.prototype.addClass = function (classNames) {
16642			if (classNames === void 0) { classNames = ''; }
16643			this._each(function (el) {
16644				// IE doesn't support multiple arguments
16645				classNames.split(' ').forEach(function (className) {
16646					if (className) {
16647						el.classList.add(className);
16648					}
16649				});
16650			});
16651			return this;
16652		};
16653		lgQuery.prototype.removeClass = function (classNames) {
16654			this._each(function (el) {
16655				// IE doesn't support multiple arguments
16656				classNames.split(' ').forEach(function (className) {
16657					if (className) {
16658						el.classList.remove(className);
16659					}
16660				});
16661			});
16662			return this;
16663		};
16664		lgQuery.prototype.hasClass = function (className) {
16665			if (!this.firstElement) {
16666				return false;
16667			}
16668			return this.firstElement.classList.contains(className);
16669		};
16670		lgQuery.prototype.hasAttribute = function (attribute) {
16671			if (!this.firstElement) {
16672				return false;
16673			}
16674			return this.firstElement.hasAttribute(attribute);
16675		};
16676		lgQuery.prototype.toggleClass = function (className) {
16677			if (!this.firstElement) {
16678				return this;
16679			}
16680			if (this.hasClass(className)) {
16681				this.removeClass(className);
16682			}
16683			else {
16684				this.addClass(className);
16685			}
16686			return this;
16687		};
16688		lgQuery.prototype.css = function (property, value) {
16689			var _this = this;
16690			this._each(function (el) {
16691				_this._setCssVendorPrefix(el, property, value);
16692			});
16693			return this;
16694		};
16695		// Need to pass separate namespaces for separate elements
16696		lgQuery.prototype.on = function (events, listener) {
16697			var _this = this;
16698			if (!this.selector) {
16699				return this;
16700			}
16701			events.split(' ').forEach(function (event) {
16702				if (!Array.isArray(lgQuery.eventListeners[event])) {
16703					lgQuery.eventListeners[event] = [];
16704				}
16705				lgQuery.eventListeners[event].push(listener);
16706				_this.selector.addEventListener(event.split('.')[0], listener);
16707			});
16708			return this;
16709		};
16710		// @todo - test this
16711		lgQuery.prototype.once = function (event, listener) {
16712			var _this = this;
16713			this.on(event, function () {
16714				_this.off(event);
16715				listener(event);
16716			});
16717			return this;
16718		};
16719		lgQuery.prototype.off = function (event) {
16720			var _this = this;
16721			if (!this.selector) {
16722				return this;
16723			}
16724			Object.keys(lgQuery.eventListeners).forEach(function (eventName) {
16725				if (_this.isEventMatched(event, eventName)) {
16726					lgQuery.eventListeners[eventName].forEach(function (listener) {
16727						_this.selector.removeEventListener(eventName.split('.')[0], listener);
16728					});
16729					lgQuery.eventListeners[eventName] = [];
16730				}
16731			});
16732			return this;
16733		};
16734		lgQuery.prototype.trigger = function (event, detail) {
16735			if (!this.firstElement) {
16736				return this;
16737			}
16738			var customEvent = new CustomEvent(event.split('.')[0], {
16739				detail: detail || null,
16740			});
16741			this.firstElement.dispatchEvent(customEvent);
16742			return this;
16743		};
16744		// Does not support IE
16745		lgQuery.prototype.load = function (url) {
16746			var _this = this;
16747			fetch(url)
16748				.then(function (res) { return res.text(); })
16749				.then(function (html) {
16750				_this.selector.innerHTML = html;
16751			});
16752			return this;
16753		};
16754		lgQuery.prototype.html = function (html) {
16755			if (html === undefined) {
16756				if (!this.firstElement) {
16757					return '';
16758				}
16759				return this.firstElement.innerHTML;
16760			}
16761			this._each(function (el) {
16762				el.innerHTML = html;
16763			});
16764			return this;
16765		};
16766		lgQuery.prototype.append = function (html) {
16767			this._each(function (el) {
16768				if (typeof html === 'string') {
16769					el.insertAdjacentHTML('beforeend', html);
16770				}
16771				else {
16772					el.appendChild(html);
16773				}
16774			});
16775			return this;
16776		};
16777		lgQuery.prototype.prepend = function (html) {
16778			this._each(function (el) {
16779				el.insertAdjacentHTML('afterbegin', html);
16780			});
16781			return this;
16782		};
16783		lgQuery.prototype.remove = function () {
16784			this._each(function (el) {
16785				el.parentNode.removeChild(el);
16786			});
16787			return this;
16788		};
16789		lgQuery.prototype.empty = function () {
16790			this._each(function (el) {
16791				el.innerHTML = '';
16792			});
16793			return this;
16794		};
16795		lgQuery.prototype.scrollTop = function (scrollTop) {
16796			if (scrollTop !== undefined) {
16797				document.body.scrollTop = scrollTop;
16798				document.documentElement.scrollTop = scrollTop;
16799				return this;
16800			}
16801			else {
16802				return (window.pageYOffset ||
16803					document.documentElement.scrollTop ||
16804					document.body.scrollTop ||
16805					0);
16806			}
16807		};
16808		lgQuery.prototype.scrollLeft = function (scrollLeft) {
16809			if (scrollLeft !== undefined) {
16810				document.body.scrollLeft = scrollLeft;
16811				document.documentElement.scrollLeft = scrollLeft;
16812				return this;
16813			}
16814			else {
16815				return (window.pageXOffset ||
16816					document.documentElement.scrollLeft ||
16817					document.body.scrollLeft ||
16818					0);
16819			}
16820		};
16821		lgQuery.prototype.offset = function () {
16822			if (!this.firstElement) {
16823				return {
16824					left: 0,
16825					top: 0,
16826				};
16827			}
16828			var rect = this.firstElement.getBoundingClientRect();
16829			var bodyMarginLeft = $LG('body').style().marginLeft;
16830			// Minus body margin - https://stackoverflow.com/questions/30711548/is-getboundingclientrect-left-returning-a-wrong-value
16831			return {
16832				left: rect.left - parseFloat(bodyMarginLeft) + this.scrollLeft(),
16833				top: rect.top + this.scrollTop(),
16834			};
16835		};
16836		lgQuery.prototype.style = function () {
16837			if (!this.firstElement) {
16838				return {};
16839			}
16840			return (this.firstElement.currentStyle ||
16841				window.getComputedStyle(this.firstElement));
16842		};
16843		// Width without padding and border even if box-sizing is used.
16844		lgQuery.prototype.width = function () {
16845			var style = this.style();
16846			return (this.firstElement.clientWidth -
16847				parseFloat(style.paddingLeft) -
16848				parseFloat(style.paddingRight));
16849		};
16850		// Height without padding and border even if box-sizing is used.
16851		lgQuery.prototype.height = function () {
16852			var style = this.style();
16853			return (this.firstElement.clientHeight -
16854				parseFloat(style.paddingTop) -
16855				parseFloat(style.paddingBottom));
16856		};
16857		lgQuery.eventListeners = {};
16858		return lgQuery;
16859	}());
16860	function $LG(selector) {
16861		initLgPolyfills();
16862		return new lgQuery(selector);
16863	}
16864
16865	var defaultDynamicOptions = [
16866		'src',
16867		'sources',
16868		'subHtml',
16869		'subHtmlUrl',
16870		'html',
16871		'video',
16872		'poster',
16873		'slideName',
16874		'responsive',
16875		'srcset',
16876		'sizes',
16877		'iframe',
16878		'downloadUrl',
16879		'download',
16880		'width',
16881		'facebookShareUrl',
16882		'tweetText',
16883		'iframeTitle',
16884		'twitterShareUrl',
16885		'pinterestShareUrl',
16886		'pinterestText',
16887		'fbHtml',
16888		'disqusIdentifier',
16889		'disqusUrl',
16890	];
16891	// Convert html data-attribute to camalcase
16892	function convertToData(attr) {
16893		// FInd a way for lgsize
16894		if (attr === 'href') {
16895			return 'src';
16896		}
16897		attr = attr.replace('data-', '');
16898		attr = attr.charAt(0).toLowerCase() + attr.slice(1);
16899		attr = attr.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); });
16900		return attr;
16901	}
16902	var utils = {
16903		/**
16904		 * get possible width and height from the lgSize attribute. Used for ZoomFromOrigin option
16905		 */
16906		//Uncode edit ##START##
16907		getSize: function (el, container, spacing, defaultLgSize, galleryItem) {
16908		// getSize: function (el, container, spacing, defaultLgSize) {
16909		//Uncode edit ##END##
16910			if (spacing === void 0) { spacing = 0; }
16911			var LGel = $LG(el);
16912			var lgSize = LGel.attr('data-lg-size') || defaultLgSize;
16913			//Uncode edit ##START##
16914			if ( typeof galleryItem.size && galleryItem.size != null ) {
16915				lgSize = galleryItem.size;
16916			}
16917			//Uncode edit ##END##
16918			if (!lgSize) {
16919				return;
16920			}
16921			var isResponsiveSizes = lgSize.split(',');
16922			// if at-least two viewport sizes are available
16923			if (isResponsiveSizes[1]) {
16924				var wWidth = window.innerWidth;
16925				for (var i = 0; i < isResponsiveSizes.length; i++) {
16926					var size_1 = isResponsiveSizes[i];
16927					var responsiveWidth = parseInt(size_1.split('-')[2], 10);
16928					if (responsiveWidth > wWidth) {
16929						lgSize = size_1;
16930						break;
16931					}
16932					// take last item as last option
16933					if (i === isResponsiveSizes.length - 1) {
16934						lgSize = size_1;
16935					}
16936				}
16937			}
16938			var size = lgSize.split('-');
16939			var width = parseInt(size[0], 10);
16940			var height = parseInt(size[1], 10);
16941			var cWidth = container.width();
16942			var cHeight = container.height() - spacing;
16943			var maxWidth = Math.min(cWidth, width);
16944			var maxHeight = Math.min(cHeight, height);
16945			var ratio = Math.min(maxWidth / width, maxHeight / height);
16946			return { width: width * ratio, height: height * ratio };
16947		},
16948		/**
16949		 * @desc Get transform value based on the imageSize. Used for ZoomFromOrigin option
16950		 * @param {jQuery Element}
16951		 * @returns {String} Transform CSS string
16952		 */
16953		getTransform: function (el, container, top, bottom, imageSize) {
16954			if (!imageSize) {
16955				return;
16956			}
16957			var LGel = $LG(el).find('img').first();
16958			if (!LGel.get()) {
16959				return;
16960			}
16961			var containerRect = container.get().getBoundingClientRect();
16962			var wWidth = containerRect.width;
16963			// using innerWidth to include mobile safari bottom bar
16964			var wHeight = container.height() - (top + bottom);
16965			var elWidth = LGel.width();
16966			var elHeight = LGel.height();
16967			var elStyle = LGel.style();
16968			var x = (wWidth - elWidth) / 2 -
16969				LGel.offset().left +
16970				(parseFloat(elStyle.paddingLeft) || 0) +
16971				(parseFloat(elStyle.borderLeft) || 0) +
16972				$LG(window).scrollLeft() +
16973				containerRect.left;
16974			var y = (wHeight - elHeight) / 2 -
16975				LGel.offset().top +
16976				(parseFloat(elStyle.paddingTop) || 0) +
16977				(parseFloat(elStyle.borderTop) || 0) +
16978				$LG(window).scrollTop() +
16979				top;
16980			var scX = elWidth / imageSize.width;
16981			var scY = elHeight / imageSize.height;
16982			var transform = 'translate3d(' +
16983				(x *= -1) +
16984				'px, ' +
16985				(y *= -1) +
16986				'px, 0) scale3d(' +
16987				scX +
16988				', ' +
16989				scY +
16990				', 1)';
16991			return transform;
16992		},
16993		getIframeMarkup: function (iframeWidth, iframeHeight, iframeMaxWidth, iframeMaxHeight, src, iframeTitle) {
16994			var title = iframeTitle ? 'title="' + iframeTitle + '"' : '';
16995			return "<div class=\"lg-video-cont lg-has-iframe\" style=\"width:" 
vendor: 2,803 bytes, lines 16995-17067
16995+ iframeWidth + "; max-width:" + iframeMaxWidth + "; height: " + iframeHeight + "; max-height:" + iframeMaxHeight + "\">\n                    <iframe class=\"lg-object\" frameborder=\"0\" " + title + " src=\"" + src + "\"  allowfullscreen=\"true\"></iframe>\n                </div>";
16996		},
16997		getImgMarkup: function (index, src, altAttr, srcset, sizes, sources) {
16998			var srcsetAttr = srcset ? "srcset=\"" + srcset + "\"" : '';
16999			var sizesAttr = sizes ? "sizes=\"" + sizes + "\"" : '';
17000			var imgMarkup = "<img " + altAttr + " " + srcsetAttr + "  " + sizesAttr + " class=\"lg-object lg-image\" data-index=\"" + index + "\" src=\"" + src + "\" />";
17001			var sourceTag = '';
17002			if (sources) {
17003				var sourceObj = typeof sources === 'string' ? JSON.parse(sources) : sources;
17004				sourceTag = sourceObj.map(function (source) {
17005					var attrs = '';
17006					Object.keys(source).forEach(function (key) {
17007						// Do not remove the first space as it is required to separate the attributes
17008						attrs += " " + key + "=\"" + source[key] + "\"";
17009					});
17010					return "<source " + attrs + "></source>";
17011				});
17012			}
17013			return "" + sourceTag + imgMarkup;
17014		},
17015		// Get src from responsive src
17016		getResponsiveSrc: function (srcItms) {
17017			var rsWidth = [];
17018			var rsSrc = [];
17019			var src = '';
17020			for (var i = 0; i < srcItms.length; i++) {
17021				var _src = srcItms[i].split(' ');
17022				// Manage empty space
17023				if (_src[0] === '') {
17024					_src.splice(0, 1);
17025				}
17026				rsSrc.push(_src[0]);
17027				rsWidth.push(_src[1]);
17028			}
17029			var wWidth = window.innerWidth;
17030			for (var j = 0; j < rsWidth.length; j++) {
17031				if (parseInt(rsWidth[j], 10) > wWidth) {
17032					src = rsSrc[j];
17033					break;
17034				}
17035			}
17036			return src;
17037		},
17038		isImageLoaded: function (img) {
17039			if (!img)
17040				return false;
17041			// During the onload event, IE correctly identifies any images that
17042			// weren’t downloaded as not complete. Others should too. Gecko-based
17043			// browsers act like NS4 in that they report this incorrectly.
17044			if (!img.complete) {
17045				return false;
17046			}
17047			// However, they do have two very useful properties: naturalWidth and
17048			// naturalHeight. These give the true size of the image. If it failed
17049			// to load, either of these should be zero.
17050			if (img.naturalWidth === 0) {
17051				return false;
17052			}
17053			// No other way of checking: assume it’s ok.
17054			return true;
17055		},
17056		getVideoPosterMarkup: function (_poster, dummyImg, videoContStyle, playVideoString, _isVideo) {
17057			var videoClass = '';
17058			if (_isVideo && _isVideo.youtube) {
17059				videoClass = 'lg-has-youtube';
17060			}
17061			else if (_isVideo && _isVideo.vimeo) {
17062				videoClass = 'lg-has-vimeo';
17063			}
17064			else {
17065				videoClass = 'lg-has-html5';
17066			}
17067			return "<div class=\"lg-video-cont " + videoClass + "\" style=\"" + videoContStyle + "\">\n                <div class=\"lg-video-play-button\">
vendor: 4,991 bytes, lines 17067-17178
17067\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>";
17068		},
17069		getFocusableElements: function (container) {
17070			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])');
17071			var visibleElements = [].filter.call(elements, function (element) {
17072				var style = window.getComputedStyle(element);
17073				return style.display !== 'none' && style.visibility !== 'hidden';
17074			});
17075			return visibleElements;
17076		},
17077		/**
17078		 * @desc Create dynamic elements array from gallery items when dynamic option is false
17079		 * It helps to avoid frequent DOM interaction
17080		 * and avoid multiple checks for dynamic elments
17081		 *
17082		 * @returns {Array} dynamicEl
17083		 */
17084		getDynamicOptions: function (items, extraProps, getCaptionFromTitleOrAlt, exThumbImage) {
17085			var dynamicElements = [];
17086			var availableDynamicOptions = __spreadArrays(defaultDynamicOptions, extraProps);
17087			[].forEach.call(items, function (item) {
17088				var dynamicEl = {};
17089				for (var i = 0; i < item.attributes.length; i++) {
17090					var attr = item.attributes[i];
17091					if (attr.specified) {
17092						var dynamicAttr = convertToData(attr.name);
17093						var label = '';
17094						if (availableDynamicOptions.indexOf(dynamicAttr) > -1) {
17095							label = dynamicAttr;
17096						}
17097						if (label) {
17098							dynamicEl[label] = attr.value;
17099						}
17100					}
17101				}
17102				var currentItem = $LG(item);
17103				var alt = currentItem.find('img').first().attr('alt');
17104				var title = currentItem.attr('title');
17105				//Uncode edit ##START##
17106				// var thumb = exThumbImage
17107				var thumb = exThumbImage && currentItem.attr(exThumbImage)
17108				//Uncode edit ##END##
17109					? currentItem.attr(exThumbImage)
17110					: currentItem.find('img').first().attr('src');
17111				dynamicEl.thumb = thumb;
17112				//Uncode edit ##START##
17113				if (getCaptionFromTitleOrAlt && !dynamicEl.subHtml) {
17114					// dynamicEl.subHtml = title || alt || '';
17115					dynamicEl.subHtml = title || '';
17116				}
17117				// dynamicEl.alt = alt || title || '';
17118				dynamicEl.alt = title || '';
17119				var inlineType = currentItem.attr('data-type');
17120				dynamicEl.type = inlineType;
17121				//Uncode edit ##END##
17122				dynamicElements.push(dynamicEl);
17123			});
17124			return dynamicElements;
17125		},
17126		isMobile: function () {
17127			return /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
17128		},
17129		/**
17130		 * @desc Check the given src is video
17131		 * @param {String} src
17132		 * @return {Object} video type
17133		 * Ex:{ youtube  :  ["//www.youtube.com/watch?v=c0asJgSyxcY", "c0asJgSyxcY"] }
17134		 *
17135		 * @todo - this information can be moved to dynamicEl to avoid frequent calls
17136		 */
17137		isVideo: function (src, isHTML5VIdeo, index) {
17138			if (!src) {
17139				if (isHTML5VIdeo) {
17140					return {
17141						html5: true,
17142					};
17143				}
17144				else {
17145					console.warn('lightGallery :- data-src is not provided on slide item ' +
17146						(index + 1) +
17147						'. Please make sure the selector property is properly configured. More info - https://www.lightgalleryjs.com/demos/html-markup/');
17148					return;
17149				}
17150			}
17151			var youtube = src.match(/\/\/(?:www\.)?youtu(?:\.be|be\.com|be-nocookie\.com)\/(?:watch\?v=|embed\/)?([a-z0-9\-\_\%]+)([\&|?][\S]*)*/i);
17152			var vimeo = src.match(/\/\/(?:www\.)?(?:player\.)?vimeo.com\/(?:video\/)?([0-9a-z\-_]+)(.*)?/i);
17153			var wistia = src.match(/https?:\/\/(.+)?(wistia\.com|wi\.st)\/(medias|embed)\/([0-9a-z\-_]+)(.*)/);
17154			if (youtube) {
17155				return {
17156					youtube: youtube,
17157				};
17158			}
17159			else if (vimeo) {
17160				return {
17161					vimeo: vimeo,
17162				};
17163			}
17164			else if (wistia) {
17165				return {
17166					wistia: wistia,
17167				};
17168			}
17169		},
17170	};
17171
17172	// @ref - https://stackoverflow.com/questions/3971841/how-to-resize-images-proportionally-keeping-the-aspect-ratio
17173	// @ref - https://2ality.com/2017/04/setting-up-multi-platform-packages.html
17174	// Unique id for each gallery
17175	var lgId = 0;
17176	var LightGallery = /** @class */ (function () {
17177		function LightGallery(element, options) {
17178			this.lgOpened = false;
vendor: 4,563 bytes, lines 17179-17313
17179			this.index = 0;
17180			// lightGallery modules
17181			this.plugins = [];
17182			// false when lightGallery load first slide content;
17183			this.lGalleryOn = false;
17184			// True when a slide animation is in progress
17185			this.lgBusy = false;
17186			this.currentItemsInDom = [];
17187			// Scroll top value before lightGallery is opened
17188			this.prevScrollTop = 0;
17189			this.bodyPaddingRight = 0;
17190			this.isDummyImageRemoved = false;
17191			this.dragOrSwipeEnabled = false;
17192			this.mediaContainerPosition = {
17193				top: 0,
17194				bottom: 0,
17195			};
17196			if (!element) {
17197				return this;
17198			}
17199			lgId++;
17200			this.lgId = lgId;
17201			this.el = element;
17202			this.LGel = $LG(element);
17203			this.generateSettings(options);
17204			this.buildModules();
17205			// When using dynamic mode, ensure dynamicEl is an array
17206			if (this.settings.dynamic &&
17207				this.settings.dynamicEl !== undefined &&
17208				!Array.isArray(this.settings.dynamicEl)) {
17209				throw 'When using dynamic mode, you must also define dynamicEl as an Array.';
17210			}
17211			this.galleryItems = this.getItems();
17212			this.normalizeSettings();
17213			// Gallery items
17214			this.init();
17215			//Uncode edit ##START##
17216			// this.validateLicense();
17217			//Uncode edit ##END##
17218			return this;
17219		}
17220		LightGallery.prototype.generateSettings = function (options) {
17221			// lightGallery settings
17222			this.settings = __assign(__assign({}, lightGalleryCoreSettings), options);
17223			if (this.settings.isMobile &&
17224				typeof this.settings.isMobile === 'function'
17225				? this.settings.isMobile()
17226				: utils.isMobile()) {
17227				var mobileSettings = __assign(__assign({}, this.settings.mobileSettings), this.settings.mobileSettings);
17228				this.settings = __assign(__assign({}, this.settings), mobileSettings);
17229			}
17230		};
17231		LightGallery.prototype.normalizeSettings = function () {
17232			if (this.settings.slideEndAnimation) {
17233				this.settings.hideControlOnEnd = false;
17234			}
17235			if (!this.settings.closable) {
17236				this.settings.swipeToClose = false;
17237			}
17238			// And reset it on close to get the correct value next time
17239			this.zoomFromOrigin = this.settings.zoomFromOrigin;
17240			// At the moment, Zoom from image doesn't support dynamic options
17241			// @todo add zoomFromOrigin support for dynamic images
17242			if (this.settings.dynamic) {
17243				this.zoomFromOrigin = false;
17244			}
17245			if (!this.settings.container) {
17246				this.settings.container = document.body;
17247			}
17248			// settings.preload should not be grater than $item.length
17249			this.settings.preload = Math.min(this.settings.preload, this.galleryItems.length);
17250		};
17251		LightGallery.prototype.init = function () {
17252			var _this = this;
17253			this.addSlideVideoInfo(this.galleryItems);
17254			this.buildStructure();
17255			this.LGel.trigger(lGEvents.init, {
17256				instance: this,
17257			});
17258			if (this.settings.keyPress) {
17259				this.keyPress();
17260			}
17261			setTimeout(function () {
17262				_this.enableDrag();
17263				_this.enableSwipe();
17264				_this.triggerPosterClick();
17265			}, 50);
17266			this.arrow();
17267			if (this.settings.mousewheel) {
17268				this.mousewheel();
17269			}
17270			if (!this.settings.dynamic) {
17271				this.openGalleryOnItemClick();
17272			}
17273		};
17274		LightGallery.prototype.openGalleryOnItemClick = function () {
17275			var _this = this;
17276			var _loop_1 = function (index) {
17277				var element = this_1.items[index];
17278				var $element = $LG(element);
17279				// Using different namespace for click because click event should not unbind if selector is same object('this')
17280				// @todo manage all event listners - should have namespace that represent element
17281				var uuid = lgQuery.generateUUID();
17282				$element
17283					.attr('data-lg-id', uuid)
17284					.on("click.lgcustom-item-" + uuid, function (e) {
17285					e.preventDefault();
17286					var currentItemIndex = _this.settings.index || index;
17287					_this.openGallery(currentItemIndex, element);
17288				});
17289			};
17290			var this_1 = this;
17291			// Using for loop instead of using bubbling as the items can be any html element.
17292			for (var index = 0; index < this.items.length; index++) {
17293				_loop_1(index);
17294			}
17295		};
17296		/**
17297		 * Module constructor
17298		 * Modules are build incrementally.
17299		 * Gallery should be opened only once all the modules are initialized.
17300		 * use moduleBuildTimeout to make sure this
17301		 */
17302		LightGallery.prototype.buildModules = function () {
17303			var _this = this;
17304			this.settings.plugins.forEach(function (plugin) {
17305				_this.plugins.push(new plugin(_this, $LG));
17306			});
17307		};
17308		LightGallery.prototype.validateLicense = function () {
17309			if (!this.settings.licenseKey) {
17310				console.warn('Please provide a valid license key');
17311			}
17312			else if (this.settings.licenseKey === '0000-0000-000-0000') {
17313				console.warn("lightGallery: " + this.settings.licenseKey + " license key is not val
vendor: 17,473 bytes, lines 17313-17727
17313id for production use");
17314			}
17315		};
17316		LightGallery.prototype.getSlideItem = function (index) {
17317			return $LG(this.getSlideItemId(index));
17318		};
17319		LightGallery.prototype.getSlideItemId = function (index) {
17320			return "#lg-item-" + this.lgId + "-" + index;
17321		};
17322		LightGallery.prototype.getIdName = function (id) {
17323			return id + "-" + this.lgId;
17324		};
17325		LightGallery.prototype.getElementById = function (id) {
17326			return $LG("#" + this.getIdName(id));
17327		};
17328		LightGallery.prototype.manageSingleSlideClassName = function () {
17329			if (this.galleryItems.length < 2) {
17330				this.outer.addClass('lg-single-item');
17331			}
17332			else {
17333				this.outer.removeClass('lg-single-item');
17334			}
17335		};
17336		LightGallery.prototype.buildStructure = function () {
17337			var _this = this;
17338			var container = this.$container && this.$container.get();
17339			if (container) {
17340				return;
17341			}
17342			var controls = '';
17343			var subHtmlCont = '';
17344			// Create controls
17345			if (this.settings.controls) {
17346				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>";
17347			}
17348			if (this.settings.appendSubHtmlTo !== '.lg-item') {
17349				subHtmlCont =
17350					'<div class="lg-sub-html" role="status" aria-live="polite"></div>';
17351			}
17352			var addClasses = '';
17353			if (this.settings.allowMediaOverlap) {
17354				// Do not remove space before last single quote
17355				addClasses += 'lg-media-overlap ';
17356			}
17357			var ariaLabelledby = this.settings.ariaLabelledby
17358				? 'aria-labelledby="' + this.settings.ariaLabelledby + '"'
17359				: '';
17360			var ariaDescribedby = this.settings.ariaDescribedby
17361				? 'aria-describedby="' + this.settings.ariaDescribedby + '"'
17362				: '';
17363			var containerClassName = "lg-container " + this.settings.addClass + " " + (document.body !== this.settings.container ? 'lg-inline' : '');
17364			var closeIcon = this.settings.closable && this.settings.showCloseIcon
17365				? "<button type=\"button\" aria-label=\"" + this.settings.strings['closeGallery'] + "\" id=\"" + this.getIdName('lg-close') + "\" class=\"lg-close lg-icon\"></button>"
17366				: '';
17367			var maximizeIcon = this.settings.showMaximizeIcon
17368				? "<button type=\"button\" aria-label=\"" + this.settings.strings['toggleMaximize'] + "\" id=\"" + this.getIdName('lg-maximize') + "\" class=\"lg-maximize lg-icon\"></button>"
17369				: '';
17370			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'
17371				? subHtmlCont
17372				: '') + "\n                <div id=\"" + this.getIdName('lg-components') + "\" class=\"lg-components\">\n                    " + (this.settings.appendSubHtmlTo === '.lg-sub-html'
17373				? subHtmlCont
17374				: '') + "\n                </div>\n            </div>\n        </div>\n        ";
17375			$LG(this.settings.container).append(template);
17376			if (document.body !== this.settings.container) {
17377				$LG(this.settings.container).css('position', 'relative');
17378			}
17379			this.outer = this.getElementById('lg-outer');
17380			this.$lgComponents = this.getElementById('lg-components');
17381			this.$backdrop = this.getElementById('lg-backdrop');
17382			this.$container = this.getElementById('lg-container');
17383			this.$inner = this.getElementById('lg-inner');
17384			this.$content = this.getElementById('lg-content');
17385			this.$toolbar = this.getElementById('lg-toolbar');
17386			this.$backdrop.css('transition-duration', this.settings.backdropDuration + 'ms');
17387			var outerClassNames = this.settings.mode + " ";
17388			this.manageSingleSlideClassName();
17389			if (this.settings.enableDrag) {
17390				outerClassNames += 'lg-grab ';
17391			}
17392			this.outer.addClass(outerClassNames);
17393			this.$inner.css('transition-timing-function', this.settings.easing);
17394			this.$inner.css('transition-duration', this.settings.speed + 'ms');
17395			if (this.settings.download) {
17396				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>");
17397			}
17398			this.counter();
17399			$LG(window).on("resize.lg.global" + this.lgId + " orientationchange.lg.global" + this.lgId, function () {
17400				_this.refreshOnResize();
17401			});
17402			this.hideBars();
17403			this.manageCloseGallery();
17404			this.toggleMaximize();
17405			this.initModules();
17406		};
17407		LightGallery.prototype.refreshOnResize = function () {
17408			if (this.lgOpened) {
17409				var currentGalleryItem = this.galleryItems[this.index];
17410				var __slideVideoInfo = currentGalleryItem.__slideVideoInfo;
17411				this.mediaContainerPosition = this.getMediaContainerPosition();
17412				var _a = this.mediaContainerPosition, top_1 = _a.top, bottom = _a.bottom;
17413				//Uncode edit ##START##
17414				this.currentImageSize = utils.getSize(this.items[this.index], this.outer, top_1 + bottom, __slideVideoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
17415				// this.currentImageSize = utils.getSize(this.items[this.index], this.outer, top_1 + bottom, __slideVideoInfo && this.settings.videoMaxSize);
17416				//Uncode edit ##END##
17417				if (__slideVideoInfo) {
17418					this.resizeVideoSlide(this.index, this.currentImageSize);
17419				}
17420				if (this.zoomFromOrigin && !this.isDummyImageRemoved) {
17421					var imgStyle = this.getDummyImgStyles(this.currentImageSize);
17422					this.outer
17423						.find('.lg-current .lg-dummy-img')
17424						.first()
17425						.attr('style', imgStyle);
17426				}
17427				this.LGel.trigger(lGEvents.containerResize);
17428			}
17429		};
17430		LightGallery.prototype.resizeVideoSlide = function (index, imageSize) {
17431			var lgVideoStyle = this.getVideoContStyle(imageSize);
17432			var currentSlide = this.getSlideItem(index);
17433			currentSlide.find('.lg-video-cont').attr('style', lgVideoStyle);
17434		};
17435		/**
17436		 * Update slides dynamically.
17437		 * Add, edit or delete slides dynamically when lightGallery is opened.
17438		 * Modify the current gallery items and pass it via updateSlides method
17439		 * @note
17440		 * - Do not mutate existing lightGallery items directly.
17441		 * - Always pass new list of gallery items
17442		 * - You need to take care of thumbnails outside the gallery if any
17443		 * - user this method only if you want to update slides when the gallery is opened. Otherwise, use `refresh()` method.
17444		 * @param items Gallery items
17445		 * @param index After the update operation, which slide gallery should navigate to
17446		 * @category lGPublicMethods
17447		 * @example
17448		 * const plugin = lightGallery();
17449		 *
17450		 * // Adding slides dynamically
17451		 * let galleryItems = [
17452		 * // Access existing lightGallery items
17453		 * // galleryItems are automatically generated internally from the gallery HTML markup
17454		 * // or directly from galleryItems when dynamic gallery is used
17455		 *   ...plugin.galleryItems,
17456		 *     ...[
17457		 *       {
17458		 *         src: 'img/img-1.png',
17459		 *           thumb: 'img/thumb1.png',
17460		 *         },
17461		 *     ],
17462		 *   ];
17463		 *   plugin.updateSlides(
17464		 *     galleryItems,
17465		 *     plugin.index,
17466		 *   );
17467		 *
17468		 *
17469		 * // Remove slides dynamically
17470		 * galleryItems = JSON.parse(
17471		 *   JSON.stringify(updateSlideInstance.galleryItems),
17472		 * );
17473		 * galleryItems.shift();
17474		 * updateSlideInstance.updateSlides(galleryItems, 1);
17475		 * @see <a href="/demos/update-slides/">Demo</a>
17476		 */
17477		LightGallery.prototype.updateSlides = function (items, index) {
17478			if (this.index > items.length - 1) {
17479				this.index = items.length - 1;
17480			}
17481			if (items.length === 1) {
17482				this.index = 0;
17483			}
17484			if (!items.length) {
17485				this.closeGallery();
17486				return;
17487			}
17488			var currentSrc = this.galleryItems[index].src;
17489			this.galleryItems = items;
17490			this.updateControls();
17491			this.$inner.empty();
17492			this.currentItemsInDom = [];
17493			var _index = 0;
17494			// Find the current index based on source value of the slide
17495			this.galleryItems.some(function (galleryItem, itemIndex) {
17496				if (galleryItem.src === currentSrc) {
17497					_index = itemIndex;
17498					return true;
17499				}
17500				return false;
17501			});
17502			this.currentItemsInDom = this.organizeSlideItems(_index, -1);
17503			this.loadContent(_index, true);
17504			this.getSlideItem(_index).addClass('lg-current');
17505			this.index = _index;
17506			this.updateCurrentCounter(_index);
17507			this.LGel.trigger(lGEvents.updateSlides);
17508		};
17509		// Get gallery items based on multiple conditions
17510		LightGallery.prototype.getItems = function () {
17511			// Gallery items
17512			this.items = [];
17513			if (!this.settings.dynamic) {
17514				if (this.settings.selector === 'this') {
17515					this.items.push(this.el);
17516				}
17517				else if (this.settings.selector) {
17518					if (typeof this.settings.selector === 'string') {
17519						if (this.settings.selectWithin) {
17520							var selectWithin = $LG(this.settings.selectWithin);
17521							this.items = selectWithin
17522								.find(this.settings.selector)
17523								.get();
17524						}
17525						else {
17526							this.items = this.el.querySelectorAll(this.settings.selector);
17527						}
17528					}
17529					else {
17530						this.items = this.settings.selector;
17531					}
17532				}
17533				else {
17534					this.items = this.el.children;
17535				}
17536				return utils.getDynamicOptions(this.items, this.settings.extraProps, this.settings.getCaptionFromTitleOrAlt, this.settings.exThumbImage);
17537			}
17538			else {
17539				return this.settings.dynamicEl || [];
17540			}
17541		};
17542		LightGallery.prototype.shouldHideScrollbar = function () {
17543			return (this.settings.hideScrollbar &&
17544				document.body === this.settings.container);
17545		};
17546		LightGallery.prototype.hideScrollbar = function () {
17547			if (!this.shouldHideScrollbar()) {
17548				return;
17549			}
17550			this.bodyPaddingRight = parseFloat($LG('body').style().paddingRight);
17551			var bodyRect = document.documentElement.getBoundingClientRect();
17552			var scrollbarWidth = window.innerWidth - bodyRect.width;
17553			$LG(document.body).css('padding-right', scrollbarWidth + this.bodyPaddingRight + 'px');
17554			$LG(document.body).addClass('lg-overlay-open');
17555		};
17556		LightGallery.prototype.resetScrollBar = function () {
17557			if (!this.shouldHideScrollbar()) {
17558				return;
17559			}
17560			$LG(document.body).css('padding-right', this.bodyPaddingRight + 'px');
17561			$LG(document.body).removeClass('lg-overlay-open');
17562		};
17563		/**
17564		 * Open lightGallery.
17565		 * Open gallery with specific slide by passing index of the slide as parameter.
17566		 * @category lGPublicMethods
17567		 * @param {Number} index  - index of the slide
17568		 * @param {HTMLElement} element - Which image lightGallery should zoom from
17569		 *
17570		 * @example
17571		 * const $dynamicGallery = document.getElementById('dynamic-gallery-demo');
17572		 * const dynamicGallery = lightGallery($dynamicGallery, {
17573		 *     dynamic: true,
17574		 *     dynamicEl: [
17575		 *         {
17576		 *              src: 'img/1.jpg',
17577		 *              thumb: 'img/thumb-1.jpg',
17578		 *              subHtml: '<h4>Image 1 title</h4><p>Image 1 descriptions.</p>',
17579		 *         },
17580		 *         ...
17581		 *     ],
17582		 * });
17583		 * $dynamicGallery.addEventListener('click', function () {
17584		 *     // Starts with third item.(Optional).
17585		 *     // This is useful if you want use dynamic mode with
17586		 *     // custom thumbnails (thumbnails outside gallery),
17587		 *     dynamicGallery.openGallery(2);
17588		 * });
17589		 *
17590		 */
17591		LightGallery.prototype.openGallery = function (index, element) {
17592			var _this = this;
17593			if (index === void 0) { index = this.settings.index; }
17594			// prevent accidental double execution
17595			if (this.lgOpened)
17596				return;
17597			this.lgOpened = true;
17598			this.outer.removeClass('lg-hide-items');
17599			this.hideScrollbar();
17600			// Add display block, but still has opacity 0
17601			this.$container.addClass('lg-show');
17602			var itemsToBeInsertedToDom = this.getItemsToBeInsertedToDom(index, index);
17603			this.currentItemsInDom = itemsToBeInsertedToDom;
17604			var items = '';
17605			itemsToBeInsertedToDom.forEach(function (item) {
17606				items = items + ("<div id=\"" + item + "\" class=\"lg-item\"></div>");
17607			});
17608			this.$inner.append(items);
17609			this.addHtml(index);
17610			var transform = '';
17611			this.mediaContainerPosition = this.getMediaContainerPosition();
17612			var _a = this.mediaContainerPosition, top = _a.top, bottom = _a.bottom;
17613			if (!this.settings.allowMediaOverlap) {
17614				this.setMediaContainerPosition(top, bottom);
17615			}
17616			var __slideVideoInfo = this.galleryItems[index].__slideVideoInfo;
17617			if (this.zoomFromOrigin && element) {
17618				//Uncode edit ##START##
17619				this.currentImageSize = utils.getSize(element, this.outer, top + bottom, __slideVideoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
17620				// this.currentImageSize = utils.getSize(element, this.outer, top + bottom, __slideVideoInfo && this.settings.videoMaxSize);
17621				//Uncode edit ##END##
17622				transform = utils.getTransform(element, this.outer, top, bottom, this.currentImageSize);
17623			}
17624			if (!this.zoomFromOrigin || !transform) {
17625				this.outer.addClass(this.settings.startClass);
17626				this.getSlideItem(index).removeClass('lg-complete');
17627			}
17628			var timeout = this.settings.zoomFromOrigin
17629				? 100
17630				: this.settings.backdropDuration;
17631			setTimeout(function () {
17632				_this.outer.addClass('lg-components-open');
17633			}, timeout);
17634			this.index = index;
17635			//Uncode edit ##START##
17636			// this.LGel.trigger(lGEvents.beforeOpen);
17637			this.LGel.trigger(lGEvents.beforeOpen, {
17638				galleryItems: this.galleryItems,
17639				items: this.items,
17640				outer: this.outer,
17641			});
17642			//Uncode edit ##END##
17643			// add class lg-current to remove initial transition
17644			this.getSlideItem(index).addClass('lg-current');
17645			this.lGalleryOn = false;
17646			// Store the current scroll top value to scroll back after closing the gallery..
17647			this.prevScrollTop = $LG(window).scrollTop();
17648			setTimeout(function () {
17649				// Need to check both zoomFromOrigin and transform values as we need to set set the
17650				// default opening animation if user missed to add the lg-size attribute
17651				if (_this.zoomFromOrigin && transform) {
17652					var currentSlide_1 = _this.getSlideItem(index);
17653					currentSlide_1.css('transform', transform);
17654					setTimeout(function () {
17655						currentSlide_1
17656							.addClass('lg-start-progress lg-start-end-progress')
17657							.css('transition-duration', _this.settings.startAnimationDuration + 'ms');
17658						_this.outer.addClass('lg-zoom-from-image');
17659					});
17660					setTimeout(function () {
17661						currentSlide_1.css('transform', 'translate3d(0, 0, 0)');
17662					}, 100);
17663				}
17664				setTimeout(function () {
17665					_this.$backdrop.addClass('in');
17666					_this.$container.addClass('lg-show-in');
17667				}, 10);
17668				setTimeout(function () {
17669					if (_this.settings.trapFocus &&
17670						document.body === _this.settings.container) {
17671						_this.trapFocus();
17672					}
17673				}, _this.settings.backdropDuration + 50);
17674				// lg-visible class resets gallery opacity to 1
17675				if (!_this.zoomFromOrigin || !transform) {
17676					setTimeout(function () {
17677						_this.outer.addClass('lg-visible');
17678					}, _this.settings.backdropDuration);
17679				}
17680				// initiate slide function
17681				_this.slide(index, false, false, false);
17682				_this.LGel.trigger(lGEvents.afterOpen);
17683			});
17684			if (document.body === this.settings.container) {
17685				$LG('html').addClass('lg-on');
17686			}
17687		};
17688		/**
17689		 * Note - Changing the position of the media on every slide transition creates a flickering effect.
17690		 * Therefore, The height of the caption is calculated dynamically, only once based on the first slide caption.
17691		 * if you have dynamic captions for each media,
17692		 * you can provide an appropriate height for the captions via allowMediaOverlap option
17693		 */
17694		LightGallery.prototype.getMediaContainerPosition = function () {
17695			if (this.settings.allowMediaOverlap) {
17696				return {
17697					top: 0,
17698					bottom: 0,
17699				};
17700			}
17701			var top = this.$toolbar.get().clientHeight || 0;
17702			var subHtml = this.outer.find('.lg-components .lg-sub-html').get();
17703			var captionHeight = this.settings.defaultCaptionHeight ||
17704				(subHtml && subHtml.clientHeight) ||
17705				0;
17706			var thumbContainer = this.outer.find('.lg-thumb-outer').get();
17707			var thumbHeight = thumbContainer ? thumbContainer.clientHeight : 0;
17708			var bottom = thumbHeight + captionHeight;
17709			//Uncode edit ##START##
17710			bottom = bottom < 55 ? 55 : bottom;
17711			//Uncode edit ##END##
17712			return {
17713				top: top,
17714				bottom: bottom,
17715			};
17716		};
17717		LightGallery.prototype.setMediaContainerPosition = function (top, bottom) {
17718			if (top === void 0) { top = 0; }
17719			if (bottom === void 0) { bottom = 0; }
17720			this.$content.css('top', top + 'px').css('bottom', bottom + 'px');
17721		};
17722		LightGallery.prototype.hideBars = function () {
17723			var _this = this;
17724			// Hide controllers if mouse doesn't move for some period
17725			setTimeout(function () {
17726				_this.outer.removeClass('lg-hide-items');
17727				if (_this.settings.hideBarsDelay > 0) {
vendor: 4,223 bytes, lines 17728-17858
17728					_this.outer.on('mousemove.lg click.lg touchstart.lg', function () {
17729						_this.outer.removeClass('lg-hide-items');
17730						clearTimeout(_this.hideBarTimeout);
17731						// Timeout will be cleared on each slide movement also
17732						_this.hideBarTimeout = setTimeout(function () {
17733							_this.outer.addClass('lg-hide-items');
17734						}, _this.settings.hideBarsDelay);
17735					});
17736					_this.outer.trigger('mousemove.lg');
17737				}
17738			}, this.settings.showBarsAfter);
17739		};
17740		LightGallery.prototype.initPictureFill = function ($img) {
17741			if (this.settings.supportLegacyBrowser) {
17742				try {
17743					picturefill({
17744						elements: [$img.get()],
17745					});
17746				}
17747				catch (e) {
17748					console.warn('lightGallery :- If you want srcset or picture tag to be supported for older browser please include picturefil javascript library in your document.');
17749				}
17750			}
17751		};
17752		/**
17753		 *  @desc Create image counter
17754		 *  Ex: 1/10
17755		 */
17756		LightGallery.prototype.counter = function () {
17757			if (this.settings.counter) {
17758				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>";
17759				this.outer.find(this.settings.appendCounterTo).append(counterHtml);
17760			}
17761		};
17762		/**
17763		 *  @desc add sub-html into the slide
17764		 *  @param {Number} index - index of the slide
17765		 */
17766		LightGallery.prototype.addHtml = function (index) {
17767			var subHtml;
17768			var subHtmlUrl;
17769			if (this.galleryItems[index].subHtmlUrl) {
17770				subHtmlUrl = this.galleryItems[index].subHtmlUrl;
17771			}
17772			else {
17773				subHtml = this.galleryItems[index].subHtml;
17774			}
17775			if (!subHtmlUrl) {
17776				if (subHtml) {
17777					// get first letter of sub-html
17778					// if first letter starts with . or # get the html form the jQuery object
17779					var fL = subHtml.substring(0, 1);
17780					if (fL === '.' || fL === '#') {
17781						if (this.settings.subHtmlSelectorRelative &&
17782							!this.settings.dynamic) {
17783							subHtml = $LG(this.items)
17784								.eq(index)
17785								.find(subHtml)
17786								.first()
17787								.html();
17788						}
17789						else {
17790							subHtml = $LG(subHtml).first().html();
17791						}
17792					}
17793				}
17794				else {
17795					subHtml = '';
17796				}
17797			}
17798			if (this.settings.appendSubHtmlTo !== '.lg-item') {
17799				if (subHtmlUrl) {
17800					this.outer.find('.lg-sub-html').load(subHtmlUrl);
17801				}
17802				else {
17803					this.outer.find('.lg-sub-html').html(subHtml);
17804				}
17805			}
17806			else {
17807				var currentSlide = $LG(this.getSlideItemId(index));
17808				if (subHtmlUrl) {
17809					currentSlide.load(subHtmlUrl);
17810				}
17811				else {
17812					currentSlide.append("<div class=\"lg-sub-html\">" + subHtml + "</div>");
17813				}
17814			}
17815			// Add lg-empty-html class if title doesn't exist
17816			if (typeof subHtml !== 'undefined' && subHtml !== null) {
17817				if (subHtml === '') {
17818					this.outer
17819						.find(this.settings.appendSubHtmlTo)
17820						.addClass('lg-empty-html');
17821				}
17822				else {
17823					this.outer
17824						.find(this.settings.appendSubHtmlTo)
17825						.removeClass('lg-empty-html');
17826				}
17827			}
17828			this.LGel.trigger(lGEvents.afterAppendSubHtml, {
17829				index: index,
17830			});
17831		};
17832		/**
17833		 *  @desc Preload slides
17834		 *  @param {Number} index - index of the slide
17835		 * @todo preload not working for the first slide, Also, should work for the first and last slide as well
17836		 */
17837		LightGallery.prototype.preload = function (index) {
17838			for (var i = 1; i <= this.settings.preload; i++) {
17839				if (i >= this.galleryItems.length - index) {
17840					break;
17841				}
17842				this.loadContent(index + i, false);
17843			}
17844			for (var j = 1; j <= this.settings.preload; j++) {
17845				if (index - j < 0) {
17846					break;
17847				}
17848				this.loadContent(index - j, false);
17849			}
17850		};
17851		LightGallery.prototype.getDummyImgStyles = function (imageSize) {
17852			if (!imageSize)
17853				return '';
17854			return "width:" + imageSize.width + "px;\n                margin-left: -" + imageSize.width / 2 + "px;\n                margin-top: -" + imageSize.height / 2 + "px;\n                height:" + imageSize.height + "px";
17855		};
17856		LightGallery.prototype.getVideoContStyle = function (imageSize) {
17857			if (!imageSize)
17858				return '';
17859			return "width:" + imageSize.width + "px;\n                height:" + imageSize.height + "px";
17860		};
17861		LightGallery.prototype.getDummyImageContent = function ($currentSlide, index, alt) {
17862			var $currentItem;
17863			if (!this.settings.dynamic) {
17864				$currentItem = $LG(this.items).eq(index);
17865			}
17866			if ($currentItem) {
17867				var _dummyImgSrc = void 0;
17868				if (!this.settings.exThumbImage) {
17869					_dummyImgSrc = $currentItem.find('img').first().attr('src');
17870				}
17871				else {
17872					_dummyImgSrc = $currentItem.attr(this.settings.exThumbImage);
17873				}
17874				if (!_dummyImgSrc)
17875					return '';
17876				var imgStyle = this.getDummyImgStyles(this.currentImageSize);
17877				var dummyImgContent = "<img " + alt + " style=\"" + imgStyle + "\" class=\"lg-dummy-img\" src=\"" + _dummyImgSrc + "\" />";
17878				$currentSlide.addClass('lg-first-slide');
17879				this.outer.addClass('lg-first-slide-loading');
17880				return dummyImgContent;
17881			}
17882			return '';
17883		};
17884		LightGallery.prototype.setImgMarkup = function (src, $currentSlide, index) {
17885			var currentGalleryItem = this.galleryItems[index];
17886			var alt = currentGalleryItem.alt, srcset = currentGalleryItem.srcset, sizes = currentGalleryItem.sizes, sources = currentGalleryItem.sources;
17887			// Use the thumbnail as dummy image which will be resized to actual image size and
17888			// displayed on top of actual image
17889			var imgContent = '';
17890			var altAttr = alt ? 'alt="' + alt + '"' : '';
17891			if (this.isFirstSlideWithZoomAnimation()) {
17892				imgContent = this.getDummyImageContent($currentSlide, index, altAttr);
17893			}
17894			else {
17895				imgContent = utils.getImgMarkup(index, src, altAttr, srcset, sizes, sources);
17896			}
17897			var imgMarkup = "<picture class=\"lg-img-wrap\"> " + imgContent + "</picture>";
17898			$currentSlide.prepend(imgMarkup);
17899		};
17900		LightGallery.prototype.onSlideObjectLoad = function ($slide, isHTML5VideoWithoutPoster, onLoad, onError) {
17901			var mediaObject = $slide.find('.lg-object').first();
17902			if (utils.isImageLoaded(mediaObject.get()) ||
17903				isHTML5VideoWithoutPoster) {
17904				onLoad();
17905			}
17906			else {
17907				mediaObject.on('load.lg error.lg', function () {
17908					onLoad && onLoad();
17909				});
17910				mediaObject.on('error.lg', function () {
17911					onError && onError();
17912				});
17913			}
17914		};
17915		/**
17916		 *
17917		 * @param $el Current slide item
17918		 * @param index
17919		 * @param delay Delay is 0 except first time
17920		 * @param speed Speed is same as delay, except it is 0 if gallery is opened via hash plugin
17921		 * @param isFirstSlide
17922		 */
17923		LightGallery.prototype.onLgObjectLoad = function (currentSlide, index, delay, speed, isFirstSlide, isHTML5VideoWithoutPoster) {
17924			var _this = this;
17925			//Uncode edit ##START##
17926			var $item = _this.galleryItems[index],
17927				type = $item.type;
17928
17929			if ( typeof $item.src !== 'undefined' ) {
17930				var inline_id = $item.src.replace('#', ''),
17931					$inline = document.getElementById(inline_id),
17932					inline_html;
17933
17934				if ( type === 'inline' && inline_id != null && typeof $inline !== 'undefined' ) {
17935					inline_html = $inline.innerHTML;
17936				} else {
17937					inline_html = '';
17938				}
17939			}
17940			//Uncode edit ##END##
17941			this.onSlideObjectLoad(currentSlide, true, function () {
17942				_this.triggerSlideItemLoad(currentSlide, index, delay, speed, isFirstSlide);
17943			}, function () {
17944				currentSlide.addClass('lg-complete lg-complete_');
17945				//Uncode edit ##START##
17946				// currentSlide.html('<span class="lg-error-msg">Oops... Failed to load content...</span>');
17947				if ( inline_html !== '' ) {
17948					currentSlide.html(inline_html);
17949				} else {
17950					currentSlide.html('<span class="lg-error-msg">Oops... Failed to load content...</span>');
17951				}
17952				//Uncode edit ##END##
17953			});
17954		};
17955		LightGallery.prototype.triggerSlideItemLoad = function ($currentSlide, index, delay, speed, isFirstSlide) {
17956			var _this = this;
17957			var currentGalleryItem = this.galleryItems[index];
17958			// Adding delay for video slides without poster for better performance and user experience
17959			// Videos should start playing once once the gallery is completely loaded
17960			var _speed = isFirstSlide &&
vendor: 37,617 bytes, lines 17961-19043
17961				this.getSlideType(currentGalleryItem) === 'video' &&
17962				!currentGalleryItem.poster
17963				? speed
17964				: 0;
17965			setTimeout(function () {
17966				$currentSlide.addClass('lg-complete lg-complete_');
17967				_this.LGel.trigger(lGEvents.slideItemLoad, {
17968					index: index,
17969					delay: delay || 0,
17970					isFirstSlide: isFirstSlide,
17971				});
17972			}, _speed);
17973		};
17974		LightGallery.prototype.isFirstSlideWithZoomAnimation = function () {
17975			return !!(!this.lGalleryOn &&
17976				this.zoomFromOrigin &&
17977				this.currentImageSize);
17978		};
17979		// Add video slideInfo
17980		LightGallery.prototype.addSlideVideoInfo = function (items) {
17981			var _this = this;
17982			items.forEach(function (element, index) {
17983				element.__slideVideoInfo = utils.isVideo(element.src, !!element.video, index);
17984				if (element.__slideVideoInfo &&
17985					_this.settings.loadYouTubePoster &&
17986					!element.poster &&
17987					element.__slideVideoInfo.youtube) {
17988					element.poster = "//img.youtube.com/vi/" + element.__slideVideoInfo.youtube[1] + "/maxresdefault.jpg";
17989				}
17990			});
17991		};
17992		/**
17993		 *  Load slide content into slide.
17994		 *  This is used to load content into slides that is not visible too
17995		 *  @param {Number} index - index of the slide.
17996		 *  @param {Boolean} rec - if true call loadcontent() function again.
17997		 */
17998		LightGallery.prototype.loadContent = function (index, rec) {
17999			var _this = this;
18000			var currentGalleryItem = this.galleryItems[index];
18001			var $currentSlide = $LG(this.getSlideItemId(index));
18002			var poster = currentGalleryItem.poster, srcset = currentGalleryItem.srcset, sizes = currentGalleryItem.sizes, sources = currentGalleryItem.sources;
18003			var src = currentGalleryItem.src;
18004			var video = currentGalleryItem.video;
18005			var _html5Video = video && typeof video === 'string' ? JSON.parse(video) : video;
18006			if (currentGalleryItem.responsive) {
18007				var srcDyItms = currentGalleryItem.responsive.split(',');
18008				src = utils.getResponsiveSrc(srcDyItms) || src;
18009			}
18010			var videoInfo = currentGalleryItem.__slideVideoInfo;
18011			var lgVideoStyle = '';
18012			var iframe = !!currentGalleryItem.iframe;
18013			var isFirstSlide = !this.lGalleryOn;
18014			// delay for adding complete class. it is 0 except first time.
18015			var delay = 0;
18016			if (isFirstSlide) {
18017				if (this.zoomFromOrigin && this.currentImageSize) {
18018					delay = this.settings.startAnimationDuration + 10;
18019				}
18020				else {
18021					delay = this.settings.backdropDuration + 10;
18022				}
18023			}
18024			if (!$currentSlide.hasClass('lg-loaded')) {
18025				if (videoInfo) {
18026					var _a = this.mediaContainerPosition, top_2 = _a.top, bottom = _a.bottom;
18027					//Uncode edit ##START##
18028					var videoSize = utils.getSize(this.items[index], this.outer, top_2 + bottom, videoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
18029					// var videoSize = utils.getSize(this.items[index], this.outer, top_2 + bottom, videoInfo && this.settings.videoMaxSize);
18030					//Uncode edit ##END##
18031					lgVideoStyle = this.getVideoContStyle(videoSize);
18032				}
18033				if (iframe) {
18034					var markup = utils.getIframeMarkup(this.settings.iframeWidth, this.settings.iframeHeight, this.settings.iframeMaxWidth, this.settings.iframeMaxHeight, src, currentGalleryItem.iframeTitle);
18035					$currentSlide.prepend(markup);
18036				}
18037				else if (poster) {
18038					var dummyImg = '';
18039					var hasStartAnimation = isFirstSlide &&
18040						this.zoomFromOrigin &&
18041						this.currentImageSize;
18042					if (hasStartAnimation) {
18043						dummyImg = this.getDummyImageContent($currentSlide, index, '');
18044					}
18045					var markup = utils.getVideoPosterMarkup(poster, dummyImg || '', lgVideoStyle, this.settings.strings['playVideo'], videoInfo);
18046					$currentSlide.prepend(markup);
18047				}
18048				//Uncode edit ##START##
18049				// else if (videoInfo) {
18050				else if (videoInfo || this.getSlideType(currentGalleryItem) === 'audio') {
18051					if (! _html5Video) {
18052						var markup = "<div class=\"lg-video-cont \" style=\"" + lgVideoStyle + "\"></div>";
18053					}
18054					//Uncode edit ##END##
18055					$currentSlide.prepend(markup);
18056				}
18057				else {
18058					this.setImgMarkup(src, $currentSlide, index);
18059					if (srcset || sources) {
18060						var $img = $currentSlide.find('.lg-object');
18061						this.initPictureFill($img);
18062					}
18063				}
18064				if (poster || videoInfo) {
18065					this.LGel.trigger(lGEvents.hasVideo, {
18066						index: index,
18067						src: src,
18068						html5Video: _html5Video,
18069						hasPoster: !!poster,
18070					});
18071				}
18072				this.LGel.trigger(lGEvents.afterAppendSlide, { index: index });
18073				if (this.lGalleryOn &&
18074					this.settings.appendSubHtmlTo === '.lg-item') {
18075					this.addHtml(index);
18076				}
18077			}
18078			// For first time add some delay for displaying the start animation.
18079			var _speed = 0;
18080			// Do not change the delay value because it is required for zoom plugin.
18081			// If gallery opened from direct url (hash) speed value should be 0
18082			if (delay && !$LG(document.body).hasClass('lg-from-hash')) {
18083				_speed = delay;
18084			}
18085			// Only for first slide and zoomFromOrigin is enabled
18086			if (this.isFirstSlideWithZoomAnimation()) {
18087				setTimeout(function () {
18088					$currentSlide
18089						.removeClass('lg-start-end-progress lg-start-progress')
18090						.removeAttr('style');
18091				}, this.settings.startAnimationDuration + 100);
18092				if (!$currentSlide.hasClass('lg-loaded')) {
18093					setTimeout(function () {
18094						if (_this.getSlideType(currentGalleryItem) === 'image') {
18095							var alt = currentGalleryItem.alt;
18096							var altAttr = alt ? 'alt="' + alt + '"' : '';
18097							$currentSlide
18098								.find('.lg-img-wrap')
18099								.append(utils.getImgMarkup(index, src, altAttr, srcset, sizes, currentGalleryItem.sources));
18100							if (srcset || sources) {
18101								var $img = $currentSlide.find('.lg-object');
18102								_this.initPictureFill($img);
18103							}
18104						}
18105						if (_this.getSlideType(currentGalleryItem) === 'image' ||
18106							(_this.getSlideType(currentGalleryItem) === 'video' &&
18107								poster)) {
18108							_this.onLgObjectLoad($currentSlide, index, delay, _speed, true, false);
18109							// load remaining slides once the slide is completely loaded
18110							_this.onSlideObjectLoad($currentSlide, !!(videoInfo && videoInfo.html5 && !poster), function () {
18111								_this.loadContentOnFirstSlideLoad(index, $currentSlide, _speed);
18112							}, function () {
18113								_this.loadContentOnFirstSlideLoad(index, $currentSlide, _speed);
18114							});
18115						}
18116					}, this.settings.startAnimationDuration + 100);
18117				}
18118			}
18119			// SLide content has been added to dom
18120			$currentSlide.addClass('lg-loaded');
18121			if (!this.isFirstSlideWithZoomAnimation() ||
18122				(this.getSlideType(currentGalleryItem) === 'video' && !poster)) {
18123				//Uncode edit ##START##
18124				// this.onLgObjectLoad($currentSlide, index, delay, _speed, isFirstSlide, !!(videoInfo && videoInfo.html5 && !poster));
18125				this.onLgObjectLoad($currentSlide, index, delay, _speed, isFirstSlide, !!( (videoInfo && videoInfo.html5 && !poster) || this.getSlideType(currentGalleryItem) === 'audio'));
18126				//Uncode edit ##END##
18127			}
18128			// When gallery is opened once content is loaded (second time) need to add lg-complete class for css styling
18129			if ((!this.zoomFromOrigin || !this.currentImageSize) &&
18130				$currentSlide.hasClass('lg-complete_') &&
18131				!this.lGalleryOn) {
18132				setTimeout(function () {
18133					$currentSlide.addClass('lg-complete');
18134				}, this.settings.backdropDuration);
18135			}
18136			// Content loaded
18137			// Need to set lGalleryOn before calling preload function
18138			this.lGalleryOn = true;
18139			if (rec === true) {
18140				if (!$currentSlide.hasClass('lg-complete_')) {
18141					$currentSlide
18142						.find('.lg-object')
18143						.first()
18144						.on('load.lg error.lg', function () {
18145						_this.preload(index);
18146					});
18147				}
18148				else {
18149					this.preload(index);
18150				}
18151			}
18152		};
18153		/**
18154		 * @desc Remove dummy image content and load next slides
18155		 * Called only for the first time if zoomFromOrigin animation is enabled
18156		 * @param index
18157		 * @param $currentSlide
18158		 * @param speed
18159		 */
18160		LightGallery.prototype.loadContentOnFirstSlideLoad = function (index, $currentSlide, speed) {
18161			var _this = this;
18162			setTimeout(function () {
18163				$currentSlide.find('.lg-dummy-img').remove();
18164				$currentSlide.removeClass('lg-first-slide');
18165				_this.outer.removeClass('lg-first-slide-loading');
18166				_this.isDummyImageRemoved = true;
18167				_this.preload(index);
18168			}, speed + 300);
18169		};
18170		LightGallery.prototype.getItemsToBeInsertedToDom = function (index, prevIndex, numberOfItems) {
18171			var _this = this;
18172			if (numberOfItems === void 0) { numberOfItems = 0; }
18173			var itemsToBeInsertedToDom = [];
18174			// Minimum 2 items should be there
18175			var possibleNumberOfItems = Math.max(numberOfItems, 3);
18176			possibleNumberOfItems = Math.min(possibleNumberOfItems, this.galleryItems.length);
18177			var prevIndexItem = "lg-item-" + this.lgId + "-" + prevIndex;
18178			if (this.galleryItems.length <= 3) {
18179				this.galleryItems.forEach(function (_element, index) {
18180					itemsToBeInsertedToDom.push("lg-item-" + _this.lgId + "-" + index);
18181				});
18182				return itemsToBeInsertedToDom;
18183			}
18184			if (index < (this.galleryItems.length - 1) / 2) {
18185				for (var idx = index; idx > index - possibleNumberOfItems / 2 && idx >= 0; idx--) {
18186					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + idx);
18187				}
18188				var numberOfExistingItems = itemsToBeInsertedToDom.length;
18189				for (var idx = 0; idx < possibleNumberOfItems - numberOfExistingItems; idx++) {
18190					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (index + idx + 1));
18191				}
18192			}
18193			else {
18194				for (var idx = index; idx <= this.galleryItems.length - 1 &&
18195					idx < index + possibleNumberOfItems / 2; idx++) {
18196					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + idx);
18197				}
18198				var numberOfExistingItems = itemsToBeInsertedToDom.length;
18199				for (var idx = 0; idx < possibleNumberOfItems - numberOfExistingItems; idx++) {
18200					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (index - idx - 1));
18201				}
18202			}
18203			if (this.settings.loop) {
18204				if (index === this.galleryItems.length - 1) {
18205					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + 0);
18206				}
18207				else if (index === 0) {
18208					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (this.galleryItems.length - 1));
18209				}
18210			}
18211			if (itemsToBeInsertedToDom.indexOf(prevIndexItem) === -1) {
18212				itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + prevIndex);
18213			}
18214			return itemsToBeInsertedToDom;
18215		};
18216		LightGallery.prototype.organizeSlideItems = function (index, prevIndex) {
18217			var _this = this;
18218			var itemsToBeInsertedToDom = this.getItemsToBeInsertedToDom(index, prevIndex, this.settings.numberOfSlideItemsInDom);
18219			itemsToBeInsertedToDom.forEach(function (item) {
18220				if (_this.currentItemsInDom.indexOf(item) === -1) {
18221					_this.$inner.append("<div id=\"" + item + "\" class=\"lg-item\"></div>");
18222				}
18223			});
18224			this.currentItemsInDom.forEach(function (item) {
18225				if (itemsToBeInsertedToDom.indexOf(item) === -1) {
18226					$LG("#" + item).remove();
18227				}
18228			});
18229			return itemsToBeInsertedToDom;
18230		};
18231		/**
18232		 * Get previous index of the slide
18233		 */
18234		LightGallery.prototype.getPreviousSlideIndex = function () {
18235			var prevIndex = 0;
18236			try {
18237				var currentItemId = this.outer
18238					.find('.lg-current')
18239					.first()
18240					.attr('id');
18241				prevIndex = parseInt(currentItemId.split('-')[3]) || 0;
18242			}
18243			catch (error) {
18244				prevIndex = 0;
18245			}
18246			return prevIndex;
18247		};
18248		LightGallery.prototype.setDownloadValue = function (index) {
18249			if (this.settings.download) {
18250				var currentGalleryItem = this.galleryItems[index];
18251				var hideDownloadBtn = currentGalleryItem.downloadUrl === false ||
18252					currentGalleryItem.downloadUrl === 'false';
18253				if (hideDownloadBtn) {
18254					this.outer.addClass('lg-hide-download');
18255				}
18256				else {
18257					var $download = this.getElementById('lg-download');
18258					this.outer.removeClass('lg-hide-download');
18259					$download.attr('href', currentGalleryItem.downloadUrl ||
18260						currentGalleryItem.src);
18261					if (currentGalleryItem.download) {
18262						//Uncode edit ##START##
18263						var download_url = currentGalleryItem.downloadUrl || currentGalleryItem.src,
18264							download_name = download_url.substring(download_url.lastIndexOf('/')+1);
18265						$download.attr('download', download_name);
18266						// $download.attr('download', currentGalleryItem.download);
18267						//Uncode edit ##END##
18268					}
18269				}
18270			}
18271		};
18272		LightGallery.prototype.makeSlideAnimation = function (direction, currentSlideItem, previousSlideItem) {
18273			var _this = this;
18274			if (this.lGalleryOn) {
18275				previousSlideItem.addClass('lg-slide-progress');
18276			}
18277			setTimeout(function () {
18278				// remove all transitions
18279				_this.outer.addClass('lg-no-trans');
18280				_this.outer
18281					.find('.lg-item')
18282					.removeClass('lg-prev-slide lg-next-slide');
18283				if (direction === 'prev') {
18284					//prevslide
18285					currentSlideItem.addClass('lg-prev-slide');
18286					previousSlideItem.addClass('lg-next-slide');
18287				}
18288				else {
18289					// next slide
18290					currentSlideItem.addClass('lg-next-slide');
18291					previousSlideItem.addClass('lg-prev-slide');
18292				}
18293				// give 50 ms for browser to add/remove class
18294				setTimeout(function () {
18295					_this.outer.find('.lg-item').removeClass('lg-current');
18296					currentSlideItem.addClass('lg-current');
18297					// reset all transitions
18298					_this.outer.removeClass('lg-no-trans');
18299				}, 50);
18300			}, this.lGalleryOn ? this.settings.slideDelay : 0);
18301		};
18302		/**
18303		 * Goto a specific slide.
18304		 * @param {Number} index - index of the slide
18305		 * @param {Boolean} fromTouch - true if slide function called via touch event or mouse drag
18306		 * @param {Boolean} fromThumb - true if slide function called via thumbnail click
18307		 * @param {String} direction - Direction of the slide(next/prev)
18308		 * @category lGPublicMethods
18309		 * @example
18310		 *  const plugin = lightGallery();
18311		 *  // to go to 3rd slide
18312		 *  plugin.slide(2);
18313		 *
18314		 */
18315		LightGallery.prototype.slide = function (index, fromTouch, fromThumb, direction) {
18316			var _this = this;
18317			var prevIndex = this.getPreviousSlideIndex();
18318			this.currentItemsInDom = this.organizeSlideItems(index, prevIndex);
18319			// Prevent multiple call, Required for hsh plugin
18320			if (this.lGalleryOn && prevIndex === index) {
18321				return;
18322			}
18323			var numberOfGalleryItems = this.galleryItems.length;
18324			if (!this.lgBusy) {
18325				if (this.settings.counter) {
18326					this.updateCurrentCounter(index);
18327				}
18328				var currentSlideItem = this.getSlideItem(index);
18329				var previousSlideItem_1 = this.getSlideItem(prevIndex);
18330				var currentGalleryItem = this.galleryItems[index];
18331				var videoInfo = currentGalleryItem.__slideVideoInfo;
18332				this.outer.attr('data-lg-slide-type', this.getSlideType(currentGalleryItem));
18333				this.setDownloadValue(index);
18334				if (videoInfo) {
18335					var _a = this.mediaContainerPosition, top_3 = _a.top, bottom = _a.bottom;
18336					//Uncode edit ##START##
18337					var videoSize = utils.getSize(this.items[index], this.outer, top_3 + bottom, videoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
18338					// var videoSize = utils.getSize(this.items[index], this.outer, top_3 + bottom, videoInfo && this.settings.videoMaxSize);
18339					//Uncode edit ##END##
18340					this.resizeVideoSlide(index, videoSize);
18341				}
18342				this.LGel.trigger(lGEvents.beforeSlide, {
18343					prevIndex: prevIndex,
18344					index: index,
18345					fromTouch: !!fromTouch,
18346					fromThumb: !!fromThumb,
18347					//Uncode edit ##START##
18348					currentSlide: currentSlideItem,
18349					previousSlide: previousSlideItem_1,
18350					info: currentGalleryItem,
18351					item: this.items[index]
18352					//Uncode edit ##END##
18353				});
18354				this.lgBusy = true;
18355				clearTimeout(this.hideBarTimeout);
18356				this.arrowDisable(index);
18357				if (!direction) {
18358					if (index < prevIndex) {
18359						direction = 'prev';
18360					}
18361					else if (index > prevIndex) {
18362						direction = 'next';
18363					}
18364				}
18365				if (!fromTouch) {
18366					this.makeSlideAnimation(direction, currentSlideItem, previousSlideItem_1);
18367				}
18368				else {
18369					this.outer
18370						.find('.lg-item')
18371						.removeClass('lg-prev-slide lg-current lg-next-slide');
18372					var touchPrev = void 0;
18373					var touchNext = void 0;
18374					if (numberOfGalleryItems > 2) {
18375						touchPrev = index - 1;
18376						touchNext = index + 1;
18377						if (index === 0 && prevIndex === numberOfGalleryItems - 1) {
18378							// next slide
18379							touchNext = 0;
18380							touchPrev = numberOfGalleryItems - 1;
18381						}
18382						else if (index === numberOfGalleryItems - 1 &&
18383							prevIndex === 0) {
18384							// prev slide
18385							touchNext = 0;
18386							touchPrev = numberOfGalleryItems - 1;
18387						}
18388					}
18389					else {
18390						touchPrev = 0;
18391						touchNext = 1;
18392					}
18393					if (direction === 'prev') {
18394						this.getSlideItem(touchNext).addClass('lg-next-slide');
18395					}
18396					else {
18397						this.getSlideItem(touchPrev).addClass('lg-prev-slide');
18398					}
18399					currentSlideItem.addClass('lg-current');
18400				}
18401				// Do not put load content in set timeout as it needs to load immediately when the gallery is opened
18402				if (!this.lGalleryOn) {
18403					this.loadContent(index, true);
18404				}
18405				else {
18406					setTimeout(function () {
18407						_this.loadContent(index, true);
18408						// Add title if this.settings.appendSubHtmlTo === lg-sub-html
18409						if (_this.settings.appendSubHtmlTo !== '.lg-item') {
18410							_this.addHtml(index);
18411						}
18412					}, this.settings.speed + 50 + (fromTouch ? 0 : this.settings.slideDelay));
18413				}
18414				setTimeout(function () {
18415					_this.lgBusy = false;
18416					previousSlideItem_1.removeClass('lg-slide-progress');
18417					_this.LGel.trigger(lGEvents.afterSlide, {
18418						prevIndex: prevIndex,
18419						index: index,
18420						fromTouch: fromTouch,
18421						fromThumb: fromThumb,
18422					});
18423				}, (this.lGalleryOn ? this.settings.speed + 100 : 100) + (fromTouch ? 0 : this.settings.slideDelay));
18424			}
18425			this.index = index;
18426		};
18427		LightGallery.prototype.updateCurrentCounter = function (index) {
18428			this.getElementById('lg-counter-current').html(index + 1 + '');
18429		};
18430		LightGallery.prototype.updateCounterTotal = function () {
18431			this.getElementById('lg-counter-all').html(this.galleryItems.length + '');
18432		};
18433		LightGallery.prototype.getSlideType = function (item) {
18434			if (item.__slideVideoInfo) {
18435				return 'video';
18436			}
18437			else if (item.iframe) {
18438				return 'iframe';
18439			}
18440			//Uncode edit ##START##
18441			else if (typeof item.src !== '' && item.src.search(/.mp3|.m4a/i) > -1) {
18442				return 'audio';
18443			}
18444			//Uncode edit ##END##
18445			else {
18446				return 'image';
18447			}
18448		};
18449		LightGallery.prototype.touchMove = function (startCoords, endCoords, e) {
18450			var distanceX = endCoords.pageX - startCoords.pageX;
18451			var distanceY = endCoords.pageY - startCoords.pageY;
18452			var allowSwipe = false;
18453			if (this.swipeDirection) {
18454				allowSwipe = true;
18455			}
18456			else {
18457				if (Math.abs(distanceX) > 15) {
18458					this.swipeDirection = 'horizontal';
18459					allowSwipe = true;
18460				}
18461				else if (Math.abs(distanceY) > 15) {
18462					this.swipeDirection = 'vertical';
18463					allowSwipe = true;
18464				}
18465			}
18466			if (!allowSwipe) {
18467				return;
18468			}
18469			var $currentSlide = this.getSlideItem(this.index);
18470			if (this.swipeDirection === 'horizontal') {
18471				e === null || e === void 0 ? void 0 : e.preventDefault();
18472				// reset opacity and transition duration
18473				this.outer.addClass('lg-dragging');
18474				// move current slide
18475				this.setTranslate($currentSlide, distanceX, 0);
18476				// move next and prev slide with current slide
18477				var width = $currentSlide.get().offsetWidth;
18478				var slideWidthAmount = (width * 15) / 100;
18479				var gutter = slideWidthAmount - Math.abs((distanceX * 10) / 100);
18480				this.setTranslate(this.outer.find('.lg-prev-slide').first(), -width + distanceX - gutter, 0);
18481				this.setTranslate(this.outer.find('.lg-next-slide').first(), width + distanceX + gutter, 0);
18482			}
18483			else if (this.swipeDirection === 'vertical') {
18484				if (this.settings.swipeToClose) {
18485					e === null || e === void 0 ? void 0 : e.preventDefault();
18486					this.$container.addClass('lg-dragging-vertical');
18487					var opacity = 1 - Math.abs(distanceY) / window.innerHeight;
18488					this.$backdrop.css('opacity', opacity);
18489					var scale = 1 - Math.abs(distanceY) / (window.innerWidth * 2);
18490					this.setTranslate($currentSlide, 0, distanceY, scale, scale);
18491					if (Math.abs(distanceY) > 100) {
18492						this.outer
18493							.addClass('lg-hide-items')
18494							.removeClass('lg-components-open');
18495					}
18496				}
18497			}
18498		};
18499		LightGallery.prototype.touchEnd = function (endCoords, startCoords, event) {
18500			var _this = this;
18501			var distance;
18502			// keep slide animation for any mode while dragg/swipe
18503			if (this.settings.mode !== 'lg-slide') {
18504				this.outer.addClass('lg-slide');
18505			}
18506			// set transition duration
18507			setTimeout(function () {
18508				_this.$container.removeClass('lg-dragging-vertical');
18509				_this.outer
18510					.removeClass('lg-dragging lg-hide-items')
18511					.addClass('lg-components-open');
18512				var triggerClick = true;
18513				if (_this.swipeDirection === 'horizontal') {
18514					distance = endCoords.pageX - startCoords.pageX;
18515					var distanceAbs = Math.abs(endCoords.pageX - startCoords.pageX);
18516					if (distance < 0 &&
18517						distanceAbs > _this.settings.swipeThreshold) {
18518						_this.goToNextSlide(true);
18519						triggerClick = false;
18520					}
18521					else if (distance > 0 &&
18522						distanceAbs > _this.settings.swipeThreshold) {
18523						_this.goToPrevSlide(true);
18524						triggerClick = false;
18525					}
18526				}
18527				else if (_this.swipeDirection === 'vertical') {
18528					distance = Math.abs(endCoords.pageY - startCoords.pageY);
18529					if (_this.settings.closable &&
18530						_this.settings.swipeToClose &&
18531						distance > 100) {
18532						_this.closeGallery();
18533						return;
18534					}
18535					else {
18536						_this.$backdrop.css('opacity', 1);
18537					}
18538				}
18539				_this.outer.find('.lg-item').removeAttr('style');
18540				if (triggerClick &&
18541					Math.abs(endCoords.pageX - startCoords.pageX) < 5) {
18542					// Trigger click if distance is less than 5 pix
18543					var target = $LG(event.target);
18544					if (_this.isPosterElement(target)) {
18545						_this.LGel.trigger(lGEvents.posterClick);
18546					}
18547				}
18548				_this.swipeDirection = undefined;
18549			});
18550			// remove slide class once drag/swipe is completed if mode is not slide
18551			setTimeout(function () {
18552				if (!_this.outer.hasClass('lg-dragging') &&
18553					_this.settings.mode !== 'lg-slide') {
18554					_this.outer.removeClass('lg-slide');
18555				}
18556			}, this.settings.speed + 100);
18557		};
18558		LightGallery.prototype.enableSwipe = function () {
18559			var _this = this;
18560			var startCoords = {};
18561			var endCoords = {};
18562			var isMoved = false;
18563			var isSwiping = false;
18564			if (this.settings.enableSwipe) {
18565				this.$inner.on('touchstart.lg', function (e) {
18566					_this.dragOrSwipeEnabled = true;
18567					var $item = _this.getSlideItem(_this.index);
18568					if (($LG(e.target).hasClass('lg-item') ||
18569						$item.get().contains(e.target)) &&
18570						!_this.outer.hasClass('lg-zoomed') &&
18571						!_this.lgBusy &&
18572						e.targetTouches.length === 1) {
18573						isSwiping = true;
18574						_this.touchAction = 'swipe';
18575						_this.manageSwipeClass();
18576						startCoords = {
18577							pageX: e.targetTouches[0].pageX,
18578							pageY: e.targetTouches[0].pageY,
18579						};
18580					}
18581				});
18582				this.$inner.on('touchmove.lg', function (e) {
18583					if (isSwiping &&
18584						_this.touchAction === 'swipe' &&
18585						e.targetTouches.length === 1) {
18586						endCoords = {
18587							pageX: e.targetTouches[0].pageX,
18588							pageY: e.targetTouches[0].pageY,
18589						};
18590						_this.touchMove(startCoords, endCoords, e);
18591						isMoved = true;
18592					}
18593				});
18594				this.$inner.on('touchend.lg', function (event) {
18595					if (_this.touchAction === 'swipe') {
18596						if (isMoved) {
18597							isMoved = false;
18598							_this.touchEnd(endCoords, startCoords, event);
18599						}
18600						else if (isSwiping) {
18601							var target = $LG(event.target);
18602							if (_this.isPosterElement(target)) {
18603								_this.LGel.trigger(lGEvents.posterClick);
18604							}
18605						}
18606						_this.touchAction = undefined;
18607						isSwiping = false;
18608					}
18609				});
18610			}
18611		};
18612		LightGallery.prototype.enableDrag = function () {
18613			var _this = this;
18614			var startCoords = {};
18615			var endCoords = {};
18616			var isDraging = false;
18617			var isMoved = false;
18618			if (this.settings.enableDrag) {
18619				this.outer.on('mousedown.lg', function (e) {
18620					_this.dragOrSwipeEnabled = true;
18621					var $item = _this.getSlideItem(_this.index);
18622					if ($LG(e.target).hasClass('lg-item') ||
18623						$item.get().contains(e.target)) {
18624						if (!_this.outer.hasClass('lg-zoomed') && !_this.lgBusy) {
18625							e.preventDefault();
18626							if (!_this.lgBusy) {
18627								_this.manageSwipeClass();
18628								startCoords = {
18629									pageX: e.pageX,
18630									pageY: e.pageY,
18631								};
18632								isDraging = true;
18633								// ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723
18634								_this.outer.get().scrollLeft += 1;
18635								_this.outer.get().scrollLeft -= 1;
18636								// *
18637								_this.outer
18638									.removeClass('lg-grab')
18639									.addClass('lg-grabbing');
18640								_this.LGel.trigger(lGEvents.dragStart);
18641							}
18642						}
18643					}
18644				});
18645				$LG(window).on("mousemove.lg.global" + this.lgId, function (e) {
18646					if (isDraging && _this.lgOpened) {
18647						isMoved = true;
18648						endCoords = {
18649							pageX: e.pageX,
18650							pageY: e.pageY,
18651						};
18652						_this.touchMove(startCoords, endCoords);
18653						_this.LGel.trigger(lGEvents.dragMove);
18654					}
18655				});
18656				$LG(window).on("mouseup.lg.global" + this.lgId, function (event) {
18657					if (!_this.lgOpened) {
18658						return;
18659					}
18660					var target = $LG(event.target);
18661					if (isMoved) {
18662						isMoved = false;
18663						_this.touchEnd(endCoords, startCoords, event);
18664						_this.LGel.trigger(lGEvents.dragEnd);
18665					}
18666					else if (_this.isPosterElement(target)) {
18667						_this.LGel.trigger(lGEvents.posterClick);
18668					}
18669					// Prevent execution on click
18670					if (isDraging) {
18671						isDraging = false;
18672						_this.outer.removeClass('lg-grabbing').addClass('lg-grab');
18673					}
18674				});
18675			}
18676		};
18677		LightGallery.prototype.triggerPosterClick = function () {
18678			var _this = this;
18679			this.$inner.on('click.lg', function (event) {
18680				if (!_this.dragOrSwipeEnabled &&
18681					_this.isPosterElement($LG(event.target))) {
18682					_this.LGel.trigger(lGEvents.posterClick);
18683				}
18684			});
18685		};
18686		LightGallery.prototype.manageSwipeClass = function () {
18687			var _touchNext = this.index + 1;
18688			var _touchPrev = this.index - 1;
18689			if (this.settings.loop && this.galleryItems.length > 2) {
18690				if (this.index === 0) {
18691					_touchPrev = this.galleryItems.length - 1;
18692				}
18693				else if (this.index === this.galleryItems.length - 1) {
18694					_touchNext = 0;
18695				}
18696			}
18697			this.outer.find('.lg-item').removeClass('lg-next-slide lg-prev-slide');
18698			if (_touchPrev > -1) {
18699				this.getSlideItem(_touchPrev).addClass('lg-prev-slide');
18700			}
18701			this.getSlideItem(_touchNext).addClass('lg-next-slide');
18702		};
18703		/**
18704		 * Go to next slide
18705		 * @param {Boolean} fromTouch - true if slide function called via touch event
18706		 * @category lGPublicMethods
18707		 * @example
18708		 *  const plugin = lightGallery();
18709		 *  plugin.goToNextSlide();
18710		 * @see <a href="/demos/methods/">Demo</a>
18711		 */
18712		LightGallery.prototype.goToNextSlide = function (fromTouch) {
18713			var _this = this;
18714			var _loop = this.settings.loop;
18715			if (fromTouch && this.galleryItems.length < 3) {
18716				_loop = false;
18717			}
18718			if (!this.lgBusy) {
18719				if (this.index + 1 < this.galleryItems.length) {
18720					this.index++;
18721					this.LGel.trigger(lGEvents.beforeNextSlide, {
18722						index: this.index,
18723					});
18724					this.slide(this.index, !!fromTouch, false, 'next');
18725				}
18726				else {
18727					if (_loop) {
18728						this.index = 0;
18729						this.LGel.trigger(lGEvents.beforeNextSlide, {
18730							index: this.index,
18731						});
18732						this.slide(this.index, !!fromTouch, false, 'next');
18733					}
18734					else if (this.settings.slideEndAnimation && !fromTouch) {
18735						this.outer.addClass('lg-right-end');
18736						setTimeout(function () {
18737							_this.outer.removeClass('lg-right-end');
18738						}, 400);
18739					}
18740				}
18741			}
18742		};
18743		/**
18744		 * Go to previous slides
18745		 * @param {Boolean} fromTouch - true if slide function called via touch event
18746		 * @category lGPublicMethods
18747		 * @example
18748		 *  const plugin = lightGallery({});
18749		 *  plugin.goToPrevSlide();
18750		 * @see <a href="/demos/methods/">Demo</a>
18751		 *
18752		 */
18753		LightGallery.prototype.goToPrevSlide = function (fromTouch) {
18754			var _this = this;
18755			var _loop = this.settings.loop;
18756			if (fromTouch && this.galleryItems.length < 3) {
18757				_loop = false;
18758			}
18759			if (!this.lgBusy) {
18760				if (this.index > 0) {
18761					this.index--;
18762					this.LGel.trigger(lGEvents.beforePrevSlide, {
18763						index: this.index,
18764						fromTouch: fromTouch,
18765					});
18766					this.slide(this.index, !!fromTouch, false, 'prev');
18767				}
18768				else {
18769					if (_loop) {
18770						this.index = this.galleryItems.length - 1;
18771						this.LGel.trigger(lGEvents.beforePrevSlide, {
18772							index: this.index,
18773							fromTouch: fromTouch,
18774						});
18775						this.slide(this.index, !!fromTouch, false, 'prev');
18776					}
18777					else if (this.settings.slideEndAnimation && !fromTouch) {
18778						this.outer.addClass('lg-left-end');
18779						setTimeout(function () {
18780							_this.outer.removeClass('lg-left-end');
18781						}, 400);
18782					}
18783				}
18784			}
18785		};
18786		LightGallery.prototype.keyPress = function () {
18787			var _this = this;
18788			$LG(window).on("keydown.lg.global" + this.lgId, function (e) {
18789				if (_this.lgOpened &&
18790					_this.settings.escKey === true &&
18791					e.keyCode === 27) {
18792					e.preventDefault();
18793					if (_this.settings.allowMediaOverlap &&
18794						_this.outer.hasClass('lg-can-toggle') &&
18795						_this.outer.hasClass('lg-components-open')) {
18796						_this.outer.removeClass('lg-components-open');
18797					}
18798					else {
18799						_this.closeGallery();
18800					}
18801				}
18802				if (_this.lgOpened && _this.galleryItems.length > 1) {
18803					if (e.keyCode === 37) {
18804						e.preventDefault();
18805						_this.goToPrevSlide();
18806					}
18807					if (e.keyCode === 39) {
18808						e.preventDefault();
18809						_this.goToNextSlide();
18810					}
18811				}
18812			});
18813		};
18814		LightGallery.prototype.arrow = function () {
18815			var _this = this;
18816			this.getElementById('lg-prev').on('click.lg', function () {
18817				_this.goToPrevSlide();
18818			});
18819			this.getElementById('lg-next').on('click.lg', function () {
18820				_this.goToNextSlide();
18821			});
18822		};
18823		LightGallery.prototype.arrowDisable = function (index) {
18824			// Disable arrows if settings.hideControlOnEnd is true
18825			if (!this.settings.loop && this.settings.hideControlOnEnd) {
18826				var $prev = this.getElementById('lg-prev');
18827				var $next = this.getElementById('lg-next');
18828				if (index + 1 === this.galleryItems.length) {
18829					$next.attr('disabled', 'disabled').addClass('disabled');
18830				}
18831				else {
18832					$next.removeAttr('disabled').removeClass('disabled');
18833				}
18834				if (index === 0) {
18835					$prev.attr('disabled', 'disabled').addClass('disabled');
18836				}
18837				else {
18838					$prev.removeAttr('disabled').removeClass('disabled');
18839				}
18840			}
18841		};
18842		LightGallery.prototype.setTranslate = function ($el, xValue, yValue, scaleX, scaleY) {
18843			if (scaleX === void 0) { scaleX = 1; }
18844			if (scaleY === void 0) { scaleY = 1; }
18845			$el.css('transform', 'translate3d(' +
18846				xValue +
18847				'px, ' +
18848				yValue +
18849				'px, 0px) scale3d(' +
18850				scaleX +
18851				', ' +
18852				scaleY +
18853				', 1)');
18854		};
18855		LightGallery.prototype.mousewheel = function () {
18856			var _this = this;
18857			var lastCall = 0;
18858			this.outer.on('wheel.lg', function (e) {
18859				if (!e.deltaY || _this.galleryItems.length < 2) {
18860					return;
18861				}
18862				e.preventDefault();
18863				var now = new Date().getTime();
18864				if (now - lastCall < 1000) {
18865					return;
18866				}
18867				lastCall = now;
18868				if (e.deltaY > 0) {
18869					_this.goToNextSlide();
18870				}
18871				else if (e.deltaY < 0) {
18872					_this.goToPrevSlide();
18873				}
18874			});
18875		};
18876		LightGallery.prototype.isSlideElement = function (target) {
18877			return (target.hasClass('lg-outer') ||
18878				target.hasClass('lg-item') ||
18879				target.hasClass('lg-img-wrap'));
18880		};
18881		LightGallery.prototype.isPosterElement = function (target) {
18882			var playButton = this.getSlideItem(this.index)
18883				.find('.lg-video-play-button')
18884				.get();
18885			return (target.hasClass('lg-video-poster') ||
18886				target.hasClass('lg-video-play-button') ||
18887				(playButton && playButton.contains(target.get())));
18888		};
18889		/**
18890		 * Maximize minimize inline gallery.
18891		 * @category lGPublicMethods
18892		 */
18893		LightGallery.prototype.toggleMaximize = function () {
18894			var _this = this;
18895			this.getElementById('lg-maximize').on('click.lg', function () {
18896				_this.$container.toggleClass('lg-inline');
18897				_this.refreshOnResize();
18898			});
18899		};
18900		LightGallery.prototype.invalidateItems = function () {
18901			for (var index = 0; index < this.items.length; index++) {
18902				var element = this.items[index];
18903				var $element = $LG(element);
18904				$element.off("click.lgcustom-item-" + $element.attr('data-lg-id'));
18905			}
18906		};
18907		LightGallery.prototype.trapFocus = function () {
18908			var _this = this;
18909			this.$container.get().focus({
18910				preventScroll: true,
18911			});
18912			$LG(window).on("keydown.lg.global" + this.lgId, function (e) {
18913				if (!_this.lgOpened) {
18914					return;
18915				}
18916				var isTabPressed = e.key === 'Tab' || e.keyCode === 9;
18917				if (!isTabPressed) {
18918					return;
18919				}
18920				var focusableEls = utils.getFocusableElements(_this.$container.get());
18921				var firstFocusableEl = focusableEls[0];
18922				var lastFocusableEl = focusableEls[focusableEls.length - 1];
18923				if (e.shiftKey) {
18924					if (document.activeElement === firstFocusableEl) {
18925						lastFocusableEl.focus();
18926						e.preventDefault();
18927					}
18928				}
18929				else {
18930					if (document.activeElement === lastFocusableEl) {
18931						firstFocusableEl.focus();
18932						e.preventDefault();
18933					}
18934				}
18935			});
18936		};
18937		LightGallery.prototype.manageCloseGallery = function () {
18938			var _this = this;
18939			if (!this.settings.closable)
18940				return;
18941			var mousedown = false;
18942			this.getElementById('lg-close').on('click.lg', function () {
18943				_this.closeGallery();
18944			});
18945			if (this.settings.closeOnTap) {
18946				// If you drag the slide and release outside gallery gets close on chrome
18947				// for preventing this check mousedown and mouseup happened on .lg-item or lg-outer
18948				this.outer.on('mousedown.lg', function (e) {
18949					var target = $LG(e.target);
18950					if (_this.isSlideElement(target)) {
18951						mousedown = true;
18952					}
18953					else {
18954						mousedown = false;
18955					}
18956				});
18957				this.outer.on('mousemove.lg', function () {
18958					mousedown = false;
18959				});
18960				this.outer.on('mouseup.lg', function (e) {
18961					var target = $LG(e.target);
18962					if (_this.isSlideElement(target) && mousedown) {
18963						if (!_this.outer.hasClass('lg-dragging')) {
18964							_this.closeGallery();
18965						}
18966					}
18967				});
18968			}
18969		};
18970		/**
18971		 * Close lightGallery if it is opened.
18972		 *
18973		 * @description If closable is false in the settings, you need to pass true via closeGallery method to force close gallery
18974		 * @return returns the estimated time to close gallery completely including the close animation duration
18975		 * @category lGPublicMethods
18976		 * @example
18977		 *  const plugin = lightGallery();
18978		 *  plugin.closeGallery();
18979		 *
18980		 */
18981		LightGallery.prototype.closeGallery = function (force) {
18982			var _this = this;
18983			if (!this.lgOpened || (!this.settings.closable && !force)) {
18984				return 0;
18985			}
18986			this.LGel.trigger(lGEvents.beforeClose);
18987			if (this.settings.resetScrollPosition && !this.settings.hideScrollbar) {
18988				$LG(window).scrollTop(this.prevScrollTop);
18989			}
18990			var currentItem = this.items[this.index];
18991			var transform;
18992			if (this.zoomFromOrigin && currentItem) {
18993				var _a = this.mediaContainerPosition, top_4 = _a.top, bottom = _a.bottom;
18994				var _b = this.galleryItems[this.index], __slideVideoInfo = _b.__slideVideoInfo, poster = _b.poster;
18995				//Uncode edit ##START##
18996				var imageSize = utils.getSize(currentItem, this.outer, top_4 + bottom, __slideVideoInfo && poster && this.settings.videoMaxSize, this.galleryItems[this.index]);
18997				// var imageSize = utils.getSize(currentItem, this.outer, top_4 + bottom, __slideVideoInfo && poster && this.settings.videoMaxSize);
18998				//Uncode edit ##END##
18999				transform = utils.getTransform(currentItem, this.outer, top_4, bottom, imageSize);
19000			}
19001			if (this.zoomFromOrigin && transform) {
19002				this.outer.addClass('lg-closing lg-zoom-from-image');
19003				this.getSlideItem(this.index)
19004					.addClass('lg-start-end-progress')
19005					.css('transition-duration', this.settings.startAnimationDuration + 'ms')
19006					.css('transform', transform);
19007			}
19008			else {
19009				this.outer.addClass('lg-hide-items');
19010				// lg-zoom-from-image is used for setting the opacity to 1 if zoomFromOrigin is true
19011				// If the closing item doesn't have the lg-size attribute, remove this class to avoid the closing css conflicts
19012				this.outer.removeClass('lg-zoom-from-image');
19013			}
19014			// Unbind all events added by lightGallery
19015			// @todo
19016			//this.$el.off('.lg.tm');
19017			this.destroyModules();
19018			this.lGalleryOn = false;
19019			this.isDummyImageRemoved = false;
19020			this.zoomFromOrigin = this.settings.zoomFromOrigin;
19021			clearTimeout(this.hideBarTimeout);
19022			this.hideBarTimeout = false;
19023			$LG('html').removeClass('lg-on');
19024			this.outer.removeClass('lg-visible lg-components-open');
19025			// Resetting opacity to 0 isd required as  vertical swipe to close function adds inline opacity.
19026			this.$backdrop.removeClass('in').css('opacity', 0);
19027			var removeTimeout = this.zoomFromOrigin && transform
19028				? Math.max(this.settings.startAnimationDuration, this.settings.backdropDuration)
19029				: this.settings.backdropDuration;
19030			this.$container.removeClass('lg-show-in');
19031			// Once the closign animation is completed and gallery is invisible
19032			setTimeout(function () {
19033				if (_this.zoomFromOrigin && transform) {
19034					_this.outer.removeClass('lg-zoom-from-image');
19035				}
19036				_this.$container.removeClass('lg-show');
19037				// Reset scrollbar
19038				_this.resetScrollBar();
19039				// Need to remove inline opacity as it is used in the stylesheet as well
19040				_this.$backdrop
19041					.removeAttr('style')
19042					.css('transition-duration', _this.settings.backdropDuration + 'ms');
19043				_this.outer.removeClass("lg-closing " + _this.settings.startClass);
vendor: 6,259 bytes, lines 19044-19247
19044				_this.getSlideItem(_this.index).removeClass('lg-start-end-progress');
19045				_this.$inner.empty();
19046				if (_this.lgOpened) {
19047					_this.LGel.trigger(lGEvents.afterClose, {
19048						instance: _this,
19049					});
19050				}
19051				if (_this.$container.get()) {
19052					_this.$container.get().blur();
19053				}
19054				_this.lgOpened = false;
19055			}, removeTimeout + 100);
19056			return removeTimeout + 100;
19057		};
19058		LightGallery.prototype.initModules = function () {
19059			this.plugins.forEach(function (module) {
19060				try {
19061					module.init();
19062				}
19063				catch (err) {
19064					console.warn("lightGallery:- make sure lightGallery module is properly initiated");
19065				}
19066			});
19067		};
19068		LightGallery.prototype.destroyModules = function (destroy) {
19069			this.plugins.forEach(function (module) {
19070				try {
19071					if (destroy) {
19072						module.destroy();
19073					}
19074					else {
19075						module.closeGallery && module.closeGallery();
19076					}
19077				}
19078				catch (err) {
19079					console.warn("lightGallery:- make sure lightGallery module is properly destroyed");
19080				}
19081			});
19082		};
19083		/**
19084		 * Refresh lightGallery with new set of children.
19085		 *
19086		 * @description This is useful to update the gallery when the child elements are changed without calling destroy method.
19087		 *
19088		 * If you are using dynamic mode, you can pass the modified array of dynamicEl as the first parameter to refresh the dynamic gallery
19089		 * @see <a href="/demos/dynamic-mode/">Demo</a>
19090		 * @category lGPublicMethods
19091		 * @example
19092		 *  const plugin = lightGallery();
19093		 *  // Delete or add children, then call
19094		 *  plugin.refresh();
19095		 *
19096		 */
19097		LightGallery.prototype.refresh = function (galleryItems) {
19098			if (!this.settings.dynamic) {
19099				this.invalidateItems();
19100			}
19101			if (galleryItems) {
19102				this.galleryItems = galleryItems;
19103			}
19104			else {
19105				this.galleryItems = this.getItems();
19106			}
19107			this.updateControls();
19108			this.openGalleryOnItemClick();
19109			this.LGel.trigger(lGEvents.updateSlides);
19110		};
19111		LightGallery.prototype.updateControls = function () {
19112			this.addSlideVideoInfo(this.galleryItems);
19113			this.updateCounterTotal();
19114			this.manageSingleSlideClassName();
19115		};
19116		/**
19117		 * Destroy lightGallery.
19118		 * Destroy lightGallery and its plugin instances completely
19119		 *
19120		 * @description This method also calls CloseGallery function internally. Returns the time takes to completely close and destroy the instance.
19121		 * In case if you want to re-initialize lightGallery right after destroying it, initialize it only once the destroy process is completed.
19122		 * You can use refresh method most of the times.
19123		 * @category lGPublicMethods
19124		 * @example
19125		 *  const plugin = lightGallery();
19126		 *  plugin.destroy();
19127		 *
19128		 */
19129		LightGallery.prototype.destroy = function () {
19130			var _this = this;
19131			var closeTimeout = this.closeGallery(true);
19132			setTimeout(function () {
19133				_this.destroyModules(true);
19134				if (!_this.settings.dynamic) {
19135					_this.invalidateItems();
19136				}
19137				$LG(window).off(".lg.global" + _this.lgId);
19138				_this.LGel.off('.lg');
19139				_this.$container.remove();
19140			}, closeTimeout);
19141			return closeTimeout;
19142		};
19143		return LightGallery;
19144	}());
19145
19146	function lightGallery(el, options) {
19147		return new LightGallery(el, options);
19148	}
19149
19150	return lightGallery;
19151
19152})));
19153
19154/*!
19155 * lightgallery | 2.5.0 | June 13th 2022
19156 * http://www.lightgalleryjs.com/
19157 * Copyright (c) 2020 Sachin Neravath;
19158 * @license GPLv3
19159 */
19160
19161(function (global, factory) {
19162	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
19163	typeof define === 'function' && define.amd ? define(factory) :
19164	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgZoom = factory());
19165}(this, (function () { 'use strict';
19166
19167	/*! *****************************************************************************
19168	Copyright (c) Microsoft Corporation.
19169
19170	Permission to use, copy, modify, and/or distribute this software for any
19171	purpose with or without fee is hereby granted.
19172
19173	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
19174	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
19175	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
19176	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
19177	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
19178	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19179	PERFORMANCE OF THIS SOFTWARE.
19180	***************************************************************************** */
19181
19182	var __assign = function() {
19183		__assign = Object.assign || function __assign(t) {
19184			for (var s, i = 1, n = arguments.length; i < n; i++) {
19185				s = arguments[i];
19186				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
19187			}
19188			return t;
19189		};
19190		return __assign.apply(this, arguments);
19191	};
19192
19193	var zoomSettings = {
19194		scale: 1,
19195		zoom: true,
19196		actualSize: true,
19197		showZoomInOutIcons: false,
19198		actualSizeIcons: {
19199			zoomIn: 'lg-zoom-in',
19200			zoomOut: 'lg-zoom-out',
19201		},
19202		enableZoomAfter: 300,
19203		zoomPluginStrings: {
19204			zoomIn: 'Zoom in',
19205			zoomOut: 'Zoom out',
19206			viewActualSize: 'View actual size',
19207		},
19208	};
19209
19210	/**
19211	 * List of lightGallery events
19212	 * All events should be documented here
19213	 * Below interfaces are used to build the website documentations
19214	 * */
19215	var lGEvents = {
19216		afterAppendSlide: 'lgAfterAppendSlide',
19217		init: 'lgInit',
19218		hasVideo: 'lgHasVideo',
19219		containerResize: 'lgContainerResize',
19220		updateSlides: 'lgUpdateSlides',
19221		afterAppendSubHtml: 'lgAfterAppendSubHtml',
19222		beforeOpen: 'lgBeforeOpen',
19223		afterOpen: 'lgAfterOpen',
19224		slideItemLoad: 'lgSlideItemLoad',
19225		beforeSlide: 'lgBeforeSlide',
19226		afterSlide: 'lgAfterSlide',
19227		posterClick: 'lgPosterClick',
19228		dragStart: 'lgDragStart',
19229		dragMove: 'lgDragMove',
19230		dragEnd: 'lgDragEnd',
19231		beforeNextSlide: 'lgBeforeNextSlide',
19232		beforePrevSlide: 'lgBeforePrevSlide',
19233		beforeClose: 'lgBeforeClose',
19234		afterClose: 'lgAfterClose',
19235		rotateLeft: 'lgRotateLeft',
19236		rotateRight: 'lgRotateRight',
19237		flipHorizontal: 'lgFlipHorizontal',
19238		flipVertical: 'lgFlipVertical',
19239		autoplay: 'lgAutoplay',
19240		autoplayStart: 'lgAutoplayStart',
19241		autoplayStop: 'lgAutoplayStop',
19242	};
19243
19244	var Zoom = /** @class */ (function () {
19245		function Zoom(instance, $LG) {
19246			// get lightGallery core plugin instance
19247			this.core = instance;
19248			this.$LG = $LG;
19249			this.settings = __assign(__assign({}, zoomSettings), this.core.settings);
19250			return this;
19251		}
19252		// Append Zoom controls. Actual size, Zoom-in, Zoom-out
19253		Zoom.prototype.buildTemplates = function () {
19254			var zoomIcons = this.settings.showZoomInOutIcons
19255				? "<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>"
19256				: '';
19257			if (this.settings.actualSize) {
19258				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>";
19259			}
19260			this.core.outer.addClass('lg-use-transition-for-zoom');
19261			this.core.$toolbar.first().append(zoomIcons);
19262		};
19263		/**
19264		 * @desc Enable zoom option only once the image is completely loaded
19265		 * If zoomFromOrigin is true, Zoom is enabled once the dummy image has been inserted
19266		 *
19267		 * Zoom styles are defined under lg-zoomable CSS class.
19268		 */
19269		Zoom.prototype.enableZoom = function (event) {
19270			var _this = this;
19271			// delay will be 0 except first time
19272			var _speed = this.settings.enableZoomAfter + event.detail.delay;
19273			// set _speed value 0 if gallery opened from direct url and if it is first slide
19274			if (this.$LG('body').first().hasClass('lg-from-hash') &&
19275				event.detail.delay) {
19276				// will execute only once
19277				_speed = 0;
19278			}
19279			else {
19280				// Remove lg-from-hash to enable starting animation.
19281				this.$LG('body').first().removeClass('lg-from-hash');
19282			}
19283			this.zoomableTimeout = setTimeout(function () {
19284				if (!_this.isImageSlide()) {
19285					return;
19286				}
19287				_this.core.getSlideItem(event.detail.index).addClass('lg-zoomable');
19288				if (event.detail.index === _this.core.index) {
19289					_this.setZoomEssentials();
19290				}
19291			}, _speed + 30);
19292		};
19293		Zoom.prototype.enableZoomOnSlideItemLoad = function () {
19294			// Add zoomable class
19295			this.core.LGel.on(lGEvents.slideItemLoad + ".zoom", this.enableZoom.bind(this));
19296		};
19297		Zoom.prototype.getModifier = function (rotateValue, axis, el) {
19298			var originalRotate = rotateValue;
19299			rotateValue = Math.abs(rotateValue);
19300			var transformValues = this.getCurrentTransform(el);
19301			if (!transformValues) {
19302				return 1;
19303			}
19304			var modifier = 1;
19305			if (axis === 'X') {
19306				var flipHorizontalValue = Math.sign(parseFloat(transformValues[0]));
19307				if (rotateValue === 0 || rotateValue === 180) {
19308					modifier = 1;
19309				}
19310				else if (rotateValue === 90) {
19311					if ((originalRotate === -90 && flipHorizontalValue === 1) ||
19312						(originalRotate === 90 && flipHorizontalValue === -1)) {
19313						modifier = -1;
19314					}
19315					else {
19316						modifier = 1;
19317					}
19318				}
19319				modifier = modifier * flipHorizontalValue;
19320			}
19321			else {
19322				var flipVerticalValue = Math.sign(parseFloat(transformValues[3]));
19323				if (rotateValue === 0 || rotateValue === 180) {
19324					modifier = 1;
19325				}
19326				else if (rotateValue === 90) {
19327					var sinX = parseFloat(transformValues[1]);
19328					var sinMinusX = parseFloat(transformValues[2]);
19329					modifier = Math.sign(sinX * sinMinusX * originalRotate * flipVerticalValue);
19330				}
19331				modifier = modifier * flipVerticalValue;
19332			}
19333			return modifier;
19334		};
19335		Zoom.prototype.getImageSize = function ($image, rotateValue, axis) {
19336			var imageSizes = {
19337				y: 'offsetHeight',
19338				x: 'offsetWidth',
19339			};
19340			if (Math.abs(rotateValue) === 90) {
19341				// Swap axis
19342				if (axis === 'x') {
19343					axis = 'y';
19344				}
19345				else {
19346					axis = 'x';
19347				}
19348			}
19349			return $image[imageSizes[axis]];
19350		};
19351		Zoom.prototype.getDragCords = function (e, rotateValue) {
19352			if (rotateValue === 90) {
19353				return {
19354					x: e.pageY,
19355					y: e.pageX,
19356				};
19357			}
19358			else {
19359				return {
19360					x: e.pageX,
19361					y: e.pageY,
19362				};
19363			}
19364		};
19365		Zoom.prototype.getSwipeCords = function (e, rotateValue) {
19366			var x = e.targetTouches[0].pageX;
19367			var y = e.targetTouches[0].pageY;
19368			if (rotateValue === 90) {
19369				return {
19370					x: y,
19371					y: x,
19372				};
19373			}
19374			else {
19375				return {
19376					x: x,
19377					y: y,
19378				};
19379			}
19380		};
19381		Zoom.prototype.getDragAllowedAxises = function (rotateValue, scale) {
19382			scale = scale || this.scale || 1;
19383			var allowY = this.imageYSize * scale > this.containerRect.height;
19384			var allowX = this.imageXSize * scale > this.containerRect.width;
19385			if (rotateValue === 90) {
19386				return {
19387					allowX: allowY,
19388					allowY: allowX,
19389				};
19390			}
19391			else {
19392				return {
19393					allowX: allowX,
19394					allowY: allowY,
19395				};
19396			}
19397		};
19398		/**
19399		 *
19400		 * @param {Element} el
19401		 * @return matrix(cos(X), sin(X), -sin(X), cos(X), 0, 0);
19402		 * Get the current transform value
19403		 */
19404		Zoom.prototype.getCurrentTransform = function (el) {
19405			if (!el) {
19406				return;
19407			}
19408			var st = window.getComputedStyle(el, null);
19409			var tm = st.getPropertyValue('-webkit-transform') ||
19410				st.getPropertyValue('-moz-transform') ||
19411				st.getPropertyValue('-ms-transform') ||
19412				st.getPropertyValue('-o-transform') ||
19413				st.getPropertyValue('transform') ||
19414				'none';
19415			if (tm !== 'none') {
19416				return tm.split('(')[1].split(')')[0].split(',');
19417			}
19418			return;
19419		};
19420		Zoom.prototype.getCurrentRotation = function (el) {
19421			if (!el) {
19422				return 0;
19423			}
19424			var values = this.getCurrentTransform(el);
19425			if (values) {
19426				return Math.round(Math.atan2(parseFloat(values[1]), parseFloat(values[0])) *
19427					(180 / Math.PI));
19428				// If you want rotate in 360
19429				//return (angle < 0 ? angle + 360 : angle);
19430			}
19431			return 0;
19432		};
19433		Zoom.prototype.setZoomEssentials = function () {
19434			var $image = this.core
19435				.getSlideItem(this.core.index)
19436				.find('.lg-image')
19437				.first();
19438			var rotateEl = this.core
19439				.getSlideItem(this.core.index)
19440				.find('.lg-img-rotate')
19441				.first()
19442				.get();
19443			this.rotateValue = this.getCurrentRotation(rotateEl);
19444			this.imageYSize = this.getImageSize($image.get(), this.rotateValue, 'y');
19445			this.imageXSize = this.getImageSize($image.get(), this.rotateValue, 'x');
19446			this.containerRect = this.core.outer.get().getBoundingClientRect();
19447			this.modifierX = this.getModifier(this.rotateValue, 'X', rotateEl);
19448			this.modifierY = this.getModifier(this.rotateValue, 'Y', rotateEl);
19449		};
19450		/**
19451		 * @desc Image zoom
19452		 * Translate the wrap and scale the image to get better user experience
19453		 *
19454		 * @param {String} scale - Zoom decrement/increment value
19455		 */
19456		Zoom.prototype.zoomImage = function (scale) {
19457			// Find offset manually to avoid issue after zoom
19458			var offsetX = (this.containerRect.width - this.imageXSize) / 2 +
19459				this.containerRect.left;
19460			var _a = this.core.mediaContainerPosition, top = _a.top, bottom = _a.bottom;
19461			var topBottomSpacing = Math.abs(top - bottom) / 2;
19462			var offsetY = (this.containerRect.height -
19463				this.imageYSize -
19464				topBottomSpacing * this.modifierX) /
19465				2 +
19466				this.scrollTop +
19467				this.containerRect.top;
19468			var originalX;
19469			var originalY;
19470			if (scale === 1) {
19471				this.positionChanged = false;
19472			}
19473			var dragAllowedAxises = this.getDragAllowedAxises(Math.abs(this.rotateValue), scale);
19474			var allowY = dragAllowedAxises.allowY, allowX = dragAllowedAxises.allowX;
19475			if (this.positionChanged) {
19476				originalX = this.left / (this.scale - 1);
19477				originalY = this.top / (this.scale - 1);
19478				this.pageX = Math.abs(originalX) + offsetX;
19479				this.pageY = Math.abs(originalY) + offsetY;
19480				this.positionChanged = false;
19481			}
19482			var possibleSwipeCords = this.getPossibleSwipeDragCords(this.rotateValue, scale);
19483			var _x = offsetX - this.pageX;
19484			var _y = offsetY - this.pageY;
19485			var x = (scale - 1) * _x;
19486			var y = (scale - 1) * _y;
19487			if (allowX) {
19488				if (this.isBeyondPossibleLeft(x, possibleSwipeCords.minX)) {
19489					x = possibleSwipeCords.minX;
19490				}
19491				else if (this.isBeyondPossibleRight(x, possibleSwipeCords.maxX)) {
19492					x = possibleSwipeCords.maxX;
19493				}
19494			}
19495			else {
19496				if (scale > 1) {
19497					if (x < possibleSwipeCords.minX) {
19498						x = possibleSwipeCords.minX;
19499					}
19500					else if (x > possibleSwipeCords.maxX) {
19501						x = possibleSwipeCords.maxX;
19502					}
19503				}
19504			}
19505			if (allowY) {
19506				if (this.isBeyondPossibleTop(y, possibleSwipeCords.minY)) {
19507					y = possibleSwipeCords.minY;
19508				}
19509				else if (this.isBeyondPossibleBottom(y, possibleSwipeCords.maxY)) {
19510					y = possibleSwipeCords.maxY;
19511				}
19512			}
19513			else {
19514				// If the translate value based on index of beyond the viewport, utilize the available space to prevent image being cut out
19515				if (scale > 1) {
19516					//If image goes beyond viewport top, use the minim possible translate value
19517					if (y < possibleSwipeCords.minY) {
19518						y = possibleSwipeCords.minY;
19519					}
19520					else if (y > possibleSwipeCords.maxY) {
19521						y = possibleSwipeCords.maxY;
19522					}
19523				}
19524			}
19525			this.setZoomStyles({
19526				x: x,
19527				y: y,
19528				scale: scale,
19529			});
19530		};
19531		/**
19532		 * @desc apply scale3d to image and translate to image wrap
19533		 * @param {style} X,Y and scale
19534		 */
19535		Zoom.prototype.setZoomStyles = function (style) {
19536			var $image = this.core
19537				.getSlideItem(this.core.index)
19538				.find('.lg-image')
19539				.first();
19540			var $dummyImage = this.core.outer
19541				.find('.lg-current .lg-dummy-img')
19542				.first();
19543			var $imageWrap = $image.parent();
19544			this.scale = style.scale;
19545			$image.css('transform', 'scale3d(' + style.scale + ', ' + style.scale + ', 1)');
19546			$dummyImage.css('transform', 'scale3d(' + style.scale + ', ' + style.scale + ', 1)');
19547			var transform = 'translate3d(' + style.x + 'px, ' + style.y + 'px, 0)';
19548			$imageWrap.css('transform', transform);
19549			this.left = style.x;
19550			this.top = style.y;
19551		};
19552		/**
19553		 * @param index - Index of the current slide
19554		 * @param event - event will be available only if the function is called on clicking/taping the imags
19555		 */
19556		Zoom.prototype.setActualSize = function (index, event) {
19557			var _this = this;
19558			// Allow zoom only on image
19559			if (!this.isImageSlide() ||
19560				this.core.outer.hasClass('lg-first-slide-loading')) {
19561				return;
19562			}
19563			var scale = this.getCurrentImageActualSizeScale();
19564			if (this.core.outer.hasClass('lg-zoomed')) {
19565				this.scale = 1;
19566			}
19567			else {
19568				this.scale = this.getScale(scale);
19569			}
19570			this.setPageCords(event);
19571			this.beginZoom(this.scale);
19572			this.zoomImage(this.scale);
19573			setTimeout(function () {
19574				_this.core.outer.removeClass('lg-grabbing').addClass('lg-grab');
19575			}, 10);
19576		};
19577		Zoom.prototype.getNaturalWidth = function (index) {
19578			var $image = this.core.getSlideItem(index).find('.lg-image').first();
19579			var naturalWidth = this.core.galleryItems[index].width;
19580			return naturalWidth
19581				? parseFloat(naturalWidth)
19582				: $image.get().naturalWidth;
19583		};
19584		Zoom.prototype.getActualSizeScale = function (naturalWidth, width) {
19585			var _scale;
19586			var scale;
19587			if (naturalWidth > width) {
19588				_scale = naturalWidth / width;
19589				scale = _scale || 2;
19590			}
19591			else {
19592				scale = 1;
19593			}
19594			return scale;
19595		};
19596		Zoom.prototype.getCurrentImageActualSizeScale = function () {
19597			var $image = this.core
19598				.getSlideItem(this.core.index)
19599				.find('.lg-image')
19600				.first();
19601			var width = $image.get().offsetWidth;
19602			var naturalWidth = this.getNaturalWidth(this.core.index) || width;
19603			return this.getActualSizeScale(naturalWidth, width);
19604		};
19605		Zoom.prototype.getPageCords = function (event) {
19606			var cords = {};
19607			if (event) {
19608				cords.x = event.pageX || event.targetTouches[0].pageX;
19609				cords.y = event.pageY || event.targetTouches[0].pageY;
19610			}
19611			else {
19612				var containerRect = this.core.outer.get().getBoundingClientRect();
19613				cords.x = containerRect.width / 2 + containerRect.left;
19614				cords.y =
19615					containerRect.height / 2 + this.scrollTop + containerRect.top;
19616			}
19617			return cords;
19618		};
19619		Zoom.prototype.setPageCords = function (event) {
19620			var pageCords = this.getPageCords(event);
19621			this.pageX = pageCords.x;
19622			this.pageY = pageCords.y;
19623		};
19624		// If true, zoomed - in else zoomed out
19625		Zoom.prototype.beginZoom = function (scale) {
19626			this.core.outer.removeClass('lg-zoom-drag-transition lg-zoom-dragging');
19627			if (scale > 1) {
19628				this.core.outer.addClass('lg-zoomed');
19629				var $actualSize = this.core.getElementById('lg-actual-size');
19630				$actualSize
19631					.removeClass(this.settings.actualSizeIcons.zoomIn)
19632					.addClass(this.settings.actualSizeIcons.zoomOut);
19633			}
19634			else {
19635				this.resetZoom();
19636			}
19637			return scale > 1;
19638		};
19639		Zoom.prototype.getScale = function (scale) {
19640			var actualSizeScale = this.getCurrentImageActualSizeScale();
19641			if (scale < 1) {
19642				scale = 1;
19643			}
19644			else if (scale > actualSizeScale) {
19645				scale = actualSizeScale;
19646			}
19647			return scale;
19648		};
19649		Zoom.prototype.init = function () {
19650			var _this = this;
19651			if (!this.settings.zoom) {
19652				return;
19653			}
19654			this.buildTemplates();
19655			this.enableZoomOnSlideItemLoad();
19656			var tapped = null;
19657			this.core.outer.on('dblclick.lg', function (event) {
19658				if (!_this.$LG(event.target).hasClass('lg-image')) {
19659					return;
19660				}
19661				_this.setActualSize(_this.core.index, event);
19662			});
19663			this.core.outer.on('touchstart.lg', function (event) {
19664				var $target = _this.$LG(event.target);
19665				if (event.targetTouches.length === 1 &&
19666					$target.hasClass('lg-image')) {
19667					if (!tapped) {
19668						tapped = setTimeout(function () {
19669							tapped = null;
19670						}, 300);
19671					}
19672					else {
19673						clearTimeout(tapped);
19674						tapped = null;
19675						event.preventDefault();
19676						_this.setActualSize(_this.core.index, event);
19677					}
19678				}
19679			});
19680			// Update zoom on resize and orientationchange
19681			this.core.LGel.on(lGEvents.containerResize + ".zoom " + lGEvents.rotateRight + ".zoom " + lGEvents.rotateLeft + ".zoom " + lGEvents.flipHorizontal + ".zoom " + lGEvents.flipVertical + ".zoom", function () {
19682				if (!_this.core.lgOpened || !_this.isImageSlide())
19683					return;
19684				_this.setPageCords();
19685				_this.setZoomEssentials();
19686				_this.zoomImage(_this.scale);
19687			});
19688			// Update zoom on resize and orientationchange
19689			this.$LG(window).on("scroll.lg.zoom.global" + this.core.lgId, function () {
19690				if (!_this.core.lgOpened)
19691					return;
19692				_this.scrollTop = _this.$LG(window).scrollTop();
19693			});
19694			this.core.getElementById('lg-zoom-out').on('click.lg', function () {
19695				if (_this.core.outer.find('.lg-current .lg-image').get()) {
19696					_this.scale -= _this.settings.scale;
19697					_this.scale = _this.getScale(_this.scale);
19698					_this.beginZoom(_this.scale);
19699					_this.zoomImage(_this.scale);
19700				}
19701			});
19702			this.core.getElementById('lg-zoom-in').on('click.lg', function () {
19703				_this.zoomIn();
19704			});
19705			this.core.getElementById('lg-actual-size').on('click.lg', function () {
19706				_this.setActualSize(_this.core.index);
19707			});
19708			this.core.LGel.on(lGEvents.beforeOpen + ".zoom", function () {
19709				_this.core.outer.find('.lg-item').removeClass('lg-zoomable');
19710			});
19711			this.core.LGel.on(lGEvents.afterOpen + ".zoom", function () {
19712				_this.scrollTop = _this.$LG(window).scrollTop();
19713				// Set the initial value center
19714				_this.pageX = _this.core.outer.width() / 2;
19715				_this.pageY = _this.core.outer.height() / 2 + _this.scrollTop;
19716				_this.scale = 1;
19717			});
19718			// Reset zoom on slide change
19719			this.core.LGel.on(lGEvents.afterSlide + ".zoom", function (event) {
19720				var prevIndex = event.detail.prevIndex;
19721				_this.scale = 1;
19722				_this.positionChanged = false;
19723				_this.resetZoom(prevIndex);
19724				if (_this.isImageSlide()) {
19725					_this.setZoomEssentials();
19726				}
19727			});
19728			// Drag option after zoom
19729			this.zoomDrag();
19730			this.pinchZoom();
19731			this.zoomSwipe();
19732			// Store the zoomable timeout value just to clear it while closing
19733			this.zoomableTimeout = false;
19734			this.positionChanged = false;
19735		};
19736		Zoom.prototype.zoomIn = function (scale) {
19737			// Allow zoom only on image
19738			if (!this.isImageSlide()) {
19739				return;
19740			}
19741			if (scale) {
19742				this.scale = scale;
19743			}
19744			else {
19745				this.scale += this.settings.scale;
19746			}
19747			this.scale = this.getScale(this.scale);
19748			this.beginZoom(this.scale);
19749			this.zoomImage(this.scale);
19750		};
19751		// Reset zoom effect
19752		Zoom.prototype.resetZoom = function (index) {
19753			this.core.outer.removeClass('lg-zoomed lg-zoom-drag-transition');
19754			var $actualSize = this.core.getElementById('lg-actual-size');
19755			var $item = this.core.getSlideItem(index !== undefined ? index : this.core.index);
19756			$actualSize
19757				.removeClass(this.settings.actualSizeIcons.zoomOut)
19758				.addClass(this.settings.actualSizeIcons.zoomIn);
19759			$item.find('.lg-img-wrap').first().removeAttr('style');
19760			$item.find('.lg-image').first().removeAttr('style');
19761			this.scale = 1;
19762			this.left = 0;
19763			this.top = 0;
19764			// Reset pagx pagy values to center
19765			this.setPageCords();
19766		};
19767		Zoom.prototype.getTouchDistance = function (e) {
19768			return Math.sqrt((e.targetTouches[0].pageX - e.targetTouches[1].pageX) *
19769				(e.targetTouches[0].pageX - e.targetTouches[1].pageX) +
19770				(e.targetTouches[0].pageY - e.targetTouches[1].pageY) *
19771					(e.targetTouches[0].pageY - e.targetTouches[1].pageY));
19772		};
19773		Zoom.prototype.pinchZoom = function () {
19774			var _this = this;
19775			var startDist = 0;
19776			var pinchStarted = false;
19777			var initScale = 1;
19778			var $item = this.core.getSlideItem(this.core.index);
19779			this.core.$inner.on('touchstart.lg', function (e) {
19780				$item = _this.core.getSlideItem(_this.core.index);
19781				if (!_this.isImageSlide()) {
19782					return;
19783				}
19784				if (e.targetTouches.length === 2 &&
19785					!_this.core.outer.hasClass('lg-first-slide-loading') &&
19786					(_this.$LG(e.target).hasClass('lg-item') ||
19787						$item.get().contains(e.target))) {
19788					initScale = _this.scale || 1;
19789					_this.core.outer.removeClass('lg-zoom-drag-transition lg-zoom-dragging');
19790					_this.core.touchAction = 'pinch';
19791					startDist = _this.getTouchDistance(e);
19792				}
19793			});
19794			this.core.$inner.on('touchmove.lg', function (e) {
19795				if (e.targetTouches.length === 2 &&
19796					_this.core.touchAction === 'pinch' &&
19797					(_this.$LG(e.target).hasClass('lg-item') ||
19798						$item.get().contains(e.target))) {
19799					e.preventDefault();
19800					var endDist = _this.getTouchDistance(e);
19801					var distance = startDist - endDist;
19802					if (!pinchStarted && Math.abs(distance) > 5) {
19803						pinchStarted = true;
19804					}
19805					if (pinchStarted) {
19806						_this.scale = Math.max(1, initScale + -distance * 0.008);
19807						_this.zoomImage(_this.scale);
19808					}
19809				}
19810			});
19811			this.core.$inner.on('touchend.lg', function (e) {
19812				if (_this.core.touchAction === 'pinch' &&
19813					(_this.$LG(e.target).hasClass('lg-item') ||
19814						$item.get().contains(e.target))) {
19815					pinchStarted = false;
19816					startDist = 0;
19817					if (_this.scale <= 1) {
19818						_this.resetZoom();
19819					}
19820					else {
19821						_this.scale = _this.getScale(_this.scale);
19822						_this.zoomImage(_this.scale);
19823						_this.core.outer.addClass('lg-zoomed');
19824					}
19825					_this.core.touchAction = undefined;
19826				}
19827			});
19828		};
19829		Zoom.prototype.touchendZoom = function (startCoords, endCoords, allowX, allowY, touchDuration, rotateValue) {
19830			var distanceXnew = endCoords.x - startCoords.x;
19831			var distanceYnew = endCoords.y - startCoords.y;
19832			var speedX = Math.abs(distanceXnew) / touchDuration + 1;
19833			var speedY = Math.abs(distanceYnew) / touchDuration + 1;
19834			if (speedX > 2) {
19835				speedX += 1;
19836			}
19837			if (speedY > 2) {
19838				speedY += 1;
19839			}
19840			distanceXnew = distanceXnew * speedX;
19841			distanceYnew = distanceYnew * speedY;
19842			var _LGel = this.core
19843				.getSlideItem(this.core.index)
19844				.find('.lg-img-wrap')
19845				.first();
19846			var distance = {};
19847			distance.x = this.left + distanceXnew * this.modifierX;
19848			distance.y = this.top + distanceYnew * this.modifierY;
19849			var possibleSwipeCords = this.getPossibleSwipeDragCords(rotateValue);
19850			if (Math.abs(distanceXnew) > 15 || Math.abs(distanceYnew) > 15) {
19851				if (allowY) {
19852					if (this.isBeyondPossibleTop(distance.y, possibleSwipeCords.minY)) {
19853						distance.y = possibleSwipeCords.minY;
19854					}
19855					else if (this.isBeyondPossibleBottom(distance.y, possibleSwipeCords.maxY)) {
19856						distance.y = possibleSwipeCords.maxY;
19857					}
19858				}
19859				if (allowX) {
19860					if (this.isBeyondPossibleLeft(distance.x, possibleSwipeCords.minX)) {
19861						distance.x = possibleSwipeCords.minX;
19862					}
19863					else if (this.isBeyondPossibleRight(distance.x, possibleSwipeCords.maxX)) {
19864						distance.x = possibleSwipeCords.maxX;
19865					}
19866				}
19867				if (allowY) {
19868					this.top = distance.y;
19869				}
19870				else {
19871					distance.y = this.top;
19872				}
19873				if (allowX) {
19874					this.left = distance.x;
19875				}
19876				else {
19877					distance.x = this.left;
19878				}
19879				this.setZoomSwipeStyles(_LGel, distance);
19880				this.positionChanged = true;
19881			}
19882		};
19883		Zoom.prototype.getZoomSwipeCords = function (startCoords, endCoords, allowX, allowY, possibleSwipeCords) {
19884			var distance = {};
19885			if (allowY) {
19886				distance.y =
19887					this.top + (endCoords.y - startCoords.y) * this.modifierY;
19888				if (this.isBeyondPossibleTop(distance.y, possibleSwipeCords.minY)) {
19889					var diffMinY = possibleSwipeCords.minY - distance.y;
19890					distance.y = possibleSwipeCords.minY - diffMinY / 6;
19891				}
19892				else if (this.isBeyondPossibleBottom(distance.y, possibleSwipeCords.maxY)) {
19893					var diffMaxY = distance.y - possibleSwipeCords.maxY;
19894					distance.y = possibleSwipeCords.maxY + diffMaxY / 6;
19895				}
19896			}
19897			else {
19898				distance.y = this.top;
19899			}
19900			if (allowX) {
19901				distance.x =
19902					this.left + (endCoords.x - startCoords.x) * this.modifierX;
19903				if (this.isBeyondPossibleLeft(distance.x, possibleSwipeCords.minX)) {
19904					var diffMinX = possibleSwipeCords.minX - distance.x;
19905					distance.x = possibleSwipeCords.minX - diffMinX / 6;
19906				}
19907				else if (this.isBeyondPossibleRight(distance.x, possibleSwipeCords.maxX)) {
19908					var difMaxX = distance.x - possibleSwipeCords.maxX;
19909					distance.x = possibleSwipeCords.maxX + difMaxX / 6;
19910				}
19911			}
19912			else {
19913				distance.x = this.left;
19914			}
19915			return distance;
19916		};
19917		Zoom.prototype.isBeyondPossibleLeft = function (x, minX) {
19918			return x >= minX;
19919		};
19920		Zoom.prototype.isBeyondPossibleRight = function (x, maxX) {
19921			return x <= maxX;
19922		};
19923		Zoom.prototype.isBeyondPossibleTop = function (y, minY) {
19924			return y >= minY;
19925		};
19926		Zoom.prototype.isBeyondPossibleBottom = function (y, maxY) {
19927			return y <= maxY;
19928		};
19929		Zoom.prototype.isImageSlide = function () {
19930			var currentItem = this.core.galleryItems[this.core.index];
19931			return this.core.getSlideType(currentItem) === 'image';
19932		};
19933		Zoom.prototype.getPossibleSwipeDragCords = function (rotateValue, scale) {
19934			var dataScale = scale || this.scale || 1;
19935			var elDataScale = Math.abs(dataScale);
19936			var _a = this.core.mediaContainerPosition, top = _a.top, bottom = _a.bottom;
19937			var topBottomSpacing = Math.abs(top - bottom) / 2;
19938			var minY = (this.imageYSize - this.containerRect.height) / 2 +
19939				topBottomSpacing * this.modifierX;
19940			var maxY = this.containerRect.height - this.imageYSize * elDataScale + minY;
19941			var minX = (this.imageXSize - this.containerRect.width) / 2;
19942			var maxX = this.containerRect.width - this.imageXSize * elDataScale + minX;
19943			var possibleSwipeCords = {
19944				minY: minY,
19945				maxY: maxY,
19946				minX: minX,
19947				maxX: maxX,
19948			};
19949			if (Math.abs(rotateValue) === 90) {
19950				possibleSwipeCords = {
19951					minY: minX,
19952					maxY: maxX,
19953					minX: minY,
19954					maxX: maxY,
19955				};
19956			}
19957			return possibleSwipeCords;
19958		};
19959		Zoom.prototype.setZoomSwipeStyles = function (LGel, distance) {
19960			LGel.css('transform', 'translate3d(' + distance.x + 'px, ' + distance.y + 'px, 0)');
19961		};
19962		Zoom.prototype.zoomSwipe = function () {
19963			var _this = this;
19964			var startCoords = {};
19965			var endCoords = {};
19966			var isMoved = false;
19967			// Allow x direction drag
19968			var allowX = false;
19969			// Allow Y direction drag
19970			var allowY = false;
19971			var startTime = new Date();
19972			var endTime = new Date();
19973			var possibleSwipeCords;
19974			var _LGel;
19975			var $item = this.core.getSlideItem(this.core.index);
19976			this.core.$inner.on('touchstart.lg', function (e) {
19977				// Allow zoom only on image
19978				if (!_this.isImageSlide()) {
19979					return;
19980				}
19981				$item = _this.core.getSlideItem(_this.core.index);
19982				if ((_this.$LG(e.target).hasClass('lg-item') ||
19983					$item.get().contains(e.target)) &&
19984					e.targetTouches.length === 1 &&
19985					_this.core.outer.hasClass('lg-zoomed')) {
19986					e.preventDefault();
19987					startTime = new Date();
19988					_this.core.touchAction = 'zoomSwipe';
19989					_LGel = _this.core
19990						.getSlideItem(_this.core.index)
19991						.find('.lg-img-wrap')
19992						.first();
19993					var dragAllowedAxises = _this.getDragAllowedAxises(Math.abs(_this.rotateValue));
19994					allowY = dragAllowedAxises.allowY;
19995					allowX = dragAllowedAxises.allowX;
19996					if (allowX || allowY) {
19997						startCoords = _this.getSwipeCords(e, Math.abs(_this.rotateValue));
19998					}
19999					possibleSwipeCords = _this.getPossibleSwipeDragCords(_this.rotateValue);
20000					// reset opacity and transition duration
20001					_this.core.outer.addClass('lg-zoom-dragging lg-zoom-drag-transition');
20002				}
20003			});
20004			this.core.$inner.on('touchmove.lg', function (e) {
20005				if (e.targetTouches.length === 1 &&
20006					_this.core.touchAction === 'zoomSwipe' &&
20007					(_this.$LG(e.target).hasClass('lg-item') ||
20008						$item.get().contains(e.target))) {
20009					e.preventDefault();
20010					_this.core.touchAction = 'zoomSwipe';
20011					endCoords = _this.getSwipeCords(e, Math.abs(_this.rotateValue));
20012					var distance = _this.getZoomSwipeCords(startCoords, endCoords, allowX, allowY, possibleSwipeCords);
20013					if (Math.abs(endCoords.x - startCoords.x) > 15 ||
20014						Math.abs(endCoords.y - startCoords.y) > 15) {
20015						isMoved = true;
20016						_this.setZoomSwipeStyles(_LGel, distance);
20017					}
20018				}
20019			});
20020			this.core.$inner.on('touchend.lg', function (e) {
20021				if (_this.core.touchAction === 'zoomSwipe' &&
20022					(_this.$LG(e.target).hasClass('lg-item') ||
20023						$item.get().contains(e.target))) {
20024					_this.core.touchAction = undefined;
20025					_this.core.outer.removeClass('lg-zoom-dragging');
20026					if (!isMoved) {
20027						return;
20028					}
20029					isMoved = false;
20030					endTime = new Date();
20031					var touchDuration = endTime.valueOf() - startTime.valueOf();
20032					_this.touchendZoom(startCoords, endCoords, allowX, allowY, touchDuration, _this.rotateValue);
20033				}
20034			});
20035		};
20036		Zoom.prototype.zoomDrag = function () {
20037			var _this = this;
20038			var startCoords = {};
20039			var endCoords = {};
20040			var isDragging = false;
20041			var isMoved = false;
20042			// Allow x direction drag
20043			var allowX = false;
20044			// Allow Y direction drag
20045			var allowY = false;
20046			var startTime;
20047			var endTime;
20048			var possibleSwipeCords;
20049			var _LGel;
20050			this.core.outer.on('mousedown.lg.zoom', function (e) {
20051				// Allow zoom only on image
20052				if (!_this.isImageSlide()) {
20053					return;
20054				}
20055				var $item = _this.core.getSlideItem(_this.core.index);
20056				if (_this.$LG(e.target).hasClass('lg-item') ||
20057					$item.get().contains(e.target)) {
20058					startTime = new Date();
20059					_LGel = _this.core
20060						.getSlideItem(_this.core.index)
20061						.find('.lg-img-wrap')
20062						.first();
20063					var dragAllowedAxises = _this.getDragAllowedAxises(Math.abs(_this.rotateValue));
20064					allowY = dragAllowedAxises.allowY;
20065					allowX = dragAllowedAxises.allowX;
20066					if (_this.core.outer.hasClass('lg-zoomed')) {
20067						if (_this.$LG(e.target).hasClass('lg-object') &&
20068							(allowX || allowY)) {
20069							e.preventDefault();
20070							startCoords = _this.getDragCords(e, Math.abs(_this.rotateValue));
20071							possibleSwipeCords = _this.getPossibleSwipeDragCords(_this.rotateValue);
20072							isDragging = true;
20073							// ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723
20074							_this.core.outer.get().scrollLeft += 1;
20075							_this.core.outer.get().scrollLeft -= 1;
20076							_this.core.outer
20077								.removeClass('lg-grab')
20078								.addClass('lg-grabbing lg-zoom-drag-transition lg-zoom-dragging');
20079							// reset opacity and transition duration
20080						}
20081					}
20082				}
20083			});
20084			this.$LG(window).on("mousemove.lg.zoom.global" + this.core.lgId, function (e) {
20085				if (isDragging) {
20086					isMoved = true;
20087					endCoords = _this.getDragCords(e, Math.abs(_this.rotateValue));
20088					var distance = _this.getZoomSwipeCords(startCoords, endCoords, allowX, allowY, possibleSwipeCords);
20089					_this.setZoomSwipeStyles(_LGel, distance);
20090				}
20091			});
20092			this.$LG(window).on("mouseup.lg.zoom.global" + this.core.lgId, function (e) {
20093				if (isDragging) {
20094					endTime = new Date();
20095					isDragging = false;
20096					_this.core.outer.removeClass('lg-zoom-dragging');
20097					// Fix for chrome mouse move on click
20098					if (isMoved &&
20099						(startCoords.x !== endCoords.x ||
20100							startCoords.y !== endCoords.y)) {
20101						endCoords = _this.getDragCords(e, Math.abs(_this.rotateValue));
20102						var touchDuration = endTime.valueOf() - startTime.valueOf();
20103						_this.touchendZoom(startCoords, endCoords, allowX, allowY, touchDuration, _this.rotateValue);
20104					}
20105					isMoved = false;
20106				}
20107				_this.core.outer.removeClass('lg-grabbing').addClass('lg-grab');
20108			});
20109		};
20110		Zoom.prototype.closeGallery = function () {
20111			this.resetZoom();
20112		};
20113		Zoom.prototype.destroy = function () {
20114			// Unbind all events added by lightGallery zoom plugin
20115			this.$LG(window).off(".lg.zoom.global" + this.core.lgId);
20116			this.core.LGel.off('.lg.zoom');
20117			this.core.LGel.off('.zoom');
20118			clearTimeout(this.zoomableTimeout);
20119			this.zoomableTimeout = false;
20120		};
20121		return Zoom;
20122	}());
20123
20124	return Zoom;
20125
20126})));
20127/*!
20128 * lightgallery | 2.5.0 | June 13th 2022
20129 * http://www.lightgalleryjs.com/
20130 * Copyright (c) 2020 Sachin Neravath;
20131 * @license GPLv3
20132 */
20133
20134(function (global, factory) {
20135	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
20136	typeof define === 'function' && define.amd ? define(factory) :
20137	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgFullscreen = factory());
20138}(this, (function () { 'use strict';
20139
20140	/*! *****************************************************************************
20141	Copyright (c) Microsoft Corporation.
20142
20143	Permission to use, copy, modify, and/or distribute this software for any
20144	purpose with or without fee is hereby granted.
20145
20146	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
20147	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
20148	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
20149	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
20150	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
20151	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20152	PERFORMANCE OF THIS SOFTWARE.
20153	***************************************************************************** */
20154
20155	var __assign = function() {
20156		__assign = Object.assign || function __assign(t) {
20157			for (var s, i = 1, n = arguments.length; i < n; i++) {
20158				s = arguments[i];
20159				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
20160			}
20161			return t;
20162		};
20163		return __assign.apply(this, arguments);
20164	};
20165
20166	var fullscreenSettings = {
20167		fullScreen: true,
20168		fullscreenPluginStrings: {
20169			toggleFullscreen: 'Toggle Fullscreen',
20170		},
20171	};
20172
20173	var FullScreen = /** @class */ (function () {
20174		function FullScreen(instance, $LG) {
20175			// get lightGallery core plugin instance
20176			this.core = instance;
20177			this.$LG = $LG;
20178			// extend module default settings with lightGallery core settings
20179			this.settings = __assign(__assign({}, fullscreenSettings), this.core.settings);
20180			return this;
20181		}
20182		FullScreen.prototype.init = function () {
20183			var fullScreen = '';
20184			if (this.settings.fullScreen) {
20185				// check for fullscreen browser support
20186				if (!document.fullscreenEnabled &&
20187					!document.webkitFullscreenEnabled &&
20188					!document.mozFullScreenEnabled &&
20189					!document.msFullscreenEnabled) {
20190					return;
20191				}
20192				else {
20193					fullScreen = "<button type=\"button\" aria-label=\"" + this.settings.fullscreenPluginStrings['toggleFullscreen'] + "\" class=\"lg-fullscreen lg-icon\"></button>";
20194					this.core.$toolbar.append(fullScreen);
20195					this.fullScreen();
20196				}
20197			}
20198		};
20199		FullScreen.prototype.isFullScreen = function () {
20200			return (document.fullscreenElement ||
20201				document.mozFullScreenElement ||
20202				document.webkitFullscreenElement ||
20203				document.msFullscreenElement);
20204		};
20205		FullScreen.prototype.requestFullscreen = function () {
20206			var el = document.documentElement;
20207			if (el.requestFullscreen) {
20208				el.requestFullscreen();
20209			}
20210			else if (el.msRequestFullscreen) {
20211				el.msRequestFullscreen();
20212			}
20213			else if (el.mozRequestFullScreen) {
20214				el.mozRequestFullScreen();
20215			}
20216			else if (el.webkitRequestFullscreen) {
20217				el.webkitRequestFullscreen();
20218			}
20219		};
20220		FullScreen.prototype.exitFullscreen = function () {
20221			if (document.exitFullscreen) {
20222				document.exitFullscreen();
20223			}
20224			else if (document.msExitFullscreen) {
20225				document.msExitFullscreen();
20226			}
20227			else if (document.mozCancelFullScreen) {
20228				document.mozCancelFullScreen();
20229			}
20230			else if (document.webkitExitFullscreen) {
20231				document.webkitExitFullscreen();
20232			}
20233		};
20234		// https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Using_full_screen_mode
20235		FullScreen.prototype.fullScreen = function () {
20236			var _this = this;
20237			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 () {
20238				if (!_this.core.lgOpened)
20239					return;
20240				_this.core.outer.toggleClass('lg-fullscreen-on');
20241			});
20242			this.core.outer
20243				.find('.lg-fullscreen')
20244				.first()
20245				.on('click.lg', function () {
20246				if (_this.isFullScreen()) {
20247					_this.exitFullscreen();
20248				}
20249				else {
20250					_this.requestFullscreen();
20251				}
20252			});
20253		};
20254		FullScreen.prototype.closeGallery = function () {
20255			// exit from fullscreen if activated
20256			if (this.isFullScreen()) {
20257				this.exitFullscreen();
20258			}
20259		};
20260		FullScreen.prototype.destroy = function () {
20261			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);
20262		};
20263		return FullScreen;
20264	}());
20265
20266	return FullScreen;
20267
20268})));
20269
20270/*!
20271 * lightgallery | 2.5.0 | June 13th 2022
20272 * http://www.lightgalleryjs.com/
20273 * Copyright (c) 2020 Sachin Neravath;
20274 * @license GPLv3
20275 */
20276
20277(function (global, factory) {
20278	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
20279	typeof define === 'function' && define.amd ? define(factory) :
20280	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgHash = factory());
20281}(this, (function () { 'use strict';
20282
20283	/*! *****************************************************************************
20284	Copyright (c) Microsoft Corporation.
20285
20286	Permission to use, copy, modify, and/or distribute this software for any
20287	purpose with or without fee is hereby granted.
20288
20289	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
20290	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
20291	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
20292	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
20293	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
20294	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20295	PERFORMANCE OF THIS SOFTWARE.
20296	***************************************************************************** */
20297
20298	var __assign = function() {
20299		__assign = Object.assign || function __assign(t) {
20300			for (var s, i = 1, n = arguments.length; i < n; i++) {
20301				s = arguments[i];
20302				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
20303			}
20304			return t;
20305		};
20306		return __assign.apply(this, arguments);
20307	};
20308
20309	/**
20310	 * List of lightGallery events
20311	 * All events should be documented here
20312	 * Below interfaces are used to build the website documentations
20313	 * */
20314	var lGEvents = {
20315		afterAppendSlide: 'lgAfterAppendSlide',
20316		init: 'lgInit',
20317		hasVideo: 'lgHasVideo',
20318		containerResize: 'lgContainerResize',
20319		updateSlides: 'lgUpdateSlides',
20320		afterAppendSubHtml: 'lgAfterAppendSubHtml',
20321		beforeOpen: 'lgBeforeOpen',
20322		afterOpen: 'lgAfterOpen',
20323		slideItemLoad: 'lgSlideItemLoad',
20324		beforeSlide: 'lgBeforeSlide',
20325		afterSlide: 'lgAfterSlide',
20326		posterClick: 'lgPosterClick',
20327		dragStart: 'lgDragStart',
20328		dragMove: 'lgDragMove',
20329		dragEnd: 'lgDragEnd',
20330		beforeNextSlide: 'lgBeforeNextSlide',
20331		beforePrevSlide: 'lgBeforePrevSlide',
20332		beforeClose: 'lgBeforeClose',
20333		afterClose: 'lgAfterClose',
20334		rotateLeft: 'lgRotateLeft',
20335		rotateRight: 'lgRotateRight',
20336		flipHorizontal: 'lgFlipHorizontal',
20337		flipVertical: 'lgFlipVertical',
20338		autoplay: 'lgAutoplay',
20339		autoplayStart: 'lgAutoplayStart',
20340		autoplayStop: 'lgAutoplayStop',
20341	};
20342
20343	var hashSettings = {
20344		hash: true,
20345		galleryId: '1',
20346		customSlideName: false,
20347	};
20348
20349	var Hash = /** @class */ (function () {
20350		function Hash(instance, $LG) {
20351			// get lightGallery core plugin instance
20352			this.core = instance;
20353			this.$LG = $LG;
20354			// extend module default settings with lightGallery core settings
20355			this.settings = __assign(__assign({}, hashSettings), this.core.settings);
20356			return this;
20357		}
20358		Hash.prototype.init = function () {
20359			var _this = this;
20360			if (!this.settings.hash) {
20361				return;
20362			}
20363			this.oldHash = window.location.hash;
20364			setTimeout(function () {
20365				_this.buildFromHash();
20366			}, 100);
20367			// Change hash value on after each slide transition
20368			this.core.LGel.on(lGEvents.afterSlide + ".hash", this.onAfterSlide.bind(this));
20369			this.core.LGel.on(lGEvents.afterClose + ".hash", this.onCloseAfter.bind(this));
20370			// Listen hash change and change the slide according to slide value
20371			this.$LG(window).on("hashchange.lg.hash.global" + this.core.lgId, this.onHashchange.bind(this));
20372		};
20373		Hash.prototype.onAfterSlide = function (event) {
20374			var slideName = this.core.galleryItems[event.detail.index].slideName;
20375			slideName = this.settings.customSlideName
20376				? slideName || event.detail.index
20377				: event.detail.index;
20378			if (history.replaceState) {
20379				history.replaceState(null, '', window.location.pathname +
20380					window.location.search +
20381					'#lg=' +
20382					this.settings.galleryId +
20383					'&slide=' +
20384					slideName);
20385			}
20386			else {
20387				window.location.hash =
20388					'lg=' + this.settings.galleryId + '&slide=' + slideName;
20389			}
20390		};
20391		/**
20392		 * Get index of the slide from custom slideName. Has to be a public method. Used in hash plugin
20393		 * @param {String} hash
20394		 * @returns {Number} Index of the slide.
20395		 */
20396		Hash.prototype.getIndexFromUrl = function (hash) {
20397			if (hash === void 0) { hash = window.location.hash; }
20398			var slideName = hash.split('&slide=')[1];
20399			var _idx = 0;
20400			if (this.settings.customSlideName) {
20401				for (var index = 0; index < this.core.galleryItems.length; index++) {
20402					var dynamicEl = this.core.galleryItems[index];
20403					if (dynamicEl.slideName === slideName) {
20404						_idx = index;
20405						break;
20406					}
20407				}
20408			}
20409			else {
20410				_idx = parseInt(slideName, 10);
20411			}
20412			return isNaN(_idx) ? 0 : _idx;
20413		};
20414		// Build Gallery if gallery id exist in the URL
20415		Hash.prototype.buildFromHash = function () {
20416			// if dynamic option is enabled execute immediately
20417			var _hash = window.location.hash;
20418			//Uncode edit ##START##
20419			// if (_hash.indexOf('lg=' + this.settings.galleryId) > 0) {
20420			if (_hash.indexOf('lg=' + this.settings.galleryId + '&') > 0) {
20421			//Uncode edit ##END##
20422				// This class is used to remove the initial animation if galleryId present in the URL
20423				this.$LG(document.body).addClass('lg-from-hash');
20424				var index = this.getIndexFromUrl(_hash);
20425				this.core.openGallery(index);
20426				return true;
20427			}
20428		};
20429		Hash.prototype.onCloseAfter = function () {
20430			// Reset to old hash value
20431			if (this.oldHash &&
20432				this.oldHash.indexOf('lg=' + this.settings.galleryId) < 0) {
20433				if (history.replaceState) {
20434					history.replaceState(null, '', this.oldHash);
20435				}
20436				else {
20437					window.location.hash = this.oldHash;
20438				}
20439			}
20440			else {
20441				if (history.replaceState) {
20442					history.replaceState(null, document.title, window.location.pathname + window.location.search);
20443				}
20444				else {
20445					window.location.hash = '';
20446				}
20447			}
20448		};
20449		Hash.prototype.onHashchange = function () {
20450			if (!this.core.lgOpened)
20451				return;
20452			var _hash = window.location.hash;
20453			var index = this.getIndexFromUrl(_hash);
20454			// it galleryId doesn't exist in the url close the gallery
20455			if (_hash.indexOf('lg=' + this.settings.galleryId) > -1) {
20456				this.core.slide(index, false, false);
20457			}
20458			else if (this.core.lGalleryOn) {
20459				this.core.closeGallery();
20460			}
20461		};
20462		Hash.prototype.closeGallery = function () {
20463			if (this.settings.hash) {
20464				this.$LG(document.body).removeClass('lg-from-hash');
20465			}
20466		};
20467		Hash.prototype.destroy = function () {
20468			this.core.LGel.off('.lg.hash');
20469			this.core.LGel.off('.hash');
20470			this.$LG(window).off("hashchange.lg.hash.global" + this.core.lgId);
20471		};
20472		return Hash;
20473	}());
20474
20475	return Hash;
20476
20477})));
20478/*!
20479 * lightgallery | 2.5.0 | June 13th 2022
20480 * http://www.lightgalleryjs.com/
20481 * Copyright (c) 2020 Sachin Neravath;
20482 * @license GPLv3
20483 */
20484
20485(function (global, factory) {
20486	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
20487	typeof define === 'function' && define.amd ? define(factory) :
20488	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgShare = factory());
20489}(this, (function () { 'use strict';
20490
20491	/*! *****************************************************************************
20492	Copyright (c) Microsoft Corporation.
20493
20494	Permission to use, copy, modify, and/or distribute this software for any
20495	purpose with or without fee is hereby granted.
20496
20497	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
20498	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
20499	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
20500	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
20501	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
20502	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20503	PERFORMANCE OF THIS SOFTWARE.
20504	***************************************************************************** */
20505
20506	var __assign = function() {
20507		__assign = Object.assign || function __assign(t) {
20508			for (var s, i = 1, n = arguments.length; i < n; i++) {
20509				s = arguments[i];
20510				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
20511			}
20512			return t;
20513		};
20514		return __assign.apply(this, arguments);
20515	};
20516
20517	function __spreadArrays() {
20518		for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
20519		for (var r = Array(s), k = 0, i = 0; i < il; i++)
20520			for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
20521				r[k] = a[j];
20522		return r;
20523	}
20524
20525	var shareSettings = {
20526		share: true,
20527		facebook: true,
20528		facebookDropdownText: 'Facebook',
20529		twitter: true,
20530		twitterDropdownText: 'Twitter',
20531		pinterest: true,
20532		pinterestDropdownText: 'Pinterest',
20533		additionalShareOptions: [],
20534		sharePluginStrings: { share: 'Share' },
20535	};
20536
20537	function getFacebookShareLink(galleryItem) {
20538		var facebookBaseUrl = '//www.facebook.com/sharer/sharer.php?u=';
20539		return (facebookBaseUrl +
20540			encodeURIComponent(galleryItem.facebookShareUrl || window.location.href));
20541	}
20542
20543	function getTwitterShareLink(galleryItem) {
20544		var twitterBaseUrl = '//twitter.com/intent/tweet?text=';
20545		var url = encodeURIComponent(galleryItem.twitterShareUrl || window.location.href);
20546		var text = galleryItem.tweetText;
20547		return twitterBaseUrl + text + '&url=' + url;
20548	}
20549
20550	function getPinterestShareLink(galleryItem) {
20551		var pinterestBaseUrl = 'http://www.pinterest.com/pin/create/button/?url=';
20552		var description = galleryItem.pinterestText;
20553		var media = encodeURIComponent(galleryItem.src);
20554		var url = encodeURIComponent(galleryItem.pinterestShareUrl || window.location.href);
20555		return (pinterestBaseUrl +
20556			url +
20557			'&media=' +
20558			media +
20559			'&description=' +
20560			description);
20561	}
20562
20563	/**
20564	 * List of lightGallery events
20565	 * All events should be documented here
20566	 * Below interfaces are used to build the website documentations
20567	 * */
20568	var lGEvents = {
20569		afterAppendSlide: 'lgAfterAppendSlide',
20570		init: 'lgInit',
20571		hasVideo: 'lgHasVideo',
20572		containerResize: 'lgContainerResize',
20573		updateSlides: 'lgUpdateSlides',
20574		afterAppendSubHtml: 'lgAfterAppendSubHtml',
20575		beforeOpen: 'lgBeforeOpen',
20576		afterOpen: 'lgAfterOpen',
20577		slideItemLoad: 'lgSlideItemLoad',
20578		beforeSlide: 'lgBeforeSlide',
20579		afterSlide: 'lgAfterSlide',
20580		posterClick: 'lgPosterClick',
20581		dragStart: 'lgDragStart',
20582		dragMove: 'lgDragMove',
20583		dragEnd: 'lgDragEnd',
20584		beforeNextSlide: 'lgBeforeNextSlide',
20585		beforePrevSlide: 'lgBeforePrevSlide',
20586		beforeClose: 'lgBeforeClose',
20587		afterClose: 'lgAfterClose',
20588		rotateLeft: 'lgRotateLeft',
20589		rotateRight: 'lgRotateRight',
20590		flipHorizontal: 'lgFlipHorizontal',
20591		flipVertical: 'lgFlipVertical',
20592		autoplay: 'lgAutoplay',
20593		autoplayStart: 'lgAutoplayStart',
20594		autoplayStop: 'lgAutoplayStop',
20595	};
20596
20597	var Share = /** @class */ (function () {
20598		function Share(instance) {
20599			this.shareOptions = [];
20600			// get lightGallery core plugin instance
20601			this.core = instance;
20602			// extend module default settings with lightGallery core settings
20603			this.settings = __assign(__assign({}, shareSettings), this.core.settings);
20604			return this;
20605		}
20606		Share.prototype.init = function () {
20607			if (!this.settings.share) {
20608				return;
20609			}
20610			this.shareOptions = __spreadArrays(this.getDefaultShareOptions(), this.settings.additionalShareOptions);
20611			this.setLgShareMarkup();
20612			this.core.outer
20613				.find('.lg-share .lg-dropdown')
20614				.append(this.getShareListHtml());
20615			this.core.LGel.on(lGEvents.afterSlide + ".share", this.onAfterSlide.bind(this));
20616		};
20617		Share.prototype.getShareListHtml = function () {
20618			var shareHtml = '';
20619			this.shareOptions.forEach(function (shareOption) {
20620				shareHtml += shareOption.dropdownHTML;
20621			});
20622			return shareHtml;
20623		};
20624		Share.prototype.setLgShareMarkup = function () {
20625			var _this = this;
20626			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>");
20627			this.core.outer.append('<div class="lg-dropdown-overlay"></div>');
20628			var $shareButton = this.core.outer.find('.lg-share');
20629			$shareButton.first().on('click.lg', function () {
20630				_this.core.outer.toggleClass('lg-dropdown-active');
20631				if (_this.core.outer.hasClass('lg-dropdown-active')) {
20632					_this.core.outer.attr('aria-expanded', true);
20633				}
20634				else {
20635					_this.core.outer.attr('aria-expanded', false);
20636				}
20637			});
20638			this.core.outer
20639				.find('.lg-dropdown-overlay')
20640				.first()
20641				.on('click.lg', function () {
20642				_this.core.outer.removeClass('lg-dropdown-active');
20643				_this.core.outer.attr('aria-expanded', false);
20644			});
20645		};
20646		Share.prototype.onAfterSlide = function (event) {
20647			var _this = this;
20648			var index = event.detail.index;
20649			var currentItem = this.core.galleryItems[index];
20650			setTimeout(function () {
20651				_this.shareOptions.forEach(function (shareOption) {
20652					var selector = shareOption.selector;
20653					_this.core.outer
20654						.find(selector)
20655						.attr('href', shareOption.generateLink(currentItem));
20656				});
20657			}, 100);
20658		};
20659		Share.prototype.getShareListItemHTML = function (type, text) {
20660			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>";
20661		};
20662		Share.prototype.getDefaultShareOptions = function () {
20663			return __spreadArrays((this.settings.facebook
20664				? [
20665					{
20666						type: 'facebook',
20667						generateLink: getFacebookShareLink,
20668						dropdownHTML: this.getShareListItemHTML('facebook', this.settings.facebookDropdownText),
20669						selector: '.lg-share-facebook',
20670					},
20671				]
20672				: []), (this.settings.twitter
20673				? [
20674					{
20675						type: 'twitter',
20676						generateLink: getTwitterShareLink,
20677						dropdownHTML: this.getShareListItemHTML('twitter', this.settings.twitterDropdownText),
20678						selector: '.lg-share-twitter',
20679					},
20680				]
20681				: []), (this.settings.pinterest
20682				? [
20683					{
20684						type: 'pinterest',
20685						generateLink: getPinterestShareLink,
20686						dropdownHTML: this.getShareListItemHTML('pinterest', this.settings.pinterestDropdownText),
20687						selector: '.lg-share-pinterest',
20688					},
20689				]
20690				: []));
20691		};
20692		Share.prototype.destroy = function () {
20693			this.core.outer.find('.lg-dropdown-overlay').remove();
20694			this.core.outer.find('.lg-share').remove();
20695			this.core.LGel.off('.lg.share');
20696			this.core.LGel.off('.share');
20697		};
20698		return Share;
20699	}());
20700
20701	return Share;
20702
20703})));
20704/*!
20705 * lightgallery | 2.5.0 | June 13th 2022
20706 * http://www.lightgalleryjs.com/
20707 * Copyright (c) 2020 Sachin Neravath;
20708 * @license GPLv3
20709 */
20710
20711(function (global, factory) {
20712	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
20713	typeof define === 'function' && define.amd ? define(factory) :
20714	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgThumbnail = factory());
20715}(this, (function () { 'use strict';
20716
20717	/*! *****************************************************************************
20718	Copyright (c) Microsoft Corporation.
20719
20720	Permission to use, copy, modify, and/or distribute this software for any
20721	purpose with or without fee is hereby granted.
20722
20723	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
20724	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
20725	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
20726	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
20727	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
20728	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20729	PERFORMANCE OF THIS SOFTWARE.
20730	***************************************************************************** */
20731
20732	var __assign = function() {
20733		__assign = Object.assign || function __assign(t) {
20734			for (var s, i = 1, n = arguments.length; i < n; i++) {
20735				s = arguments[i];
20736				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
20737			}
20738			return t;
20739		};
20740		return __assign.apply(this, arguments);
20741	};
20742
20743	var thumbnailsSettings = {
20744		thumbnail: true,
20745		animateThumb: true,
20746		currentPagerPosition: 'middle',
20747		alignThumbnails: 'middle',
20748		thumbWidth: 100,
20749		thumbHeight: '80px',
20750		thumbMargin: 5,
20751		appendThumbnailsTo: '.lg-components',
20752		toggleThumb: false,
20753		enableThumbDrag: true,
20754		enableThumbSwipe: true,
20755		thumbnailSwipeThreshold: 10,
20756		loadYouTubeThumbnail: true,
20757		youTubeThumbSize: 1,
20758		thumbnailPluginStrings: {
20759			toggleThumbnails: 'Toggle thumbnails',
20760		},
20761	};
20762
20763	/**
20764	 * List of lightGallery events
20765	 * All events should be documented here
20766	 * Below interfaces are used to build the website documentations
20767	 * */
20768	var lGEvents = {
20769		afterAppendSlide: 'lgAfterAppendSlide',
20770		init: 'lgInit',
20771		hasVideo: 'lgHasVideo',
20772		containerResize: 'lgContainerResize',
20773		updateSlides: 'lgUpdateSlides',
20774		afterAppendSubHtml: 'lgAfterAppendSubHtml',
20775		beforeOpen: 'lgBeforeOpen',
20776		afterOpen: 'lgAfterOpen',
20777		slideItemLoad: 'lgSlideItemLoad',
20778		beforeSlide: 'lgBeforeSlide',
20779		afterSlide: 'lgAfterSlide',
20780		posterClick: 'lgPosterClick',
20781		dragStart: 'lgDragStart',
20782		dragMove: 'lgDragMove',
20783		dragEnd: 'lgDragEnd',
20784		beforeNextSlide: 'lgBeforeNextSlide',
20785		beforePrevSlide: 'lgBeforePrevSlide',
20786		beforeClose: 'lgBeforeClose',
20787		afterClose: 'lgAfterClose',
20788		rotateLeft: 'lgRotateLeft',
20789		rotateRight: 'lgRotateRight',
20790		flipHorizontal: 'lgFlipHorizontal',
20791		flipVertical: 'lgFlipVertical',
20792		autoplay: 'lgAutoplay',
20793		autoplayStart: 'lgAutoplayStart',
20794		autoplayStop: 'lgAutoplayStop',
20795	};
20796
20797	var Thumbnail = /** @class */ (function () {
20798		function Thumbnail(instance, $LG) {
20799			this.thumbOuterWidth = 0;
20800			this.thumbTotalWidth = 0;
20801			this.translateX = 0;
20802			this.thumbClickable = false;
20803			// get lightGallery core plugin instance
20804			this.core = instance;
20805			this.$LG = $LG;
20806			return this;
20807		}
20808		Thumbnail.prototype.init = function () {
20809			// extend module default settings with lightGallery core settings
20810			this.settings = __assign(__assign({}, thumbnailsSettings), this.core.settings);
20811			this.thumbOuterWidth = 0;
20812			this.thumbTotalWidth =
20813				this.core.galleryItems.length *
20814					(this.settings.thumbWidth + this.settings.thumbMargin);
20815			// Thumbnail animation value
20816			this.translateX = 0;
20817			this.setAnimateThumbStyles();
20818			if (!this.core.settings.allowMediaOverlap) {
20819				this.settings.toggleThumb = false;
20820			}
20821			if (this.settings.thumbnail) {
20822				this.build();
20823				if (this.settings.animateThumb) {
20824					if (this.settings.enableThumbDrag) {
20825						this.enableThumbDrag();
20826					}
20827					if (this.settings.enableThumbSwipe) {
20828						this.enableThumbSwipe();
20829					}
20830					this.thumbClickable = false;
20831				}
20832				else {
20833					this.thumbClickable = true;
20834				}
20835				this.toggleThumbBar();
20836				this.thumbKeyPress();
20837			}
20838		};
20839		Thumbnail.prototype.build = function () {
20840			var _this = this;
20841			this.setThumbMarkup();
20842			this.manageActiveClassOnSlideChange();
20843			this.$lgThumb.first().on('click.lg touchend.lg', function (e) {
20844				var $target = _this.$LG(e.target);
20845				if (!$target.hasAttribute('data-lg-item-id')) {
20846					return;
20847				}
20848				setTimeout(function () {
20849					// In IE9 and bellow touch does not support
20850					// Go to slide if browser does not support css transitions
20851					if (_this.thumbClickable && !_this.core.lgBusy) {
20852						var index = parseInt($target.attr('data-lg-item-id'));
20853						_this.core.slide(index, false, true, false);
20854					}
20855				}, 50);
20856			});
20857			//Uncode edit ##START##
20858			// this.core.LGel.on(lGEvents.beforeSlide + ".thumb", function (event) {
20859			this.core.LGel.on(lGEvents.beforeSlide, function (event) {
20860			//Uncode edit ##END##
20861				var index = event.detail.index;
20862				_this.animateThumb(index);
20863			});
20864			//Uncode edit ##START##
20865			// this.core.LGel.on(lGEvents.beforeOpen + ".thumb", function () {
20866			this.core.LGel.on(lGEvents.beforeOpen, function () {
20867			//Uncode edit ##END##
20868				_this.thumbOuterWidth = _this.core.outer.get().offsetWidth;
20869			});
20870			//Uncode edit ##START##
20871			// this.core.LGel.on(lGEvents.updateSlides + ".thumb", function () {
20872			this.core.LGel.on(lGEvents.updateSlides, function () {
20873			//Uncode edit ##END##
20874				_this.rebuildThumbnails();
20875			});
20876			//Uncode edit ##START##
20877			// this.core.LGel.on(lGEvents.containerResize + ".thumb", function () {
20878			this.core.LGel.on(lGEvents.containerResize, function () {
20879			//Uncode edit ##END##
20880				if (!_this.core.lgOpened)
20881					return;
20882				setTimeout(function () {
20883					_this.thumbOuterWidth = _this.core.outer.get().offsetWidth;
20884					_this.animateThumb(_this.core.index);
20885					_this.thumbOuterWidth = _this.core.outer.get().offsetWidth;
20886				}, 50);
20887			});
20888		};
20889		Thumbnail.prototype.setThumbMarkup = function () {
20890			var thumbOuterClassNames = 'lg-thumb-outer ';
20891			if (this.settings.alignThumbnails) {
20892				thumbOuterClassNames += "lg-thumb-align-" + this.settings.alignThumbnails;
20893			}
20894			var html = "<div class=\"" + thumbOuterClassNames + "\">\n        <div class=\"lg-thumb lg-group\">\n        </div>\n        </div>";
20895			this.core.outer.addClass('lg-has-thumb');
20896			if (this.settings.appendThumbnailsTo === '.lg-components') {
20897				this.core.$lgComponents.append(html);
20898			}
20899			else {
20900				this.core.outer.append(html);
20901			}
20902			this.$thumbOuter = this.core.outer.find('.lg-thumb-outer').first();
20903			this.$lgThumb = this.core.outer.find('.lg-thumb').first();
20904			if (this.settings.animateThumb) {
20905				this.core.outer
20906					.find('.lg-thumb')
20907					.css('transition-duration', this.core.settings.speed + 'ms')
20908					.css('width', this.thumbTotalWidth + 'px')
20909					.css('position', 'relative');
20910			}
20911			this.setThumbItemHtml(this.core.galleryItems);
20912		};
20913		Thumbnail.prototype.enableThumbDrag = function () {
20914			var _this = this;
20915			var thumbDragUtils = {
20916				cords: {
20917					startX: 0,
20918					endX: 0,
20919				},
20920				isMoved: false,
20921				newTranslateX: 0,
20922				startTime: new Date(),
20923				endTime: new Date(),
20924				touchMoveTime: 0,
20925			};
20926			var isDragging = false;
20927			this.$thumbOuter.addClass('lg-grab');
20928			this.core.outer
20929				.find('.lg-thumb')
20930				.first()
20931				.on('mousedown.lg.thumb', function (e) {
20932				if (_this.thumbTotalWidth > _this.thumbOuterWidth) {
20933					// execute only on .lg-object
20934					e.preventDefault();
20935					thumbDragUtils.cords.startX = e.pageX;
20936					thumbDragUtils.startTime = new Date();
20937					_this.thumbClickable = false;
20938					isDragging = true;
20939					// ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723
20940					_this.core.outer.get().scrollLeft += 1;
20941					_this.core.outer.get().scrollLeft -= 1;
20942					// *
20943					_this.$thumbOuter
20944						.removeClass('lg-grab')
20945						.addClass('lg-grabbing');
20946				}
20947			});
20948			this.$LG(window).on("mousemove.lg.thumb.global" + this.core.lgId, function (e) {
20949				if (!_this.core.lgOpened)
20950					return;
20951				if (isDragging) {
20952					thumbDragUtils.cords.endX = e.pageX;
20953					thumbDragUtils = _this.onThumbTouchMove(thumbDragUtils);
20954				}
20955			});
20956			this.$LG(window).on("mouseup.lg.thumb.global" + this.core.lgId, function () {
20957				if (!_this.core.lgOpened)
20958					return;
20959				if (thumbDragUtils.isMoved) {
20960					thumbDragUtils = _this.onThumbTouchEnd(thumbDragUtils);
20961				}
20962				else {
20963					_this.thumbClickable = true;
20964				}
20965				if (isDragging) {
20966					isDragging = false;
20967					_this.$thumbOuter.removeClass('lg-grabbing').addClass('lg-grab');
20968				}
20969			});
20970		};
20971		Thumbnail.prototype.enableThumbSwipe = function () {
20972			var _this = this;
20973			var thumbDragUtils = {
20974				cords: {
20975					startX: 0,
20976					endX: 0,
20977				},
20978				isMoved: false,
20979				newTranslateX: 0,
20980				startTime: new Date(),
20981				endTime: new Date(),
20982				touchMoveTime: 0,
20983			};
20984			this.$lgThumb.on('touchstart.lg', function (e) {
20985				if (_this.thumbTotalWidth > _this.thumbOuterWidth) {
20986					e.preventDefault();
20987					thumbDragUtils.cords.startX = e.targetTouches[0].pageX;
20988					_this.thumbClickable = false;
20989					thumbDragUtils.startTime = new Date();
20990				}
20991			});
20992			this.$lgThumb.on('touchmove.lg', function (e) {
20993				if (_this.thumbTotalWidth > _this.thumbOuterWidth) {
20994					e.preventDefault();
20995					thumbDragUtils.cords.endX = e.targetTouches[0].pageX;
20996					thumbDragUtils = _this.onThumbTouchMove(thumbDragUtils);
20997				}
20998			});
20999			this.$lgThumb.on('touchend.lg', function () {
21000				if (thumbDragUtils.isMoved) {
21001					thumbDragUtils = _this.onThumbTouchEnd(thumbDragUtils);
21002				}
21003				else {
21004					_this.thumbClickable = true;
21005				}
21006			});
21007		};
21008		// Rebuild thumbnails
21009		Thumbnail.prototype.rebuildThumbnails = function () {
21010			var _this = this;
21011			// Remove transitions
21012			this.$thumbOuter.addClass('lg-rebuilding-thumbnails');
21013			setTimeout(function () {
21014				_this.thumbTotalWidth =
21015					_this.core.galleryItems.length *
21016						(_this.settings.thumbWidth + _this.settings.thumbMargin);
21017				_this.$lgThumb.css('width', _this.thumbTotalWidth + 'px');
21018				_this.$lgThumb.empty();
21019				_this.setThumbItemHtml(_this.core.galleryItems);
21020				_this.animateThumb(_this.core.index);
21021			}, 50);
21022			setTimeout(function () {
21023				_this.$thumbOuter.removeClass('lg-rebuilding-thumbnails');
21024			}, 200);
21025		};
21026		// @ts-check
21027		Thumbnail.prototype.setTranslate = function (value) {
21028			this.$lgThumb.css('transform', 'translate3d(-' + value + 'px, 0px, 0px)');
21029		};
21030		Thumbnail.prototype.getPossibleTransformX = function (left) {
21031			if (left > this.thumbTotalWidth - this.thumbOuterWidth) {
21032				left = this.thumbTotalWidth - this.thumbOuterWidth;
21033			}
21034			if (left < 0) {
21035				left = 0;
21036			}
21037			return left;
21038		};
21039		Thumbnail.prototype.animateThumb = function (index) {
21040			this.$lgThumb.css('transition-duration', this.core.settings.speed + 'ms');
21041			if (this.settings.animateThumb) {
21042				var position = 0;
21043				switch (this.settings.currentPagerPosition) {
21044					case 'left':
21045						position = 0;
21046						break;
21047					case 'middle':
21048						position =
21049							this.thumbOuterWidth / 2 - this.settings.thumbWidth / 2;
21050						break;
21051					case 'right':
21052						position = this.thumbOuterWidth - this.settings.thumbWidth;
21053				}
21054				this.translateX =
21055					(this.settings.thumbWidth + this.settings.thumbMargin) * index -
21056						1 -
21057						position;
21058				if (this.translateX > this.thumbTotalWidth - this.thumbOuterWidth) {
21059					this.translateX = this.thumbTotalWidth - this.thumbOuterWidth;
21060				}
21061				if (this.translateX < 0) {
21062					this.translateX = 0;
21063				}
21064				this.setTranslate(this.translateX);
21065			}
21066		};
21067		Thumbnail.prototype.onThumbTouchMove = function (thumbDragUtils) {
21068			thumbDragUtils.newTranslateX = this.translateX;
21069			thumbDragUtils.isMoved = true;
21070			thumbDragUtils.touchMoveTime = new Date().valueOf();
21071			thumbDragUtils.newTranslateX -=
21072				thumbDragUtils.cords.endX - thumbDragUtils.cords.startX;
21073			thumbDragUtils.newTranslateX = this.getPossibleTransformX(thumbDragUtils.newTranslateX);
21074			// move current slide
21075			this.setTranslate(thumbDragUtils.newTranslateX);
21076			this.$thumbOuter.addClass('lg-dragging');
21077			return thumbDragUtils;
21078		};
21079		Thumbnail.prototype.onThumbTouchEnd = function (thumbDragUtils) {
21080			thumbDragUtils.isMoved = false;
21081			thumbDragUtils.endTime = new Date();
21082			this.$thumbOuter.removeClass('lg-dragging');
21083			var touchDuration = thumbDragUtils.endTime.valueOf() -
21084				thumbDragUtils.startTime.valueOf();
21085			var distanceXnew = thumbDragUtils.cords.endX - thumbDragUtils.cords.startX;
21086			var speedX = Math.abs(distanceXnew) / touchDuration;
21087			// Some magical numbers
21088			// Can be improved
21089			if (speedX > 0.15 &&
21090				thumbDragUtils.endTime.valueOf() - thumbDragUtils.touchMoveTime < 30) {
21091				speedX += 1;
21092				if (speedX > 2) {
21093					speedX += 1;
21094				}
21095				speedX =
21096					speedX +
21097						speedX * (Math.abs(distanceXnew) / this.thumbOuterWidth);
21098				this.$lgThumb.css('transition-duration', Math.min(speedX - 1, 2) + 'settings');
21099				distanceXnew = distanceXnew * speedX;
21100				this.translateX = this.getPossibleTransformX(this.translateX - distanceXnew);
21101				this.setTranslate(this.translateX);
21102			}
21103			else {
21104				this.translateX = thumbDragUtils.newTranslateX;
21105			}
21106			if (Math.abs(thumbDragUtils.cords.endX - thumbDragUtils.cords.startX) <
21107				this.settings.thumbnailSwipeThreshold) {
21108				this.thumbClickable = true;
21109			}
21110			return thumbDragUtils;
21111		};
21112		Thumbnail.prototype.getThumbHtml = function (thumb, index) {
21113			var slideVideoInfo = this.core.galleryItems[index].__slideVideoInfo || {};
21114			var thumbImg;
21115			if (slideVideoInfo.youtube) {
21116				if (this.settings.loadYouTubeThumbnail) {
21117					thumbImg =
21118						'//img.youtube.com/vi/' +
21119							slideVideoInfo.youtube[1] +
21120							'/' +
21121							this.settings.youTubeThumbSize +
21122							'.jpg';
21123				}
21124				else {
21125					thumbImg = thumb;
21126				}
21127			}
21128			else {
21129				thumbImg = thumb;
21130			}
21131			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>";
21132		};
21133		Thumbnail.prototype.getThumbItemHtml = function (items) {
21134			var thumbList = '';
21135			for (var i = 0; i < items.length; i++) {
21136				thumbList += this.getThumbHtml(items[i].thumb, i);
21137			}
21138			return thumbList;
21139		};
21140		Thumbnail.prototype.setThumbItemHtml = function (items) {
21141			var thumbList = this.getThumbItemHtml(items);
21142			this.$lgThumb.html(thumbList);
21143		};
21144		Thumbnail.prototype.setAnimateThumbStyles = function () {
21145			if (this.settings.animateThumb) {
21146				this.core.outer.addClass('lg-animate-thumb');
21147			}
21148		};
21149		// Manage thumbnail active calss
21150		Thumbnail.prototype.manageActiveClassOnSlideChange = function () {
21151			var _this = this;
21152			// manage active class for thumbnail
21153			//Uncode edit ##START##
21154			// this.core.LGel.on(lGEvents.beforeSlide + ".thumb", function (event) {
21155			this.core.LGel.on(lGEvents.beforeSlide, function (event) {
21156			//Uncode edit ##END##
21157				var $thumb = _this.core.outer.find('.lg-thumb-item');
21158				var index = event.detail.index;
21159				$thumb.removeClass('active');
21160				$thumb.eq(index).addClass('active');
21161			});
21162		};
21163		// Toggle thumbnail bar
21164		Thumbnail.prototype.toggleThumbBar = function () {
21165			var _this = this;
21166			if (this.settings.toggleThumb) {
21167				this.core.outer.addClass('lg-can-toggle');
21168				this.core.$toolbar.append('<button type="button" aria-label="' +
21169					this.settings.thumbnailPluginStrings['toggleThumbnails'] +
21170					'" class="lg-toggle-thumb lg-icon"></button>');
21171				this.core.outer
21172					.find('.lg-toggle-thumb')
21173					.first()
21174					.on('click.lg', function () {
21175					_this.core.outer.toggleClass('lg-components-open');
21176				});
21177			}
21178		};
21179		Thumbnail.prototype.thumbKeyPress = function () {
21180			var _this = this;
21181			this.$LG(window).on("keydown.lg.thumb.global" + this.core.lgId, function (e) {
21182				if (!_this.core.lgOpened || !_this.settings.toggleThumb)
21183					return;
21184				if (e.keyCode === 38) {
21185					e.preventDefault();
21186					_this.core.outer.addClass('lg-components-open');
21187				}
21188				else if (e.keyCode === 40) {
21189					e.preventDefault();
21190					_this.core.outer.removeClass('lg-components-open');
21191				}
21192			});
21193		};
21194		Thumbnail.prototype.destroy = function () {
21195			if (this.settings.thumbnail) {
21196				this.$LG(window).off(".lg.thumb.global" + this.core.lgId);
21197				this.core.LGel.off('.lg.thumb');
21198				this.core.LGel.off('.thumb');
21199				this.$thumbOuter.remove();
21200				this.core.outer.removeClass('lg-has-thumb');
21201			}
21202		};
21203		return Thumbnail;
21204	}());
21205
21206	return Thumbnail;
21207
21208})));
21209/*!
21210 * lightgallery | 2.5.0 | June 13th 2022
21211 * http://www.lightgalleryjs.com/
21212 * Copyright (c) 2020 Sachin Neravath;
21213 * @license GPLv3
21214 */
21215
21216(function (global, factory) {
21217	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
21218	typeof define === 'function' && define.amd ? define(factory) :
21219	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgVideo = factory());
21220}(this, (function () { 'use strict';
21221
21222	/*! *****************************************************************************
21223	Copyright (c) Microsoft Corporation.
21224
21225	Permission to use, copy, modify, and/or distribute this software for any
21226	purpose with or without fee is hereby granted.
21227
21228	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
21229	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
21230	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
21231	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21232	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21233	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21234	PERFORMANCE OF THIS SOFTWARE.
21235	***************************************************************************** */
21236
21237	var __assign = function() {
21238		__assign = Object.assign || function __assign(t) {
21239			for (var s, i = 1, n = arguments.length; i < n; i++) {
21240				s = arguments[i];
21241				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
21242			}
21243			return t;
21244		};
21245		return __assign.apply(this, arguments);
21246	};
21247
21248	var videoSettings = {
21249		autoplayFirstVideo: true,
21250		youTubePlayerParams: false,
21251		vimeoPlayerParams: false,
21252		wistiaPlayerParams: false,
21253		gotoNextSlideOnVideoEnd: true,
21254		autoplayVideoOnSlide: false,
21255		videojs: false,
21256		videojsTheme: '',
21257		videojsOptions: {},
21258	};
21259
21260	/**
21261	 * List of lightGallery events
21262	 * All events should be documented here
21263	 * Below interfaces are used to build the website documentations
21264	 * */
21265	var lGEvents = {
21266		afterAppendSlide: 'lgAfterAppendSlide',
21267		init: 'lgInit',
21268		hasVideo: 'lgHasVideo',
21269		containerResize: 'lgContainerResize',
21270		updateSlides: 'lgUpdateSlides',
21271		afterAppendSubHtml: 'lgAfterAppendSubHtml',
21272		beforeOpen: 'lgBeforeOpen',
21273		afterOpen: 'lgAfterOpen',
21274		slideItemLoad: 'lgSlideItemLoad',
21275		beforeSlide: 'lgBeforeSlide',
21276		afterSlide: 'lgAfterSlide',
21277		posterClick: 'lgPosterClick',
21278		dragStart: 'lgDragStart',
21279		dragMove: 'lgDragMove',
21280		dragEnd: 'lgDragEnd',
21281		beforeNextSlide: 'lgBeforeNextSlide',
21282		beforePrevSlide: 'lgBeforePrevSlide',
21283		beforeClose: 'lgBeforeClose',
21284		afterClose: 'lgAfterClose',
21285		rotateLeft: 'lgRotateLeft',
21286		rotateRight: 'lgRotateRight',
21287		flipHorizontal: 'lgFlipHorizontal',
21288		flipVertical: 'lgFlipVertical',
21289		autoplay: 'lgAutoplay',
21290		autoplayStart: 'lgAutoplayStart',
21291		autoplayStop: 'lgAutoplayStop',
21292	};
21293
21294	var param = function (obj) {
21295		return Object.keys(obj)
21296			.map(function (k) {
21297			return encodeURIComponent(k) + '=' + encodeURIComponent(obj[k]);
21298		})
21299			.join('&');
21300	};
21301	var getVimeoURLParams = function (defaultParams, videoInfo) {
21302		if (!videoInfo || !videoInfo.vimeo)
21303			return '';
21304		var urlParams = videoInfo.vimeo[2] || '';
21305		var defaultPlayerParams = defaultParams && Object.keys(defaultParams).length !== 0
21306			? '&' + param(defaultParams)
21307			: '';
21308		// Support private video
21309		var urlWithHash = videoInfo.vimeo[0].split('/').pop() || '';
21310		var urlWithHashWithParams = urlWithHash.split('?')[0] || '';
21311		var hash = urlWithHashWithParams.split('#')[0];
21312		var isPrivate = videoInfo.vimeo[1] !== hash;
21313		if (isPrivate) {
21314			urlParams = urlParams.replace("/" + hash, '');
21315		}
21316		urlParams =
21317			urlParams[0] == '?' ? '&' + urlParams.slice(1) : urlParams || '';
21318		// For vimeo last params gets priority if duplicates found
21319		// Uncode edit ##START##
21320		var vimeoPlayerParams = '?autoplay=0';
21321		if ( typeof SiteParameters !== 'undefined' && typeof SiteParameters.vimeoPlayerParams !== 'undefined' && SiteParameters.vimeoPlayerParams !== '' ) {
21322			vimeoPlayerParams = SiteParameters.vimeoPlayerParams;
21323		}
21324		if ( urlParams.indexOf('muted=') < 0 && vimeoPlayerParams.indexOf('muted=') < 0 ) {
21325			vimeoPlayerParams += '&muted=1';
21326		}
21327		// var vimeoPlayerParams = "?autoplay=0&muted=1" + (isPrivate ? "&h=" + hash : '') + defaultPlayerParams + urlParams;
21328		vimeoPlayerParams += (isPrivate ? "&h=" + hash : '') + defaultPlayerParams + urlParams;
21329		// Uncode edit ##END##
21330		return vimeoPlayerParams;
21331	};
21332
21333	/**
21334	 * Video module for lightGallery
21335	 * Supports HTML5, YouTube, Vimeo, wistia videos
21336	 *
21337	 *
21338	 * @ref Wistia
21339	 * https://wistia.com/support/integrations/wordpress(How to get url)
21340	 * https://wistia.com/support/developers/embed-options#using-embed-options
21341	 * https://wistia.com/support/developers/player-api
21342	 * https://wistia.com/support/developers/construct-an-embed-code
21343	 * http://jsfiddle.net/xvnm7xLm/
21344	 * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video
21345	 * https://wistia.com/support/embed-and-share/sharing-videos
21346	 * https://private-sharing.wistia.com/medias/mwhrulrucj
21347	 *
21348	 * @ref Youtube
21349	 * https://developers.google.com/youtube/player_parameters#enablejsapi
21350	 * https://developers.google.com/youtube/iframe_api_reference
21351	 * https://developer.chrome.com/blog/autoplay/#iframe-delegation
21352	 *
21353	 * @ref Vimeo
21354	 * https://stackoverflow.com/questions/10488943/easy-way-to-get-vimeo-id-from-a-vimeo-url
21355	 * https://vimeo.zendesk.com/hc/en-us/articles/360000121668-Starting-playback-at-a-specific-timecode
21356	 * https://vimeo.zendesk.com/hc/en-us/articles/360001494447-Using-Player-Parameters
21357	 */
21358	var Video = /** @class */ (function () {
21359		function Video(instance) {
21360			// get lightGallery core plugin instance
21361			this.core = instance;
21362			this.settings = __assign(__assign({}, videoSettings), this.core.settings);
21363			return this;
21364		}
21365		Video.prototype.init = function () {
21366			var _this = this;
21367			/**
21368			 * Event triggered when video url found without poster
21369			 * Append video HTML
21370			 * Play if autoplayFirstVideo is true
21371			 */
21372			this.core.LGel.on(lGEvents.hasVideo + ".video", this.onHasVideo.bind(this));
21373			this.core.LGel.on(lGEvents.posterClick + ".video", function () {
21374				var $el = _this.core.getSlideItem(_this.core.index);
21375				_this.loadVideoOnPosterClick($el);
21376			});
21377			this.core.LGel.on(lGEvents.slideItemLoad + ".video", this.onSlideItemLoad.bind(this));
21378			// @desc fired immediately before each slide transition.
21379			this.core.LGel.on(lGEvents.beforeSlide + ".video", this.onBeforeSlide.bind(this));
21380			// @desc fired immediately after each slide transition.
21381			this.core.LGel.on(lGEvents.afterSlide + ".video", this.onAfterSlide.bind(this));
21382		};
21383		/**
21384		 * @desc Event triggered when a slide is completely loaded
21385		 *
21386		 * @param {Event} event - lightGalley custom event
21387		 */
21388		Video.prototype.onSlideItemLoad = function (event) {
21389			var _this = this;
21390			var _a = event.detail, isFirstSlide = _a.isFirstSlide, index = _a.index;
21391			// Should check the active slide as well as user may have moved to different slide before the first slide is loaded
21392			if (this.settings.autoplayFirstVideo &&
21393				isFirstSlide &&
21394				index === this.core.index) {
21395				// Delay is just for the transition effect on video load
21396				setTimeout(function () {
21397					_this.loadAndPlayVideo(index);
21398				}, 200);
21399			}
21400			// Should not call on first slide. should check only if the slide is active
21401			if (!isFirstSlide &&
21402				this.settings.autoplayVideoOnSlide &&
21403				index === this.core.index) {
21404				this.loadAndPlayVideo(index);
21405			}
21406		};
21407		/**
21408		 * @desc Event triggered when video url or poster found
21409		 * Append video HTML is poster is not given
21410		 * Play if autoplayFirstVideo is true
21411		 *
21412		 * @param {Event} event - Javascript Event object.
21413		 */
21414		Video.prototype.onHasVideo = function (event) {
21415			var _a = event.detail, index = _a.index, src = _a.src, html5Video = _a.html5Video, hasPoster = _a.hasPoster;
21416			if (!hasPoster) {
21417				// All functions are called separately if poster exist in loadVideoOnPosterClick function
21418				this.appendVideos(this.core.getSlideItem(index), {
21419					src: src,
21420					addClass: 'lg-object',
21421					index: index,
21422					html5Video: html5Video,
21423				});
21424				// Automatically navigate to next slide once video reaches the end.
21425				this.gotoNextSlideOnVideoEnd(src, index);
21426			}
21427		};
21428		/**
21429		 * @desc fired immediately before each slide transition.
21430		 * Pause the previous video
21431		 * Hide the download button if the slide contains YouTube, Vimeo, or Wistia videos.
21432		 *
21433		 * @param {Event} event - Javascript Event object.
21434		 * @param {number} prevIndex - Previous index of the slide.
21435		 * @param {number} index - Current index of the slide
21436		 */
21437		Video.prototype.onBeforeSlide = function (event) {
21438			if (this.core.lGalleryOn) {
21439				var prevIndex = event.detail.prevIndex;
21440				this.pauseVideo(prevIndex);
21441			}
21442			// Uncode edit ##START##
21443			var _a = event.detail, index = _a.index, src = _a.info.src;
21444			if ( typeof src !== 'undefined' && src.indexOf("autoplay") > -1 ) {
21445				this.loadAndPlayVideo(index);
21446
21447				var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {},
21448					$videoElement = this.core.getSlideItem(index).find('.lg-video-object').first();
21449				if (videoInfo.vimeo) {
21450					var vimeoPlayer = new Vimeo.Player($videoElement.get());
21451					vimeoPlayer.on('play', function () {
21452						vimeoPlayer.setCurrentTime(0);
21453					});
21454				} else if ( videoInfo.youtube ) {
21455					try {
21456						$videoElement.get().contentWindow.postMessage("{\"event\":\"command\",\"func\":\"seekTo\",\"args\":[0, true]}", '*');
21457					}
21458					catch (e) {
21459						console.warn(e);
21460					}
21461				}
21462			}
21463			// Uncode edit ##END##
21464		};
21465		/**
21466		 * @desc fired immediately after each slide transition.
21467		 * Play video if autoplayVideoOnSlide option is enabled.
21468		 *
21469		 * @param {Event} event - Javascript Event object.
21470		 * @param {number} prevIndex - Previous index of the slide.
21471		 * @param {number} index - Current index of the slide
21472		 * @todo should check on onSlideLoad as well if video is not loaded on after slide
21473		 */
21474		Video.prototype.onAfterSlide = function (event) {
21475			var _this = this;
21476			var _a = event.detail, index = _a.index, prevIndex = _a.prevIndex;
21477			// Do not call on first slide
21478			var $slide = this.core.getSlideItem(index);
21479			if (this.settings.autoplayVideoOnSlide && index !== prevIndex) {
21480				if ($slide.hasClass('lg-complete')) {
21481					setTimeout(function () {
21482						_this.loadAndPlayVideo(index);
21483					}, 100);
21484				}
21485			}
21486		};
21487		Video.prototype.loadAndPlayVideo = function (index) {
21488			var $slide = this.core.getSlideItem(index);
21489			var currentGalleryItem = this.core.galleryItems[index];
21490			if (currentGalleryItem.poster) {
21491				this.loadVideoOnPosterClick($slide, true);
21492			}
21493			else {
21494				//Uncode edit ##START##
21495				// this.playVideo(index);
21496				var src = currentGalleryItem.src;
21497				if ( typeof src !== 'undefined' && src.indexOf("autoplay") > -1) {
21498					if ( this.core.index == index ) {
21499						this.playVideo(index);
21500					} else {
21501						this.pauseVideo(index);
21502					}
21503				}
21504				//Uncode edit ##END##
21505			}
21506		};
21507		/**
21508		 * Play HTML5, Youtube, Vimeo or Wistia videos in a particular slide.
21509		 * @param {number} index - Index of the slide
21510		 */
21511		Video.prototype.playVideo = function (index) {
21512			this.controlVideo(index, 'play');
21513		};
21514		/**
21515		 * Pause HTML5, Youtube, Vimeo or Wistia videos in a particular slide.
21516		 * @param {number} index - Index of the slide
21517		 */
21518		Video.prototype.pauseVideo = function (index) {
21519			this.controlVideo(index, 'pause');
21520		};
21521		Video.prototype.getVideoHtml = function (src, addClass, index, html5Video) {
21522			var video = '';
21523			var videoInfo = this.core.galleryItems[index]
21524				.__slideVideoInfo || {};
21525			var currentGalleryItem = this.core.galleryItems[index];
21526			var videoTitle = currentGalleryItem.title || currentGalleryItem.alt;
21527			videoTitle = videoTitle ? 'title="' + videoTitle + '"' : '';
21528			var commonIframeProps = "allowtransparency=\"true\"\n            frameborder=\"0\"\n            scrolling=\"no\"\n            allowfullscreen\n            mozallowfullscreen\n            webkitallowfullscreen\n            oallowfullscreen\n            msallowfullscreen";
21529			if (videoInfo.youtube) {
21530				var videoId = 'lg-youtube' + index;
21531				var slideUrlParams = videoInfo.youtube[2]
21532					? videoInfo.youtube[2] + '&'
21533					: '';
21534				// For youtube first parms gets priority if duplicates found
21535				// Uncode edit ##START##
21536				// var youTubePlayerParams = "?" + slideUrlParams + "wmode=opaque&autoplay=0&mute=1&enablejsapi=1";
21537				var youTubePlayerParams = "?" + slideUrlParams + "wmode=opaque&enablejsapi=1";
21538				if ( slideUrlParams.indexOf('autoplay=') < 0 && youTubePlayerParams.indexOf('autoplay=') < 0 ) {
21539					youTubePlayerParams += '&autoplay=0';
21540				}
21541				if ( slideUrlParams.indexOf('mute=') < 0 && youTubePlayerParams.indexOf('mute=') < 0 ) {
21542					youTubePlayerParams += '&mute=1';
21543				}
21544				// Uncode edit ##END##
21545				var playerParams = youTubePlayerParams +
21546					(this.settings.youTubePlayerParams
21547						? '&' + param(this.settings.youTubePlayerParams)
21548						: '');
21549				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>";
21550			}
21551			else if (videoInfo.vimeo) {
21552				var videoId = 'lg-vimeo' + index;
21553				var playerParams = getVimeoURLParams(this.settings.vimeoPlayerParams, videoInfo);
21554				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>";
21555			}
21556			else if (videoInfo.wistia) {
21557				var wistiaId = 'lg-wistia' + index;
21558				var playerParams = param(this.settings.wistiaPlayerParams);
21559				playerParams = playerParams ? '?' + playerParams : '';
21560				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>";
21561			}
21562			else if (videoInfo.html5) {
21563				var html5VideoMarkup = '';
21564				for (var i = 0; i < html5Video.source.length; i++) {
21565					html5VideoMarkup += "<source src=\"" + html5Video.source[i].src + "\" type=\"" + html5Video.source[i].type + "\">";
21566				}
21567				if (html5Video.tracks) {
21568					var _loop_1 = function (i) {
21569						var trackAttributes = '';
21570						var track = html5Video.tracks[i];
21571						Object.keys(track || {}
21571).forEach(function (key) {
21572							trackAttributes += key + "=\"" + track[key] + "\" ";
21573						});
21574						html5VideoMarkup += "<track " + trackAttributes + ">";
21575					};
21576					for (var i = 0; i < html5Video.tracks.length; i++) {
21577						_loop_1(i);
21578					}
21579				}
21580				var html5VideoAttrs_1 = '';
21581				var videoAttributes_1 = html5Video.attributes || {};
21582				Object.keys(videoAttributes_1 || {}).forEach(function (key) {
21583					html5VideoAttrs_1 += key + "=\"" + videoAttributes_1[key] + "\" ";
21584				});
21585				video = "<video class=\"lg-video-object lg-html5 " + (this.settings.videojs && this.settings.videojsTheme
21586					? this.settings.videojsTheme + ' '
21587					: '') + " " + (this.settings.videojs ? ' video-js' : '') + "\" " + html5VideoAttrs_1 + ">\n                " + html5VideoMarkup + "\n                Your browser does not support HTML5 video.\n            </video>";
21588			}
21589			return video;
21590		};
21591		/**
21592		 * @desc - Append videos to the slide
21593		 *
21594		 * @param {HTMLElement} el - slide element
21595		 * @param {Object} videoParams - Video parameters, Contains src, class, index, htmlVideo
21596		 */
21597		Video.prototype.appendVideos = function (el, videoParams) {
21598			var _a;
21599			var videoHtml = this.getVideoHtml(videoParams.src, videoParams.addClass, videoParams.index, videoParams.html5Video);
21600			el.find('.lg-video-cont').append(videoHtml);
21601			var $videoElement = el.find('.lg-video-object').first();
21602			if (videoParams.html5Video) {
21603				$videoElement.on('mousedown.lg.video', function (e) {
21604					e.stopPropagation();
21605				});
21606			}
21607			if (this.settings.videojs && ((_a = this.core.galleryItems[videoParams.index].__slideVideoInfo) === null || _a === void 0 ? void 0 : _a.html5)) {
21608				try {
21609					return videojs($videoElement.get(), this.settings.videojsOptions);
21610				}
21611				catch (e) {
21612					console.warn('lightGallery:- Make sure you have included videojs');
21613				}
21614			}
21615		};
21616		Video.prototype.gotoNextSlideOnVideoEnd = function (src, index) {
21617			var _this = this;
21618			var $videoElement = this.core
21619				.getSlideItem(index)
21620				.find('.lg-video-object')
21621				.first();
21622			var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {};
21623			if (this.settings.gotoNextSlideOnVideoEnd) {
21624				if (videoInfo.html5) {
21625					$videoElement.on('ended', function () {
21626						_this.core.goToNextSlide();
21627					});
21628				}
21629				else if (videoInfo.vimeo) {
21630					try {
21631						// https://github.com/vimeo/player.js/#ended
21632						new Vimeo.Player($videoElement.get()).on('ended', function () {
21633							_this.core.goToNextSlide();
21634						});
21635					}
21636					catch (e) {
21637						console.warn('lightGallery:- Make sure you have included //github.com/vimeo/player.js');
21638					}
21639				}
21640				else if (videoInfo.wistia) {
21641					try {
21642						window._wq = window._wq || [];
21643						// @todo Event is gettign triggered multiple times
21644						window._wq.push({
21645							id: $videoElement.attr('id'),
21646							onReady: function (video) {
21647								video.bind('end', function () {
21648									_this.core.goToNextSlide();
21649								});
21650							},
21651						});
21652					}
21653					catch (e) {
21654						console.warn('lightGallery:- Make sure you have included //fast.wistia.com/assets/external/E-v1.js');
21655					}
21656				}
21657			}
21658		};
21659		Video.prototype.controlVideo = function (index, action) {
21660			var $videoElement = this.core
21661				.getSlideItem(index)
21662				.find('.lg-video-object')
21663				.first();
21664			var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {};
21665			if (!$videoElement.get())
21666				return;
21667			if (videoInfo.youtube) {
21668				try {
21669					$videoElement.get().contentWindow.postMessage("{\"event\":\"command\",\"func\":\"" + action + "Video\",\"args\":\"\"}", '*');
21670				}
21671				catch (e) {
21672					console.warn("lightGallery:- " + e);
21673				}
21674			}
21675			else if (videoInfo.vimeo) {
21676				try {
21677					new Vimeo.Player($videoElement.get())[action]();
21678				}
21679				catch (e) {
21680					console.warn('lightGallery:- Make sure you have included //github.com/vimeo/player.js');
21681				}
21682			}
21683			else if (videoInfo.html5) {
21684				if (this.settings.videojs) {
21685					try {
21686						videojs($videoElement.get())[action]();
21687					}
21688					catch (e) {
21689						console.warn('lightGallery:- Make sure you have included videojs');
21690					}
21691				}
21692				else {
21693					$videoElement.get()[action]();
21694				}
21695			}
21696			else if (videoInfo.wistia) {
21697				try {
21698					window._wq = window._wq || [];
21699					// @todo Find a way to destroy wistia player instance
21700					window._wq.push({
21701						id: $videoElement.attr('id'),
21702						onReady: function (video) {
21703							video[action]();
21704						},
21705					});
21706				}
21707				catch (e) {
21708					console.warn('lightGallery:- Make sure you have included //fast.wistia.com/assets/external/E-v1.js');
21709				}
21710			}
21711		};
21712		Video.prototype.loadVideoOnPosterClick = function ($el, forcePlay) {
21713			var _this = this;
21714			// check slide has poster
21715			if (!$el.hasClass('lg-video-loaded')) {
21716				// check already video element present
21717				if (!$el.hasClass('lg-has-video')) {
21718					$el.addClass('lg-has-video');
21719					var _html = void 0;
21720					var _src = this.core.galleryItems[this.core.index].src;
21721					var video = this.core.galleryItems[this.core.index].video;
21722					if (video) {
21723						_html =
21724							typeof video === 'string' ? JSON.parse(video) : video;
21725					}
21726					var videoJsPlayer_1 = this.appendVideos($el, {
21727						src: _src,
21728						addClass: '',
21729						index: this.core.index,
21730						html5Video: _html,
21731					});
21732					this.gotoNextSlideOnVideoEnd(_src, this.core.index);
21733					var $tempImg = $el.find('.lg-object').first().get();
21734					// @todo make sure it is working
21735					$el.find('.lg-video-cont').first().append($tempImg);
21736					$el.addClass('lg-video-loading');
21737					videoJsPlayer_1 &&
21738						videoJsPlayer_1.ready(function () {
21739							videoJsPlayer_1.on('loadedmetadata', function () {
21740								_this.onVideoLoadAfterPosterClick($el, _this.core.index);
21741							});
21742						});
21743					$el.find('.lg-video-object')
21744						.first()
21745						.on('load.lg error.lg loadedmetadata.lg', function () {
21746						setTimeout(function () {
21747							_this.onVideoLoadAfterPosterClick($el, _this.core.index);
21748						}, 50);
21749					});
21750				}
21751				else {
21752					this.playVideo(this.core.index);
21753				}
21754			}
21755			else if (forcePlay) {
21756				this.playVideo(this.core.index);
21757			}
21758		};
21759		Video.prototype.onVideoLoadAfterPosterClick = function ($el, index) {
21760			$el.addClass('lg-video-loaded');
21761			this.playVideo(index);
21762		};
21763		Video.prototype.destroy = function () {
21764			this.core.LGel.off('.lg.video');
21765			this.core.LGel.off('.video');
21766		};
21767		return Video;
21768	}());
21769
21770	return Video;
21771
21772})));
21773
21774
21775/*! @vimeo/player v2.17.1 | (c) 2022 Vimeo | MIT License | https://github.com/vimeo/player.js */
21776!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:{}}
21776),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 21776
21776var 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)}
21776},{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 21776-22983
21776))}(),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});
21777
21778/**
21779 * Owl carousel
21780 * @version 2.0.0-beta.3
21781 * @author Bartosz Wojciechowski
21782 * @license The MIT License (MIT)
21783 * @todo Lazy Load Icon
21784 * @todo prevent animationend bubling
21785 * @todo itemsScaleUp
21786 * @todo Test Zepto
21787 * @todo stagePadding calculate wrong active classes
21788 */
21789;(function($, window, document, undefined) {
21790
21791	/**
21792	 * Creates a carousel.
21793	 * @class The Owl Carousel.
21794	 * @public
21795	 * @param {HTMLElement|jQuery} element - The element to create the carousel for.
21796	 * @param {Object} [options] - The options
21797	 */
21798	function Owl(element, options) {
21799
21800		/**
21801		 * Current settings for the carousel.
21802		 * @public
21803		 */
21804		this.settings = null;
21805
21806		/**
21807		 * Current options set by the caller including defaults.
21808		 * @public
21809		 */
21810		this.options = $.extend({}, Owl.Defaults, options);
21811
21812		/**
21813		 * Plugin element.
21814		 * @public
21815		 */
21816		this.$element = $(element);
21817
21818		/**
21819		 * Proxied event handlers.
21820		 * @protected
21821		 */
21822		this._handlers = {};
21823
21824		/**
21825		 * References to the running plugins of this carousel.
21826		 * @protected
21827		 */
21828		this._plugins = {};
21829
21830		/**
21831		 * Currently suppressed events to prevent them from beeing retriggered.
21832		 * @protected
21833		 */
21834		this._supress = {};
21835
21836		/**
21837		 * Absolute current position.
21838		 * @protected
21839		 */
21840		this._current = null;
21841
21842		/**
21843		 * Animation speed in milliseconds.
21844		 * @protected
21845		 */
21846		this._speed = null;
21847
21848		/**
21849		 * Coordinates of all items in pixel.
21850		 * @todo The name of this member is missleading.
21851		 * @protected
21852		 */
21853		this._coordinates = [];
21854
21855		/**
21856		 * Current breakpoint.
21857		 * @todo Real media queries would be nice.
21858		 * @protected
21859		 */
21860		this._breakpoint = null;
21861
21862		/**
21863		 * Current width of the plugin element.
21864		 */
21865		this._width = null;
21866
21867		/**
21868		 * All real items.
21869		 * @protected
21870		 */
21871		this._items = [];
21872
21873		/**
21874		 * All cloned items.
21875		 * @protected
21876		 */
21877		this._clones = [];
21878
21879		/**
21880		 * Merge values of all items.
21881		 * @todo Maybe this could be part of a plugin.
21882		 * @protected
21883		 */
21884		this._mergers = [];
21885
21886		/**
21887		 * Widths of all items.
21888		 */
21889		this._widths = [];
21890
21891		/**
21892		 * Invalidated parts within the update process.
21893		 * @protected
21894		 */
21895		this._invalidated = {};
21896
21897		/**
21898		 * Ordered list of workers for the update process.
21899		 * @protected
21900		 */
21901		this._pipe = [];
21902
21903		/**
21904		 * Current state information for the drag operation.
21905		 * @todo #261
21906		 * @protected
21907		 */
21908		this._drag = {
21909			time: null,
21910			target: null,
21911			pointer: null,
21912			stage: {
21913				start: null,
21914				current: null
21915			},
21916			direction: null
21917		};
21918
21919		/**
21920		 * Current state information and their tags.
21921		 * @type {Object}
21922		 * @protected
21923		 */
21924		this._states = {
21925			current: {},
21926			tags: {
21927				'initializing': [ 'busy' ],
21928				'animating': [ 'busy' ],
21929				'dragging': [ 'interacting' ]
21930			}
21931		};
21932
21933		$.each([ 'onResize', 'onThrottledResize' ], $.proxy(function(i, handler) {
21934			this._handlers[handler] = $.proxy(this[handler], this);
21935		}, this));
21936
21937		$.each(Owl.Plugins, $.proxy(function(key, plugin) {
21938			this._plugins[key.charAt(0).toLowerCase() + key.slice(1)]
21939				= new plugin(this);
21940		}, this));
21941
21942		$.each(Owl.Workers, $.proxy(function(priority, worker) {
21943			this._pipe.push({
21944				'filter': worker.filter,
21945				'run': $.proxy(worker.run, this)
21946			});
21947		}, this));
21948
21949		this.setup();
21950		this.initialize();
21951	}
21952
21953	/**
21954	 * Default options for the carousel.
21955	 * @public
21956	 */
21957	Owl.Defaults = {
21958		items: 3,
21959		loop: false,
21960		center: false,
21961		rewind: false,
21962
21963		mouseDrag: true,
21964		touchDrag: true,
21965		pullDrag: true,
21966		freeDrag: false,
21967
21968		margin: 0,
21969		stagePadding: 0,
21970
21971		merge: false,
21972		mergeFit: true,
21973		autoWidth: false,
21974
21975		startPosition: 0,
21976		rtl: false,
21977
21978		smartSpeed: 250,
21979		fluidSpeed: false,
21980		dragEndSpeed: false,
21981
21982		responsive: {},
21983		responsiveRefreshRate: 200,
21984		responsiveBaseElement: window,
21985
21986		fallbackEasing: 'swing',
21987
21988		info: false,
21989
21990		nestedItemSelector: false,
21991		itemElement: 'div',
21992		stageElement: 'div',
21993
21994		refreshClass: 'owl-refresh',
21995		loadedClass: 'owl-loaded',
21996		loadingClass: 'owl-loading',
21997		rtlClass: 'owl-rtl',
21998		responsiveClass: 'owl-responsive',
21999		dragClass: 'owl-drag',
22000		itemClass: 'owl-item',
22001		stageClass: 'owl-stage',
22002		stageOuterClass: 'owl-stage-outer',
22003		grabClass: 'owl-grab'
22004	};
22005
22006	/**
22007	 * Enumeration for width.
22008	 * @public
22009	 * @readonly
22010	 * @enum {String}
22011	 */
22012	Owl.Width = {
22013		Default: 'default',
22014		Inner: 'inner',
22015		Outer: 'outer'
22016	};
22017
22018	/**
22019	 * Enumeration for types.
22020	 * @public
22021	 * @readonly
22022	 * @enum {String}
22023	 */
22024	Owl.Type = {
22025		Event: 'event',
22026		State: 'state'
22027	};
22028
22029	/**
22030	 * Contains all registered plugins.
22031	 * @public
22032	 */
22033	Owl.Plugins = {};
22034
22035	/**
22036	 * List of workers involved in the update process.
22037	 */
22038	Owl.Workers = [ {
22039		filter: [ 'width', 'settings' ],
22040		run: function() {
22041			this._width = (this.$element.closest('.px-gutter').length) ? 12 * Math.ceil(this.$element.width() / 12) : this.$element.width();
22042			//this._width = (UNCODE.isMobile) ? this.$element.width() : 12 * Math.ceil(this.$element.width() / 12);
22043		}
22044	}, {
22045		filter: [ 'width', 'items', 'settings' ],
22046		run: function(cache) {
22047			cache.current = this._items && this._items[this.relative(this._current)];
22048		}
22049	}, {
22050		filter: [ 'items', 'settings' ],
22051		run: function() {
22052			this.$stage.children('.cloned').remove();
22053		}
22054	}, {
22055		filter: [ 'width', 'items', 'settings' ],
22056		run: function(cache) {
22057			var margin = this.settings.margin || '',
22058				grid = !this.settings.autoWidth,
22059				rtl = this.settings.rtl,
22060				css = {
22061					'width': 'auto',
22062					'margin-left': rtl ? margin : '',
22063					'margin-right': rtl ? '' : margin
22064				};
22065
22066			!grid && this.$stage.children().css(css);
22067
22068			cache.css = css;
22069		}
22070	}, {
22071		filter: [ 'width', 'items', 'settings' ],
22072		run: function(cache) {
22073			//UNCODE edit to fix Chrome stage padding issue
22074			var width = Math.round((this.width() / this.settings.items).toFixed(3) - this.settings.margin),
22075				merge = null,
22076				iterator = this._items.length,
22077				grid = !this.settings.autoWidth,
22078				widths = [];
22079
22080			cache.items = {
22081				merge: false,
22082				width: width
22083			};
22084
22085			while (iterator--) {
22086				merge = this._mergers[iterator];
22087				merge = this.settings.mergeFit && Math.min(merge, this.settings.items) || merge;
22088
22089				cache.items.merge = merge > 1 || cache.items.merge;
22090
22091				widths[iterator] = !grid ? this._items[iterator].width() : width * merge;
22092			}
22093
22094			this._widths = widths;
22095		}
22096	}, {
22097		filter: [ 'items', 'settings' ],
22098		run: function() {
22099			var clones = [],
22100				items = this._items,
22101				settings = this.settings,
22102				view = Math.max(settings.items * 2, 4),
22103				size = Math.ceil(items.length / 2) * 2,
22104				repeat = settings.loop && items.length ? settings.rewind ? view : Math.max(view, size) : 0,
22105				append = '',
22106				prepend = '';
22107
22108			repeat /= 2;
22109
22110			while (repeat--) {
22111				clones.push(this.normalize(clones.length / 2, true));
22112				append = append + items[clones[clones.length - 1]][0].outerHTML;
22113				clones.push(this.normalize(items.length - 1 - (clones.length - 1) / 2, true));
22114				prepend = items[clones[clones.length - 1]][0].outerHTML + prepend;
22115			}
22116
22117			this._clones = clones;
22118
22119			// var appendVideo = $(append).find('.uncode-video-container');
22120			// if (appendVideo.length) {
22121			// 	appendVideo.attr('data-id', Math.round(Math.random() * 100000));
22122			// }
22123			// var prependVideo = $(prepend).find('.uncode-video-container');
22124			// if (prependVideo.length) {
22125			// 	prependVideo.attr('data-id', Math.round(Math.random() * 100000));
22126			// }
22127			$(append).addClass('cloned').appendTo(this.$stage);
22128			$(prepend).addClass('cloned').prependTo(this.$stage);
22129		}
22130	}, {
22131		filter: [ 'width', 'items', 'settings' ],
22132		run: function() {
22133			var rtl = this.settings.rtl ? 1 : -1,
22134				size = this._clones.length + this._items.length,
22135				iterator = -1,
22136				previous = 0,
22137				current = 0,
22138				coordinates = [];
22139
22140			while (++iterator < size) {
22141				previous = coordinates[iterator - 1] || 0;
22142				current = this._widths[this.relative(iterator)] + this.settings.margin;
22143				coordinates.push(previous + current * rtl);
22144			}
22145
22146			this._coordinates = coordinates;
22147		}
22148	}, {
22149		filter: [ 'width', 'items', 'settings' ],
22150		run: function() {
22151			var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200,
22152				padding = stagePadding,
22153				coordinates = this._coordinates,
22154				css = {
22155					'width': Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2,
22156					'padding-left': padding || '',
22157					'padding-right': padding || ''
22158				};
22159
22160			this.$stage.css(css);
22161		}
22162	}, {
22163		filter: [ 'width', 'items', 'settings' ],
22164		run: function(cache) {
22165			var iterator = this._coordinates.length,
22166				grid = !this.settings.autoWidth,
22167				items = this.$stage.children();
22168
22169			if (grid && cache.items.merge) {
22170				while (iterator--) {
22171					cache.css.width = this._widths[this.relative(iterator)];
22172					items.eq(iterator).css(cache.css);
22173				}
22174			} else if (grid) {
22175				cache.css.width = cache.items.width;
22176				items.css(cache.css);
22177			}
22178		}
22179	}, {
22180		filter: [ 'items' ],
22181		run: function() {
22182			this._coordinates.length < 1 && this.$stage.removeAttr('style');
22183		}
22184	}, {
22185		filter: [ 'width', 'items', 'settings' ],
22186		run: function(cache) {
22187			cache.current = cache.current ? this.$stage.children().index(cache.current) : 0;
22188			cache.current = Math.max(this.minimum(), Math.min(this.maximum(), cache.current));
22189			this.reset(cache.current);
22190		}
22191	}, {
22192		filter: [ 'position' ],
22193		run: function() {
22194			this.animate(this.coordinates(this._current));
22195		}
22196	}, {
22197		filter: [ 'width', 'position', 'items', 'settings' ],
22198		run: function() {
22199			var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200,
22200				rtl = this.settings.rtl ? 1 : -1,
22201				padding = this.settings.stagePadding * 2,
22202				begin = this.coordinates(this.current()) + padding,
22203				end = begin + this.width() * rtl,
22204				inner, outer, matches = [], i, n;
22205
22206			for (i = 0, n = this._coordinates.length; i < n; i++) {
22207				inner = this._coordinates[i - 1] || 0;
22208				outer = Math.abs(this._coordinates[i]) + padding * rtl;
22209
22210				if ((this.op(inner, '<=', begin) && (this.op(inner, '>', end)))
22211					|| (this.op(outer, '<', begin) && this.op(outer, '>', end))) {
22212					matches.push(i);
22213				}
22214			}
22215
22216			this.$stage.children('.active').removeClass('active');
22217			this.$stage.children(':eq(' + matches.join('), :eq(') + ')').addClass('active');
22218
22219			if (this.settings.center) {
22220				this.$stage.children('.center').removeClass('center');
22221				this.$stage.children().eq(this.current()).addClass('center');
22222			}
22223		}
22224	} ];
22225
22226	/**
22227	 * Initializes the carousel.
22228	 * @protected
22229	 */
22230	Owl.prototype.initialize = function() {
22231		this.enter('initializing');
22232		this.trigger('initialize');
22233
22234		this.$element.toggleClass(this.settings.rtlClass, this.settings.rtl);
22235
22236		if (this.settings.autoWidth && !this.is('pre-loading')) {
22237			var imgs, nestedSelector, width;
22238			imgs = this.$element.find('img');
22239			nestedSelector = this.settings.nestedItemSelector ? '.' + this.settings.nestedItemSelector : undefined;
22240			width = this.$element.children(nestedSelector).width();
22241
22242			if (imgs.length && width <= 0) {
22243				this.preloadAutoWidthImages(imgs);
22244			}
22245		}
22246
22247		this.$element.addClass(this.options.loadingClass);
22248
22249		// create stage
22250		this.$stage = $('<' + this.settings.stageElement + ' class="' + this.settings.stageClass + '"/>')
22251			.wrap('<div class="' + this.settings.stageOuterClass + '"/>');
22252
22253		// append stage
22254		this.$element.append(this.$stage.parent());
22255
22256		// append content
22257		this.replace(this.$element.children().not(this.$stage.parent()));
22258
22259		// check visibility
22260		if (this.$element.is(':visible')) {
22261			// update view
22262			this.refresh();
22263		} else {
22264			// invalidate width
22265			this.invalidate('width');
22266		}
22267
22268		this.$element
22269			.removeClass(this.options.loadingClass)
22270			.addClass(this.options.loadedClass);
22271
22272		// register event handlers
22273		this.registerEventHandlers();
22274
22275		this.leave('initializing');
22276		this.trigger('initialized');
22277	};
22278
22279	/**
22280	 * Setups the current settings.
22281	 * @todo Remove responsive classes. Why should adaptive designs be brought into IE8?
22282	 * @todo Support for media queries by using `matchMedia` would be nice.
22283	 * @public
22284	 */
22285	Owl.prototype.setup = function() {
22286		var viewport = this.viewport(),
22287			overwrites = this.options.responsive,
22288			match = -1,
22289			settings = null;
22290
22291		if (!overwrites) {
22292			settings = $.extend({}, this.options);
22293		} else {
22294			$.each(overwrites, function(breakpoint) {
22295				if (breakpoint <= viewport && breakpoint > match) {
22296					match = Number(breakpoint);
22297				}
22298			});
22299
22300			settings = $.extend({}, this.options, overwrites[match]);
22301			delete settings.responsive;
22302
22303			// responsive class
22304			if (settings.responsiveClass) {
22305				this.$element.attr('class',
22306					this.$element.attr('class').replace(new RegExp('(' + this.options.responsiveClass + '-)\\S+\\s', 'g'), '$1' + match)
22307				);
22308			}
22309		}
22310
22311		if (this.settings === null || this._breakpoint !== match) {
22312			this.trigger('change', { property: { name: 'settings', value: settings } });
22313			this._breakpoint = match;
22314			this.settings = settings;
22315			this.invalidate('settings');
22316			this.trigger('changed', { property: { name: 'settings', value: this.settings } });
22317		}
22318	};
22319
22320	/**
22321	 * Updates option logic if necessery.
22322	 * @protected
22323	 */
22324	Owl.prototype.optionsLogic = function() {
22325		if (this.settings.autoWidth) {
22326			this.settings.stagePadding = false;
22327			this.settings.merge = false;
22328		}
22329	};
22330
22331	/**
22332	 * Prepares an item before add.
22333	 * @todo Rename event parameter `content` to `item`.
22334	 * @protected
22335	 * @returns {jQuery|HTMLElement} - The item container.
22336	 */
22337	Owl.prototype.prepare = function(item, index) {
22338		var event = this.trigger('prepare', { content: item });
22339		if (!event.data) {
22340			event.data = $('<' + this.settings.itemElement + '/>')
22341				.addClass(this.options.itemClass).attr('data-index', index + 1).append(item)
22342		}
22343
22344		this.trigger('prepared', { content: event.data });
22345
22346		return event.data;
22347	};
22348
22349	/**
22350	 * Updates the view.
22351	 * @public
22352	 */
22353	Owl.prototype.update = function() {
22354		var i = 0,
22355			n = this._pipe.length,
22356			filter = $.proxy(function(p) { return this[p] }, this._invalidated),
22357			cache = {};
22358
22359		while (i < n) {
22360			if (this._invalidated.all || $.grep(this._pipe[i].filter, filter).length > 0) {
22361				this._pipe[i].run(cache);
22362			}
22363			i++;
22364		}
22365
22366		this._invalidated = {};
22367
22368		!this.is('valid') && this.enter('valid');
22369	};
22370
22371	/**
22372	 * Gets the width of the view.
22373	 * @public
22374	 * @param {Owl.Width} [dimension=Owl.Width.Default] - The dimension to return.
22375	 * @returns {Number} - The width of the view in pixel.
22376	 */
22377	Owl.prototype.width = function(dimension) {
22378		dimension = dimension || Owl.Width.Default;
22379		var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200;
22380		switch (dimension) {
22381			case Owl.Width.Inner:
22382			case Owl.Width.Outer:
22383				return this._width;
22384			default:
22385				return this._width - stagePadding * 2 + this.settings.margin;
22386		}
22387	};
22388
22389	/**
22390	 * Refreshes the carousel primarily for adaptive purposes.
22391	 * @public
22392	 */
22393	Owl.prototype.refresh = function() {
22394		this.enter('refreshing');
22395		this.trigger('refresh');
22396
22397		this.setup();
22398
22399		this.optionsLogic();
22400
22401		this.$element.addClass(this.options.refreshClass);
22402
22403		this.update();
22404
22405		this.$element.removeClass(this.options.refreshClass);
22406
22407		this.leave('refreshing');
22408		this.trigger('refreshed');
22409	};
22410
22411	/**
22412	 * Checks window `resize` event.
22413	 * @protected
22414	 */
22415	Owl.prototype.onThrottledResize = function() {
22416		window.clearTimeout(this.resizeTimer);
22417		this.resizeTimer = window.setTimeout(this._handlers.onResize, this.settings.responsiveRefreshRate);
22418	};
22419
22420	/**
22421	 * Checks window `resize` event.
22422	 * @protected
22423	 */
22424	Owl.prototype.onResize = function() {
22425		if (!this._items.length) {
22426			return false;
22427		}
22428
22429		if (this._width === this.$element.width()) {
22430			return false;
22431		}
22432
22433		if (!this.$element.is(':visible')) {
22434			return false;
22435		}
22436
22437		this.enter('resizing');
22438
22439		if (this.trigger('resize').isDefaultPrevented()) {
22440			this.leave('resizing');
22441			return false;
22442		}
22443
22444		this.invalidate('width');
22445
22446		this.refresh();
22447
22448		this.leave('resizing');
22449		this.trigger('resized');
22450	};
22451
22452	/**
22453	 * Registers event handlers.
22454	 * @todo Check `msPointerEnabled`
22455	 * @todo #261
22456	 * @protected
22457	 */
22458	Owl.prototype.registerEventHandlers = function() {
22459		if ($.support.transition) {
22460			this.$stage.on($.support.transition.end + '.owl.core', $.proxy(this.onTransitionEnd, this));
22461		}
22462
22463		if (this.settings.responsive !== false) {
22464			this.on(window, 'resize', this._handlers.onThrottledResize);
22465		}
22466
22467		if (this.settings.mouseDrag) {
22468			this.$element.addClass(this.options.dragClass);
22469			this.$stage.on('mousedown.owl.core', $.proxy(this.onDragStart, this));
22470			this.$stage.on('dragstart.owl.core selectstart.owl.core', function() { return false });
22471		}
22472
22473		if (this.settings.touchDrag){
22474			this.$stage.on('touchstart.owl.core', $.proxy(this.onDragStart, this));
22475			this.$stage.on('touchcancel.owl.core', $.proxy(this.onDragEnd, this));
22476		}
22477	};
22478
22479	/**
22480	 * Handles `touchstart` and `mousedown` events.
22481	 * @todo Horizontal swipe threshold as option
22482	 * @todo #261
22483	 * @protected
22484	 * @param {Event} event - The event arguments.
22485	 */
22486	Owl.prototype.onDragStart = function(event) {
22487		var stage = null;
22488
22489		if (event.which === 3) {
22490			return;
22491		}
22492
22493		if ($.support.transform) {
22494			stage = this.$stage.css('transform').replace(/.*\(|\)| /g, '').split(',');
22495			stage = {
22496				x: stage[stage.length === 16 ? 12 : 4],
22497				y: stage[stage.length === 16 ? 13 : 5]
22498			};
22499		} else {
22500			stage = this.$stage.position();
22501			stage = {
22502				x: this.settings.rtl ?
22503					stage.left + this.$stage.width() - this.width() + this.settings.margin :
22504					stage.left,
22505				y: stage.top
22506			};
22507		}
22508
22509		if (this.is('animating')) {
22510			$.support.transform ? this.animate(stage.x) : this.$stage.stop()
22511			this.invalidate('position');
22512		}
22513
22514		this.$element.toggleClass(this.options.grabClass, event.type === 'mousedown');
22515
22516		this.speed(0);
22517
22518		this._drag.time = new Date().getTime();
22519		this._drag.target = $(event.target);
22520		this._drag.stage.start = stage;
22521		this._drag.stage.current = stage;
22522		this._drag.pointer = this.pointer(event);
22523
22524		$(document).on('mouseup.owl.core touchend.owl.core', $.proxy(this.onDragEnd, this));
22525
22526		$(document).one('mousemove.owl.core touchmove.owl.core', $.proxy(function(event) {
22527			var delta = this.difference(this._drag.pointer, this.pointer(event));
22528
22529			$(document).on('mousemove.owl.core touchmove.owl.core', $.proxy(this.onDragMove, this));
22530
22531			if (Math.abs(delta.x) < Math.abs(delta.y) && this.is('valid')) {
22532				return;
22533			}
22534
22535			event.preventDefault();
22536
22537			this.enter('dragging');
22538			this.trigger('drag');
22539		}, this));
22540	};
22541
22542	/**
22543	 * Handles the `touchmove` and `mousemove` events.
22544	 * @todo #261
22545	 * @protected
22546	 * @param {Event} event - The event arguments.
22547	 */
22548	Owl.prototype.onDragMove = function(event) {
22549		var minimum = null,
22550			maximum = null,
22551			pull = null,
22552			delta = this.difference(this._drag.pointer, this.pointer(event)),
22553			stage = this.difference(this._drag.stage.start, delta);
22554
22555		if (!this.is('dragging')) {
22556			return;
22557		}
22558
22559		event.preventDefault();
22560
22561		if (this.settings.loop) {
22562			minimum = this.coordinates(this.minimum());
22563			maximum = this.coordinates(this.maximum() + 1) - minimum;
22564			stage.x = (((stage.x - minimum) % maximum + maximum) % maximum) + minimum;
22565		} else {
22566			minimum = this.settings.rtl ? this.coordinates(this.maximum()) : this.coordinates(this.minimum());
22567			maximum = this.settings.rtl ? this.coordinates(this.minimum()) : this.coordinates(this.maximum());
22568			pull = this.settings.pullDrag ? -1 * delta.x / 5 : 0;
22569			stage.x = Math.max(Math.min(stage.x, minimum + pull), maximum + pull);
22570		}
22571
22572		this._drag.stage.current = stage;
22573
22574		this.animate(stage.x);
22575	};
22576
22577	/**
22578	 * Handles the `touchend` and `mouseup` events.
22579	 * @todo #261
22580	 * @todo Threshold for click event
22581	 * @protected
22582	 * @param {Event} event - The event arguments.
22583	 */
22584	Owl.prototype.onDragEnd = function(event) {
22585		var delta = this.difference(this._drag.pointer, this.pointer(event)),
22586			stage = this._drag.stage.current,
22587			direction = delta.x > 0 ^ this.settings.rtl ? 'left' : 'right';
22588
22589		$(document).off('.owl.core');
22590
22591		this.$element.removeClass(this.options.grabClass);
22592
22593		if (delta.x !== 0 && this.is('dragging') || !this.is('valid')) {
22594			this.speed(this.settings.dragEndSpeed || this.settings.smartSpeed);
22595			this.current(this.closest(stage.x, delta.x !== 0 ? direction : this._drag.direction));
22596			this.invalidate('position');
22597			this.update();
22598
22599			this._drag.direction = direction;
22600
22601			if (Math.abs(delta.x) > 3 || new Date().getTime() - this._drag.time > 300) {
22602				this._drag.target.one('click.owl.core', function() { return false; });
22603			}
22604		}
22605
22606		if (!this.is('dragging')) {
22607			return;
22608		}
22609
22610		this.leave('dragging');
22611		this.trigger('dragged');
22612	};
22613
22614	/**
22615	 * Gets absolute position of the closest item for a coordinate.
22616	 * @todo Setting `freeDrag` makes `closest` not reusable. See #165.
22617	 * @protected
22618	 * @param {Number} coordinate - The coordinate in pixel.
22619	 * @param {String} direction - The direction to check for the closest item. Ether `left` or `right`.
22620	 * @return {Number} - The absolute position of the closest item.
22621	 */
22622	Owl.prototype.closest = function(coordinate, direction) {
22623		var position = -1,
22624			pull = 30,
22625			width = this.width(),
22626			coordinates = this.coordinates();
22627
22628		if (!this.settings.freeDrag) {
22629			// check closest item
22630			$.each(coordinates, $.proxy(function(index, value) {
22631				if (coordinate > value - pull && coordinate < value + pull) {
22632					position = index;
22633				} else if (this.op(coordinate, '<', value)
22634					&& this.op(coordinate, '>', coordinates[index + 1] || value - width)) {
22635					position = direction === 'left' ? index + 1 : index;
22636				}
22637				return position === -1;
22638			}, this));
22639		}
22640
22641		if (!this.settings.loop) {
22642			// non loop boundries
22643			if (this.op(coordinate, '>', coordinates[this.minimum()])) {
22644				position = coordinate = this.minimum();
22645			} else if (this.op(coordinate, '<', coordinates[this.maximum()])) {
22646				position = coordinate = this.maximum();
22647			}
22648		}
22649
22650		return position;
22651	};
22652
22653	/**
22654	 * Animates the stage.
22655	 * @todo #270
22656	 * @public
22657	 * @param {Number} coordinate - The coordinate in pixels.
22658	 */
22659	Owl.prototype.animate = function(coordinate) {
22660		var animate = this.speed() > 0;
22661
22662		this.is('animating') && this.onTransitionEnd();
22663
22664		if (animate) {
22665			this.enter('animating');
22666			this.trigger('translate');
22667		}
22668
22669		if ($.support.transform3d && $.support.transition) {
22670			this.$stage.css({
22671				transform: 'translate3d(' + coordinate + 'px,0px,0px)',
22672				transition: (this.speed() / 1000) + 's'
22673			});
22674		} else if (animate) {
22675			this.$stage.animate({
22676				left: coordinate + 'px'
22677			}, this.speed(), this.settings.fallbackEasing, $.proxy(this.onTransitionEnd, this));
22678		} else {
22679			this.$stage.css({
22680				left: coordinate + 'px'
22681			});
22682		}
22683	};
22684
22685	/**
22686	 * Checks whether the carousel is in a specific state or not.
22687	 * @param {String} state - The state to check.
22688	 * @returns {Boolean} - The flag which indicates if the carousel is busy.
22689	 */
22690	Owl.prototype.is = function(state) {
22691		return this._states.current[state] && this._states.current[state] > 0;
22692	};
22693
22694	/**
22695	 * Sets the absolute position of the current item.
22696	 * @public
22697	 * @param {Number} [position] - The new absolute position or nothing to leave it unchanged.
22698	 * @returns {Number} - The absolute position of the current item.
22699	 */
22700	Owl.prototype.current = function(position) {
22701		if (position === undefined) {
22702			return this._current;
22703		}
22704
22705		if (this._items.length === 0) {
22706			return undefined;
22707		}
22708
22709		position = this.normalize(position);
22710
22711		if (this._current !== position) {
22712			var event = this.trigger('change', { property: { name: 'position', value: position } });
22713
22714			if (event.data !== undefined) {
22715				position = this.normalize(event.data);
22716			}
22717
22718			this._current = position;
22719
22720			this.invalidate('position');
22721
22722			this.trigger('changed', { property: { name: 'position', value: this._current } });
22723		}
22724
22725		return this._current;
22726	};
22727
22728	/**
22729	 * Invalidates the given part of the update routine.
22730	 * @param {String} [part] - The part to invalidate.
22731	 * @returns {Array.<String>} - The invalidated parts.
22732	 */
22733	Owl.prototype.invalidate = function(part) {
22734		if ($.type(part) === 'string') {
22735			this._invalidated[part] = true;
22736			this.is('valid') && this.leave('valid');
22737		}
22738		return $.map(this._invalidated, function(v, i) { return i });
22739	};
22740
22741	/**
22742	 * Resets the absolute position of the current item.
22743	 * @public
22744	 * @param {Number} position - The absolute position of the new item.
22745	 */
22746	Owl.prototype.reset = function(position) {
22747		position = this.normalize(position);
22748
22749		if (position === undefined) {
22750			return;
22751		}
22752
22753		this._speed = 0;
22754		this._current = position;
22755
22756		this.suppress([ 'translate', 'translated' ]);
22757
22758		this.animate(this.coordinates(position));
22759
22760		this.release([ 'translate', 'translated' ]);
22761	};
22762
22763	/**
22764	 * Normalizes an absolute or a relative position of an item.
22765	 * @public
22766	 * @param {Number} position - The absolute or relative position to normalize.
22767	 * @param {Boolean} [relative=false] - Whether the given position is relative or not.
22768	 * @returns {Number} - The normalized position.
22769	 */
22770	Owl.prototype.normalize = function(position, relative) {
22771		var n = this._items.length,
22772			m = relative ? 0 : this._clones.length;
22773
22774		if (!$.isNumeric(position) || n < 1) {
22775			position = undefined;
22776		} else if (position < 0 || position >= n + m) {
22777			position = ((position - m / 2) % n + n) % n + m / 2;
22778		}
22779
22780		return position;
22781	};
22782
22783	/**
22784	 * Converts an absolute position of an item into a relative one.
22785	 * @public
22786	 * @param {Number} position - The absolute position to convert.
22787	 * @returns {Number} - The converted position.
22788	 */
22789	Owl.prototype.relative = function(position) {
22790		position -= this._clones.length / 2;
22791		return this.normalize(position, true);
22792	};
22793
22794	/**
22795	 * Gets the maximum position for the current item.
22796	 * @public
22797	 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
22798	 * @returns {Number}
22799	 */
22800	Owl.prototype.maximum = function(relative) {
22801		var settings = this.settings,
22802			maximum = this._coordinates.length,
22803			boundary = Math.abs(this._coordinates[maximum - 1]) - this._width,
22804			i = -1, j;
22805
22806		if (settings.loop) {
22807			maximum = this._clones.length / 2 + this._items.length - 1;
22808		} else if (settings.autoWidth || settings.merge) {
22809			// binary search
22810			while (maximum - i > 1) {
22811				Math.abs(this._coordinates[j = maximum + i >> 1]) < boundary
22812					? i = j : maximum = j;
22813			}
22814		} else if (settings.center) {
22815			maximum = this._items.length - 1;
22816		} else {
22817			maximum = this._items.length - settings.items;
22818		}
22819
22820		if (relative) {
22821			maximum -= this._clones.length / 2;
22822		}
22823
22824		return Math.max(maximum, 0);
22825	};
22826
22827	/**
22828	 * Gets the minimum position for the current item.
22829	 * @public
22830	 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
22831	 * @returns {Number}
22832	 */
22833	Owl.prototype.minimum = function(relative) {
22834		return relative ? 0 : this._clones.length / 2;
22835	};
22836
22837	/**
22838	 * Gets an item at the specified relative position.
22839	 * @public
22840	 * @param {Number} [position] - The relative position of the item.
22841	 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
22842	 */
22843	Owl.prototype.items = function(position) {
22844		if (position === undefined) {
22845			return this._items.slice();
22846		}
22847
22848		position = this.normalize(position, true);
22849		return this._items[position];
22850	};
22851
22852	/**
22853	 * Gets an item at the specified relative position.
22854	 * @public
22855	 * @param {Number} [position] - The relative position of the item.
22856	 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
22857	 */
22858	Owl.prototype.mergers = function(position) {
22859		if (position === undefined) {
22860			return this._mergers.slice();
22861		}
22862
22863		position = this.normalize(position, true);
22864		return this._mergers[position];
22865	};
22866
22867	/**
22868	 * Gets the absolute positions of clones for an item.
22869	 * @public
22870	 * @param {Number} [position] - The relative position of the item.
22871	 * @returns {Array.<Number>} - The absolute positions of clones for the item or all if no position was given.
22872	 */
22873	Owl.prototype.clones = function(position) {
22874		var odd = this._clones.length / 2,
22875			even = odd + this._items.length,
22876			map = function(index) { return index % 2 === 0 ? even + index / 2 : odd - (index + 1) / 2 };
22877
22878		if (position === undefined) {
22879			return $.map(this._clones, function(v, i) { return map(i) });
22880		}
22881
22882		return $.map(this._clones, function(v, i) { return v === position ? map(i) : null });
22883	};
22884
22885	/**
22886	 * Sets the current animation speed.
22887	 * @public
22888	 * @param {Number} [speed] - The animation speed in milliseconds or nothing to leave it unchanged.
22889	 * @returns {Number} - The current animation speed in milliseconds.
22890	 */
22891	Owl.prototype.speed = function(speed) {
22892		if (speed !== undefined) {
22893			this._speed = speed;
22894		}
22895
22896		return this._speed;
22897	};
22898
22899	/**
22900	 * Gets the coordinate of an item.
22901	 * @todo The name of this method is missleanding.
22902	 * @public
22903	 * @param {Number} position - The absolute position of the item within `minimum()` and `maximum()`.
22904	 * @returns {Number|Array.<Number>} - The coordinate of the item in pixel or all coordinates.
22905	 */
22906	Owl.prototype.coordinates = function(position) {
22907		var coordinate = null;
22908
22909		if (position === undefined) {
22910			return $.map(this._coordinates, $.proxy(function(coordinate, index) {
22911				return this.coordinates(index);
22912			}, this));
22913		}
22914
22915		if (this.settings.center) {
22916			coordinate = this._coordinates[position];
22917			coordinate += (this.width() - coordinate + (this._coordinates[position - 1] || 0)) / 2 * (this.settings.rtl ? -1 : 1);
22918		} else {
22919			coordinate = this._coordinates[position - 1] || 0;
22920		}
22921
22922		return coordinate;
22923	};
22924
22925	/**
22926	 * Calculates the speed for a translation.
22927	 * @protected
22928	 * @param {Number} from - The absolute position of the start item.
22929	 * @param {Number} to - The absolute position of the target item.
22930	 * @param {Number} [factor=undefined] - The time factor in milliseconds.
22931	 * @returns {Number} - The time in milliseconds for the translation.
22932	 */
22933	Owl.prototype.duration = function(from, to, factor) {
22934		return Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((factor || this.settings.smartSpeed));
22935	};
22936
22937	/**
22938	 * Slides to the specified item.
22939	 * @public
22940	 * @param {Number} position - The position of the item.
22941	 * @param {Number} [speed] - The time in milliseconds for the transition.
22942	 */
22943	Owl.prototype.to = function(position, speed) {
22944		var current = this.current(),
22945			revert = null,
22946			distance = position - this.relative(current),
22947			direction = (distance > 0) - (distance < 0),
22948			items = this._items.length,
22949			minimum = this.minimum(),
22950			maximum = this.maximum();
22951
22952		if (this.settings.loop) {
22953			if (!this.settings.rewind && Math.abs(distance) > items / 2) {
22954				distance += direction * -1 * items;
22955			}
22956
22957			position = current + distance;
22958			revert = ((position - minimum) % items + items) % items + minimum;
22959
22960			if (revert !== position && revert - distance <= maximum && revert - distance > 0) {
22961				current = revert - distance;
22962				position = revert;
22963				this.reset(current);
22964			}
22965		} else if (this.settings.rewind) {
22966			maximum += 1;
22967			position = (position % maximum + maximum) % maximum;
22968		} else {
22969			position = Math.max(minimum, Math.min(maximum, position));
22970		}
22971
22972		this.speed(this.duration(current, position, speed));
22973		this.current(position);
22974
22975		if (this.$element.is(':visible')) {
22976			this.update();
22977		}
22978	};
22979
22980	/**
22981	 * Slides to the next item.
22982	 * @public
22983	 * @param {Number}
vendor: 12,284 bytes, lines 22983-23403
22983 [speed] - The time in milliseconds for the transition.
22984	 */
22985	Owl.prototype.next = function(speed) {
22986		speed = speed || false;
22987		this.to(this.relative(this.current()) + 1, speed);
22988	};
22989
22990	/**
22991	 * Slides to the previous item.
22992	 * @public
22993	 * @param {Number} [speed] - The time in milliseconds for the transition.
22994	 */
22995	Owl.prototype.prev = function(speed) {
22996		speed = speed || false;
22997		this.to(this.relative(this.current()) - 1, speed);
22998	};
22999
23000	/**
23001	 * Handles the end of an animation.
23002	 * @protected
23003	 * @param {Event} event - The event arguments.
23004	 */
23005	Owl.prototype.onTransitionEnd = function(event) {
23006
23007		// if css2 animation then event object is undefined
23008		if (event !== undefined) {
23009			event.stopPropagation();
23010
23011			// Catch only owl-stage transitionEnd event
23012			if ((event.target || event.srcElement || event.originalTarget) !== this.$stage.get(0)) {
23013				return false;
23014			}
23015		}
23016
23017		this.leave('animating');
23018		this.trigger('translated');
23019	};
23020
23021	/**
23022	 * Gets viewport width.
23023	 * @protected
23024	 * @return {Number} - The width in pixel.
23025	 */
23026	Owl.prototype.viewport = function() {
23027		var width;
23028		if (this.options.responsiveBaseElement !== window) {
23029			width = $(this.options.responsiveBaseElement).width();
23030		} else if (window.innerWidth) {
23031			width = window.innerWidth;
23032		} else if (document.documentElement && document.documentElement.clientWidth) {
23033			width = document.documentElement.clientWidth;
23034		} else {
23035			throw 'Can not detect viewport width.';
23036		}
23037
23038		return width;
23039	};
23040
23041	/**
23042	 * Replaces the current content.
23043	 * @public
23044	 * @param {HTMLElement|jQuery|String} content - The new content.
23045	 */
23046	Owl.prototype.replace = function(content) {
23047		this.$stage.empty();
23048		this._items = [];
23049
23050		if (content) {
23051			content = (content instanceof jQuery) ? content : $(content);
23052		}
23053
23054		if (this.settings.nestedItemSelector) {
23055			content = content.find('.' + this.settings.nestedItemSelector);
23056		}
23057
23058		content.filter(function() {
23059			return this.nodeType === 1;
23060		}).each($.proxy(function(index, item) {
23061			item = this.prepare(item, index);
23062			this.$stage.append(item);
23063			this._items.push(item);
23064			this._mergers.push(item.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1);
23065		}, this));
23066
23067		this.reset($.isNumeric(this.settings.startPosition) ? this.settings.startPosition : 0);
23068
23069		this.invalidate('items');
23070	};
23071
23072	/**
23073	 * Adds an item.
23074	 * @todo Use `item` instead of `content` for the event arguments.
23075	 * @public
23076	 * @param {HTMLElement|jQuery|String} content - The item content to add.
23077	 * @param {Number} [position] - The relative position at which to insert the item otherwise the item will be added to the end.
23078	 */
23079	Owl.prototype.add = function(content, position) {
23080		var current = this.relative(this._current);
23081
23082		position = position === undefined ? this._items.length : this.normalize(position, true);
23083		content = content instanceof jQuery ? content : $(content);
23084
23085		this.trigger('add', { content: content, position: position });
23086
23087		content = this.prepare(content, this._items[current].index());
23088
23089		if (this._items.length === 0 || position === this._items.length) {
23090			this._items.length === 0 && this.$stage.append(content);
23091			this._items.length !== 0 && this._items[position - 1].after(content);
23092			this._items.push(content);
23093			this._mergers.push(content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1);
23094		} else {
23095			this._items[position].before(content);
23096			this._items.splice(position, 0, content);
23097			this._mergers.splice(position, 0, content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1);
23098		}
23099
23100		this._items[current] && this.reset(this._items[current].index());
23101
23102		this.invalidate('items');
23103
23104		this.trigger('added', { content: content, position: position });
23105	};
23106
23107	/**
23108	 * Removes an item by its position.
23109	 * @todo Use `item` instead of `content` for the event arguments.
23110	 * @public
23111	 * @param {Number} position - The relative position of the item to remove.
23112	 */
23113	Owl.prototype.remove = function(position) {
23114		position = this.normalize(position, true);
23115
23116		if (position === undefined) {
23117			return;
23118		}
23119
23120		this.trigger('remove', { content: this._items[position], position: position });
23121
23122		this._items[position].remove();
23123		this._items.splice(position, 1);
23124		this._mergers.splice(position, 1);
23125
23126		this.invalidate('items');
23127
23128		this.trigger('removed', { content: null, position: position });
23129	};
23130
23131	/**
23132	 * Preloads images with auto width.
23133	 * @todo Replace by a more generic approach
23134	 * @protected
23135	 */
23136	Owl.prototype.preloadAutoWidthImages = function(images) {
23137		images.each($.proxy(function(i, element) {
23138			this.enter('pre-loading');
23139			element = $(element);
23140			$(new Image()).one('load', $.proxy(function(e) {
23141				element.attr('src', e.target.src);
23142				element.css('opacity', 1);
23143				this.leave('pre-loading');
23144				!this.is('pre-loading') && !this.is('initializing') && this.refresh();
23145			}, this)).attr('src', element.attr('src') || element.attr('data-src') || element.attr('data-src-retina'));
23146		}, this));
23147	};
23148
23149	/**
23150	 * Destroys the carousel.
23151	 * @public
23152	 */
23153	Owl.prototype.destroy = function() {
23154
23155		this.$element.off('.owl.core');
23156		this.$stage.off('.owl.core');
23157		$(document).off('.owl.core');
23158
23159		if (this.settings.responsive !== false) {
23160			window.clearTimeout(this.resizeTimer);
23161			this.off(window, 'resize', this._handlers.onThrottledResize);
23162		}
23163
23164		for (var i in this._plugins) {
23165			this._plugins[i].destroy();
23166		}
23167
23168		this.$stage.children('.cloned').remove();
23169
23170		this.$stage.unwrap();
23171		this.$stage.children().contents().unwrap();
23172		this.$stage.children().unwrap();
23173
23174		this.$element
23175			.removeClass(this.options.refreshClass)
23176			.removeClass(this.options.loadingClass)
23177			.removeClass(this.options.loadedClass)
23178			.removeClass(this.options.rtlClass)
23179			.removeClass(this.options.dragClass)
23180			.removeClass(this.options.grabClass)
23181			.attr('class', this.$element.attr('class').replace(new RegExp(this.options.responsiveClass + '-\\S+\\s', 'g'), ''))
23182			.removeData('owl.carousel');
23183	};
23184
23185	/**
23186	 * Operators to calculate right-to-left and left-to-right.
23187	 * @protected
23188	 * @param {Number} [a] - The left side operand.
23189	 * @param {String} [o] - The operator.
23190	 * @param {Number} [b] - The right side operand.
23191	 */
23192	Owl.prototype.op = function(a, o, b) {
23193		var rtl = this.settings.rtl;
23194		switch (o) {
23195			case '<':
23196				return rtl ? a > b : a < b;
23197			case '>':
23198				return rtl ? a < b : a > b;
23199			case '>=':
23200				return rtl ? a <= b : a >= b;
23201			case '<=':
23202				return rtl ? a >= b : a <= b;
23203			default:
23204				break;
23205		}
23206	};
23207
23208	/**
23209	 * Attaches to an internal event.
23210	 * @protected
23211	 * @param {HTMLElement} element - The event source.
23212	 * @param {String} event - The event name.
23213	 * @param {Function} listener - The event handler to attach.
23214	 * @param {Boolean} capture - Wether the event should be handled at the capturing phase or not.
23215	 */
23216	Owl.prototype.on = function(element, event, listener, capture) {
23217		if (element.addEventListener) {
23218			element.addEventListener(event, listener, capture);
23219		} else if (element.attachEvent) {
23220			element.attachEvent('on' + event, listener);
23221		}
23222	};
23223
23224	/**
23225	 * Detaches from an internal event.
23226	 * @protected
23227	 * @param {HTMLElement} element - The event source.
23228	 * @param {String} event - The event name.
23229	 * @param {Function} listener - The attached event handler to detach.
23230	 * @param {Boolean} capture - Wether the attached event handler was registered as a capturing listener or not.
23231	 */
23232	Owl.prototype.off = function(element, event, listener, capture) {
23233		if (element.removeEventListener) {
23234			element.removeEventListener(event, listener, capture);
23235		} else if (element.detachEvent) {
23236			element.detachEvent('on' + event, listener);
23237		}
23238	};
23239
23240	/**
23241	 * Triggers a public event.
23242	 * @todo Remove `status`, `relatedTarget` should be used instead.
23243	 * @protected
23244	 * @param {String} name - The event name.
23245	 * @param {*} [data=null] - The event data.
23246	 * @param {String} [namespace=carousel] - The event namespace.
23247	 * @param {String} [state] - The state which is associated with the event.
23248	 * @param {Boolean} [enter=false] - Indicates if the call enters the specified state or not.
23249	 * @returns {Event} - The event arguments.
23250	 */
23251	Owl.prototype.trigger = function(name, data, namespace, state, enter) {
23252		var status = {
23253			item: { count: this._items.length, index: this.current() }
23254		}, handler = $.camelCase(
23255			$.grep([ 'on', name, namespace ], function(v) { return v })
23256				.join('-').toLowerCase()
23257		), event = $.Event(
23258			[ name, 'owl', namespace || 'carousel' ].join('.').toLowerCase(),
23259			$.extend({ relatedTarget: this }, status, data)
23260		);
23261
23262		if (!this._supress[name]) {
23263			$.each(this._plugins, function(name, plugin) {
23264				if (plugin.onTrigger) {
23265					plugin.onTrigger(event);
23266				}
23267			});
23268
23269			this.register({ type: Owl.Type.Event, name: name });
23270			this.$element.trigger(event);
23271
23272			if (this.settings && typeof this.settings[handler] === 'function') {
23273				this.settings[handler].call(this, event);
23274			}
23275		}
23276
23277		return event;
23278	};
23279
23280	/**
23281	 * Enters a state.
23282	 * @param name - The state name.
23283	 */
23284	Owl.prototype.enter = function(name) {
23285		$.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
23286			if (this._states.current[name] === undefined) {
23287				this._states.current[name] = 0;
23288			}
23289
23290			this._states.current[name]++;
23291		}, this));
23292	};
23293
23294	/**
23295	 * Leaves a state.
23296	 * @param name - The state name.
23297	 */
23298	Owl.prototype.leave = function(name) {
23299		$.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
23300			this._states.current[name]--;
23301		}, this));
23302	};
23303
23304	/**
23305	 * Registers an event or state.
23306	 * @public
23307	 * @param {Object} object - The event or state to register.
23308	 */
23309	Owl.prototype.register = function(object) {
23310		if (object.type === Owl.Type.Event) {
23311			if (!$.event.special[object.name]) {
23312				$.event.special[object.name] = {};
23313			}
23314
23315			if (!$.event.special[object.name].owl) {
23316				var _default = $.event.special[object.name]._default;
23317				$.event.special[object.name]._default = function(e) {
23318					if (_default && _default.apply && (!e.namespace || e.namespace.indexOf('owl') === -1)) {
23319						return _default.apply(this, arguments);
23320					}
23321					return e.namespace && e.namespace.indexOf('owl') > -1;
23322				};
23323				$.event.special[object.name].owl = true;
23324			}
23325		} else if (object.type === Owl.Type.State) {
23326			if (!this._states.tags[object.name]) {
23327				this._states.tags[object.name] = object.tags;
23328			} else {
23329				this._states.tags[object.name] = this._states.tags[object.name].concat(object.tags);
23330			}
23331
23332			this._states.tags[object.name] = $.grep(this._states.tags[object.name], $.proxy(function(tag, i) {
23333				return $.inArray(tag, this._states.tags[object.name]) === i;
23334			}, this));
23335		}
23336	};
23337
23338	/**
23339	 * Suppresses events.
23340	 * @protected
23341	 * @param {Array.<String>} events - The events to suppress.
23342	 */
23343	Owl.prototype.suppress = function(events) {
23344		$.each(events, $.proxy(function(index, event) {
23345			this._supress[event] = true;
23346		}, this));
23347	};
23348
23349	/**
23350	 * Releases suppressed events.
23351	 * @protected
23352	 * @param {Array.<String>} events - The events to release.
23353	 */
23354	Owl.prototype.release = function(events) {
23355		$.each(events, $.proxy(function(index, event) {
23356			delete this._supress[event];
23357		}, this));
23358	};
23359
23360	/**
23361	 * Gets unified pointer coordinates from event.
23362	 * @todo #261
23363	 * @protected
23364	 * @param {Event} - The `mousedown` or `touchstart` event.
23365	 * @returns {Object} - Contains `x` and `y` coordinates of current pointer position.
23366	 */
23367	Owl.prototype.pointer = function(event) {
23368		var result = { x: null, y: null };
23369
23370		event = event.originalEvent || event || window.event;
23371
23372		event = event.touches && event.touches.length ?
23373			event.touches[0] : event.changedTouches && event.changedTouches.length ?
23374				event.changedTouches[0] : event;
23375
23376		if (event.pageX) {
23377			result.x = event.pageX;
23378			result.y = event.pageY;
23379		} else {
23380			result.x = event.clientX;
23381			result.y = event.clientY;
23382		}
23383
23384		return result;
23385	};
23386
23387	/**
23388	 * Gets the difference of two vectors.
23389	 * @todo #261
23390	 * @protected
23391	 * @param {Object} - The first vector.
23392	 * @param {Object} - The second vector.
23393	 * @returns {Object} - The difference.
23394	 */
23395	Owl.prototype.difference = function(first, second) {
23396		return {
23397			x: first.x - second.x,
23398			y: first.y - second.y
23399		};
23400	};
23401
23402	/**
23403	 * The jQuery Plugin for the Owl Carousel
vendor: 32,216 bytes, lines 23404-24686
23404	 * @todo Navigation plugin `next` and `prev`
23405	 * @public
23406	 */
23407	$.fn.owlCarousel = function(option) {
23408		var args = Array.prototype.slice.call(arguments, 1);
23409
23410		return this.each(function() {
23411			var $this = $(this),
23412				data = $this.data('owl.carousel');
23413
23414			if (!data) {
23415				data = new Owl(this, typeof option == 'object' && option);
23416				$this.data('owl.carousel', data);
23417
23418				$.each([
23419					'next', 'prev', 'to', 'destroy', 'refresh', 'replace', 'add', 'remove'
23420				], function(i, event) {
23421					data.register({ type: Owl.Type.Event, name: event });
23422					data.$element.on(event + '.owl.carousel.core', $.proxy(function(e) {
23423						if (e.namespace && e.relatedTarget !== this) {
23424							this.suppress([ event ]);
23425							data[event].apply(this, [].slice.call(arguments, 1));
23426							this.release([ event ]);
23427						}
23428					}, data));
23429				});
23430			}
23431
23432			if (typeof option == 'string' && option.charAt(0) !== '_') {
23433				data[option].apply(data, args);
23434			}
23435		});
23436	};
23437
23438	/**
23439	 * The constructor for the jQuery Plugin
23440	 * @public
23441	 */
23442	$.fn.owlCarousel.Constructor = Owl;
23443
23444})(window.Zepto || window.jQuery, window, document);
23445
23446/**
23447 * AutoRefresh Plugin
23448 * @version 2.0.0-beta.3
23449 * @author Artus Kolanowski
23450 * @license The MIT License (MIT)
23451 */
23452;(function($, window, document, undefined) {
23453
23454	/**
23455	 * Creates the auto refresh plugin.
23456	 * @class The Auto Refresh Plugin
23457	 * @param {Owl} carousel - The Owl Carousel
23458	 */
23459	var AutoRefresh = function(carousel) {
23460		/**
23461		 * Reference to the core.
23462		 * @protected
23463		 * @type {Owl}
23464		 */
23465		this._core = carousel;
23466
23467		/**
23468		 * Refresh interval.
23469		 * @protected
23470		 * @type {number}
23471		 */
23472		this._interval = null;
23473
23474		/**
23475		 * Whether the element is currently visible or not.
23476		 * @protected
23477		 * @type {Boolean}
23478		 */
23479		this._visible = null;
23480
23481		/**
23482		 * All event handlers.
23483		 * @protected
23484		 * @type {Object}
23485		 */
23486		this._handlers = {
23487			'initialized.owl.carousel': $.proxy(function(e) {
23488				if (e.namespace && this._core.settings.autoRefresh) {
23489					this.watch();
23490				}
23491			}, this)
23492		};
23493
23494		// set default options
23495		this._core.options = $.extend({}, AutoRefresh.Defaults, this._core.options);
23496
23497		// register event handlers
23498		this._core.$element.on(this._handlers);
23499	};
23500
23501	/**
23502	 * Default options.
23503	 * @public
23504	 */
23505	AutoRefresh.Defaults = {
23506		autoRefresh: true,
23507		autoRefreshInterval: 500
23508	};
23509
23510	/**
23511	 * Watches the element.
23512	 */
23513	AutoRefresh.prototype.watch = function() {
23514		if (this._interval) {
23515			return;
23516		}
23517
23518		this._visible = this._core.$element.is(':visible');
23519		this._interval = window.setInterval($.proxy(this.refresh, this), this._core.settings.autoRefreshInterval);
23520	};
23521
23522	/**
23523	 * Refreshes the element.
23524	 */
23525	AutoRefresh.prototype.refresh = function() {
23526		if (this._core.$element.is(':visible') === this._visible) {
23527			return;
23528		}
23529
23530		this._visible = !this._visible;
23531
23532		this._core.$element.toggleClass('owl-hidden', !this._visible);
23533
23534		this._visible && (this._core.invalidate('width') && this._core.refresh());
23535	};
23536
23537	/**
23538	 * Destroys the plugin.
23539	 */
23540	AutoRefresh.prototype.destroy = function() {
23541		var handler, property;
23542
23543		window.clearInterval(this._interval);
23544
23545		for (handler in this._handlers) {
23546			this._core.$element.off(handler, this._handlers[handler]);
23547		}
23548		for (property in Object.getOwnPropertyNames(this)) {
23549			typeof this[property] != 'function' && (this[property] = null);
23550		}
23551	};
23552
23553	$.fn.owlCarousel.Constructor.Plugins.AutoRefresh = AutoRefresh;
23554
23555})(window.Zepto || window.jQuery, window, document);
23556
23557/**
23558 * Lazy Plugin
23559 * @version 2.0.0-beta.3
23560 * @author Bartosz Wojciechowski
23561 * @license The MIT License (MIT)
23562 */
23563;(function($, window, document, undefined) {
23564
23565	/**
23566	 * Creates the lazy plugin.
23567	 * @class The Lazy Plugin
23568	 * @param {Owl} carousel - The Owl Carousel
23569	 */
23570	var Lazy = function(carousel) {
23571
23572		/**
23573		 * Reference to the core.
23574		 * @protected
23575		 * @type {Owl}
23576		 */
23577		this._core = carousel;
23578
23579		/**
23580		 * Already loaded items.
23581		 * @protected
23582		 * @type {Array.<jQuery>}
23583		 */
23584		this._loaded = [];
23585
23586		/**
23587		 * Event handlers.
23588		 * @protected
23589		 * @type {Object}
23590		 */
23591		this._handlers = {
23592			'initialized.owl.carousel change.owl.carousel': $.proxy(function(e) {
23593				if (!e.namespace) {
23594					return;
23595				}
23596
23597				if (!this._core.settings || !this._core.settings.lazyLoad) {
23598					return;
23599				}
23600
23601				if ((e.property && e.property.name == 'position') || e.type == 'initialized') {
23602					var settings = this._core.settings,
23603						n = (settings.center && Math.ceil(settings.items / 2) || settings.items),
23604						i = ((settings.center && n * -1) || 0),
23605						position = ((e.property && e.property.value) || this._core.current()) + i,
23606						clones = this._core.clones().length,
23607						load = $.proxy(function(i, v) { this.load(v) }, this);
23608
23609					while (i++ < n) {
23610						this.load(clones / 2 + this._core.relative(position));
23611						clones && $.each(this._core.clones(this._core.relative(position)), load);
23612						position++;
23613					}
23614				}
23615			}, this)
23616		};
23617
23618		// set the default options
23619		this._core.options = $.extend({}, Lazy.Defaults, this._core.options);
23620
23621		// register event handler
23622		this._core.$element.on(this._handlers);
23623	}
23624
23625	/**
23626	 * Default options.
23627	 * @public
23628	 */
23629	Lazy.Defaults = {
23630		lazyLoad: false
23631	}
23632
23633	/**
23634	 * Loads all resources of an item at the specified position.
23635	 * @param {Number} position - The absolute position of the item.
23636	 * @protected
23637	 */
23638	Lazy.prototype.load = function(position) {
23639		var $item = this._core.$stage.children().eq(position),
23640			$elements = $item && $item.find('.owl-lazy');
23641
23642		if (!$elements || $.inArray($item.get(0), this._loaded) > -1) {
23643			return;
23644		}
23645
23646		$elements.each($.proxy(function(index, element) {
23647			var $element = $(element), image,
23648				url = (window.devicePixelRatio > 1 && $element.attr('data-src-retina')) || $element.attr('data-src');
23649
23650			this._core.trigger('load', { element: $element, url: url }, 'lazy');
23651
23652			if ($element.is('img')) {
23653				$element.one('load.owl.lazy', $.proxy(function() {
23654					$element.css('opacity', 1);
23655					this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
23656				}, this)).attr('src', url);
23657			} else {
23658				image = new Image();
23659				image.onload = $.proxy(function() {
23660					$element.css({
23661						'background-image': 'url(' + url + ')',
23662						'opacity': '1'
23663					});
23664					this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
23665				}, this);
23666				image.src = url;
23667			}
23668		}, this));
23669
23670		this._loaded.push($item.get(0));
23671	}
23672
23673	/**
23674	 * Destroys the plugin.
23675	 * @public
23676	 */
23677	Lazy.prototype.destroy = function() {
23678		var handler, property;
23679
23680		for (handler in this.handlers) {
23681			this._core.$element.off(handler, this.handlers[handler]);
23682		}
23683		for (property in Object.getOwnPropertyNames(this)) {
23684			typeof this[property] != 'function' && (this[property] = null);
23685		}
23686	};
23687
23688	$.fn.owlCarousel.Constructor.Plugins.Lazy = Lazy;
23689
23690})(window.Zepto || window.jQuery, window, document);
23691
23692/**
23693 * AutoHeight Plugin
23694 * @version 2.0.0-beta.3
23695 * @author Bartosz Wojciechowski
23696 * @license The MIT License (MIT)
23697 */
23698;(function($, window, document, undefined) {
23699
23700	/**
23701	 * Creates the auto height plugin.
23702	 * @class The Auto Height Plugin
23703	 * @param {Owl} carousel - The Owl Carousel
23704	 */
23705	var AutoHeight = function(carousel) {
23706		/**
23707		 * Reference to the core.
23708		 * @protected
23709		 * @type {Owl}
23710		 */
23711		this._core = carousel;
23712
23713		/**
23714		 * All event handlers.
23715		 * @protected
23716		 * @type {Object}
23717		 */
23718		this._handlers = {
23719			'initialized.owl.carousel refreshed.owl.carousel': $.proxy(function(e) {
23720				if (e.namespace && this._core.settings.autoHeight) {
23721					this.update();
23722				}
23723			}, this),
23724			'changed.owl.carousel': $.proxy(function(e) {
23725				if (e.namespace && this._core.settings.autoHeight && e.property.name == 'position'){
23726					this.update();
23727				}
23728			}, this),
23729			'loaded.owl.lazy': $.proxy(function(e) {
23730				if (e.namespace && this._core.settings.autoHeight
23731					&& e.element.closest('.' + this._core.settings.itemClass).index() === this._core.current()) {
23732					this.update();
23733				}
23734			}, this)
23735		};
23736
23737		// set default options
23738		this._core.options = $.extend({}, AutoHeight.Defaults, this._core.options);
23739
23740		// register event handlers
23741		this._core.$element.on(this._handlers);
23742	};
23743
23744	/**
23745	 * Default options.
23746	 * @public
23747	 */
23748	AutoHeight.Defaults = {
23749		autoHeight: false,
23750		autoHeightClass: 'owl-height'
23751	};
23752
23753	/**
23754	 * Updates the view.
23755	 */
23756	AutoHeight.prototype.update = function() {
23757		var start = this._core._current,
23758			end = start + this._core.settings.items,
23759			visible = this._core.$stage.children().toArray().slice(start, end);
23760			heights = [],
23761			maxheight = 0;
23762
23763		$.each(visible, function(index, item) {
23764			heights.push($(item).height());
23765		});
23766
23767		maxheight = Math.max.apply(null, heights);
23768
23769		this._core.$stage.parent()
23770			.height(maxheight)
23771			.addClass(this._core.settings.autoHeightClass);
23772	};
23773
23774	AutoHeight.prototype.destroy = function() {
23775		var handler, property;
23776
23777		for (handler in this._handlers) {
23778			this._core.$element.off(handler, this._handlers[handler]);
23779		}
23780		for (property in Object.getOwnPropertyNames(this)) {
23781			typeof this[property] != 'function' && (this[property] = null);
23782		}
23783	};
23784
23785	$.fn.owlCarousel.Constructor.Plugins.AutoHeight = AutoHeight;
23786
23787})(window.Zepto || window.jQuery, window, document);
23788
23789/**
23790 * Video Plugin
23791 * @version 2.0.0-beta.3
23792 * @author Bartosz Wojciechowski
23793 * @license The MIT License (MIT)
23794 */
23795;(function($, window, document, undefined) {
23796
23797	/**
23798	 * Creates the video plugin.
23799	 * @class The Video Plugin
23800	 * @param {Owl} carousel - The Owl Carousel
23801	 */
23802	var Video = function(carousel) {
23803		/**
23804		 * Reference to the core.
23805		 * @protected
23806		 * @type {Owl}
23807		 */
23808		this._core = carousel;
23809
23810		/**
23811		 * Cache all video URLs.
23812		 * @protected
23813		 * @type {Object}
23814		 */
23815		this._videos = {};
23816
23817		/**
23818		 * Current playing item.
23819		 * @protected
23820		 * @type {jQuery}
23821		 */
23822		this._playing = null;
23823
23824		/**
23825		 * All event handlers.
23826		 * @todo The cloned content removale is too late
23827		 * @protected
23828		 * @type {Object}
23829		 */
23830		this._handlers = {
23831			'initialized.owl.carousel': $.proxy(function(e) {
23832				if (e.namespace) {
23833					this._core.register({ type: 'state', name: 'playing', tags: [ 'interacting' ] });
23834				}
23835			}, this),
23836			'resize.owl.carousel': $.proxy(function(e) {
23837				if (e.namespace && this._core.settings.video && this.isInFullScreen()) {
23838					e.preventDefault();
23839				}
23840			}, this),
23841			'refreshed.owl.carousel': $.proxy(function(e) {
23842				if (e.namespace && this._core.is('resizing')) {
23843					this._core.$stage.find('.cloned .owl-video-frame').remove();
23844				}
23845			}, this),
23846			'changed.owl.carousel': $.proxy(function(e) {
23847				if (e.namespace && e.property.name === 'position' && this._playing) {
23848					this.stop();
23849				}
23850			}, this),
23851			'prepared.owl.carousel': $.proxy(function(e) {
23852				if (!e.namespace) {
23853					return;
23854				}
23855
23856				var $element = $(e.content).find('.owl-video');
23857
23858				if ($element.length) {
23859					$element.css('display', 'none');
23860					this.fetch($element, $(e.content));
23861				}
23862			}, this)
23863		};
23864
23865		// set default options
23866		this._core.options = $.extend({}, Video.Defaults, this._core.options);
23867
23868		// register event handlers
23869		this._core.$element.on(this._handlers);
23870
23871		this._core.$element.on('click.owl.video', '.owl-video-play-icon', $.proxy(function(e) {
23872			this.play(e);
23873		}, this));
23874	};
23875
23876	/**
23877	 * Default options.
23878	 * @public
23879	 */
23880	Video.Defaults = {
23881		video: false,
23882		videoHeight: false,
23883		videoWidth: false
23884	};
23885
23886	/**
23887	 * Gets the video ID and the type (YouTube/Vimeo only).
23888	 * @protected
23889	 * @param {jQuery} target - The target containing the video data.
23890	 * @param {jQuery} item - The item containing the video.
23891	 */
23892	Video.prototype.fetch = function(target, item) {
23893		var type = target.attr('data-vimeo-id') ? 'vimeo' : 'youtube',
23894			id = target.attr('data-vimeo-id') || target.attr('data-youtube-id'),
23895			width = target.attr('data-width') || this._core.settings.videoWidth,
23896			height = target.attr('data-height') || this._core.settings.videoHeight,
23897			url = target.attr('href');
23898
23899		if (url) {
23900			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+)?/);
23901
23902			if (id[3].indexOf('youtu') > -1) {
23903				type = 'youtube';
23904			} else if (id[3].indexOf('vimeo') > -1) {
23905				type = 'vimeo';
23906			} else {
23907				throw new Error('Video URL not supported.');
23908			}
23909			id = id[6];
23910		} else {
23911			throw new Error('Missing video URL.');
23912		}
23913
23914		this._videos[url] = {
23915			type: type,
23916			id: id,
23917			width: width,
23918			height: height
23919		};
23920
23921		item.attr('data-video', url);
23922
23923		this.thumbnail(target, this._videos[url]);
23924	};
23925
23926	/**
23927	 * Creates video thumbnail.
23928	 * @protected
23929	 * @param {jQuery} target - The target containing the video data.
23930	 * @param {Object} info - The video info object.
23931	 * @see `fetch`
23932	 */
23933	Video.prototype.thumbnail = function(target, video) {
23934		var tnLink,
23935			icon,
23936			path,
23937			dimensions = video.width && video.height ? 'style="width:' + video.width + 'px;height:' + video.height + 'px;"' : '',
23938			customTn = target.find('img'),
23939			srcType = 'src',
23940			lazyClass = '',
23941			settings = this._core.settings,
23942			create = function(path) {
23943				icon = '<div class="owl-video-play-icon"></div>';
23944
23945				if (settings.lazyLoad) {
23946					tnLink = '<div class="owl-video-tn ' + lazyClass + '" ' + srcType + '="' + path + '"></div>';
23947				} else {
23948					tnLink = '<div class="owl-video-tn" style="opacity:1;background-image:url(' + path + ')"></div>';
23949				}
23950				target.after(tnLink);
23951				target.after(icon);
23952			};
23953
23954		// wrap video content into owl-video-wrapper div
23955		target.wrap('<div class="owl-video-wrapper"' + dimensions + '></div>');
23956
23957		if (this._core.settings.lazyLoad) {
23958			srcType = 'data-src';
23959			lazyClass = 'owl-lazy';
23960		}
23961
23962		// custom thumbnail
23963		if (customTn.length) {
23964			create(customTn.attr(srcType));
23965			customTn.remove();
23966			return false;
23967		}
23968
23969		if (video.type === 'youtube') {
23970			path = "//img.youtube.com/vi/" + video.id + "/hqdefault.jpg";
23971			create(path);
23972		} else if (video.type === 'vimeo') {
23973			$.ajax({
23974				type: 'GET',
23975				url: '//vimeo.com/api/v2/video/' + video.id + '.json',
23976				jsonp: 'callback',
23977				dataType: 'jsonp',
23978				success: function(data) {
23979					path = data[0].thumbnail_large;
23980					create(path);
23981				}
23982			});
23983		}
23984	};
23985
23986	/**
23987	 * Stops the current video.
23988	 * @public
23989	 */
23990	Video.prototype.stop = function() {
23991		this._core.trigger('stop', null, 'video');
23992		this._playing.find('.owl-video-frame').remove();
23993		this._playing.removeClass('owl-video-playing');
23994		this._playing = null;
23995		this._core.leave('playing');
23996		this._core.trigger('stopped', null, 'video');
23997	};
23998
23999	/**
24000	 * Starts the current video.
24001	 * @public
24002	 * @param {Event} event - The event arguments.
24003	 */
24004	Video.prototype.play = function(event) {
24005		var target = $(event.target),
24006			item = target.closest('.' + this._core.settings.itemClass),
24007			video = this._videos[item.attr('data-video')],
24008			width = video.width || '100%',
24009			height = video.height || this._core.$stage.height(),
24010			html;
24011
24012		if (this._playing) {
24013			return;
24014		}
24015
24016		this._core.enter('playing');
24017		this._core.trigger('play', null, 'video');
24018
24019		item = this._core.items(this._core.relative(item.index()));
24020
24021		this._core.reset(item.index());
24022
24023		if (video.type === 'youtube') {
24024			html = '<iframe width="' + width + '" height="' + height + '" src="//www.youtube.com/embed/' +
24025				video.id + '?autoplay=1&v=' + video.id + '" frameborder="0" allowfullscreen></iframe>';
24026		} else if (video.type === 'vimeo') {
24027			html = '<iframe src="//player.vimeo.com/video/' + video.id +
24028				'?autoplay=1" width="' + width + '" height="' + height +
24029				'" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>';
24030		}
24031
24032		$('<div class="owl-video-frame">' + html + '</div>').insertAfter(item.find('.owl-video'));
24033
24034		this._playing = item.addClass('owl-video-playing');
24035	};
24036
24037	/**
24038	 * Checks whether an video is currently in full screen mode or not.
24039	 * @todo Bad style because looks like a readonly method but changes members.
24040	 * @protected
24041	 * @returns {Boolean}
24042	 */
24043	Video.prototype.isInFullScreen = function() {
24044		var element = document.fullscreenElement || document.mozFullScreenElement ||
24045				document.webkitFullscreenElement;
24046
24047		return element && $(element).parent().hasClass('owl-video-frame');
24048	};
24049
24050	/**
24051	 * Destroys the plugin.
24052	 */
24053	Video.prototype.destroy = function() {
24054		var handler, property;
24055
24056		this._core.$element.off('click.owl.video');
24057
24058		for (handler in this._handlers) {
24059			this._core.$element.off(handler, this._handlers[handler]);
24060		}
24061		for (property in Object.getOwnPropertyNames(this)) {
24062			typeof this[property] != 'function' && (this[property] = null);
24063		}
24064	};
24065
24066	$.fn.owlCarousel.Constructor.Plugins.Video = Video;
24067
24068})(window.Zepto || window.jQuery, window, document);
24069
24070/**
24071 * Animate Plugin
24072 * @version 2.0.0-beta.3
24073 * @author Bartosz Wojciechowski
24074 * @license The MIT License (MIT)
24075 */
24076;(function($, window, document, undefined) {
24077
24078	/**
24079	 * Creates the animate plugin.
24080	 * @class The Navigation Plugin
24081	 * @param {Owl} scope - The Owl Carousel
24082	 */
24083	var Animate = function(scope) {
24084		this.core = scope;
24085		this.core.options = $.extend({}, Animate.Defaults, this.core.options);
24086		this.swapping = true;
24087		this.previous = undefined;
24088		this.next = undefined;
24089
24090		this.handlers = {
24091			'change.owl.carousel': $.proxy(function(e) {
24092				if (e.namespace && e.property.name == 'position') {
24093					this.previous = this.core.current();
24094					this.next = e.property.value;
24095				}
24096			}, this),
24097			'drag.owl.carousel dragged.owl.carousel translated.owl.carousel': $.proxy(function(e) {
24098				if (e.namespace) {
24099					this.swapping = e.type == 'translated';
24100				}
24101			}, this),
24102			'translate.owl.carousel': $.proxy(function(e) {
24103				if (e.namespace && this.swapping && (this.core.options.animateOut || this.core.options.animateIn)) {
24104					this.swap();
24105				}
24106			}, this)
24107		};
24108
24109		this.core.$element.on(this.handlers);
24110	};
24111
24112	/**
24113	 * Default options.
24114	 * @public
24115	 */
24116	Animate.Defaults = {
24117		animateOut: false,
24118		animateIn: false
24119	};
24120
24121	/**
24122	 * Toggles the animation classes whenever an translations starts.
24123	 * @protected
24124	 * @returns {Boolean|undefined}
24125	 */
24126	Animate.prototype.swap = function() {
24127
24128		if (this.core.settings.items !== 1) {
24129			return;
24130		}
24131
24132		if (!$.support.animation || !$.support.transition) {
24133			return;
24134		}
24135
24136		this.core.speed(0);
24137
24138		var left,
24139			clear = $.proxy(this.clear, this),
24140			previous = this.core.$stage.children().eq(this.previous),
24141			next = this.core.$stage.children().eq(this.next),
24142			incoming = this.core.settings.animateIn,
24143			outgoing = this.core.settings.animateOut;
24144
24145		if (this.core.current() === this.previous) {
24146			return;
24147		}
24148
24149		if (outgoing) {
24150			left = this.core.coordinates(this.previous) - this.core.coordinates(this.next);
24151			previous.css( { 'left': left + 'px' } )
24152				.addClass('animated owl-animated-out')
24153				.addClass(outgoing)
24154				.on($.support.animation.end, clear);
24155		}
24156
24157		if (incoming) {
24158			next.addClass('animated owl-animated-in')
24159				.addClass(incoming)
24160				.on($.support.animation.end, clear);
24161		}
24162	};
24163
24164	Animate.prototype.clear = function(e) {
24165		if ($(e.target).hasClass('animated')) {
24166			$(e.target).css( { 'left': '' } )
24167				.removeClass('animated owl-animated-out owl-animated-in')
24168				.removeClass(this.core.settings.animateIn)
24169				.removeClass(this.core.settings.animateOut);
24170			this.core.onTransitionEnd();
24171		}
24172	};
24173
24174	/**
24175	 * Destroys the plugin.
24176	 * @public
24177	 */
24178	Animate.prototype.destroy = function() {
24179		var handler, property;
24180
24181		for (handler in this.handlers) {
24182			this.core.$element.off(handler, this.handlers[handler]);
24183		}
24184		for (property in Object.getOwnPropertyNames(this)) {
24185			typeof this[property] != 'function' && (this[property] = null);
24186		}
24187	};
24188
24189	$.fn.owlCarousel.Constructor.Plugins.Animate = Animate;
24190
24191})(window.Zepto || window.jQuery, window, document);
24192
24193/**
24194 * Autoplay Plugin
24195 * @version 2.0.0-beta.3
24196 * @author Bartosz Wojciechowski
24197 * @author Artus Kolanowski
24198 * @license The MIT License (MIT)
24199 */
24200;(function($, window, document, undefined) {
24201
24202	/**
24203	 * Creates the autoplay plugin.
24204	 * @class The Autoplay Plugin
24205	 * @param {Owl} scope - The Owl Carousel
24206	 */
24207	var Autoplay = function(carousel) {
24208		/**
24209		 * Reference to the core.
24210		 * @protected
24211		 * @type {Owl}
24212		 */
24213		this._core = carousel;
24214
24215		/**
24216		 * The autoplay interval.
24217		 * @type {Number}
24218		 */
24219		this._interval = null;
24220
24221		/**
24222		 * Indicates whenever the autoplay is paused.
24223		 * @type {Boolean}
24224		 */
24225		this._paused = false;
24226
24227		/**
24228		 * All event handlers.
24229		 * @protected
24230		 * @type {Object}
24231		 */
24232		this._handlers = {
24233			'changed.owl.carousel': $.proxy(function(e) {
24234				if (e.namespace && e.property.name === 'settings') {
24235					if (this._core.settings.autoplay) {
24236						this.play();
24237					} else {
24238						this.stop();
24239					}
24240				}
24241			}, this),
24242			'initialized.owl.carousel': $.proxy(function(e) {
24243				if (e.namespace && this._core.settings.autoplay) {
24244					this.play();
24245				}
24246			}, this),
24247			'play.owl.autoplay': $.proxy(function(e, t, s) {
24248				if (e.namespace) {
24249					this.play(t, s);
24250				}
24251			}, this),
24252			'stop.owl.autoplay': $.proxy(function(e) {
24253				if (e.namespace) {
24254					this.stop();
24255				}
24256			}, this),
24257			'mouseover.owl.autoplay': $.proxy(function() {
24258				if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
24259					this.pause();
24260				}
24261			}, this),
24262			'mouseleave.owl.autoplay': $.proxy(function() {
24263				if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
24264					this.play();
24265				}
24266			}, this)
24267		};
24268
24269		// register event handlers
24270		this._core.$element.on(this._handlers);
24271
24272		// set default options
24273		this._core.options = $.extend({}, Autoplay.Defaults, this._core.options);
24274	};
24275
24276	/**
24277	 * Default options.
24278	 * @public
24279	 */
24280	Autoplay.Defaults = {
24281		autoplay: false,
24282		autoplayTimeout: 5000,
24283		autoplayHoverPause: false,
24284		autoplaySpeed: false
24285	};
24286
24287	/**
24288	 * Starts the autoplay.
24289	 * @public
24290	 * @param {Number} [timeout] - The interval before the next animation starts.
24291	 * @param {Number} [speed] - The animation speed for the animations.
24292	 */
24293	Autoplay.prototype.play = function(timeout, speed) {
24294		this._paused = false;
24295
24296		if (this._core.is('rotating')) {
24297			return;
24298		}
24299
24300		this._core.enter('rotating');
24301
24302		this._interval = window.setInterval($.proxy(function() {
24303			if (this._paused || this._core.is('busy') || this._core.is('interacting') || document.hidden) {
24304				return;
24305			}
24306			this._core.next(speed || this._core.settings.autoplaySpeed);
24307		}, this), timeout || this._core.settings.autoplayTimeout);
24308	};
24309
24310	/**
24311	 * Stops the autoplay.
24312	 * @public
24313	 */
24314	Autoplay.prototype.stop = function() {
24315		if (!this._core.is('rotating')) {
24316			return;
24317		}
24318
24319		window.clearInterval(this._interval);
24320		this._core.leave('rotating');
24321	};
24322
24323	/**
24324	 * Stops the autoplay.
24325	 * @public
24326	 */
24327	Autoplay.prototype.pause = function() {
24328		if (!this._core.is('rotating')) {
24329			return;
24330		}
24331
24332		this._paused = true;
24333	};
24334
24335	/**
24336	 * Destroys the plugin.
24337	 */
24338	Autoplay.prototype.destroy = function() {
24339		var handler, property;
24340
24341		this.stop();
24342
24343		for (handler in this._handlers) {
24344			this._core.$element.off(handler, this._handlers[handler]);
24345		}
24346		for (property in Object.getOwnPropertyNames(this)) {
24347			typeof this[property] != 'function' && (this[property] = null);
24348		}
24349	};
24350
24351	$.fn.owlCarousel.Constructor.Plugins.autoplay = Autoplay;
24352
24353})(window.Zepto || window.jQuery, window, document);
24354
24355/**
24356 * Navigation Plugin
24357 * @version 2.0.0-beta.3
24358 * @author Artus Kolanowski
24359 * @license The MIT License (MIT)
24360 */
24361;(function($, window, document, undefined) {
24362	'use strict';
24363
24364	/**
24365	 * Creates the navigation plugin.
24366	 * @class The Navigation Plugin
24367	 * @param {Owl} carousel - The Owl Carousel.
24368	 */
24369	var Navigation = function(carousel) {
24370		/**
24371		 * Reference to the core.
24372		 * @protected
24373		 * @type {Owl}
24374		 */
24375		this._core = carousel;
24376
24377		/**
24378		 * Indicates whether the plugin is initialized or not.
24379		 * @protected
24380		 * @type {Boolean}
24381		 */
24382		this._initialized = false;
24383
24384		/**
24385		 * The current paging indexes.
24386		 * @protected
24387		 * @type {Array}
24388		 */
24389		this._pages = [];
24390
24391		/**
24392		 * All DOM elements of the user interface.
24393		 * @protected
24394		 * @type {Object}
24395		 */
24396		this._controls = {};
24397
24398		/**
24399		 * Markup for an indicator.
24400		 * @protected
24401		 * @type {Array.<String>}
24402		 */
24403		this._templates = [];
24404
24405		/**
24406		 * The carousel element.
24407		 * @type {jQuery}
24408		 */
24409		this.$element = this._core.$element;
24410
24411		/**
24412		 * Overridden methods of the carousel.
24413		 * @protected
24414		 * @type {Object}
24415		 */
24416		this._overrides = {
24417			next: this._core.next,
24418			prev: this._core.prev,
24419			to: this._core.to
24420		};
24421
24422		/**
24423		 * All event handlers.
24424		 * @protected
24425		 * @type {Object}
24426		 */
24427		this._handlers = {
24428			'prepared.owl.carousel': $.proxy(function(e) {
24429				if (e.namespace && this._core.settings.dotsData) {
24430					this._templates.push('<div class="' + this._core.settings.dotClass + '">' +
24431						$(e.content).find('[data-dot]').andSelf('[data-dot]').attr('data-dot') + '</div>');
24432				}
24433			}, this),
24434			'added.owl.carousel': $.proxy(function(e) {
24435				if (e.namespace && this._core.settings.dotsData) {
24436					this._templates.splice(e.position, 0, this._templates.pop());
24437				}
24438			}, this),
24439			'remove.owl.carousel': $.proxy(function(e) {
24440				if (e.namespace && this._core.settings.dotsData) {
24441					this._templates.splice(e.position, 1);
24442				}
24443			}, this),
24444			'changed.owl.carousel': $.proxy(function(e) {
24445				if (e.namespace && e.property.name == 'position') {
24446					this.draw();
24447				}
24448			}, this),
24449			'initialized.owl.carousel': $.proxy(function(e) {
24450				if (e.namespace && !this._initialized) {
24451					this._core.trigger('initialize', null, 'navigation');
24452					this.initialize();
24453					this.update();
24454					this.draw();
24455					this._initialized = true;
24456					this._core.trigger('initialized', null, 'navigation');
24457				}
24458			}, this),
24459			'refreshed.owl.carousel': $.proxy(function(e) {
24460				if (e.namespace && this._initialized) {
24461					this._core.trigger('refresh', null, 'navigation');
24462					this.update();
24463					this.draw();
24464					this._core.trigger('refreshed', null, 'navigation');
24465				}
24466			}, this)
24467		};
24468
24469		// set default options
24470		this._core.options = $.extend({}, Navigation.Defaults, this._core.options);
24471
24472		// register event handlers
24473		this.$element.on(this._handlers);
24474	};
24475
24476	/**
24477	 * Default options.
24478	 * @public
24479	 * @todo Rename `slideBy` to `navBy`
24480	 */
24481	Navigation.Defaults = {
24482		nav: false,
24483		navText: [ 'prev', 'next' ],
24484		navSpeed: false,
24485		navElement: 'div',
24486		navContainer: false,
24487		navContainerClass: 'owl-nav',
24488		navClass: [ 'owl-prev', 'owl-next' ],
24489		slideBy: 1,
24490		dotClass: 'owl-dot',
24491		dotsClass: 'owl-dots',
24492		dots: true,
24493		dotsEach: false,
24494		dotsData: false,
24495		dotsSpeed: false,
24496		dotsContainer: false
24497	};
24498
24499	/**
24500	 * Initializes the layout of the plugin and extends the carousel.
24501	 * @protected
24502	 */
24503	Navigation.prototype.initialize = function() {
24504		var override,
24505			settings = this._core.settings;
24506
24507		// create DOM structure for relative navigation
24508		this._controls.$relative = (settings.navContainer ? $(settings.navContainer)
24509			: $('<div>').addClass(settings.navContainerClass).appendTo(this.$element)).addClass('disabled');
24510
24511		this._controls.$previous = $('<' + settings.navElement + '>')
24512			.addClass(settings.navClass[0])
24513			.html(settings.navText[0])
24514			.prependTo(this._controls.$relative)
24515			.on('click', $.proxy(function(e) {
24516				this.prev(settings.navSpeed);
24517			}, this));
24518		this._controls.$next = $('<' + settings.navElement + '>')
24519			.addClass(settings.navClass[1])
24520			.html(settings.navText[1])
24521			.appendTo(this._controls.$relative)
24522			.on('click', $.proxy(function(e) {
24523				this.next(settings.navSpeed);
24524			}, this));
24525
24526		// create DOM structure for absolute navigation
24527		if (!settings.dotsData) {
24528			this._templates = [ $('<div>')
24529				.addClass(settings.dotClass)
24530				.append($('<span>'))
24531				.prop('outerHTML') ];
24532		}
24533
24534		this._controls.$absolute = (settings.dotsContainer ? $(settings.dotsContainer)
24535			: $('<div>').addClass(settings.dotsClass).appendTo(this.$element)).addClass('disabled');
24536
24537		this._controls.$absolute.on('click', 'div', $.proxy(function(e) {
24538			var index = $(e.target).parent().is(this._controls.$absolute)
24539				? $(e.target).index() : $(e.target).parent().index();
24540
24541			e.preventDefault();
24542
24543			this.to(index, settings.dotsSpeed);
24544		}, this));
24545
24546		// override public methods of the carousel
24547		for (override in this._overrides) {
24548			this._core[override] = $.proxy(this[override], this);
24549		}
24550	};
24551
24552	/**
24553	 * Destroys the plugin.
24554	 * @protected
24555	 */
24556	Navigation.prototype.destroy = function() {
24557		var handler, control, property, override;
24558
24559		for (handler in this._handlers) {
24560			this.$element.off(handler, this._handlers[handler]);
24561		}
24562		for (control in this._controls) {
24563			this._controls[control].remove();
24564		}
24565		for (override in this.overides) {
24566			this._core[override] = this._overrides[override];
24567		}
24568		for (property in Object.getOwnPropertyNames(this)) {
24569			typeof this[property] != 'function' && (this[property] = null);
24570		}
24571	};
24572
24573	/**
24574	 * Updates the internal state.
24575	 * @protected
24576	 */
24577	Navigation.prototype.update = function() {
24578		var i, j, k,
24579			lower = this._core.clones().length / 2,
24580			upper = lower + this._core.items().length,
24581			maximum = this._core.maximum(true),
24582			settings = this._core.settings,
24583			size = settings.center || settings.autoWidth || settings.dotsData
24584				? 1 : settings.dotsEach || settings.items;
24585
24586		if (settings.slideBy !== 'page') {
24587			settings.slideBy = Math.min(settings.slideBy, settings.items);
24588		}
24589
24590		if (settings.dots || settings.slideBy == 'page') {
24591			this._pages = [];
24592
24593			for (i = lower, j = 0, k = 0; i < upper; i++) {
24594				if (j >= size || j === 0) {
24595					this._pages.push({
24596						start: Math.min(maximum, i - lower),
24597						end: i - lower + size - 1
24598					});
24599					if (Math.min(maximum, i - lower) === maximum) {
24600						break;
24601					}
24602					j = 0, ++k;
24603				}
24604				j += this._core.mergers(this._core.relative(i));
24605			}
24606		}
24607	};
24608
24609	/**
24610	 * Draws the user interface.
24611	 * @todo The option `dotsData` wont work.
24612	 * @protected
24613	 */
24614	Navigation.prototype.draw = function() {
24615		var difference,
24616			settings = this._core.settings,
24617			disabled = this._core.items().length <= settings.items,
24618			index = this._core.relative(this._core.current()),
24619			loop = settings.loop || settings.rewind;
24620
24621		this._controls.$relative.toggleClass('disabled', !settings.nav || disabled);
24622
24623		if (settings.nav) {
24624			this._controls.$previous.toggleClass('disabled', !loop && index <= this._core.minimum(true));
24625			this._controls.$next.toggleClass('disabled', !loop && index >= this._core.maximum(true));
24626		}
24627
24628		this._controls.$absolute.toggleClass('disabled', !settings.dots || disabled);
24629
24630		if (settings.dots) {
24631			difference = this._pages.length - this._controls.$absolute.children().length;
24632
24633			if (settings.dotsData && difference !== 0) {
24634				this._controls.$absolute.html(this._templates.join(''));
24635			} else if (difference > 0) {
24636				this._controls.$absolute.append(new Array(difference + 1).join(this._templates[0]));
24637			} else if (difference < 0) {
24638				this._controls.$absolute.children().slice(difference).remove();
24639			}
24640
24641			this._controls.$absolute.find('.active').removeClass('active');
24642			this._controls.$absolute.children().eq($.inArray(this.current(), this._pages)).addClass('active');
24643		}
24644	};
24645
24646	/**
24647	 * Extends event data.
24648	 * @protected
24649	 * @param {Event} event - The event object which gets thrown.
24650	 */
24651	Navigation.prototype.onTrigger = function(event) {
24652		var settings = this._core.settings;
24653
24654		event.page = {
24655			index: $.inArray(this.current(), this._pages),
24656			count: this._pages.length,
24657			size: settings && (settings.center || settings.autoWidth || settings.dotsData
24658				? 1 : settings.dotsEach || settings.items)
24659		};
24660	};
24661
24662	/**
24663	 * Gets the current page position of the carousel.
24664	 * @protected
24665	 * @returns {Number}
24666	 */
24667	Navigation.prototype.current = function() {
24668		var current = this._core.relative(this._core.current());
24669		return $.grep(this._pages, $.proxy(function(page, index) {
24670			return page.start <= current && page.end >= current;
24671		}, this)).pop();
24672	};
24673
24674	/**
24675	 * Gets the current succesor/predecessor position.
24676	 * @protected
24677	 * @returns {Number}
24678	 */
24679	Navigation.prototype.getPosition = function(successor) {
24680		var position, length,
24681			settings = this._core.settings;
24682
24683		if (settings.slideBy == 'page') {
24684			position = $.inArray(this.current(), this._pages);
24685			length = this._pages.length;
24686			successor ? ++position : --position;
vendor: 5,678 bytes, lines 24687-24911
24687			position = this._pages[((position % length) + length) % length].start;
24688		} else {
24689			position = this._core.relative(this._core.current());
24690			length = this._core.items().length;
24691			successor ? position += settings.slideBy : position -= settings.slideBy;
24692		}
24693
24694		return position;
24695	};
24696
24697	/**
24698	 * Slides to the next item or page.
24699	 * @public
24700	 * @param {Number} [speed=false] - The time in milliseconds for the transition.
24701	 */
24702	Navigation.prototype.next = function(speed) {
24703		$.proxy(this._overrides.to, this._core)(this.getPosition(true), speed);
24704	};
24705
24706	/**
24707	 * Slides to the previous item or page.
24708	 * @public
24709	 * @param {Number} [speed=false] - The time in milliseconds for the transition.
24710	 */
24711	Navigation.prototype.prev = function(speed) {
24712		$.proxy(this._overrides.to, this._core)(this.getPosition(false), speed);
24713	};
24714
24715	/**
24716	 * Slides to the specified item or page.
24717	 * @public
24718	 * @param {Number} position - The position of the item or page.
24719	 * @param {Number} [speed] - The time in milliseconds for the transition.
24720	 * @param {Boolean} [standard=false] - Whether to use the standard behaviour or not.
24721	 */
24722	Navigation.prototype.to = function(position, speed, standard) {
24723		var length;
24724
24725		if (!standard) {
24726			length = this._pages.length;
24727			$.proxy(this._overrides.to, this._core)(this._pages[((position % length) + length) % length].start, speed);
24728		} else {
24729			$.proxy(this._overrides.to, this._core)(position, speed);
24730		}
24731	};
24732
24733	$.fn.owlCarousel.Constructor.Plugins.Navigation = Navigation;
24734
24735})(window.Zepto || window.jQuery, window, document);
24736
24737/**
24738 * Hash Plugin
24739 * @version 2.0.0-beta.3
24740 * @author Artus Kolanowski
24741 * @license The MIT License (MIT)
24742 */
24743;(function($, window, document, undefined) {
24744	'use strict';
24745
24746	/**
24747	 * Creates the hash plugin.
24748	 * @class The Hash Plugin
24749	 * @param {Owl} carousel - The Owl Carousel
24750	 */
24751	var Hash = function(carousel) {
24752		/**
24753		 * Reference to the core.
24754		 * @protected
24755		 * @type {Owl}
24756		 */
24757		this._core = carousel;
24758
24759		/**
24760		 * Hash index for the items.
24761		 * @protected
24762		 * @type {Object}
24763		 */
24764		this._hashes = {};
24765
24766		/**
24767		 * The carousel element.
24768		 * @type {jQuery}
24769		 */
24770		this.$element = this._core.$element;
24771
24772		/**
24773		 * All event handlers.
24774		 * @protected
24775		 * @type {Object}
24776		 */
24777		this._handlers = {
24778			/*'initialized.owl.carousel': $.proxy(function(e) {
24779				if (e.namespace && this._core.settings.startPosition === 'URLHash') {
24780					$(window).trigger('hashchange.owl.navigation');
24781				}
24782			}, this),*/
24783			'prepared.owl.carousel': $.proxy(function(e) {
24784				if (e.namespace) {
24785					var hash = $(e.content).find('[data-hash]').addBack('[data-hash]').attr('data-hash');
24786
24787					if (!hash) {
24788						return;
24789					}
24790
24791					this._hashes[hash] = e.content;
24792				}
24793			}, this),
24794			'changed.owl.carousel': $.proxy(function(e) {
24795				if (e.namespace && e.property.name === 'position') {
24796					var current = this._core.items(this._core.relative(this._core.current())),
24797						hash = $.map(this._hashes, function(item, hash) {
24798							return item === current ? hash : null;
24799						}).join();
24800
24801					if (!hash || window.location.hash.slice(1) === hash) {
24802						return;
24803					}
24804
24805					window.location.hash = hash;
24806				}
24807			}, this)
24808		};
24809
24810		// set default options
24811		this._core.options = $.extend({}, Hash.Defaults, this._core.options);
24812
24813		// register the event handlers
24814		this.$element.on(this._handlers);
24815
24816		// register event listener for hash navigation
24817		/*$(window).on('hashchange.owl.navigation', $.proxy(function(e) {
24818			var hash = window.location.hash.substring(1),
24819				items = this._core.$stage.children(),
24820				position = this._hashes[hash] && items.index(this._hashes[hash]);
24821
24822			if (position === undefined || position === this._core.current()) {
24823				return;
24824			}
24825
24826			this._core.to(this._core.relative(position), false, true);
24827		}, this));*/
24828	};
24829
24830	/**
24831	 * Default options.
24832	 * @public
24833	 */
24834	Hash.Defaults = {
24835		URLhashListener: false
24836	};
24837
24838	/**
24839	 * Destroys the plugin.
24840	 * @public
24841	 */
24842	Hash.prototype.destroy = function() {
24843		var handler, property;
24844
24845		$(window).off('hashchange.owl.navigation');
24846
24847		for (handler in this._handlers) {
24848			this._core.$element.off(handler, this._handlers[handler]);
24849		}
24850		for (property in Object.getOwnPropertyNames(this)) {
24851			typeof this[property] != 'function' && (this[property] = null);
24852		}
24853	};
24854
24855	$.fn.owlCarousel.Constructor.Plugins.Hash = Hash;
24856
24857})(window.Zepto || window.jQuery, window, document);
24858
24859/**
24860 * Support Plugin
24861 *
24862 * @version 2.0.0-beta.3
24863 * @author Vivid Planet Software GmbH
24864 * @author Artus Kolanowski
24865 * @license The MIT License (MIT)
24866 */
24867;(function($, window, document, undefined) {
24868
24869	var style = $('<support>').get(0).style,
24870		prefixes = 'Webkit Moz O ms'.split(' '),
24871		events = {
24872			transition: {
24873				end: {
24874					WebkitTransition: 'webkitTransitionEnd',
24875					MozTransition: 'transitionend',
24876					OTransition: 'oTransitionEnd',
24877					transition: 'transitionend'
24878				}
24879			},
24880			animation: {
24881				end: {
24882					WebkitAnimation: 'webkitAnimationEnd',
24883					MozAnimation: 'animationend',
24884					OAnimation: 'oAnimationEnd',
24885					animation: 'animationend'
24886				}
24887			}
24888		},
24889		tests = {
24890			csstransforms: function() {
24891				return !!test('transform');
24892			},
24893			csstransforms3d: function() {
24894				return !!test('perspective');
24895			},
24896			csstransitions: function() {
24897				return !!test('transition');
24898			},
24899			cssanimations: function() {
24900				return !!test('animation');
24901			}
24902		};
24903
24904	function test(property, prefixed) {
24905		var result = false,
24906			upper = property.charAt(0).toUpperCase() + property.slice(1);
24907
24908		$.each((property + ' ' + prefixes.join(upper + ' ') + upper).split(' '), function(i, property) {
24909			if (style[property] !== undefined) {
24910				result = prefixed ? property : true;
24911				return false;
24912			}
24913		});
24914
24915		return result;
24916	}
24917
24918	function prefixed(property) {
24919		return test(property, true);
24920	}
24921
24922	if (tests.csstransitions()) {
24923		/* jshint -W053 */
24924		$.support.transition = new String(prefixed('transition'))
24925		$.support.transition.end = events.transition.end[ $.support.transition ];
24926	}
24927
24928	if (tests.cssanimations()) {
24929		/* jshint -W053 */
24930		$.support.animation = new String(prefixed('animation'))
24931		$.support.animation.end = events.animation.end[ $.support.animation ];
24932	}
24933
24934	if (tests.csstransforms()) {
24935		/* jshint -W053 */
24936		$.support.transform = new String(prefixed('transform'));
24937		$.support.transform3d = tests.csstransforms3d();
24938	}
24939
24940})(window.Zepto || window.jQuery, window, document);
24941
24942(function(window, document, undefined) {
24943
24944	/**
24945	 * Find the absolute position of an element
24946	 */
24947	var absPos = function(element) {
24948		var offsetLeft, offsetTop;
24949		offsetLeft = offsetTop = 0;
24950		if (element.offsetParent) {
24951			do {
24952				offsetLeft += element.offsetLeft;
24953				offsetTop += element.offsetTop;
24954			} while (element = element.offsetParent);
24955		}
24956		return [offsetLeft, offsetTop];
24957	};
24958
24959	/**
24960	 * @constructor Progress Circle class
24961	 * @param params.canvas Canvas on which the circles will be drawn.
24962	 * @param params.minRadius Inner radius of the innermost circle, in px.
24963	 * @param params.arcWidth Width of each circle(to be more accurate, ring).
24964	 * @param params.gapWidth Space between each circle.
24965	 * @param params.centerX X coordinate of the center of circles.
24966	 * @param params.centerY Y coordinate of the center of circles.
24967	 * @param params.infoLineBaseAngle Base angle of the info line.
24968	 * @param params.infoLineAngleInterval Angles between the info lines.
24969	 */
24970	var ProgressCircle = function(params) {
24971		this.canvas = params.canvas;
24972		this.minRadius = params.minRadius || 15;
24973		this.arcWidth = params.arcWidth || 5;
24974		this.gapWidth = params.gapWidth || 3;
24975		this.centerX = params.centerX || this.canvas.width / 2;
24976		this.centerY = params.centerY || this.canvas.height / 2;
24977		this.infoLineLength = params.infoLineLength || 60;
24978		this.horizLineLength = params.horizLineLength || 10;
24979		this.infoLineAngleInterval = params.infoLineAngleInterval || Math.PI / 8;
24980		this.infoLineBaseAngle = params.infoLineBaseAngle || Math.PI / 6;
24981
24982		this.context = this.canvas.getContext('2d');
24983
24984		this.width = this.canvas.width;
24985		this.height = this.canvas.height;
24986
24987		this.circles = [];
24988		this.runningCount = 0;
24989	};
24990
24991	ProgressCircle.prototype = {
24992		constructor: ProgressCircle,
24993
24994		/**
24995		 * @method Adds an progress monitor entry.
24996		 * @param params.fillColor Color to fill in the circle.
24997		 * @param params.outlineColor Color to outline the circle.
24998		 * @param params.progressListener Callback function to fetch the progress.
24999		 * @param params.infoListener Callback function to fetch the info.
25000		 * @returns this
25001		 */
25002		addEntry: function(params) {
25003			this.circles.push(new Circle({
25004				canvas: this.canvas,
25005				context: this.context,
25006				centerX: this.centerX,
25007				centerY: this.centerY,
25008				innerRadius: this.minRadius + this.circles.length *
25009					(this.gapWidth + this.arcWidth),
25010				arcWidth: this.arcWidth,
25011				infoLineLength: this.infoLineLength,
25012				horizLineLength: this.horizLineLength,
25013
25014				id: this.circles.length,
25015				fillColor: params.fillColor,
25016				outlineColor: params.outlineColor,
25017				progressListener: params.progressListener,
25018				infoListener: params.infoListener,
25019				infoLineAngle: this.infoLineBaseAngle +
25020					this.circles.length * this.infoLineAngleInterval,
25021			}));
25022
25023			return this;
25024		},
25025
25026		/**
25027		 * @method Starts the monitor and updates with the given interval.
25028		 * @param interval Interval between updates, in millisecond.
25029		 * @returns this
25030		 */
25031		start: function(interval) {
25032			var self = this;
25033			this.timer = setInterval(function() {
25034				self._update();
25035			}, interval || 33);
25036
25037			return this;
25038		},
25039
25040		/**
25041		 * @method Stop the animation.
25042		 */
25043		stop: function() {
25044			clearTimeout(this.timer);
25045		},
25046
25047		/**
25048		 * @private
25049		 * @method Call update on each circle and redraw them.
25050		 * @returns this
25051		 */
25052		_update: function() {
25053			this._clear();
25054			this.circles.forEach(function(circle, idx, array) {
25055				circle.update();
25056			});
25057
25058			return this;
25059		},
25060
25061		/**
25062		 * @private
25063		 * @method Clear the canvas.
25064		 * @returns this
25065		 */
25066		_clear: function() {
25067			this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
25068
25069			return this;
25070		},
25071
25072	};
25073
25074	/**
25075	 * @private
25076	 * @class Individual progress circle.
25077	 * @param params.canvas Canvas on which the circle will be drawn.
25078	 * @param params.context Context of the canvas.
25079	 * @param params.innerRadius Inner radius of the circle, in px.
25080	 * @param params.arcWidth Width of each arc(circle).
25081	 * @param params.gapWidth Distance between each arc.
25082	 * @param params.centerX X coordinate of the center of circles.
25083	 * @param params.centerY Y coordinate of the center of circles.
25084	 * @param params.fillColor Color to fill in the circle.
25085	 * @param params.outlineColor Color to outline the circle.
25086	 * @param params.progressListener Callback function to fetch the progress.
25087	 * @param params.infoListener Callback function to fetch the info.
25088	 * @param params.infoLineAngle Angle of info line.
25089	 */
25090	var Circle = function(params) {
25091		this.id = params.id;
25092		this.canvas = params.canvas;
25093		this.context = params.context;
25094		this.centerX = params.centerX;
25095		this.centerY = params.centerY;
25096		this.arcWidth = params.arcWidth;
25097		this.innerRadius = params.innerRadius || 0;
25098		this.fillColor = params.fillColor || '#fff';
25099		this.outlineColor = params.outlineColor || this.fillColor;
25100		this.progressListener = params.progressListener;
25101		this.infoLineLength = params.infoLineLength || 250;
25102		this.horizLineLength = params.horizLineLength || 50;
25103		this.infoListener = params.infoListener;
25104		this.infoLineAngle = params.infoLineAngle;
25105
25106		this.outerRadius = this.innerRadius + this.arcWidth;
25107
25108		// If the info listener is not registered, then don't calculate
25109		// the related coordinates
25110		if (!this.infoListener) return;
25111
25112		// calculate the info-line turning points
25113		var angle = this.infoLineAngle,
25114			arcDistance = (this.innerRadius + this.outerRadius) / 2,
25115
25116			sinA = Math.sin(angle),
25117			cosA = Math.cos(angle);
25118
25119		this.infoLineStartX = this.centerX + sinA * arcDistance;
25120		this.infoLineStartY = this.centerY - cosA * arcDistance;
25121
25122		this.infoLineMidX = this.centerX + sinA * this.infoLineLength;
25123		this.infoLineMidY = this.centerY - cosA * this.infoLineLength;
25124
25125		this.infoLineEndX = this.infoLineMidX +
25126			 (sinA < 0 ? -this.horizLineLength : this.horizLineLength);
25127		this.infoLineEndY = this.infoLineMidY;
25128
25129		var infoText = document.createElement('div'),
25130			style = infoText.style;
25131
25132		style.color = this.fillColor;
25133		style.position = 'absolute';
25134		style.left = this.infoLineEndX + absPos(this.canvas)[0] + 'px';
25135		// style.top will be calculated in the `drawInfo` method. Since
25136		// user may want to change the size of the font, so the top offset
25137		// must be updated in each loop.
25138		infoText.className = 'ProgressCircleInfo'; // For css styling
25139		infoText.id = 'progress_circle_info_' + this.id;
25140		document.body.appendChild(infoText);
25141		this.infoText = infoText;
25142	};
25143
25144	Circle.prototype = {
25145		constructor: Circle,
25146
25147		update: function() {
25148			this.progress = this.progressListener();
25149			this._draw();
25150
25151			if (this.infoListener) {
25152				this.info = this.infoListener();
25153				this._drawInfo();
25154			}
25155		},
25156
25157		/**
25158		 * @private
25159		 * @method Draw the circle on the canvas.
25160		 * @returns this
25161		 */
25162		_draw: function() {
25163			var ctx = this.context,
25164
25165				ANGLE_OFFSET = -Math.PI / 2,
25166
25167				startAngle = 0 + ANGLE_OFFSET,
25168				endAngle= startAngle + this.progress * Math.PI * 2,
25169
25170				x = this.centerX,
25171				y = this.centerY,
25172
25173				innerRadius = this.innerRadius - this.arcWidth - 1,
25174				outerRadius = this.outerRadius - this.arcWidth - 1;
25175
25176			if ( innerRadius < 0 )
25177				return;
25178
25179			ctx.fillStyle = this.fillColor;
25180			ctx.strokeStyle = this.outlineColor;
25181
25182			ctx.beginPath();
25183			ctx.arc(x, y, innerRadius, startAngle, endAngle, false);
25184			ctx.arc(x, y, outerRadius, endAngle, startAngle, true);
25185			ctx.closePath();
25186			ctx.stroke();
25187			ctx.fill();
25188
25189			return this;
25190		},
25191
25192		/**
25193		 * @private
25194		 * @method Draw the info lines and info text.
25195		 * @returns this
25196		 */
25197		_drawInfo: function() {
25198
25199			var pointList, lineHeight;
25200
25201			pointList = [
25202				[this.infoLineStartX, this.infoLineStartY],
25203				[this.infoLineMidX, this.infoLineMidY],
25204				[this.infoLineEndX, this.infoLineEndY],
25205			];
25206			this._drawSegments(pointList, false);
25207
25208			this.infoText.innerHTML = this.info;
25209
25210			lineHeight = this.infoText.offsetHeight;
25211			this.infoText.style.top = this.infoLineEndY +
25212				absPos(this.canvas)[1] - lineHeight / 2 + 'px';
25213
25214			return this;
25215		},
25216
25217		/**
25218		 * @private
25219		 * @method Helper function to draw the segments
25220		 * @param pointList An array of points in the form of [x, y].
25221		 * @param close Whether to connect the first and last point.
25222		 */
25223		_drawSegments: function(pointList, close) {
25224			var ctx = this.context;
25225
25226			ctx.beginPath();
25227			ctx.moveTo(pointList[0][0], pointList[0][1]);
25228			for (var i = 1; i < pointList.length; ++i) {
25229				ctx.lineTo(pointList[i][0], pointList[i][1]);
25230			}
25231
25232			if (close) {
25233				ctx.closePath();
25234			}
25235			ctx.stroke();
25236		},
25237	};
25238
25239	window.ProgressCircle = ProgressCircle;
25240
25241})(window, document);
25242
25243
25244
25245
25246/* =========================================================
25247 * jquery.vc_chart.js v1.0
25248 * =========================================================
25249 * Copyright 2013 Wpbakery
25250 *
25251 * Jquery chart plugin for the Visual Composer.
25252 * ========================================================= */
25253(function($){
25254	/**
25255	 * Pie chart animated.
25256	 * @param element - DOM element
25257	 * @param options - settings object.
25258	 * @constructor
25259	 */
25260	var VcChart = function(element, options) {
25261		this.el = element;
25262		this.$el = $(this.el);
25263		var $this = this;
25264		$this.options = $.extend({
25265			color: 'wpb_button',
25266			units: '',
25267			width: '',
25268			label_selector: '.vc_pie_chart_value',
25269			back_selector: '.vc_pie_chart_back',
25270			responsive: true
25271		}, options);
25272		$this.init();
25273	};
25274	VcChart.prototype = {
25275		constructor: VcChart,
25276		_progress_v: 0,
25277		animated: false,
25278		colors: {
25279			'wpb_button': 'rgba(247, 247, 247, 1)',
25280			'btn-primary': 'rgba(0, 136, 204, 1)',
25281			'btn-info': 'rgba(88, 185, 218, 1)',
25282			'btn-success': 'rgba(106, 177, 101, 1)',
25283			'btn-warning': 'rgba(255, 153, 0, 1)',
25284			'btn-danger': 'rgba(255, 103, 91, 1)',
25285			'btn-inverse': 'rgba(85, 85, 85, 1)'
25286		},
25287		init: function() {
25288			this.setupColor();
25289			this.value = this.$el.data('pie-value')/100;
25290			this.label_value = this.$el.data('pie-label-value') || this.$el.data('pie-value');
25291			this.$wrapper = $('.vc_pie_wrapper', this.$el);
25292			this.$label = $(this.options.label_selector, this.$el);
25293			this.$back = $(this.options.back_selector, this.$el);
25294			this.$canvas = this.$el.find('canvas');
25295			this.arcWidth = this.$el.data('pie-width') * 2;
25296			this.draw();
25297			this.setWayPoint();
25298			if(this.options.responsive === true) this.setResponsive();
25299			if (UNCODE.isMobile) this._progress_v = this.value;
25300		},
25301		setupColor: function() {
25302			// if(typeof this.colors[this.options.color] !== 'undefined') {
25303			//     this.color = this.colors[this.options.color];
25304			// } else if(typeof this.options.color === 'string' && this.options.color.match(/^rgba?\([^\)]+\)/)) {
25305			//     this.color = this.options.color;
25306			// } else {
25307			//     this.color = 'rgba(247, 247, 247, 0.2)';
25308			// }
25309			if(typeof this.options.color !== 'undefined') {
25310				this.color = this.options.color;
25311			} else this.color = 'rgba(247, 247, 247, 0.2)';
25312
25313		},
25314		setResponsive: function() {
25315			var that = this;
25316			if (!UNCODE.isMobile) {
25317				$(window).resize(function(){
25318					if(that.animated === true) that.circle.stop();
25319					that.draw(true);
25320				});
25321			}
25322		},
25323		draw: function(redraw) {
25324			var w = this.$el.addClass('vc_ready').width() * 2,
25325				border_w = this.arcWidth,
25326				radius;
25327			if(!w) w = this.$el.parents(':visible').first().width()-2;
25328			//w = Math.round(w/100*80);
25329			//if (w < 250) w = 250;
25330			radius = w/2;
25331			this.$wrapper.css({"width" : (w / 2) + "px"});
25332			this.$label.css({"width" : (w / 2), "height" : (w / 2), "line-height" : (w / 2)+"px"});
25333			this.$back.css({"width" : (w / 2), "height" : (w / 2)});
25334			this.$canvas.attr({"width" : w + "px", "height" : w + "px"});
25335			this.$el.addClass('vc_ready');
25336			this.circle = new ProgressCircle({
25337				canvas: this.$canvas.get(0),
25338				minRadius: radius,
25339				arcWidth: border_w
25340			});
25341			if(redraw === true && this.animated === true) {
25342				this._progress_v = this.value;
25343				this.circle.addEntry({
25344					fillColor: this.color,
25345					progressListener: $.proxy(this.setProgress, this)
25346				}).start();
25347			}
25348		},
25349		setProgress: function() {
25350			if (this._progress_v >= this.value) {
25351				this.circle.stop();
25352				this.animated = true;
25353				this.$label.html(this.label_value + this.options.units);
25354				return this._progress_v;
25355			}
25356			this._progress_v += 0.01;
25357			if (!isNaN(this.label_value)) {
25358				var label_value = this._progress_v/this.value*this.label_value;
25359				var val = Math.round(label_value) + this.options.units;
25360				this.$label.html(val);
25361			} else this.$label.html(this.label_value + this.options.units);
25362			return this._progress_v;
25363		},
25364		animate: function() {
25365			if(this.animated !== true) {
25366				this.circle.addEntry({
25367					fillColor: this.color,
25368					progressListener: $.proxy(this.setProgress, this)
25369				}).start(10);
25370			}
25371		},
25372		setWayPoint: function() {
25373			if (typeof $.fn.waypoint !== 'undefined' && !UNCODE.isMobile) {
25374				this.$el.waypoint($.proxy(this.animate, this), { offset: '85%' });
25375			} else {
25376				this.animate();
25377			}
25378		}
25379	};
25380	/**
25381	 * jQuery plugin
25382	 * @param option - object with settings
25383	 * @return {*}
25384	 */
25385	$.fn.vcChat = function(option, value) {
25386		return this.each(function () {
25387			var $this = $(this),
25388				data = $this.data('vc_chart'),
25389				options = typeof option === 'object' ? option : {
25390					color: $this.data('pie-color'),
25391					units: $this.data('pie-units')
25392				};
25393			if (typeof option == 'undefined') $this.data('vc_chart', (data = new VcChart(this, options)));
25394			if (typeof option == 'string') data[option](value);
25395		});
25396	};
25397	/**
25398	 * Allows users to rewrite function inside theme.
25399	 */
25400	if ( typeof window['vc_pieChart'] !== 'function' ) {
25401		window.vc_pieChart = function() {
25402			$('.vc_pie_chart:visible:not(.vc_ready)').vcChat();
25403		}
25404	}
25405	$(document).ready(function(){
25406		!window.vc_iframe && vc_pieChart();
25407
25408		/**
25409		* Tab and collapse integration.
25410		*/
25411		$('.nav-tabs a').on('shown.bs.tab', function(e){
25412			var $cont = $(e.target).closest('.tab-container'),
25413				$active = $('.tab-pane.active', $cont);
25414			$('.vc_pie_chart:not(.vc_ready)', $active).vcChat();
25415		});
25416
25417		$('.panel-collapse').on('shown.bs.collapse', function (e) {
25418			$('.vc_pie_chart:not(.vc_ready)', e.target).vcChat();
25419		})
25420	});
25421
25422})(window.jQuery);
25423
25424/* Progress bar
25425 ---------------------------------------------------------- */
25426function uncode_progress_bar() {
25427	jQuery.each(jQuery('.vc_progress_bar'), function(index, val) {
25428		if (UNCODE.isUnmodalOpen && !val.closest('#unmodal-content')) {
25429			return;
25430		}
25431		if (!UNCODE.isMobile) {
25432			new Waypoint({
25433				context: UNCODE.isUnmodalOpen ? document.getElementById('unmodal-content') : window,
25434				element: val,
25435				handler: function() {
25436					var element = jQuery(this.element);
25437					element.find('.vc_single_bar').each(function(index) {
25438						var $this = jQuery(this),
25439							bar = $this.find('.vc_bar'),
25440							val = bar.data('percentage-value');
25441						setTimeout(function() {
25442							bar.css({
25443								"width": val + '%'
25444							});
25445						}, index * 200);
25446					});
25447				},
25448				offset: '80%'
25449			});
25450		} else {
25451			var element = jQuery(val);
25452			element.find('.vc_single_bar').each(function(index) {
25453				var $this = jQuery(this),
25454					bar = $this.find('.vc_bar'),
25455					val = bar.data('percentage-value');
25456				setTimeout(function() {
25457					bar.css({
25458						"width": val + '%'
25459					});
25460				}, index * 200);
25461			});
25462		}
25463	});
25464};
25465uncode_progress_bar();
25466
25467/*!
25468 * jquery.counterup.js 1.0
25469 *
25470 * Copyright 2013, Benjamin Intal http://gambit.ph @bfintal
25471 * Released under the GPL v2 License
25472 *
25473 * Date: Nov 26, 2013
25474 */
25475(function($) {
25476	"use strict";
25477	$.fn.counterUp = function(options) {
25478		// Defaults
25479		var settings = $.extend({
25480			'time': 400,
25481			'delay': 10
25482		}, options);
25483		return this.each(function() {
25484			// Store the object
25485			var $this = $(this);
25486			var $settings = settings;
25487			var counterUpper = function() {
25488				var nums = [];
25489				var divisions = $settings.time / $settings.delay;
25490				var numReal = $this.attr('data-val'),
25491				num = numReal;
25492				var isComma = /[0-9]+,[0-9]+/.test(num);
25493				num = num.replace(/,/g, '');
25494				var isInt = /^[0-9]+$/.test(num);
25495				var isFloat = /^[0-9]+\.[0-9]+$/.test(num);
25496				var decimalPlaces = isFloat ? (num.split('.')[1] || []).length : 0;
25497				// Generate list of incremental numbers to display
25498				for (var i = divisions; i >= 1; i--) {
25499					// Preserve as int if input was int
25500					var newNum = parseInt(num / divisions * i);
25501					// Preserve float if input was float
25502					if (isFloat) {
25503						newNum = parseFloat(num / divisions * i).toFixed(decimalPlaces);
25504					}
25505					// Preserve commas if input had commas
25506					if (isComma) {
25507						while (/(\d+)(\d{3})/.test(newNum.toString())) {
25508							newNum = newNum.toString().replace(/(\d+)(\d{3})/, '$1' + ',' + '$2');
25509						}
25510					}
25511					nums.unshift(newNum);
25512				}
25513				nums.push(numReal);
25514				$this.data('counterup-nums', nums);
25515				$this.text('0');
25516				// Updates the number until we're done
25517				var f = function() {
25518					if ($this.data('counterup-nums') != null) {
25519						$this.text($this.data('counterup-nums').shift());
25520						if ($this.data('counterup-nums').length) {
25521							setTimeout($this.data('counterup-func'), $settings.delay);
25522						} else {
25523							delete $this.data('counterup-nums');
25524							$this.data('counterup-nums', null);
25525							$this.data('counterup-func', null);
25526						}
25527					}
25528				};
25529				$this.data('counterup-func', f);
25530				// Start the count up
25531				setTimeout($this.data('counterup-func'), $settings.delay);
25532			};
25533			// Perform counts when the element gets into view
25534			new Waypoint({
25535				context: UNCODE.isUnmodalOpen ? document.getElementById('unmodal-content') : window,
25536				element: this,
25537				handler: function() {
25538					counterUpper();
25539					if (!UNCODE.isUnmodalOpen) {
25540						this.destroy();
25541					}
25542				},
25543				offset: '100%'
25544			});
25545		});
25546	};
25547})(jQuery);
25548
25549/*!
25550 * The Final Countdown for jQuery v2.2.0 (http://hilios.github.io/jQuery.countdown/)
25551 * Copyright (c) 2016 Edson Hilios
25552 *
25553 * Permission is hereby granted, free of charge, to any person obtaining a copy of
25554 * this software and associated documentation files (the "Software"), to deal in
25555 * the Software without restriction, including without limitation the rights to
25556 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
25557 * the Software, and to permit persons to whom the Software is furnished to do so,
25558 * subject to the following conditions:
25559 *
25560 * The above copyright notice and this permission notice shall be included in all
25561 * copies or substantial portions of the Software.
25562 *
25563 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25564 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
25565 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
25566 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
25567 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25568 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25569 */
25570(function(factory) {
25571	"use strict";
25572	if (typeof define === "function" && define.amd) {
25573		define([ "jquery" ], factory);
25574	} else {
25575		factory(jQuery);
25576	}
25577})(function($) {
25578	"use strict";
25579	var instances = [], matchers = [], defaultOptions = {
25580		precision: 100,
25581		elapse: false,
25582		defer: false
25583	};
25584	matchers.push(/^[0-9]*$/.source);
25585	matchers.push(/([0-9]{1,2}\/){2}[0-9]{4}( [0-9]{1,2}(:[0-9]{2}){2})?/.source);
25586	matchers.push(/[0-9]{4}([\/\-][0-9]{1,2}){2}( [0-9]{1,2}(:[0-9]{2}){2})?/.source);
25587	matchers = new RegExp(matchers.join("|"));
25588	function parseDateString(dateString) {
25589		if (dateString instanceof Date) {
25590			return dateString;
25591		}
25592		if (String(dateString).match(matchers)) {
25593			if (String(dateString).match(/^[0-9]*$/)) {
25594				dateString = Number(dateString);
25595			}
25596			if (String(dateString).match(/\-/)) {
25597				dateString = String(dateString).replace(/\-/g, "/");
25598			}
25599			return new Date(dateString);
25600		} else {
25601			throw new Error("Couldn't cast `" + dateString + "` to a date object.");
25602		}
25603	}
25604	var DIRECTIVE_KEY_MAP = {
25605		Y: "years",
25606		m: "months",
25607		n: "daysToMonth",
25608		d: "daysToWeek",
25609		w: "weeks",
25610		W: "weeksToMonth",
25611		H: "hours",
25612		M: "minutes",
25613		S: "seconds",
25614		D: "totalDays",
25615		I: "totalHours",
25616		N: "totalMinutes",
25617		T: "totalSeconds"
25618	};
25619	function escapedRegExp(str) {
25620		var sanitize = str.toString().replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
25621		return new RegExp(sanitize);
25622	}
25623	function strftime(offsetObject) {
25624		return function(format) {
25625			var directives = format.match(/%(-|!)?[A-Z]{1}(:[^;]+;)?/gi);
25626			if (directives) {
25627				for (var i = 0, len = directives.length; i < len; ++i) {
25628					var directive = directives[i].match(/%(-|!)?([a-zA-Z]{1})(:[^;]+;)?/), regexp = escapedRegExp(directive[0]), modifier = directive[1] || "", plural = directive[3] || "", value = null;
25629					directive = directive[2];
25630					if (DIRECTIVE_KEY_MAP.hasOwnProperty(directive)) {
25631						value = DIRECTIVE_KEY_MAP[directive];
25632						value = Number(offsetObject[value]);
25633					}
25634					if (value !== null) {
25635						if (modifier === "!") {
25636							value = pluralize(plural, value);
25637						}
25638						if (modifier === "") {
25639							if (value < 10) {
25640								value = "0" + value.toString();
25641							}
25642						}
25643						format = format.replace(regexp, value.toString());
25644					}
25645				}
25646			}
25647			format = format.replace(/%%/, "%");
25648			return format;
25649		};
25650	}
25651	function pluralize(format, count) {
25652		var plural = "s", singular = "";
25653		if (format) {
25654			format = format.rep
vendor: 8,618 bytes, lines 25654-25798
25654lace(/(:|;|\s)/gi, "").split(/\,/);
25655			if (format.length === 1) {
25656				plural = format[0];
25657			} else {
25658				singular = format[0];
25659				plural = format[1];
25660			}
25661		}
25662		if (Math.abs(count) > 1) {
25663			return plural;
25664		} else {
25665			return singular;
25666		}
25667	}
25668	var Countdown = function(el, finalDate, options) {
25669		this.el = el;
25670		this.$el = $(el);
25671		this.interval = null;
25672		this.offset = {};
25673		this.options = $.extend({}, defaultOptions);
25674		this.instanceNumber = instances.length;
25675		instances.push(this);
25676		this.$el.data("countdown-instance", this.instanceNumber);
25677		if (options) {
25678			if (typeof options === "function") {
25679				this.$el.on("update.countdown", options);
25680				this.$el.on("stoped.countdown", options);
25681				this.$el.on("finish.countdown", options);
25682			} else {
25683				this.options = $.extend({}, defaultOptions, options);
25684			}
25685		}
25686		this.setFinalDate(finalDate);
25687		if (this.options.defer === false) {
25688			this.start();
25689		}
25690	};
25691	$.extend(Countdown.prototype, {
25692		start: function() {
25693			if (this.interval !== null) {
25694				clearInterval(this.interval);
25695			}
25696			var self = this;
25697			this.update();
25698			this.interval = setInterval(function() {
25699				self.update.call(self);
25700			}, this.options.precision);
25701		},
25702		stop: function() {
25703			clearInterval(this.interval);
25704			this.interval = null;
25705			this.dispatchEvent("stoped");
25706		},
25707		toggle: function() {
25708			if (this.interval) {
25709				this.stop();
25710			} else {
25711				this.start();
25712			}
25713		},
25714		pause: function() {
25715			this.stop();
25716		},
25717		resume: function() {
25718			this.start();
25719		},
25720		remove: function() {
25721			this.stop.call(this);
25722			instances[this.instanceNumber] = null;
25723			delete this.$el.data().countdownInstance;
25724		},
25725		setFinalDate: function(value) {
25726			this.finalDate = parseDateString(value);
25727		},
25728		update: function() {
25729			if (this.$el.closest("html").length === 0) {
25730				this.remove();
25731				return;
25732			}
25733			var hasEventsAttached = $._data(this.el, "events") !== undefined, now = new Date(), newTotalSecsLeft;
25734			newTotalSecsLeft = this.finalDate.getTime() - now.getTime();
25735			newTotalSecsLeft = Math.ceil(newTotalSecsLeft / 1e3);
25736			newTotalSecsLeft = !this.options.elapse && newTotalSecsLeft < 0 ? 0 : Math.abs(newTotalSecsLeft);
25737			if (this.totalSecsLeft === newTotalSecsLeft || !hasEventsAttached) {
25738				return;
25739			} else {
25740				this.totalSecsLeft = newTotalSecsLeft;
25741			}
25742			this.elapsed = now >= this.finalDate;
25743			this.offset = {
25744				seconds: this.totalSecsLeft % 60,
25745				minutes: Math.floor(this.totalSecsLeft / 60) % 60,
25746				hours: Math.floor(this.totalSecsLeft / 60 / 60) % 24,
25747				days: Math.floor(this.totalSecsLeft / 60 / 60 / 24) % 7,
25748				daysToWeek: Math.floor(this.totalSecsLeft / 60 / 60 / 24) % 7,
25749				daysToMonth: Math.floor(this.totalSecsLeft / 60 / 60 / 24 % 30.4368),
25750				weeks: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 7),
25751				weeksToMonth: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 7) % 4,
25752				months: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 30.4368),
25753				years: Math.abs(this.finalDate.getFullYear() - now.getFullYear()),
25754				totalDays: Math.floor(this.totalSecsLeft / 60 / 60 / 24),
25755				totalHours: Math.floor(this.totalSecsLeft / 60 / 60),
25756				totalMinutes: Math.floor(this.totalSecsLeft / 60),
25757				totalSeconds: this.totalSecsLeft
25758			};
25759			if (!this.options.elapse && this.totalSecsLeft === 0) {
25760				this.stop();
25761				this.dispatchEvent("finish");
25762			} else {
25763				this.dispatchEvent("update");
25764			}
25765		},
25766		dispatchEvent: function(eventName) {
25767			var event = $.Event(eventName + ".countdown");
25768			event.finalDate = this.finalDate;
25769			event.elapsed = this.elapsed;
25770			event.offset = $.extend({}, this.offset);
25771			event.strftime = strftime(this.offset);
25772			this.$el.trigger(event);
25773		}
25774	});
25775	$.fn.countdown = function() {
25776		var argumentsArray = Array.prototype.slice.call(arguments, 0);
25777		return this.each(function() {
25778			var instanceNumber = $(this).data("countdown-instance");
25779			if (instanceNumber !== undefined) {
25780				var instance = instances[instanceNumber], method = argumentsArray[0];
25781				if (Countdown.prototype.hasOwnProperty(method)) {
25782					instance[method].apply(instance, argumentsArray.slice(1));
25783				} else if (String(method).match(/^[$A-Z_][0-9A-Z_$]*$/i) === null) {
25784					instance.setFinalDate.call(instance, method);
25785					instance.start();
25786				} else {
25787					$.error("Method %s does not exist on jQuery.countdown".replace(/\%s/gi, method));
25788				}
25789			} else {
25790				new Countdown(this, argumentsArray[0], argumentsArray[1]);
25791			}
25792		});
25793	};
25794});
25795
25796!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;
25797function getStyles(config){
25798  // 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;
25798left: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+"}"
25799};
25800  var ShareUtils;
25801
25802if ((!("classList" in document.documentElement)) && Object.defineProperty && typeof HTMLElement !== "undefined") {
25803  Object.defineProperty(HTMLElement.prototype, "classList", {
25804    get: function() {
25805      var ret, self, update;
25806      update = function(fn) {
25807        return function(value) {
25808          var classes, index;
25809          classes = self.className.split(/\s+/);
25810          index = classes.indexOf(value);
25811          fn(classes, index, value);
25812          self.className = classes.join(" ");
25813        };
25814      };
25815      self = this;
25816      ret = {
25817        add: update(function(classes, index, value) {
25818          ~index || classes.push(value);
25819        }),
25820        remove: update(function(classes, index) {
25821          ~index && classes.splice(index, 1);
25822        }),
25823        toggle: update(function(classes, index, value) {
25824          if (~index) {
25825            classes.splice(index, 1);
25826          } else {
25827            classes.push(value);
25828          }
25829        }),
25830        contains: function(value) {
25831          return !!~self.className.split(/\s+/).indexOf(value);
25832        },
25833        item: function(i) {
25834          return self.className.split(/\s+/)[i] || null;
25835        }
25836      };
25837      Object.defineProperty(ret, "length", {
25838        get: function() {
25839          return self.className.split(/\s+/).length;
25840        }
25841      });
25842      return ret;
25843    }
25844  });
25845}
25846
25847String.prototype.to_rfc3986 = function() {
25848  var tmp;
25849  tmp = encodeURIComponent(this);
25850  return tmp.replace(/[!'()*]/g, function(c) {
25851    return "%" + c.charCodeAt(0).toString(16);
25852  });
25853};
25854
25855ShareUtils = (function() {
25856  function ShareUtils() {}
25857
25858  ShareUtils.prototype.extend = function(to, from, overwrite) {
25859    var hasProp, prop;
25860    for (prop in from) {
25861      hasProp = to[prop] !== undefined;
25862      if (hasProp && typeof from[prop] === "object") {
25863        this.extend(to[prop], from[prop], overwrite);
25864      } else {
25865        if (overwrite || !hasProp) {
25866          to[prop] = from[prop];
25867        }
25868      }
25869    }
25870  };
25871
25872  ShareUtils.prototype.hide = function(el) {
25873    return el.style.display = "none";
25874  };
25875
25876  ShareUtils.prototype.show = function(el) {
25877    return el.style.display = "block";
25878  };
25879
25880  ShareUtils.prototype.has_class = function(el, class_name) {
25881    return el.classList.contains(class_name);
25882  };
25883
25884  ShareUtils.prototype.add_class = function(el, class_name) {
25885    return el.classList.add(class_name);
25886  };
25887
25888  ShareUtils.prototype.remove_class = function(el, class_name) {
25889    return el.classList.remove(class_name);
25890  };
25891
25892  ShareUtils.prototype.is_encoded = function(str) {
25893    str = str.to_rfc3986();
25894    return decodeURIComponent(str) !== str;
25895  };
25896
25897  ShareUtils.prototype.encode = function(str) {
25898    if (typeof str === "undefined" || this.is_encoded(str)) {
25899      return str;
25900    } else {
25901      return str.to_rfc3986();
25902    }
25903  };
25904
25905  ShareUtils.prototype.popup = function(url, params) {
25906    var k, popup, qs, v;
25907    if (params == null) {
25908      params = {};
25909    }
25910    popup = {
25911      width: 500,
25912      height: 350
25913    };
25914    popup.top = (screen.height / 2) - (popup.height / 2);
25915    popup.left = (screen.width / 2) - (popup.width / 2);
25916    qs = ((function() {
25917      var _results;
25918      _results = [];
25919      for (k in params) {
25920        v = params[k];
25921        _results.push("" + k + "=" + (this.encode(v)));
25922      }
25923      return _results;
25924    }).call(this)).join('&');
25925    if (qs) {
25926      qs = "?" + qs;
25927    }
25928    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=" 
25928+ popup.width + ",height=" + popup.height);
25929  };
25930
25931  return ShareUtils;
25932
25933})();
25934var Share,
25935  __hasProp = {}.hasOwnProperty,
25936  __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; };
25937
25938Share = (function(_super) {
25939  __extends(Share, _super);
25940
25941  function Share(element, options) {
25942    this.element = element;
25943    this.el = {
25944      head: document.getElementsByTagName('head')[0],
25945      body: document.getElementsByTagName('body')[0]
25946    };
25947    this.config = {
25948      enabled_networks: 0,
25949      protocol: ['http', 'https'].indexOf(window.location.href.split(':')[0]) === -1 ? 'https://' : '//',
25950      url: window.location.href.replace("&", "%26"),
25951      caption: null,
25952      title: this.default_title(),
25953      image: this.default_image(),
25954      description: this.default_description(),
25955      ui: {
25956        flyout: 'top center',
25957        button_text: 'Share',
25958        button_font: true,
25959        icon_font: true
25960      },
25961      networks: {
25962        twitter: {
25963          enabled: true,
25964          url: null,
25965          title: null,
25966          description: null
25967        },
25968        facebook: {
25969          enabled: true,
25970          load_sdk: true,
25971          url: null,
25972          app_id: null,
25973          title: null,
25974          caption: null,
25975          description: null,
25976          image: null
25977        },
25978        pinterest: {
25979          enabled: true,
25980          url: null,
25981          image: null,
25982          description: null
25983        },
25984        reddit: {
25985          enabled: true,
25986          url: null,
25987          title: null
25988        },
25989        linkedin: {
25990          enabled: true,
25991          url: null,
25992          title: null,
25993          description: null
25994        },
25995        xing: {
25996          enabled: true,
25997          url: null,
25998          title: null,
25999          image: null,
26000          description: null
26001        },
26002        whatsapp: {
26003          enabled: true,
26004          description: null,
26005          url: null
26006        },
26007        email: {
26008          enabled: true,
26009          title: null,
26010          description: null,
26011          url: null
26012        }
26013      }
26014    };
26015    this.setup(element, options);
26016    return this;
26017  }
26018
26019  Share.prototype.setup = function(element, opts) {
26020    var index, instance, instances, _i, _len;
26021    instances = document.querySelectorAll(element);
26022    this.extend(this.config, opts, true);
26023    this.set_global_configuration();
26024    this.normalize_network_configuration();
26025    if (this.config.ui.icon_font) {
26026      this.inject_icons();
26027    }
26028    if (this.config.ui.button_font) {
26029      this.inject_fonts();
26030    }
26031    if (this.config.networks.facebook.enabled && this.config.networks.facebook.load_sdk) {
26032      this.inject_facebook_sdk();
26033    }
26034    for (index = _i = 0, _len = instances.length; _i < _len; index = ++_i) {
26035      instance = instances[index];
26036      this.setup_instance(element, index);
26037    }
26038  };
26039
26040  Share.prototype.setup_instance = function(element, index) {
26041    var button, instance, label, network, networks, _i, _len, _results,
26042      _this = this;
26043    instance = document.querySelectorAll(element)[index];
26044    this.hide(instance);
26045    this.add_class(instance, "sharer-" + index);
26046    instance = document.querySelectorAll(element)[index];
26047    this.inject_css(instance);
26048    this.inject_html(instance);
26049    this.show(instance);
26050    label = instance.getElementsByTagName("label")[0];
26051    button = instance.getElementsByClassName("social")[0];
26052    networks = instance.getElementsByTagName('li');
26053    this.add_class(button, "networks-" + this.config.enabled_networks);
26054    label.addEventListener("click", function() {
26055      return _this.event_toggle(button);
26056    });
26057    _this = this;
26058    _results = [];
26059    for (index = _i = 0, _len = networks.length; _i < _len; index = ++_i) {
26060      network = networks[index];
26061      _results.push(network.addEventListener("click", function() {
26062        _this.event_network(instance, this);
26063        return _this.event_close(button);
26064      }));
26065    }
26066    return _results;
26067  };
26068
26069  Share.prototype.event_toggle = function(button) {
26070    if (this.has_class(button, "active")) {
26071      return this.event_close(button);
26072    } else {
26073      return this.event_open(button);
26074    }
26075  };
26076
26077  Share.prototype.event_open = function(button) {
26078    if (this.has_class(button, "load")) {
26079      this.remove_class(button, "load");
26080    }
26081    return this.add_class(button, "active");
26082  };
26083
26084  Share.prototype.event_close = function(button) {
26085    return this.remove_class(button, "active");
26086  };
26087
26088  Share.prototype.event_network = function(instance, network) {
26089    var name;
26090    name = network.getAttribute("data-network");
26091    this.hook("before", name, instance);
26092    this["network_" + name]();
26093    return this.hook("after", name, instance);
26094  };
26095
26096  Share.prototype.open = function() {
26097    return this["public"]("open");
26098  };
26099
26100  Share.prototype.close = function() {
26101    return this["public"]("close");
26102  };
26103
26104  Share.prototype.toggle = function() {
26105    return this["public"]("toggle");
26106  };
26107
26108  Share.prototype["public"] = function(action) {
26109    var button, index, instance, _i, _len, _ref, _results;
26110    _ref = document.querySelectorAll(this.element);
26111    _results = [];
26112    for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) {
26113      instance = _ref[index];
26114      button = instance.getElementsByClassName("social")[0];
26115      _results.push(this["event_" + action](button));
26116    }
26117    return _results;
26118  };
26119
26120  Share.prototype.network_facebook = function() {
26121    if (this.config.networks.facebook.load_sdk) {
26122      if (!window.FB) {
26123        return console.error("The Facebook JS SDK hasn't loaded yet.");
26124      }
26125      return FB.ui({
26126        method: 'feed',
26127        name: this.config.networks.facebook.title,
26128        link: this.config.networks.facebook.url,
26129        picture: this.config.networks.facebook.image,
26130        caption: this.config.networks.facebook.caption,
26131        description: this.config.networks.facebook.description
26132      });
26133    } else {
26134      return this.popup('https://www.facebook.com/sharer/sharer.php', {
26135        u: this.config.networks.facebook.url
26136      });
26137    }
26138  };
26139
26140  Share.prototype.network_twitter = function() {
26141    return this.popup('https://twitter.com/intent/tweet', {
26142      text: this.config.networks.twitter.title,
26143      url: this.config.networks.twitter.url
26144    });
26145  };
26146
26147  Share.prototype.network_pinterest = function() {
26148    return this.popup('https://www.pinterest.com/pin/create/button', {
26149      url: this.config.networks.pinterest.url,
26150      media: this.config.networks.pinterest.image,
26151      description: this.config.networks.pinterest.description
26152    });
26153  };
26154
26155  Share.prototype.network_linkedin = function() {
26156    return this.popup('https://www.linkedin.com/shareArticle', {
26157      url: this.config.networks.linkedin.url,
26158      title: this.config.networks.linkedin.title,
26159      summary: this.config.networks.linkedin.description
26160    });
26161  }
26162
26163  Share.prototype.network_xing = function() {
26164    return this.popup('https://www.xing.com/spi/shares/new', {
26165      url: this.config.networks.xing.url,
26166      image: this.config.networks.xing.image,
26167      title: this.config.networks.xing.title,
26168      summary: this.config.networks.xing.description
26169    });
26170  }
26171
26172  Share.prototype.network_email = function() {
26173    return this.popup('mailto:', {
26174      subject: this.config.networks.email.title,
26175      body: this.config.networks.email.url + '%0A%0A' + this.config.networks.email.description,
26176    });
26177  };
26178
26179  Share.prototype.inject_icons = function() {
26180  //  return this.inject_stylesheet("https://www.sharebutton.co/fonts/v2/entypo.min.css");
26181  };
26182
26183  Share.prototype.inject_fonts = function() {
26184   // return this.inject_stylesheet("http://fonts.googleapis.com/css?family=Lato:900&text=" + this.config.ui.button_text);
26185  };
26186
26187  Share.prototype.inject_stylesheet = function(url) {
26188    var link;
26189    if (!this.el.head.querySelector("link[href=\"" + url + "\"]")) {
26190      link = document.createElement("link");
26191      link.setAttribute("rel", "stylesheet");
26192      link.setAttribute("href", url);
26193      return this.el.head.appendChild(link);
26194    }
26195  };
26196
26197  Share.prototype.inject_css = function(instance) {
26198    var css, meta, selector, style;
26199    selector = "." + (instance.getAttribute('class').split(" ").join("."));
26200    if (!this.el.head.querySelector("meta[name='sharer" + selector + "']")) {
26201      this.config.selector = selector;
26202      css = getStyles(this.config);
26203      style = document.createElement("style");
26204      style.type = "text/css";
26205      if (style.styleSheet) {
26206        style.styleSheet.cssText = css;
26207      } else {
26208        style.appendChild(document.createTextNode(css));
26209      }
26210      this.el.head.appendChild(style);
26211      delete this.config.selector;
26212      meta = document.createElement("meta");
26213      meta.setAttribute("name", "sharer" + selector);
26214      return this.el.head.appendChild(meta);
26215    }
26216  };
26217
26218  Share.prototype.inject_html = function(instance) {
26219    //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>";
26220    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-xing' data-network='xing' tabindex='0'></li><li class='social-paper-plane' data-network='email' tabindex='0'></li></ul></div>";
26221  };
26222
26223  Share.prototype.inject_facebook_sdk = function() {
26224    var fb_root, script;
26225    if (!window.FB && this.config.networks.facebook.app_id && !this.el.body.querySelector('#fb-root')) {
26226      script = document.createElement("script");
26227      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')";
26228      fb_root = document.createElement("div");
26229      fb_root.id = "fb-root";
26230      this.el.body.appendChild(fb_root);
26231      return this.el.body.appendChild(script);
26232    }
26233  };
26234
26235  Share.prototype.hook = function(type, network, instance) {
26236    var fn, opts;
26237    fn = this.config.networks[network][type];
26238    if (typeof fn === "function") {
26239      opts = fn.call(this.config.networks[network], instance);
26240      if (opts !== void 0) {
26241        opts = this.normalize_filter_config_updates(opts);
26242        this.extend(this.config.networks[network], opts, true);
26243        this.normalize_network_configuration();
26244      }
26245    }
26246  };
26247
26248  Share.prototype.default_title = function() {
26249    var content;
26250    if (content = document.querySelector('meta[property="og:title"]') || document.querySelector('meta[name="twitter:title"]')) {
26251      return encodeURIComponent(content.getAttribute('content'));
26252    } else if (content = document.querySelector('title')) {
26253      return encodeURIComponent(content.innerText);
26254    }
26255  };
26256
26257  Share.prototype.default_image = function() {
26258    var content;
26259    if (content = document.querySelector('meta[property="og:image"]') || document.querySelector('meta[name="twitter:image"]')) {
26260      return content.getAttribute('content');
26261    }
26262  };
26263
26264  Share.prototype.default_description = function() {
26265    var content;
26266    if (content = document.querySelector('meta[property="og:description"]') || document.querySelector('meta[name="twitter:description"]') || document.querySelector('meta[name="description"]')) {
26267      return encodeURIComponent(content.getAttribute('content'));
26268    } else {
26269      return '';
26270    }
26271  };
26272
26273  Share.prototype.set_global_configuration = function() {
26274    var display, network, option, options, _ref, _results;
26275    _ref = this.config.networks;
26276    _results = [];
26277    for (network in _ref) {
26278      options = _ref[network];
26279      for (option in options) {
26280        if (this.config.networks[network][option] == null) {
26281          this.config.networks[network][option] = this.config[option];
26282        }
26283      }
26284      if (this.config.networks[network].enabled) {
26285        display = 'block';
26286        this.config.enabled_networks += 1;
26287      } else {
26288        display = 'none';
26289      }
26290      _results.push(this.config.networks[network].display = display);
26291    }
26292    return _results;
26293  };
26294
26295  Share.prototype.normalize_network_configuration = function() {
26296    if (!this.config.networks.facebook.app_id) {
26297      this.config.networks.facebook.load_sdk = false;
26298    }
26299    if (!this.is_encoded(this.config.networks.twitter.description)) {
26300      this.config.networks.twitter.description = encodeURIComponent(this.config.networks.twitter.description);
26301    }
26302    if (typeof this.config.networks.facebook.app_id === 'number') {
26303      return this.config.networks.facebook.app_id = this.config.networks.facebook.app_id.toString();
26304    }
26305  };
26306
26307  Share.prototype.normalize_filter_config_updates = function(opts) {
26308    if (this.config.networks.facebook.app_id !== opts.app_id) {
26309      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.");
26310      delete opts.app_id;
26311    }
26312    if (this.config.networks.facebook.load_sdk !== opts.load_sdk) {
26313      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.");
26314      delete opts.app_id;
26315    }
26316    return opts;
26317  };
26318
26319  return Share;
26320
26321})(ShareUtils);
26322 return Share;
26323});
26324
26325// Generated by CoffeeScript 1.9.2
26326
26327// @license Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net
26328
26329(function() {
26330  var $, win;
26331
26332  $ = this.jQuery || window.jQuery;
26333
26334  win = $(window);
26335
26336  $.fn.stick_in_parent = function(opts) {
26337    var doc, elm, enable_bottoming, fn, i, inner_scrolling, len, manual_spacer, offset_top, outer_width, parent_selector, recalc_every, sticky_class;
26338    if (opts == null) {
26339      opts = {};
26340    }
26341    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;
26342    if (offset_top == null) {
26343      offset_top = 0;
26344    }
26345    if (parent_selector == null) {
26346      parent_selector = void 0;
26347    }
26348    if (inner_scrolling == null) {
26349      inner_scrolling = true;
26350    }
26351    if (sticky_class == null) {
26352      sticky_class = "is_stuck";
26353    }
26354    doc = $(document);
26355    if (enable_bottoming == null) {
26356      enable_bottoming = true;
26357    }
26358    outer_width = function(el) {
26359      var _el, computed, w;
26360      if (window.getComputedStyle) {
26361        _el = el[0];
26362        computed = window.getComputedStyle(el[0]);
26363        w = parseFloat(computed.getPropertyValue("width")) + parseFloat(computed.getPropertyValue("margin-left")) + parseFloat(computed.getPropertyValue("margin-right"));
26364        if (computed.getPropertyValue("box-sizing") !== "border-box") {
26365          w += parseFloat(computed.getPropertyValue("border-left-width")) + parseFloat(computed.getPropertyValue("border-right-width")) + parseFloat(computed.getPropertyValue("padding-left")) + parseFloat(computed.getPropertyValue("padding-right"));
26366        }
26367        return w;
26368      } else {
26369        return el.outerWidth(true);
26370      }
26371    };
26372    fn = function(elm, padding_bottom, parent_top, parent_height, top, height, el_float, detached) {
26373      var bottomed, detach, fixed, last_pos, last_scroll_height, offset, parent, recalc, recalc_and_tick, recalc_counter, spacer, tick;
26374      if (elm.data("sticky_kit")) {
26375        return;
26376      }
26377      elm.data("sticky_kit", true);
26378      last_scroll_height = doc.height();
26379      parent = elm.parent();
26380      if (parent_selector != null) {
26381        parent = parent.closest(parent_selector);
26382      }
26383      if (!parent.length) {
26384        throw "failed to find stick parent";
26385      }
26386      fixed = false;
26387      bottomed = false;
26388      spacer = manual_spacer != null ? manual_spacer && elm.closest(manual_spacer) : $("<div />");
26389      if (spacer) {
26390        spacer.css('position', elm.css('position'));
26391      }
26392      recalc = function() {
26393        var border_top, padding_top, restore;
26394        if (detached) {
26395          return;
26396        }
26397        last_scroll_height = doc.height();
26398        border_top = parseInt(parent.css("border-top-width"), 10);
26399        padding_top = parseInt(parent.css("padding-top"), 10);
26400        padding_bottom = parseInt(parent.css("padding-bottom"), 10);
26401        parent_top = parent.offset().top + border_top + padding_top;
26402        parent_height = parent.height();
26403        if (fixed) {
26404          fixed = false;
vendor: 6,068 bytes, lines 26405-26599
26405          bottomed = false;
26406          if (manual_spacer == null) {
26407            elm.insertAfter(spacer);
26408            spacer.detach();
26409          }
26410          elm.css({
26411            position: "",
26412            top: "",
26413            width: "",
26414            bottom: ""
26415          }).removeClass(sticky_class);
26416          restore = true;
26417        }
26418        top = elm.offset().top - (parseInt(elm.css("margin-top"), 10) || 0) - offset_top;
26419        height = elm.outerHeight(true);
26420        el_float = elm.css("float");
26421        if (spacer) {
26422          spacer.css({
26423            width: outer_width(elm),
26424            height: height,
26425            display: elm.css("display"),
26426            "vertical-align": elm.css("vertical-align"),
26427            "float": el_float
26428          });
26429        }
26430        if (restore) {
26431          return tick();
26432        }
26433      };
26434      recalc();
26435      if (height === parent_height) {
26436        return;
26437      }
26438      last_pos = void 0;
26439      offset = offset_top;
26440      recalc_counter = recalc_every;
26441      tick = function() {
26442        var css, delta, recalced, scroll, will_bottom, win_height;
26443        if (detached) {
26444          return;
26445        }
26446        recalced = false;
26447        if (recalc_counter != null) {
26448          recalc_counter -= 1;
26449          if (recalc_counter <= 0) {
26450            recalc_counter = recalc_every;
26451            recalc();
26452            recalced = true;
26453          }
26454        }
26455        if (!recalced && doc.height() !== last_scroll_height) {
26456          recalc();
26457          recalced = true;
26458        }
26459        scroll = win.scrollTop();
26460        if (last_pos != null) {
26461          delta = scroll - last_pos;
26462        }
26463        last_pos = scroll;
26464        if (fixed) {
26465          if (enable_bottoming) {
26466            will_bottom = scroll + height + offset > parent_height + parent_top;
26467            if (bottomed && !will_bottom) {
26468              bottomed = false;
26469              elm.css({
26470                position: "fixed",
26471                bottom: "",
26472                top: offset
26473              }).trigger("sticky_kit:unbottom");
26474            }
26475          }
26476          if (scroll < top) {
26477            fixed = false;
26478            offset = offset_top;
26479            if (manual_spacer == null) {
26480              if (el_float === "left" || el_float === "right") {
26481                elm.insertAfter(spacer);
26482              }
26483              spacer.detach();
26484            }
26485            css = {
26486              position: "",
26487              width: "",
26488              top: ""
26489            };
26490            elm.css(css).removeClass(sticky_class).trigger("sticky_kit:unstick");
26491          }
26492          if (inner_scrolling) {
26493            win_height = win.height();
26494            if (height + offset_top > win_height) {
26495              if (!bottomed) {
26496                offset -= delta;
26497                offset = Math.max(win_height - height, offset);
26498                offset = Math.min(offset_top, offset);
26499                if (fixed) {
26500                  elm.css({
26501                    top: offset + "px"
26502                  });
26503                }
26504              }
26505            }
26506          }
26507        } else {
26508          if (scroll > top) {
26509            fixed = true;
26510            css = {
26511              position: "fixed",
26512              top: offset
26513            };
26514            css.width = elm.css("box-sizing") === "border-box" ? elm.outerWidth() + "px" : elm.width() + "px";
26515            elm.css(css).addClass(sticky_class);
26516            if (manual_spacer == null) {
26517              elm.after(spacer);
26518              if (el_float === "left" || el_float === "right") {
26519                spacer.append(elm);
26520              }
26521            }
26522            elm.trigger("sticky_kit:stick");
26523          }
26524        }
26525        if (fixed && enable_bottoming) {
26526          if (will_bottom == null) {
26527            will_bottom = scroll + height + offset > parent_height + parent_top;
26528          }
26529          if (!bottomed && will_bottom) {
26530            bottomed = true;
26531            if (parent.css("position") === "static") {
26532              parent.css({
26533                position: "relative"
26534              });
26535            }
26536            return elm.css({
26537              position: "absolute",
26538              bottom: padding_bottom,
26539              top: "auto"
26540            }).trigger("sticky_kit:bottom");
26541          }
26542        }
26543      };
26544      recalc_and_tick = function() {
26545        recalc();
26546        return tick();
26547      };
26548      detach = function() {
26549        detached = true;
26550        win.off("touchmove", tick);
26551        win.off("scroll", tick);
26552        win.off("resize", recalc_and_tick);
26553        $(document.body).off("sticky_kit:recalc", recalc_and_tick);
26554        elm.off("sticky_kit:detach", detach);
26555        elm.removeData("sticky_kit");
26556        elm.css({
26557          position: "",
26558          bottom: "",
26559          top: "",
26560          width: ""
26561        });
26562        parent.position("position", "");
26563        if (fixed) {
26564          if (manual_spacer == null) {
26565            if (el_float === "left" || el_float === "right") {
26566              elm.insertAfter(spacer);
26567            }
26568            spacer.remove();
26569          }
26570          return elm.removeClass(sticky_class);
26571        }
26572      };
26573      win.on("touchmove", tick);
26574      win.on("scroll", tick);
26575      win.on("resize", recalc_and_tick);
26576      $(document.body).on("sticky_kit:recalc", recalc_and_tick);
26577      elm.on("sticky_kit:detach", detach);
26578      return setTimeout(tick, 0);
26579    };
26580    for (i = 0, len = this.length; i < len; i++) {
26581      elm = this[i];
26582      fn($(elm));
26583    }
26584    return this;
26585  };
26586
26587}).call(this);
26588/* ==========================================================================
26589 * bootstrap-tab-history.js
26590 * Author: Michael Narayan <[email protected]>
26591 * Repository: https://github.com/mnarayan01/bootstrap-tab-history/
26592 * ==========================================================================
26593 * Licensed under the Apache License, Version 2.0 (the "License"); you may
26594 * not use this file except in compliance with the License. You may obtain a
26595 * copy of the License at
26596 *
26597 * http://www.apache.org/licenses/LICENSE-2.0
26598 *
26599 * Unless required by applicable law or agreed to in writing, softw
26599are
26600 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
26601 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
26602 * License for the specific language governing permissions and limitations
26603 * under the License.
26604 * ========================================================================== */
26605
26606/* ========================================================================== */
26607/* JSHint directives                                                          */
26608/*                                                                            */
26609/* global BootstrapTabHistory: true                                           */
26610/*                                                                            */
26611/* global document                                                            */
26612/* global jQuery                                                              */
26613/* global history                                                             */
26614/* global window                                                              */
26615/* ========================================================================== */
26616
26617/**
26618 * Integrate [HTML5 history state tracking](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history)
26619 * with [`bootstrap/tab.js`](http://getbootstrap.com/javascript/#tabs). To enable tracking on a tab element, simply set
26620 * the `data-tab-history` attribute to true (or a string denoting a tab grouping).
26621 *
26622 * See the README for additional information.
26623 *
26624 * Functionality based upon bootstrap/tab.js v3.1.0; reference it when making any changes.
26625 */
26626
26627BootstrapTabHistory = {
26628  options: {
26629    /**
26630     * When the anchor portion of the URI is used to activate a tab, scroll down to the given offset, rather than the
26631     * element with the given `id` attribute. Set to null to disable. Only relevant if showTabsBasedOnAnchor is true.
26632     *
26633     * May be overriden on a per-element basis by the attribute `data-tab-history-anchor-y-offset`.
26634     *
26635     * @public
26636     * @type {?number}
26637     */
26638    defaultAnchorYOffset: 0,
26639    /**
26640     * Either 'push' or 'replace', for whether to use `history.pushState` or `history.replaceState`, resp.
26641     *
26642     * May be overriden on a per-element basis by the attribute `data-tab-history-changer`.
26643     *
26644     * @public
26645     * @type {string}
26646     */
26647    defaultChanger: 'replace',
26648    /**
26649     * If true, update the URL in onShownTab in the calls to `history.pushState` and `history.replaceState`. Otherwise,
26650     * `null` is passed as the third parameter to these calls.
26651     *
26652     * May be overriden on a per-element basis by the attribute `data-tab-history-update-url`.
26653     *
26654     * @public
26655     * @type {boolean}
26656     */
26657    defaultUpdateURL: false,
26658    /**
26659     * Should the anchor portion of the loaded URI be used to activate a single tab if no history was present on page
26660     * load.
26661     *
26662     * @public
26663     * @type {boolean}
26664     */
26665    showTabsBasedOnAnchor: true
26666  }
26667};
26668
26669(function () {
26670  'use strict';
26671
26672  jQuery(function () {
26673    if(history && history.pushState && history.replaceState) {
26674      var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory;
26675
26676      if(bootstrapTabHistory) {
26677        showTabsBasedOnState(bootstrapTabHistory);
26678      } else {
26679        showTabsBasedOnAnchor();
26680      }
26681
26682      backfillHistoryState();
26683
26684      jQuery(document).on('shown.bs.tab show.bs.collapse', onShownTab);
26685      jQuery(window).on('popstate', onPopState);
26686    } else {
26687      showTabsBasedOnAnchor();
26688    }
26689  });
26690
26691  /**
26692   * Used to prevent onShownTab from registering shown events that we triggered via showTabsBasedOnState.
26693   *
26694   * @type {boolean}
26695   */
26696  var showingTabsBasedOnState = false;
26697
26698  /**
26699   * Used to update `history.state` to reflect the default active tabs on initial page load. This supports proper
26700   * `history.back` handling when `data-tab-history-update-url` is true.
26701   */
26702  function backfillHistoryState() {
26703    var newState = null;
26704
26705    jQuery('li.active > [data-tab-history], .panel-title.active [data-tab-history]').each(function () {//edited by Uncode
26706      var $activeTabElement = jQuery(this);
26707      var selector = getTabSelector($activeTabElement);
26708
26709      if(selector) {
26710        var tabGroup = getTabGroup($activeTabElement);
26711
26712        if(tabGroup) {
26713          newState = createNewHistoryState(newState || history.state, tabGroup, selector);
26714        }
26715      }
26716    });
26717
26718    if(newState) {
26719      history.replaceState(newState, '', null);
26720    }
26721  }
26722
26723  /**
26724   * Clone the existing state, ensure its bootstrapTabHistory attribute is an Object, and add the provided tabGroup to
26725   * said bootstrapTabHistory attribute.
26726   *
26727   * @param {?object} existingState
26728   * @param {!string} tabGroup
26729   * @param {!string} selector
26730   * @returns {!object}
26731   */
26732  function createNewHistoryState(existingState, tabGroup, selector) {
26733    // Clone history.state and ensure it has a bootstrapTabHistory entry.
26734    var newState = jQuery.extend(true, {}, existingState, {
26735      bootstrapTabHistory: {}
26736    });
26737
26738    newState.bootstrapTabHistory[tabGroup] = selector;
26739
26740    return newState;
26741  }
26742
26743  /**
26744   * @param {jQuery} $tab
26745   * @returns {?string}
26746   */
26747  function getTabGroup($tab) {
26748    return parseTruthyAttributeValue($tab.data('tab-history'));
26749  }
26750
26751  /**
26752   * @param {jQuery} $tab
26753   * @returns {?string}
26754   */
26755  function getTabSelector($tab) {
26756    return $tab.data('target') || $tab.attr('href');
26757  }
26758
26759  /**
26760   * Receives the `shown.bs.tab` event. Updates `history.state` as appropriate.
26761   *
26762   * @param {jQuery.Event} shownEvt
26763   */
26764  function onShownTab(shownEvt) {
26765    if(!showingTabsBasedOnState) {
26766      var $activatedTab = jQuery(shownEvt.target);
26767      if ( $activatedTab.hasClass('panel-collapse') )
26768        $activatedTab = $activatedTab.closest('.panel').find('a');
26769      var selector = getTabSelector($activatedTab);
26770
26771      if(selector) {
26772        var tabGroup = getTabGroup($activatedTab);
26773
26774        if(tabGroup) {
26775          var historyChanger = $activatedTab.data('tab-history-changer') || BootstrapTabHistory.options.defaultChanger;
26776          var newState = createNewHistoryState(history.state, tabGroup, selector);
26777          var updateURL = (function ($activatedTab) {
26778            if(selector[0] === '#') {
26779              var elementUpdateURLOption = parseTruthyAttributeValue($activatedTab.data('tab-history-update-url'));
26780
26781              if(elementUpdateURLOption === undefined) {
26782                return BootstrapTabHistory.options.defaultUpdateURL;
26783              } else {
26784                return elementUpdateURLOption;
26785              }
26786            } else {
26787              return false;
26788            }
26789          })($activatedTab);
26790
26791          switch(historyChanger) {
26792            case 'push':
26793              history.pushState(newState, '', updateURL ? selector : null);
26794              break;
26795            case 'replace':
26796              history.replaceState(newState, '', updateURL ? selector : null);
26797              break;
26798            default:
26799              throw new Error('Unknown tab-history-changer: ' + historyChanger);
26800          }
26801        }
26802      }
26803    }
26804  }
26805
26806  /**
26807   * Receives the `popstate` event. Shows tabs based on the value of `history.state` as appropriate.
26808   */
26809  function onPopState() {
26810    var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory;
26811
26812    if(bootstrapTabHistory) {
26813      showTabsBasedOnState(bootstrapTabHistory);
26814    }
26815  }
26816
26817  /**
26818   * Returns the given value, _unless_ that value is an empty string, in which case `true` is returned.
26819   *
26820   * Rationale: HAML data attributes which are set to `true` are rendered as a blank string.
26821   *
26822   * @param {*} value
26823   * @returns {*}
26824   */
26825  function parseTruthyAttributeValue(value) {
26826    if(value) {
26827      return value;
26828    } else if(value === '') {
26829      return true;
26830    } else {
26831      return value;
26832    }
26833  }
26834
26835  /**
26836   * Show tabs based upon the anchor component of `window.location`.
26837   */
26838  function showTabsBasedOnAnchor() {
26839    if(BootstrapTabHistory.options.showTabsBasedOnAnchor) {
26840      var anchor = window.location && window.location.hash;
26841
26842      if(anchor) {
26843        var $tabElement = showTabForSelector(anchor);
26844
26845        if($tabElement && window.addEventListener && window.removeEventListener) {
26846          var anchorYOffset = (function ($tabElement) {
26847            var elementSetting = $tabElement.data('tab-history-anchor-y-offset');
26848
26849            if(elementSetting === undefined) {
26850              return BootstrapTabHistory.options.defaultAnchorYOffset;
26851            } else {
26852              return elementSetting;
26853            }
26854          })($tabElement);
26855
26856          // HACK: This prevents scrolling to the tab on page load. This relies on the fact that we should never get
26857          //   here on `history.forward`, `history.back`, or `location.reload`, since in all those situations the
26858          //   `history.state` object should have been used (unless the browser did not support the modern History API).
26859          if(anchorYOffset || anchorYOffset === 0) {
26860            var scrollListener = function resetAnchorScroll () {
26861              window.removeEventListener('scroll', scrollListener);
26862              window.scrollTo(0, anchorYOffset);
26863            };
26864
26865            window.addEventListener('scroll', scrollListener);
26866          }
26867        }
26868      }
26869    }
26870  }
26871
26872  /**
26873   * Show a tab which corresponds to the provided selector.
26874   *
26875   * @param {string} selector - A CSS selector.
26876   * @returns {?jQuery} - The tab which was found to show (even if said tab was already active).
26877   */
26878  function showTabForSelector(selector) {
26879    var $tabElement = (function (selector) {
26880      var $ret = null;
26881
26882      jQuery('[data-toggle="tab"], [data-toggle="pill"], [data-toggle="collapse"]').each(function () {
26883        var $potentialTab = jQuery(this);
26884
26885        if(($potentialTab.attr('href') === selector || $potentialTab.data('target') === selector ) && getTabGroup($potentialTab)) {
26886          $ret = $potentialTab;
26887          return false;
vendor: 43,417 bytes, lines 26888-28102
26888        } else {
26889         return null;
26890        }
26891      });
26892
26893      return $ret;
26894    })(selector);
26895
26896    if($tabElement) {
26897      $tabElement.trigger('click');
26898      //$tabElement.tab('show');
26899    }
26900
26901    return $tabElement;
26902  }
26903
26904  /**
26905   * Iterate through the provided set of tab tab groups, showing the tabs based on the stored selectors.
26906   *
26907   * @param {object} bootstrapTabHistory - Each of the values is passed to showTabForSelector; the keys are actually irrelevant.
26908   */
26909  function showTabsBasedOnState(bootstrapTabHistory) {
26910    showingTabsBasedOnState = true;
26911
26912    try {
26913      for(var k in bootstrapTabHistory) {
26914        if(bootstrapTabHistory.hasOwnProperty(k)) {
26915          showTabForSelector(bootstrapTabHistory[k]);
26916        }
26917      }
26918    } finally {
26919      showingTabsBasedOnState = false;
26920    }
26921  }
26922})();
26923
26924/*!
26925 * justifiedGallery - v3.8.1
26926 * http://miromannino.github.io/Justified-Gallery/
26927 * Copyright (c) 2020 Miro Mannino
26928 * Licensed under the MIT license.
26929 */
26930(function (factory) {
26931  if (typeof define === 'function' && define.amd) {
26932    // AMD. Register as an anonymous module.
26933    define(['jquery'], factory);
26934  } else if (typeof module === 'object' && module.exports) {
26935    // Node/CommonJS
26936    module.exports = function (root, jQuery) {
26937      if (jQuery === undefined) {
26938        // require('jQuery') returns a factory that requires window to
26939        // build a jQuery instance, we normalize how we use modules
26940        // that require this pattern but the window provided is a noop
26941        // if it's defined (how jquery works)
26942        if (typeof window !== 'undefined') {
26943          jQuery = require('jquery');
26944        }
26945        else {
26946          jQuery = require('jquery')(root);
26947        }
26948      }
26949      factory(jQuery);
26950      return jQuery;
26951    };
26952  } else {
26953    // Browser globals
26954    factory(jQuery);
26955  }
26956}(function ($) {
26957
26958  /**
26959   * Justified Gallery controller constructor
26960   *
26961   * @param $gallery the gallery to build
26962   * @param settings the settings (the defaults are in JustifiedGallery.defaults)
26963   * @constructor
26964   */
26965  var JustifiedGallery = function ($gallery, settings) {
26966
26967    this.settings = settings;
26968    this.checkSettings();
26969
26970    this.imgAnalyzerTimeout = null;
26971    this.entries = null;
26972    this.buildingRow = {
26973      entriesBuff: [],
26974      width: 0,
26975      height: 0,
26976      aspectRatio: 0
26977    };
26978    this.lastFetchedEntry = null;
26979    this.lastAnalyzedIndex = -1;
26980    this.yield = {
26981      every: 2, // do a flush every n flushes (must be greater than 1)
26982      flushed: 0 // flushed rows without a yield
26983    };
26984    this.border = settings.border >= 0 ? settings.border : settings.margins;
26985    this.maxRowHeight = this.retrieveMaxRowHeight();
26986    this.suffixRanges = this.retrieveSuffixRanges();
26987    this.offY = this.border;
26988    this.rows = 0;
26989    this.spinner = {
26990      phase: 0,
26991      timeSlot: 150,
26992      $el: $('<div class="jg-spinner"><span></span><span></span><span></span></div>'),
26993      intervalId: null
26994    };
26995    this.scrollBarOn = false;
26996    this.checkWidthIntervalId = null;
26997    this.galleryWidth = $gallery.width();
26998    this.$gallery = $gallery;
26999
27000  };
27001
27002  /** @returns {String} the best suffix given the width and the height */
27003  JustifiedGallery.prototype.getSuffix = function (width, height) {
27004    var longestSide, i;
27005    longestSide = (width > height) ? width : height;
27006    for (i = 0; i < this.suffixRanges.length; i++) {
27007      if (longestSide <= this.suffixRanges[i]) {
27008        return this.settings.sizeRangeSuffixes[this.suffixRanges[i]];
27009      }
27010    }
27011    return this.settings.sizeRangeSuffixes[this.suffixRanges[i - 1]];
27012  };
27013
27014  /**
27015   * Remove the suffix from the string
27016   *
27017   * @returns {string} a new string without the suffix
27018   */
27019  JustifiedGallery.prototype.removeSuffix = function (str, suffix) {
27020    return str.substring(0, str.length - suffix.length);
27021  };
27022
27023  /**
27024   * @returns {boolean} a boolean to say if the suffix is contained in the str or not
27025   */
27026  JustifiedGallery.prototype.endsWith = function (str, suffix) {
27027    return str.indexOf(suffix, str.length - suffix.length) !== -1;
27028  };
27029
27030  /**
27031   * Get the used suffix of a particular url
27032   *
27033   * @param str
27034   * @returns {String} return the used suffix
27035   */
27036  JustifiedGallery.prototype.getUsedSuffix = function (str) {
27037    for (var si in this.settings.sizeRangeSuffixes) {
27038      if (this.settings.sizeRangeSuffixes.hasOwnProperty(si)) {
27039        if (this.settings.sizeRangeSuffixes[si].length === 0) continue;
27040        if (this.endsWith(str, this.settings.sizeRangeSuffixes[si])) return this.settings.sizeRangeSuffixes[si];
27041      }
27042    }
27043    return '';
27044  };
27045
27046  /**
27047   * Given an image src, with the width and the height, returns the new image src with the
27048   * best suffix to show the best quality thumbnail.
27049   *
27050   * @returns {String} the suffix to use
27051   */
27052  JustifiedGallery.prototype.newSrc = function (imageSrc, imgWidth, imgHeight, image) {
27053    var newImageSrc;
27054
27055    if (this.settings.thumbnailPath) {
27056      newImageSrc = this.settings.thumbnailPath(imageSrc, imgWidth, imgHeight, image);
27057    } else {
27058      var matchRes = imageSrc.match(this.settings.extension);
27059      var ext = (matchRes !== null) ? matchRes[0] : '';
27060      newImageSrc = imageSrc.replace(this.settings.extension, '');
27061      newImageSrc = this.removeSuffix(newImageSrc, this.getUsedSuffix(newImageSrc));
27062      newImageSrc += this.getSuffix(imgWidth, imgHeight) + ext;
27063    }
27064
27065    return newImageSrc;
27066  };
27067
27068  /**
27069   * Shows the images that is in the given entry
27070   *
27071   * @param $entry the entry
27072   * @param callback the callback that is called when the show animation is finished
27073   */
27074  JustifiedGallery.prototype.showImg = function ($entry, callback) {
27075    if (this.settings.cssAnimation) {
27076      $entry.addClass('jg-entry-visible');
27077      if (callback) callback();
27078    } else {
27079      $entry.stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback);
27080      $entry.find(this.settings.imgSelector).stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback);
27081    }
27082  };
27083
27084  /**
27085   * Extract the image src form the image, looking from the 'safe-src', and if it can't be found, from the
27086   * 'src' attribute. It saves in the image data the 'jg.originalSrc' field, with the extracted src.
27087   *
27088   * @param $image the image to analyze
27089   * @returns {String} the extracted src
27090   */
27091  JustifiedGallery.prototype.extractImgSrcFromImage = function ($image) {
27092    var imageSrc = $image.data('safe-src');
27093    var imageSrcLoc = 'data-safe-src';
27094    // Begin Uncode edit
27095    if (typeof imageSrc === 'undefined') {
27096    	var imageCurrentSrc = $image[0].currentSrc;
27097    	if (imageCurrentSrc) {
27098    		imageSrc = imageCurrentSrc;
27099    	} else {
27100    		imageSrc = $image.attr('src');
27101    	}
27102		imageSrcLoc = 'src';
27103    }
27104    // End Uncode edit
27105    $image.data('jg.originalSrc', imageSrc); // this is saved for the destroy method
27106    $image.data('jg.src', imageSrc); // this will change overtime
27107    $image.data('jg.originalSrcLoc', imageSrcLoc); // this is saved for the destroy method
27108    return imageSrc;
27109  };
27110
27111  /** @returns {jQuery} the image in the given entry */
27112  JustifiedGallery.prototype.imgFromEntry = function ($entry) {
27113    var $img = $entry.find(this.settings.imgSelector);
27114    if ($img.length === 0) $img = $entry.find('.t-entry-visual-cont img');//hacked by Uncode
27115    return $img.length === 0 ? null : $img;
27116  };
27117
27118  /** @returns {jQuery} the caption in the given entry */
27119  JustifiedGallery.prototype.captionFromEntry = function ($entry) {
27120    var $caption = $entry.find('> .jg-caption');
27121    return $caption.length === 0 ? null : $caption;
27122  };
27123
27124  /**
27125   * Display the entry
27126   *
27127   * @param {jQuery} $entry the entry to display
27128   * @param {int} x the x position where the entry must be positioned
27129   * @param y the y position where the entry must be positioned
27130   * @param imgWidth the image width
27131   * @param imgHeight the image height
27132   * @param rowHeight the row height of the row that owns the entry
27133   */
27134  JustifiedGallery.prototype.displayEntry = function ($entry, x, y, imgWidth, imgHeight, rowHeight) {
27135    $entry.width(imgWidth);
27136    $entry.height(Math.floor(rowHeight));//hacked by Uncode
27137    $entry.css('top', Math.floor(y));//hacked by Uncode
27138    $entry.css('left', x);
27139
27140    var $image = this.imgFromEntry($entry);
27141    if ($image !== null) {
27142      $image.css('width', imgWidth);
27143      $image.css('height', imgHeight);
27144      $image.css('margin-left', - imgWidth / 2);
27145      $image.css('margin-top', - imgHeight / 2);
27146
27147      // Image reloading for an high quality of thumbnails
27148      var imageSrc = $image.data('jg.src');
27149      if (imageSrc) {
27150        imageSrc = this.newSrc(imageSrc, imgWidth, imgHeight, $image[0]);
27151
27152        $image.one('error', function () {
27153           this.resetImgSrc($image); //revert to the original thumbnail
27154        });
27155
27156        var loadNewImage = function () {
27157          // if (imageSrc !== newImageSrc) {
27158            $image.attr('src', imageSrc);
27159          // }
27160        };
27161
27162        if ($entry.data('jg.loaded') === 'skipped' && imageSrc) {
27163          this.onImageEvent(imageSrc, (function() {
27164            this.showImg($entry, loadNewImage); //load the new image after the fadeIn
27165            $entry.data('jg.loaded', true);
27166          }).bind(this));
27167        } else {
27168          this.showImg($entry, loadNewImage); //load the new image after the fadeIn
27169        }
27170
27171      }
27172
27173    } else {
27174      this.showImg($entry);
27175    }
27176
27177    this.displayEntryCaption($entry);
27178  };
27179
27180  /**
27181   * Display the entry caption. If the caption element doesn't exists, it creates the caption using the 'alt'
27182   * or the 'title' attributes.
27183   *
27184   * @param {jQuery} $entry the entry to process
27185   */
27186  JustifiedGallery.prototype.displayEntryCaption = function ($entry) {
27187    var $image = this.imgFromEntry($entry);
27188    if ($image !== null && this.settings.captions) {
27189      var $imgCaption = this.captionFromEntry($entry);
27190
27191      // Create it if it doesn't exists
27192      if ($imgCaption === null) {
27193        var caption = $image.attr('alt');
27194        if (!this.isValidCaption(caption)) caption = $entry.attr('title');
27195        if (this.isValidCaption(caption)) { // Create only we found something
27196          $imgCaption = $('<div class="jg-caption">' + caption + '</div>');
27197          $entry.append($imgCaption);
27198          $entry.data('jg.createdCaption', true);
27199        }
27200      }
27201
27202      // Create events (we check again the $imgCaption because it can be still inexistent)
27203      if ($imgCaption !== null) {
27204        if (!this.settings.cssAnimation) $imgCaption.stop().fadeTo(0, this.settings.captionSettings.nonVisibleOpacity);
27205        this.addCaptionEventsHandlers($entry);
27206      }
27207    } else {
27208      this.removeCaptionEventsHandlers($entry);
27209    }
27210  };
27211
27212  /**
27213   * Validates the caption
27214   *
27215   * @param caption The caption that should be validated
27216   * @return {boolean} Validation result
27217   */
27218  JustifiedGallery.prototype.isValidCaption = function (caption) {
27219    return (typeof caption !== 'undefined' && caption.length > 0);
27220  };
27221
27222  /**
27223   * The callback for the event 'mouseenter'. It assumes that the event currentTarget is an entry.
27224   * It shows the caption using jQuery (or using CSS if it is configured so)
27225   *
27226   * @param {Event} eventObject the event object
27227   */
27228  JustifiedGallery.prototype.onEntryMouseEnterForCaption = function (eventObject) {
27229    var $caption = this.captionFromEntry($(eventObject.currentTarget));
27230    if (this.settings.cssAnimation) {
27231      $caption.addClass('jg-caption-visible').removeClass('jg-caption-hidden');
27232    } else {
27233      $caption.stop().fadeTo(this.settings.captionSettings.animationDuration,
27234        this.settings.captionSettings.visibleOpacity);
27235    }
27236  };
27237
27238  /**
27239   * The callback for the event 'mouseleave'. It assumes that the event currentTarget is an entry.
27240   * It hides the caption using jQuery (or using CSS if it is configured so)
27241   *
27242   * @param {Event} eventObject the event object
27243   */
27244  JustifiedGallery.prototype.onEntryMouseLeaveForCaption = function (eventObject) {
27245    var $caption = this.captionFromEntry($(eventObject.currentTarget));
27246    if (this.settings.cssAnimation) {
27247      $caption.removeClass('jg-caption-visible').removeClass('jg-caption-hidden');
27248    } else {
27249      $caption.stop().fadeTo(this.settings.captionSettings.animationDuration,
27250        this.settings.captionSettings.nonVisibleOpacity);
27251    }
27252  };
27253
27254  /**
27255   * Add the handlers of the entry for the caption
27256   *
27257   * @param $entry the entry to modify
27258   */
27259  JustifiedGallery.prototype.addCaptionEventsHandlers = function ($entry) {
27260    var captionMouseEvents = $entry.data('jg.captionMouseEvents');
27261    if (typeof captionMouseEvents === 'undefined') {
27262      captionMouseEvents = {
27263        mouseenter: $.proxy(this.onEntryMouseEnterForCaption, this),
27264        mouseleave: $.proxy(this.onEntryMouseLeaveForCaption, this)
27265      };
27266      $entry.on('mouseenter', undefined, undefined, captionMouseEvents.mouseenter);
27267      $entry.on('mouseleave', undefined, undefined, captionMouseEvents.mouseleave);
27268      $entry.data('jg.captionMouseEvents', captionMouseEvents);
27269    }
27270  };
27271
27272  /**
27273   * Remove the handlers of the entry for the caption
27274   *
27275   * @param $entry the entry to modify
27276   */
27277  JustifiedGallery.prototype.removeCaptionEventsHandlers = function ($entry) {
27278    var captionMouseEvents = $entry.data('jg.captionMouseEvents');
27279    if (typeof captionMouseEvents !== 'undefined') {
27280      $entry.off('mouseenter', undefined, captionMouseEvents.mouseenter);
27281      $entry.off('mouseleave', undefined, captionMouseEvents.mouseleave);
27282      $entry.removeData('jg.captionMouseEvents');
27283    }
27284  };
27285
27286  /**
27287   * Clear the building row data to be used for a new row
27288   */
27289  JustifiedGallery.prototype.clearBuildingRow = function () {
27290    this.buildingRow.entriesBuff = [];
27291    this.buildingRow.aspectRatio = 0;
27292    this.buildingRow.width = 0;
27293  };
27294
27295  /**
27296   * Justify the building row, preparing it to
27297   *
27298   * @param isLastRow
27299   * @param hiddenRow undefined or false for normal behavior. hiddenRow = true to hide the row.
27300   * @returns a boolean to know if the row has been justified or not
27301   */
27302  JustifiedGallery.prototype.prepareBuildingRow = function (isLastRow, hiddenRow) {
27303    var i, $entry, imgAspectRatio, newImgW, newImgH, justify = true;
27304    var minHeight = 0;
27305    var availableWidth = this.galleryWidth - 2 * this.border - (
27306      (this.buildingRow.entriesBuff.length - 1) * this.settings.margins);
27307    var rowHeight = Math.floor( availableWidth / this.buildingRow.aspectRatio );//hacked by Uncode
27308    var defaultRowHeight = this.settings.rowHeight;
27309    var justifiable = this.buildingRow.width / availableWidth > this.settings.justifyThreshold;
27310
27311    //Skip the last row if we can't justify it and the lastRow == 'hide'
27312    if (hiddenRow || (isLastRow && this.settings.lastRow === 'hide' && !justifiable)) {
27313      for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
27314        $entry = this.buildingRow.entriesBuff[i];
27315        if (this.settings.cssAnimation)
27316          $entry.removeClass('jg-entry-visible');
27317        else {
27318          $entry.stop().fadeTo(0, 0.1);
27319          $entry.find('> img, > a > img').fadeTo(0, 0);
27320        }
27321      }
27322      return -1;
27323    }
27324
27325    // With lastRow = nojustify, justify if is justificable (the images will not become too big)
27326    if (isLastRow && !justifiable && this.settings.lastRow !== 'justify' && this.settings.lastRow !== 'hide') {
27327      justify = false;
27328
27329      if (this.rows > 0) {
27330        defaultRowHeight = (this.offY - this.border - this.settings.margins * this.rows) / this.rows;
27331        justify = defaultRowHeight * this.buildingRow.aspectRatio / availableWidth > this.settings.justifyThreshold;
27332      }
27333    }
27334
27335    for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
27336      $entry = this.buildingRow.entriesBuff[i];
27337      imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height');
27338
27339      if (justify) {
27340        newImgW = (i === this.buildingRow.entriesBuff.length - 1) ? availableWidth : rowHeight * imgAspectRatio;
27341        newImgH = rowHeight;
27342      } else {
27343        newImgW = defaultRowHeight * imgAspectRatio;
27344        newImgH = defaultRowHeight;
27345      }
27346
27347      availableWidth -= Math.round(newImgW);
27348      $entry.data('jg.jwidth', Math.round(newImgW));
27349      $entry.data('jg.jheight', Math.ceil(newImgH));
27350      if (i === 0 || minHeight > newImgH) minHeight = newImgH;
27351    }
27352
27353    this.buildingRow.height = minHeight;
27354    return justify;
27355  };
27356
27357  /**
27358   * Flush a row: justify it, modify the gallery height accordingly to the row height
27359   *
27360   * @param isLastRow
27361   * @param hiddenRow undefined or false for normal behavior. hiddenRow = true to hide the row.
27362   */
27363  JustifiedGallery.prototype.flushRow = function (isLastRow, hiddenRow) {
27364    var settings = this.settings;
27365    var $entry, buildingRowRes, offX = this.border, i;
27366
27367    buildingRowRes = this.prepareBuildingRow(isLastRow, hiddenRow);
27368    if (hiddenRow || (isLastRow && settings.lastRow === 'hide' && buildingRowRes === -1)) {
27369      this.clearBuildingRow();
27370      return;
27371    }
27372
27373    if (this.maxRowHeight) {
27374      if (this.maxRowHeight < this.buildingRow.height) this.buildingRow.height = this.maxRowHeight;
27375    }
27376
27377    //Align last (unjustified) row
27378    if (isLastRow && (settings.lastRow === 'center' || settings.lastRow === 'right')) {
27379      var availableWidth = this.galleryWidth - 2 * this.border - (this.buildingRow.entriesBuff.length - 1) * settings.margins;
27380
27381      for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
27382        $entry = this.buildingRow.entriesBuff[i];
27383        availableWidth -= $entry.data('jg.jwidth');
27384      }
27385
27386      if (settings.lastRow === 'center')
27387        offX += Math.round(availableWidth / 2);
27388      else if (settings.lastRow === 'right')
27389        offX += availableWidth;
27390    }
27391
27392    var lastEntryIdx = this.buildingRow.entriesBuff.length - 1;
27393    for (i = 0; i <= lastEntryIdx; i++) {
27394      $entry = this.buildingRow.entriesBuff[this.settings.rtl ? lastEntryIdx - i : i];
27395      this.displayEntry($entry, offX, this.offY, $entry.data('jg.jwidth'), $entry.data('jg.jheight'), this.buildingRow.height);
27396      offX += $entry.data('jg.jwidth') + settings.margins;
27397    }
27398
27399    //Gallery Height
27400    this.galleryHeightToSet = this.offY + this.buildingRow.height + this.border;
27401    this.setGalleryTempHeight(this.galleryHeightToSet + this.getSpinnerHeight());
27402
27403    if (!isLastRow || (this.buildingRow.height <= settings.rowHeight && buildingRowRes)) {
27404      //Ready for a new row
27405      this.offY += this.buildingRow.height + settings.margins;
27406      this.rows += 1;
27407      this.clearBuildingRow();
27408      this.settings.triggerEvent.call(this, 'jg.rowflush');
27409    }
27410  };
27411
27412
27413  // Scroll position not restoring: https://github.com/miromannino/Justified-Gallery/issues/221
27414  var galleryPrevStaticHeight = 0;
27415
27416  JustifiedGallery.prototype.rememberGalleryHeight = function () {
27417    galleryPrevStaticHeight = this.$gallery.height();
27418    this.$gallery.height(galleryPrevStaticHeight);
27419  };
27420
27421  // grow only
27422  JustifiedGallery.prototype.setGalleryTempHeight = function (height) {
27423    galleryPrevStaticHeight = Math.max(height, galleryPrevStaticHeight);
27424    this.$gallery.height(galleryPrevStaticHeight);
27425  };
27426
27427  JustifiedGallery.prototype.setGalleryFinalHeight = function (height) {
27428    galleryPrevStaticHeight = height;
27429    this.$gallery.height(height);
27430  };
27431
27432  /**
27433   * Checks the width of the gallery container, to know if a new justification is needed
27434   */
27435  JustifiedGallery.prototype.checkWidth = function () {
27436    this.checkWidthIntervalId = setInterval($.proxy(function () {
27437
27438      // if the gallery is not currently visible, abort.
27439      if (!this.$gallery.is(":visible")) return;
27440
27441      var galleryWidth = parseFloat(this.$gallery.width());
27442      if (Math.abs(galleryWidth - this.galleryWidth) > this.settings.refreshSensitivity) {
27443        this.galleryWidth = galleryWidth;
27444        this.rewind();
27445
27446        this.rememberGalleryHeight();
27447
27448        // Restart to analyze
27449        this.startImgAnalyzer(true);
27450      }
27451    }, this), this.settings.refreshTime);
27452  };
27453
27454  /**
27455   * @returns {boolean} a boolean saying if the spinner is active or not
27456   */
27457  JustifiedGallery.prototype.isSpinnerActive = function () {
27458    return this.spinner.intervalId !== null;
27459  };
27460
27461  /**
27462   * @returns {int} the spinner height
27463   */
27464  JustifiedGallery.prototype.getSpinnerHeight = function () {
27465    return this.spinner.$el.innerHeight();
27466  };
27467
27468  /**
27469   * Stops the spinner animation and modify the gallery height to exclude the spinner
27470   */
27471  JustifiedGallery.prototype.stopLoadingSpinnerAnimation = function () {
27472    clearInterval(this.spinner.intervalId);
27473    this.spinner.intervalId = null;
27474    this.setGalleryTempHeight(this.$gallery.height() - this.getSpinnerHeight());
27475    this.spinner.$el.detach();
27476  };
27477
27478  /**
27479   * Starts the spinner animation
27480   */
27481  JustifiedGallery.prototype.startLoadingSpinnerAnimation = function () {
27482    var spinnerContext = this.spinner;
27483    var $spinnerPoints = spinnerContext.$el.find('span');
27484    clearInterval(spinnerContext.intervalId);
27485    this.$gallery.append(spinnerContext.$el);
27486    this.setGalleryTempHeight(this.offY + this.buildingRow.height + this.getSpinnerHeight());
27487    spinnerContext.intervalId = setInterval(function () {
27488      if (spinnerContext.phase < $spinnerPoints.length) {
27489        $spinnerPoints.eq(spinnerContext.phase).fadeTo(spinnerContext.timeSlot, 1);
27490      } else {
27491        $spinnerPoints.eq(spinnerContext.phase - $spinnerPoints.length).fadeTo(spinnerContext.timeSlot, 0);
27492      }
27493      spinnerContext.phase = (spinnerContext.phase + 1) % ($spinnerPoints.length * 2);
27494    }, spinnerContext.timeSlot);
27495  };
27496
27497  /**
27498   * Rewind the image analysis to start from the first entry.
27499   */
27500  JustifiedGallery.prototype.rewind = function () {
27501    this.lastFetchedEntry = null;
27502    this.lastAnalyzedIndex = -1;
27503    this.offY = this.border;
27504    this.rows = 0;
27505    this.clearBuildingRow();
27506  };
27507
27508  /**
27509   * @returns {String} `settings.selector` rejecting spinner element
27510   */
27511  JustifiedGallery.prototype.getSelectorWithoutSpinner = function () {
27512    return this.settings.selector + ', div:not(.jg-spinner)';
27513  };
27514
27515  /**
27516   * @returns {Array} all entries matched by `settings.selector`
27517   */
27518  JustifiedGallery.prototype.getAllEntries = function () {
27519    var selector = this.getSelectorWithoutSpinner();
27520    return this.$gallery.children(selector).toArray();
27521  };
27522
27523  /**
27524   * Update the entries searching it from the justified gallery HTML element
27525   *
27526   * @param norewind if norewind only the new entries will be changed (i.e. randomized, sorted or filtered)
27527   * @returns {boolean} true if some entries has been founded
27528   */
27529  JustifiedGallery.prototype.updateEntries = function (norewind) {
27530    var newEntries;
27531
27532    if (norewind && this.lastFetchedEntry != null) {
27533      var selector = this.getSelectorWithoutSpinner();
27534      newEntries = $(this.lastFetchedEntry).nextAll(selector).toArray();
27535    } else {
27536      this.entries = [];
27537      newEntries = this.getAllEntries();
27538    }
27539
27540    if (newEntries.length > 0) {
27541
27542      // Sort or randomize
27543      if ($.isFunction(this.settings.sort)) {
27544        newEntries = this.sortArray(newEntries);
27545      } else if (this.settings.randomize) {
27546        newEntries = this.shuffleArray(newEntries);
27547      }
27548      this.lastFetchedEntry = newEntries[newEntries.length - 1];
27549
27550      // Filter
27551      if (this.settings.filter) {
27552        newEntries = this.filterArray(newEntries);
27553      } else {
27554        this.resetFilters(newEntries);
27555      }
27556
27557    }
27558
27559    this.entries = this.entries.concat(newEntries);
27560    return true;
27561  };
27562
27563  /**
27564   * Apply the entries order to the DOM, iterating the entries and appending the images
27565   *
27566   * @param entries the entries that has been modified and that must be re-ordered in the DOM
27567   */
27568  JustifiedGallery.prototype.insertToGallery = function (entries) {
27569    var that = this;
27570    $.each(entries, function () {
27571      $(this).appendTo(that.$gallery);
27572    });
27573  };
27574
27575  /**
27576   * Shuffle the array using the Fisher-Yates shuffle algorithm
27577   *
27578   * @param a the array to shuffle
27579   * @return the shuffled array
27580   */
27581  JustifiedGallery.prototype.shuffleArray = function (a) {
27582    var i, j, temp;
27583    for (i = a.length - 1; i > 0; i--) {
27584      j = Math.floor(Math.random() * (i + 1));
27585      temp = a[i];
27586      a[i] = a[j];
27587      a[j] = temp;
27588    }
27589    this.insertToGallery(a);
27590    return a;
27591  };
27592
27593  /**
27594   * Sort the array using settings.comparator as comparator
27595   *
27596   * @param a the array to sort (it is sorted)
27597   * @return the sorted array
27598   */
27599  JustifiedGallery.prototype.sortArray = function (a) {
27600    a.sort(this.settings.sort);
27601    this.insertToGallery(a);
27602    return a;
27603  };
27604
27605  /**
27606   * Reset the filters removing the 'jg-filtered' class from all the entries
27607   *
27608   * @param a the array to reset
27609   */
27610  JustifiedGallery.prototype.resetFilters = function (a) {
27611    for (var i = 0; i < a.length; i++) $(a[i]).removeClass('jg-filtered');
27612  };
27613
27614  /**
27615   * Filter the entries considering theirs classes (if a string has been passed) or using a function for filtering.
27616   *
27617   * @param a the array to filter
27618   * @return the filtered array
27619   */
27620  JustifiedGallery.prototype.filterArray = function (a) {
27621    var settings = this.settings;
27622    if ($.type(settings.filter) === 'string') {
27623      // Filter only keeping the entries passed in the string
27624      return a.filter(function (el) {
27625        var $el = $(el);
27626        if ($el.is(settings.filter)) {
27627          $el.removeClass('jg-filtered');
27628          return true;
27629        } else {
27630          $el.addClass('jg-filtered').removeClass('jg-visible');
27631          return false;
27632        }
27633      });
27634    } else if ($.isFunction(settings.filter)) {
27635      // Filter using the passed function
27636      var filteredArr = a.filter(settings.filter);
27637      for (var i = 0; i < a.length; i++) {
27638        if (filteredArr.indexOf(a[i]) === -1) {
27639          $(a[i]).addClass('jg-filtered').removeClass('jg-visible');
27640        } else {
27641          $(a[i]).removeClass('jg-filtered');
27642        }
27643      }
27644      return filteredArr;
27645    }
27646  };
27647
27648  /**
27649   * Revert the image src to the default value.
27650   */
27651  JustifiedGallery.prototype.resetImgSrc = function ($img) {
27652    if ($img.data('jg.originalSrcLoc') === 'src') {
27653      $img.attr('src', $img.data('jg.originalSrc'));
27654    } else {
27655      $img.attr('src', '');
27656    }
27657  };
27658
27659  /**
27660   * Destroy the Justified Gallery instance.
27661   *
27662   * It clears all the css properties added in the style attributes. We doesn't backup the original
27663   * values for those css attributes, because it costs (performance) and because in general one
27664   * shouldn't use the style attribute for an uniform set of images (where we suppose the use of
27665   * classes). Creating a backup is also difficult because JG could be called multiple times and
27666   * with different style attributes.
27667   */
27668  JustifiedGallery.prototype.destroy = function () {
27669    clearInterval(this.checkWidthIntervalId);
27670    this.stopImgAnalyzerStarter();
27671
27672    // Get fresh entries list since filtered entries are absent in `this.entries`
27673    $.each(this.getAllEntries(), $.proxy(function (_, entry) {
27674      var $entry = $(entry);
27675
27676      // Reset entry style
27677      $entry.css('width', '');
27678      $entry.css('height', '');
27679      $entry.css('top', '');
27680      $entry.css('left', '');
27681      $entry.data('jg.loaded', undefined);
27682      $entry.removeClass('jg-entry jg-filtered jg-entry-visible');
27683
27684      // Reset image style
27685      var $img = this.imgFromEntry($entry);
27686      if ($img) {
27687        $img.css('width', '');
27688        $img.css('height', '');
27689        $img.css('margin-left', '');
27690        $img.css('margin-top', '');
27691        this.resetImgSrc($img);
27692        $img.data('jg.originalSrc', undefined);
27693        $img.data('jg.originalSrcLoc', undefined);
27694        $img.data('jg.src', undefined);
27695      }
27696
27697      // Remove caption
27698      this.removeCaptionEventsHandlers($entry);
27699      var $caption = this.captionFromEntry($entry);
27700      if ($entry.data('jg.createdCaption')) {
27701        // remove also the caption element (if created by jg)
27702        $entry.data('jg.createdCaption', undefined);
27703        if ($caption !== null) $caption.remove();
27704      } else {
27705        if ($caption !== null) $caption.fadeTo(0, 1);
27706      }
27707
27708    }, this));
27709
27710    this.$gallery.css('height', '');
27711    this.$gallery.removeClass('justified-gallery');
27712    this.$gallery.data('jg.controller', undefined);
27713    this.settings.triggerEvent.call(this, 'jg.destroy');
27714  };
27715
27716  /**
27717   * Analyze the images and builds the rows. It returns if it found an image that is not loaded.
27718   *
27719   * @param isForResize if the image analyzer is called for resizing or not, to call a different callback at the end
27720   */
27721  JustifiedGallery.prototype.analyzeImages = function (isForResize) {
27722    for (var i = this.lastAnalyzedIndex + 1; i < this.entries.length; i++) {
27723      var $entry = $(this.entries[i]);
27724      if ($entry.data('jg.loaded') === true || $entry.data('jg.loaded') === 'skipped') {
27725        var availableWidth = this.galleryWidth - 2 * this.border - (
27726          (this.buildingRow.entriesBuff.length - 1) * this.settings.margins);
27727        var imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height');
27728
27729        this.buildingRow.entriesBuff.push($entry);
27730        this.buildingRow.aspectRatio += imgAspectRatio;
27731        this.buildingRow.width += imgAspectRatio * this.settings.rowHeight;
27732        this.lastAnalyzedIndex = i;
27733
27734        if (availableWidth / (this.buildingRow.aspectRatio + imgAspectRatio) < this.settings.rowHeight) {
27735          this.flushRow(false, this.settings.maxRowsCount > 0 && this.rows === this.settings.maxRowsCount);
27736
27737          if (++this.yield.flushed >= this.yield.every) {
27738            this.startImgAnalyzer(isForResize);
27739            return;
27740          }
27741        }
27742      } else if ($entry.data('jg.loaded') !== 'error') {
27743        return;
27744      }
27745    }
27746
27747    // Last row flush (the row is not full)
27748    if (this.buildingRow.entriesBuff.length > 0) {
27749      this.flushRow(true, this.settings.maxRowsCount > 0 && this.rows === this.settings.maxRowsCount);
27750    }
27751
27752    if (this.isSpinnerActive()) {
27753      this.stopLoadingSpinnerAnimation();
27754    }
27755
27756    /* Stop, if there is, the timeout to start the analyzeImages.
27757     This is because an image can be set loaded, and the timeout can be set,
27758     but this image can be analyzed yet.
27759     */
27760    this.stopImgAnalyzerStarter();
27761
27762    this.setGalleryFinalHeight(this.galleryHeightToSet);
27763
27764    //On complete callback
27765    this.settings.triggerEvent.call(this, isForResize ? 'jg.resize' : 'jg.complete');
27766  };
27767
27768  /**
27769   * Stops any ImgAnalyzer starter (that has an assigned timeout)
27770   */
27771  JustifiedGallery.prototype.stopImgAnalyzerStarter = function () {
27772    this.yield.flushed = 0;
27773    if (this.imgAnalyzerTimeout !== null) {
27774      clearTimeout(this.imgAnalyzerTimeout);
27775      this.imgAnalyzerTimeout = null;
27776    }
27777  };
27778
27779  /**
27780   * Starts the image analyzer. It is not immediately called to let the browser to update the view
27781   *
27782   * @param isForResize specifies if the image analyzer must be called for resizing or not
27783   */
27784  JustifiedGallery.prototype.startImgAnalyzer = function (isForResize) {
27785    var that = this;
27786    this.stopImgAnalyzerStarter();
27787    this.imgAnalyzerTimeout = setTimeout(function () {
27788      that.analyzeImages(isForResize);
27789    }, 0.001); // we can't start it immediately due to a IE different behaviour
27790  };
27791
27792  /**
27793   * Checks if the image is loaded or not using another image object. We cannot use the 'complete' image property,
27794   * because some browsers, with a 404 set complete = true.
27795   *
27796   * @param imageSrc the image src to load
27797   * @param onLoad callback that is called when the image has been loaded
27798   * @param onError callback that is called in case of an error
27799   */
27800  JustifiedGallery.prototype.onImageEvent = function (imageSrc, onLoad, onError) {
27801    if (!onLoad && !onError) return;
27802
27803    var memImage = new Image();
27804    var $memImage = $(memImage);
27805    if (onLoad) {
27806      $memImage.one('load', function () {
27807        $memImage.off('load error');
27808        onLoad(memImage);
27809      });
27810    }
27811    if (onError) {
27812      $memImage.one('error', function () {
27813        $memImage.off('load error');
27814        onError(memImage);
27815      });
27816    }
27817    memImage.src = imageSrc;
27818  };
27819
27820  /**
27821   * Init of Justified Gallery controlled
27822   * It analyzes all the entries starting theirs loading and calling the image analyzer (that works with loaded images)
27823   */
27824  JustifiedGallery.prototype.init = function () {
27825    var imagesToLoad = false, skippedImages = false, that = this;
27826    $.each(this.entries, function (index, entry) {
27827      var $entry = $(entry);
27828      var $image = that.imgFromEntry($entry);
27829
27830      $entry.addClass('jg-entry');
27831
27832      if ($entry.data('jg.loaded') !== true && $entry.data('jg.loaded') !== 'skipped') {
27833
27834        // Link Rel global overwrite
27835        if (that.settings.rel !== null) $entry.attr('rel', that.settings.rel);
27836
27837        // Link Target global overwrite
27838        if (that.settings.target !== null) $entry.attr('target', that.settings.target);
27839
27840        if ($image !== null) {
27841
27842          // Image src
27843          var imageSrc = that.extractImgSrcFromImage($image);
27844
27845          /* If we have the height and the width, we don't wait that the image is loaded,
27846             but we start directly with the justification */
27847          if (that.settings.waitThumbnailsLoad === false || !imageSrc) {
27848            var width = parseFloat($image.attr('width'));
27849            var height = parseFloat($image.attr('height'));
27850            if ($image.prop('tagName') === 'svg') {
27851              width = parseFloat($image[0].getBBox().width);
27852              height = parseFloat($image[0].getBBox().height);
27853            }
27854            if (!isNaN(width) && !isNaN(height)) {
27855              $entry.data('jg.width', width);
27856              $entry.data('jg.height', height);
27857              $entry.data('jg.loaded', 'skipped');
27858              skippedImages = true;
27859              that.startImgAnalyzer(false);
27860              return true; // continue
27861            }
27862          }
27863
27864          $entry.data('jg.loaded', false);
27865          imagesToLoad = true;
27866
27867          // Spinner start
27868          if (!that.isSpinnerActive()) that.startLoadingSpinnerAnimation();
27869
27870          that.onImageEvent(imageSrc, function (loadImg) { // image loaded
27871            $entry.data('jg.width', loadImg.width);
27872            $entry.data('jg.height', loadImg.height);
27873            $entry.data('jg.loaded', true);
27874            that.startImgAnalyzer(false);
27875          }, function () { // image load error
27876            $entry.data('jg.loaded', 'error');
27877            that.startImgAnalyzer(false);
27878          });
27879
27880        } else {
27881          $entry.data('jg.loaded', true);
27882          $entry.data('jg.width', $entry.width() | parseFloat($entry.css('width')) | 1);
27883          $entry.data('jg.height', $entry.height() | parseFloat($entry.css('height')) | 1);
27884        }
27885
27886      }
27887
27888    });
27889
27890    if (!imagesToLoad && !skippedImages) this.startImgAnalyzer(false);
27891    this.checkWidth();
27892  };
27893
27894  /**
27895   * Checks that it is a valid number. If a string is passed it is converted to a number
27896   *
27897   * @param settingContainer the object that contains the setting (to allow the conversion)
27898   * @param settingName the setting name
27899   */
27900  JustifiedGallery.prototype.checkOrConvertNumber = function (settingContainer, settingName) {
27901    if ($.type(settingContainer[settingName]) === 'string') {
27902      settingContainer[settingName] = parseFloat(settingContainer[settingName]);
27903    }
27904
27905    if ($.type(settingContainer[settingName]) === 'number') {
27906      if (isNaN(settingContainer[settingName])) throw 'invalid number for ' + settingName;
27907    } else {
27908      throw settingName + ' must be a number';
27909    }
27910  };
27911
27912  /**
27913   * Checks the sizeRangeSuffixes and, if necessary, converts
27914   * its keys from string (e.g. old settings with 'lt100') to int.
27915   */
27916  JustifiedGallery.prototype.checkSizeRangesSuffixes = function () {
27917    if ($.type(this.settings.sizeRangeSuffixes) !== 'object') {
27918      throw 'sizeRangeSuffixes must be defined and must be an object';
27919    }
27920
27921    var suffixRanges = [];
27922    for (var rangeIdx in this.settings.sizeRangeSuffixes) {
27923      if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(rangeIdx);
27924    }
27925
27926    var newSizeRngSuffixes = { 0: '' };
27927    for (var i = 0; i < suffixRanges.length; i++) {
27928      if ($.type(suffixRanges[i]) === 'string') {
27929        try {
27930          var numIdx = parseInt(suffixRanges[i].replace(/^[a-z]+/, ''), 10);
27931          newSizeRngSuffixes[numIdx] = this.settings.sizeRangeSuffixes[suffixRanges[i]];
27932        } catch (e) {
27933          throw 'sizeRangeSuffixes keys must contains correct numbers (' + e + ')';
27934        }
27935      } else {
27936        newSizeRngSuffixes[suffixRanges[i]] = this.settings.sizeRangeSuffixes[suffixRanges[i]];
27937      }
27938    }
27939
27940    this.settings.sizeRangeSuffixes = newSizeRngSuffixes;
27941  };
27942
27943  /**
27944   * check and convert the maxRowHeight setting
27945   * requires rowHeight to be already set
27946   * TODO: should be always called when only rowHeight is changed
27947   * @return number or null
27948   */
27949  JustifiedGallery.prototype.retrieveMaxRowHeight = function () {
27950    var newMaxRowHeight = null;
27951    var rowHeight = this.settings.rowHeight;
27952
27953    if ($.type(this.settings.maxRowHeight) === 'string') {
27954      if (this.settings.maxRowHeight.match(/^[0-9]+%$/)) {
27955        newMaxRowHeight = rowHeight * parseFloat(this.settings.maxRowHeight.match(/^([0-9]+)%$/)[1]) / 100;
27956      } else {
27957        newMaxRowHeight = parseFloat(this.settings.maxRowHeight);
27958      }
27959    } else if ($.type(this.settings.maxRowHeight) === 'number') {
27960      newMaxRowHeight = this.settings.maxRowHeight;
27961    } else if (this.settings.maxRowHeight === false || this.settings.maxRowHeight == null) {
27962      return null;
27963    } else {
27964      throw 'maxRowHeight must be a number or a percentage';
27965    }
27966
27967    // check if the converted value is not a number
27968    if (isNaN(newMaxRowHeight)) throw 'invalid number for maxRowHeight';
27969
27970    // check values, maxRowHeight must be >= rowHeight
27971    if (newMaxRowHeight < rowHeight) newMaxRowHeight = rowHeight;
27972
27973    return newMaxRowHeight;
27974  };
27975
27976  /**
27977   * Checks the settings
27978   */
27979  JustifiedGallery.prototype.checkSettings = function () {
27980    this.checkSizeRangesSuffixes();
27981
27982    this.checkOrConvertNumber(this.settings, 'rowHeight');
27983    this.checkOrConvertNumber(this.settings, 'margins');
27984    this.checkOrConvertNumber(this.settings, 'border');
27985    this.checkOrConvertNumber(this.settings, 'maxRowsCount');
27986
27987    var lastRowModes = [
27988      'justify',
27989      'nojustify',
27990      'left',
27991      'center',
27992      'right',
27993      'hide'
27994    ];
27995    if (lastRowModes.indexOf(this.settings.lastRow) === -1) {
27996      throw 'lastRow must be one of: ' + lastRowModes.join(', ');
27997    }
27998
27999    this.checkOrConvertNumber(this.settings, 'justifyThreshold');
28000    if (this.settings.justifyThreshold < 0 || this.settings.justifyThreshold > 1) {
28001      throw 'justifyThreshold must be in the interval [0,1]';
28002    }
28003    if ($.type(this.settings.cssAnimation) !== 'boolean') {
28004      throw 'cssAnimation must be a boolean';
28005    }
28006
28007    if ($.type(this.settings.captions) !== 'boolean') throw 'captions must be a boolean';
28008    this.checkOrConvertNumber(this.settings.captionSettings, 'animationDuration');
28009
28010    this.checkOrConvertNumber(this.settings.captionSettings, 'visibleOpacity');
28011    if (this.settings.captionSettings.visibleOpacity < 0 ||
28012      this.settings.captionSettings.visibleOpacity > 1) {
28013      throw 'captionSettings.visibleOpacity must be in the interval [0, 1]';
28014    }
28015
28016    this.checkOrConvertNumber(this.settings.captionSettings, 'nonVisibleOpacity');
28017    if (this.settings.captionSettings.nonVisibleOpacity < 0 ||
28018      this.settings.captionSettings.nonVisibleOpacity > 1) {
28019      throw 'captionSettings.nonVisibleOpacity must be in the interval [0, 1]';
28020    }
28021
28022    this.checkOrConvertNumber(this.settings, 'imagesAnimationDuration');
28023    this.checkOrConvertNumber(this.settings, 'refreshTime');
28024    this.checkOrConvertNumber(this.settings, 'refreshSensitivity');
28025    if ($.type(this.settings.randomize) !== 'boolean') throw 'randomize must be a boolean';
28026    if ($.type(this.settings.selector) !== 'string') throw 'selector must be a string';
28027
28028    if (this.settings.sort !== false && !$.isFunction(this.settings.sort)) {
28029      throw 'sort must be false or a comparison function';
28030    }
28031
28032    if (this.settings.filter !== false && !$.isFunction(this.settings.filter) &&
28033      $.type(this.settings.filter) !== 'string') {
28034      throw 'filter must be false, a string or a filter function';
28035    }
28036  };
28037
28038  /**
28039   * It brings all the indexes from the sizeRangeSuffixes and it orders them. They are then sorted and returned.
28040   * @returns {Array} sorted suffix ranges
28041   */
28042  JustifiedGallery.prototype.retrieveSuffixRanges = function () {
28043    var suffixRanges = [];
28044    for (var rangeIdx in this.settings.sizeRangeSuffixes) {
28045      if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(parseInt(rangeIdx, 10));
28046    }
28047    suffixRanges.sort(function (a, b) { return a > b ? 1 : a < b ? -1 : 0; });
28048    return suffixRanges;
28049  };
28050
28051  /**
28052   * Update the existing settings only changing some of them
28053   *
28054   * @param newSettings the new settings (or a subgroup of them)
28055   */
28056  JustifiedGallery.prototype.updateSettings = function (newSettings) {
28057    // In this case Justified Gallery has been called again changing only some options
28058    this.settings = $.extend({}, this.settings, newSettings);
28059    this.checkSettings();
28060
28061    // As reported in the settings: negative value = same as margins, 0 = disabled
28062    this.border = this.settings.border >= 0 ? this.settings.border : this.settings.margins;
28063
28064    this.maxRowHeight = this.retrieveMaxRowHeight();
28065    this.suffixRanges = this.retrieveSuffixRanges();
28066  };
28067
28068  JustifiedGallery.prototype.defaults = {
28069    sizeRangeSuffixes: {}, /* e.g. Flickr configuration
28070        {
28071          100: '_t',  // used when longest is less than 100px
28072          240: '_m',  // used when longest is between 101px and 240px
28073          320: '_n',  // ...
28074          500: '',
28075          640: '_z',
28076          1024: '_b'  // used as else case because it is the last
28077        }
28078    */
28079    thumbnailPath: undefined, /* If defined, sizeRangeSuffixes is not used, and this function is used to determine the
28080    path relative to a specific thumbnail size. The function should accept respectively three arguments:
28081    current path, width and height */
28082    rowHeight: 120, // required? required to be > 0?
28083    maxRowHeight: false, // false or negative value to deactivate. Positive number to express the value in pixels,
28084    // A string '[0-9]+%' to express in percentage (e.g. 300% means that the row height
28085    // can't exceed 3 * rowHeight)
28086    maxRowsCount: 0, // maximum number of rows to be displayed (0 = disabled)
28087    margins: 1,
28088    border: -1, // negative value = same as margins, 0 = disabled, any other value to set the border
28089
28090    lastRow: 'nojustify', // … which is the same as 'left', or can be 'justify', 'center', 'right' or 'hide'
28091
28092    justifyThreshold: 0.90, /* if row width / available space > 0.90 it will be always justified
28093                             * (i.e. lastRow setting is not considered) */
28094    waitThumbnailsLoad: true,
28095    captions: true,
28096    cssAnimation: true,
28097    imagesAnimationDuration: 500, // ignored with css animations
28098    captionSettings: { // ignored with css animations
28099      animationDuration: 500,
28100      visibleOpacity: 0.7,
28101      nonVisibleOpacity: 0.0
28102    },
28103    rel: null, // rewrite the rel of each analyzed links
28104    target: null, // rewrite the target of all links
28105    extension: /\.[^.\\/]+$/, // regexp to capture the extension of an image
28106    refreshTime: 200, // time interval (in ms) to check if the page changes its width
28107    refreshSensitivity: 0, // change in width allowed (in px) without re-building the gallery
28108    randomize: false,
28109    rtl: false, // right-to-left mode
28110    sort: false, /*
28111      - false: to do not sort
28112      - function: to sort them using the function as comparator (see Array.prototype.sort())
28113    */
28114    filter: false, /*
28115      - false, null or undefined: for a disabled filter
28116      - a string: an entry is kept if entry.is(filter string) returns true
28117                  see jQuery's .is() function for further information
28118      - a function: invoked with arguments (entry, index, array). Return true to keep the entry, false otherwise.
28119                    It follows the specifications of the Array.prototype.filter() function of JavaScript.
28120    */
28121    selector: 'a', // The selector that is used to know what are the entries of the gallery
28122    imgSelector: '> img, > a > img, > svg, > a > svg', // The selector that is used to know what are the images of each entry
28123    triggerEvent: function (event) { // This is called to trigger events, the default behavior is to call $.trigger
28124      this.$gallery.trigger(event);  // Consider that 'this' is this set to the JustifiedGallery object, so it can
28125    }                                // access to fields such as $gallery, useful to trigger events with jQuery.
28126  };
28127
28128
28129  /**
28130   * Justified Gallery plugin for jQuery
28131   *
28132   * Events
28133   *  - jg.complete : called when all the gallery has been created
28134   *  - jg.resize : called when the gallery has been resized
28135   *  - jg.rowflush : when a new row appears
28136   *
28137   * @param arg the action (or the settings) passed when the plugin is called
28138   * @returns {*} the object itself
28139   */
28140  $.fn.justifiedGallery = function (arg) {
28141    return this.each(function (index, gallery) {
28142
28143      var $gallery = $(gallery);
28144      $gallery.addClass('justified-gallery');
28145
28146      var controller = $gallery.data('jg.controller');
28147      if (typeof controller === 'undefined') {
28148        // Create controller and assign it to the object data
28149        if (typeof arg !== 'undefined' && arg !== null && $.type(arg) !== 'object') {
28150          if (arg === 'destroy') return; // Just a call to an unexisting object
28151          throw 'The argument must be an object';
28152        }
28153        controller = new JustifiedGallery($gallery, $.extend({}, JustifiedGallery.prototype.defaults, arg));
28154        $gallery.data('jg.controller', controller);
28155      } else if (arg === 'norewind') {
28156        // In this case we don't rewind: we analyze only the latest images (e.g. to complete the last unfinished row
28157        // ... left to be more readable
28158      } else if (arg === 'destroy') {
28159        controller.destroy();
28160        return;
28161      } else {
28162        // In this case Justified Gallery has been called again changing only some options
28163        controller.updateSettings(arg);
28164        controller.rewind();
28165      }
28166
28167      // Update the entries list
28168      if (!controller.updateEntries(arg === 'norewind')) return;
28169
28170      // Init justified gallery
28171      controller.init();
28172
28173    });
28174  };
28175
28176}));
28177
28178/*!
28179* Customized version of iScroll.js 0.0.1
28180* It fixes bugs affecting its integration with fullpage.js
28181*/
28182/*! iScroll v5.2.0 ~ (c) 2008-2016 Matteo Spinelli ~ http://cubiq.org/license */
28183(function (window, document, Math) {
28184var rAF = window.requestAnimationFrame  ||
28185    window.webkitRequestAnimationFrame  ||
28186    window.mozRequestAnimationFrame     ||
28187    window.oRequestAnimationFrame       ||
28188    window.msRequestAnimationFrame      ||
28189    function (callback) { window.setTimeout(callback, 1000 / 60); };
28190
28191var utils = (function () {
28192    var me = {};
28193
28194    var _elementStyle = document.createElement('div').style;
28195    var _vendor = (function () {
28196        var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'],
28197            transform,
28198            i = 0,
28199            l = vendors.length;
28200
28201        for ( ; i < l; i++ ) {
28202            transform = vendors[i] + 'ransform';
28203            if ( transform in _elementStyle ) return vendors[i].substr(0, vendors[i].length-1);
28204        }
28205
28206        return false;
vendor: 5,154 bytes, lines 28207-28359
28207    })();
28208
28209    function _prefixStyle (style) {
28210        if ( _vendor === false ) return false;
28211        if ( _vendor === '' ) return style;
28212        return _vendor + style.charAt(0).toUpperCase() + style.substr(1);
28213    }
28214
28215    me.getTime = Date.now || function getTime () { return new Date().getTime(); };
28216
28217    me.extend = function (target, obj) {
28218        for ( var i in obj ) {
28219            target[i] = obj[i];
28220        }
28221    };
28222
28223    me.addEvent = function (el, type, fn, capture) {
28224        el.addEventListener(type, fn, !!capture);
28225    };
28226
28227    me.removeEvent = function (el, type, fn, capture) {
28228        el.removeEventListener(type, fn, !!capture);
28229    };
28230
28231    me.prefixPointerEvent = function (pointerEvent) {
28232        return window.MSPointerEvent ?
28233            'MSPointer' + pointerEvent.charAt(7).toUpperCase() + pointerEvent.substr(8):
28234            pointerEvent;
28235    };
28236
28237    me.momentum = function (current, start, time, lowerMargin, wrapperSize, deceleration) {
28238        var distance = current - start,
28239            speed = Math.abs(distance) / time,
28240            destination,
28241            duration;
28242
28243        deceleration = deceleration === undefined ? 0.0006 : deceleration;
28244
28245        destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 );
28246        duration = speed / deceleration;
28247
28248        if ( destination < lowerMargin ) {
28249            destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin;
28250            distance = Math.abs(destination - current);
28251            duration = distance / speed;
28252        } else if ( destination > 0 ) {
28253            destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0;
28254            distance = Math.abs(current) + destination;
28255            duration = distance / speed;
28256        }
28257
28258        return {
28259            destination: Math.round(destination),
28260            duration: duration
28261        };
28262    };
28263
28264    var _transform = _prefixStyle('transform');
28265
28266    me.extend(me, {
28267        hasTransform: _transform !== false,
28268        hasPerspective: _prefixStyle('perspective') in _elementStyle,
28269        hasTouch: 'ontouchstart' in window,
28270        hasPointer: !!(window.PointerEvent || window.MSPointerEvent), // IE10 is prefixed
28271        hasTransition: _prefixStyle('transition') in _elementStyle
28272    });
28273
28274    /*
28275    This should find all Android browsers lower than build 535.19 (both stock browser and webview)
28276    - galaxy S2 is ok
28277    - 2.3.6 : `AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1`
28278    - 4.0.4 : `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
28279   - galaxy S3 is badAndroid (stock brower, webview)
28280     `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
28281   - galaxy S4 is badAndroid (stock brower, webview)
28282     `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
28283   - galaxy S5 is OK
28284     `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`
28285   - galaxy S6 is OK
28286     `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`
28287  */
28288    me.isBadAndroid = (function() {
28289        var appVersion = window.navigator.appVersion;
28290        // Android browser is not a chrome browser.
28291        if (/Android/.test(appVersion) && !(/Chrome\/\d/.test(appVersion))) {
28292            var safariVersion = appVersion.match(/Safari\/(\d+.\d)/);
28293            if(safariVersion && typeof safariVersion === "object" && safariVersion.length >= 2) {
28294                return parseFloat(safariVersion[1]) < 535.19;
28295            } else {
28296                return true;
28297            }
28298        } else {
28299            return false;
28300        }
28301    })();
28302
28303    me.extend(me.style = {}, {
28304        transform: _transform,
28305        transitionTimingFunction: _prefixStyle('transitionTimingFunction'),
28306        transitionDuration: _prefixStyle('transitionDuration'),
28307        transitionDelay: _prefixStyle('transitionDelay'),
28308        transformOrigin: _prefixStyle('transformOrigin')
28309    });
28310
28311    me.hasClass = function (e, c) {
28312        var re = new RegExp("(^|\\s)" + c + "(\\s|$)");
28313        return re.test(e.className);
28314    };
28315
28316    me.addClass = function (e, c) {
28317        if ( me.hasClass(e, c) ) {
28318            return;
28319        }
28320
28321        var newclass = e.className.split(' ');
28322        newclass.push(c);
28323        e.className = newclass.join(' ');
28324    };
28325
28326    me.removeClass = function (e, c) {
28327        if ( !me.hasClass(e, c) ) {
28328            return;
28329        }
28330
28331        var re = new RegExp("(^|\\s)" + c + "(\\s|$)", 'g');
28332        e.className = e.className.replace(re, ' ');
28333    };
28334
28335    me.offset = function (el) {
28336        var left = -el.offsetLeft,
28337            top = -el.offsetTop;
28338
28339        // jshint -W084
28340        while (el = el.offsetParent) {
28341            left -= el.offsetLeft;
28342            top -= el.offsetTop;
28343        }
28344        // jshint +W084
28345
28346        return {
28347            left: left,
28348            top: top
28349        };
28350    };
28351
28352    me.preventDefaultException = function (el, exceptions) {
28353        for ( var i in exceptions ) {
28354            if ( exceptions[i].test(el[i]) ) {
28355                return true;
28356            }
28357        }
28358
28359        return false;
vendor: 5,660 bytes, lines 28360-28525
28360    };
28361
28362    me.extend(me.eventType = {}, {
28363        touchstart: 1,
28364        touchmove: 1,
28365        touchend: 1,
28366
28367        mousedown: 2,
28368        mousemove: 2,
28369        mouseup: 2,
28370
28371        pointerdown: 3,
28372        pointermove: 3,
28373        pointerup: 3,
28374
28375        MSPointerDown: 3,
28376        MSPointerMove: 3,
28377        MSPointerUp: 3
28378    });
28379
28380    me.extend(me.ease = {}, {
28381        quadratic: {
28382            style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
28383            fn: function (k) {
28384                return k * ( 2 - k );
28385            }
28386        },
28387        circular: {
28388            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)
28389            fn: function (k) {
28390                return Math.sqrt( 1 - ( --k * k ) );
28391            }
28392        },
28393        back: {
28394            style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)',
28395            fn: function (k) {
28396                var b = 4;
28397                return ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1;
28398            }
28399        },
28400        bounce: {
28401            style: '',
28402            fn: function (k) {
28403                if ( ( k /= 1 ) < ( 1 / 2.75 ) ) {
28404                    return 7.5625 * k * k;
28405                } else if ( k < ( 2 / 2.75 ) ) {
28406                    return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75;
28407                } else if ( k < ( 2.5 / 2.75 ) ) {
28408                    return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375;
28409                } else {
28410                    return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375;
28411                }
28412            }
28413        },
28414        elastic: {
28415            style: '',
28416            fn: function (k) {
28417                var f = 0.22,
28418                    e = 0.4;
28419
28420                if ( k === 0 ) { return 0; }
28421                if ( k == 1 ) { return 1; }
28422
28423                return ( e * Math.pow( 2, - 10 * k ) * Math.sin( ( k - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 );
28424            }
28425        }
28426    });
28427
28428    me.tap = function (e, eventName) {
28429        var ev = document.createEvent('Event');
28430        ev.initEvent(eventName, true, true);
28431        ev.pageX = e.pageX;
28432        ev.pageY = e.pageY;
28433        e.target.dispatchEvent(ev);
28434    };
28435
28436    me.click = function (e) {
28437        var target = e.target,
28438            ev;
28439
28440        if ( !(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName) ) {
28441            // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent
28442            // initMouseEvent is deprecated.
28443            ev = document.createEvent(window.MouseEvent ? 'MouseEvents' : 'Event');
28444            ev.initEvent('click', true, true);
28445            ev.view = e.view || window;
28446            ev.detail = 1;
28447            ev.screenX = target.screenX || 0;
28448            ev.screenY = target.screenY || 0;
28449            ev.clientX = target.clientX || 0;
28450            ev.clientY = target.clientY || 0;
28451            ev.ctrlKey = !!e.ctrlKey;
28452            ev.altKey = !!e.altKey;
28453            ev.shiftKey = !!e.shiftKey;
28454            ev.metaKey = !!e.metaKey;
28455            ev.button = 0;
28456            ev.relatedTarget = null;
28457            ev._constructed = true;
28458            target.dispatchEvent(ev);
28459        }
28460    };
28461
28462    return me;
28463})();
28464function IScroll (el, options) {
28465    this.wrapper = typeof el == 'string' ? document.querySelector(el) : el;
28466    this.scroller = this.wrapper.children[0];
28467    this.scrollerStyle = this.scroller.style;       // cache style for better performance
28468
28469    this.options = {
28470
28471        resizeScrollbars: true,
28472
28473        mouseWheelSpeed: 20,
28474
28475        snapThreshold: 0.334,
28476
28477// INSERT POINT: OPTIONS
28478        disablePointer : !utils.hasPointer,
28479        disableTouch : utils.hasPointer || !utils.hasTouch,
28480        disableMouse : utils.hasPointer || utils.hasTouch,
28481        startX: 0,
28482        startY: 0,
28483        scrollY: true,
28484        directionLockThreshold: 5,
28485        momentum: true,
28486
28487        bounce: true,
28488        bounceTime: 600,
28489        bounceEasing: '',
28490
28491        preventDefault: true,
28492        preventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT|LABEL)$/ },
28493
28494        HWCompositing: true,
28495        useTransition: true,
28496        useTransform: true,
28497        bindToWrapper: typeof window.onmousedown === "undefined"
28498    };
28499
28500    for ( var i in options ) {
28501        this.options[i] = options[i];
28502    }
28503
28504    // Normalize options
28505    this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : '';
28506
28507    this.options.useTransition = utils.hasTransition && this.options.useTransition;
28508    this.options.useTransform = utils.hasTransform && this.options.useTransform;
28509
28510    this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough;
28511    this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault;
28512
28513    // If you want eventPassthrough I have to lock one of the axes
28514    this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY;
28515    this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX;
28516
28517    // With eventPassthrough we also need lockDirection mechanism
28518    this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough;
28519    this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold;
28520
28521    this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing;
28522
28523    this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling;
28524
28525    if ( this.options.tap === true ) {
vendor: 4,893 bytes, lines 28526-28697
28526        this.options.tap = 'tap';
28527    }
28528
28529    // https://github.com/cubiq/iscroll/issues/1029
28530    if (!this.options.useTransition && !this.options.useTransform) {
28531        if(!(/relative|absolute/i).test(this.scrollerStyle.position)) {
28532            this.scrollerStyle.position = "relative";
28533        }
28534    }
28535
28536    if ( this.options.shrinkScrollbars == 'scale' ) {
28537        this.options.useTransition = false;
28538    }
28539
28540    this.options.invertWheelDirection = this.options.invertWheelDirection ? -1 : 1;
28541
28542// INSERT POINT: NORMALIZATION
28543
28544    // Some defaults
28545    this.x = 0;
28546    this.y = 0;
28547    this.directionX = 0;
28548    this.directionY = 0;
28549    this._events = {};
28550
28551// INSERT POINT: DEFAULTS
28552
28553    this._init();
28554    this.refresh();
28555
28556    this.scrollTo(this.options.startX, this.options.startY);
28557    this.enable();
28558}
28559
28560IScroll.prototype = {
28561    version: '5.2.0',
28562
28563    _init: function () {
28564        this._initEvents();
28565
28566        if ( this.options.scrollbars || this.options.indicators ) {
28567            this._initIndicators();
28568        }
28569
28570        if ( this.options.mouseWheel ) {
28571            this._initWheel();
28572        }
28573
28574        if ( this.options.snap ) {
28575            this._initSnap();
28576        }
28577
28578        if ( this.options.keyBindings ) {
28579            this._initKeys();
28580        }
28581
28582// INSERT POINT: _init
28583
28584    },
28585
28586    destroy: function () {
28587        this._initEvents(true);
28588        clearTimeout(this.resizeTimeout);
28589        this.resizeTimeout = null;
28590        this._execEvent('destroy');
28591    },
28592
28593    _transitionEnd: function (e) {
28594        if ( e.target != this.scroller || !this.isInTransition ) {
28595            return;
28596        }
28597
28598        this._transitionTime();
28599        if ( !this.resetPosition(this.options.bounceTime) ) {
28600            this.isInTransition = false;
28601            this._execEvent('scrollEnd');
28602        }
28603    },
28604
28605    _start: function (e) {
28606        // React to left mouse button only
28607        if ( utils.eventType[e.type] != 1 ) {
28608          // for button property
28609          // http://unixpapa.com/js/mouse.html
28610          var button;
28611        if (!e.which) {
28612          /* IE case */
28613          button = (e.button < 2) ? 0 :
28614                   ((e.button == 4) ? 1 : 2);
28615        } else {
28616          /* All others */
28617          button = e.button;
28618        }
28619            if ( button !== 0 ) {
28620                return;
28621            }
28622        }
28623
28624        if ( !this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated) ) {
28625            return;
28626        }
28627
28628        if ( this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {
28629            e.preventDefault();
28630        }
28631
28632        var point = e.touches ? e.touches[0] : e,
28633            pos;
28634
28635        this.initiated  = utils.eventType[e.type];
28636        this.moved      = false;
28637        this.distX      = 0;
28638        this.distY      = 0;
28639        this.directionX = 0;
28640        this.directionY = 0;
28641        this.directionLocked = 0;
28642
28643        this.startTime = utils.getTime();
28644
28645        if ( this.options.useTransition && this.isInTransition ) {
28646            this._transitionTime();
28647            this.isInTransition = false;
28648            pos = this.getComputedPosition();
28649            this._translate(Math.round(pos.x), Math.round(pos.y));
28650            this._execEvent('scrollEnd');
28651        } else if ( !this.options.useTransition && this.isAnimating ) {
28652            this.isAnimating = false;
28653            this._execEvent('scrollEnd');
28654        }
28655
28656        this.startX    = this.x;
28657        this.startY    = this.y;
28658        this.absStartX = this.x;
28659        this.absStartY = this.y;
28660        this.pointX    = point.pageX;
28661        this.pointY    = point.pageY;
28662
28663        this._execEvent('beforeScrollStart');
28664    },
28665
28666    _move: function (e) {
28667        if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
28668            return;
28669        }
28670
28671        if ( this.options.preventDefault ) {    // increases performance on Android? TODO: check!
28672            e.preventDefault();
28673        }
28674
28675        var point       = e.touches ? e.touches[0] : e,
28676            deltaX      = point.pageX - this.pointX,
28677            deltaY      = point.pageY - this.pointY,
28678            timestamp   = utils.getTime(),
28679            newX, newY,
28680            absDistX, absDistY;
28681
28682        this.pointX     = point.pageX;
28683        this.pointY     = point.pageY;
28684
28685        this.distX      += deltaX;
28686        this.distY      += deltaY;
28687        absDistX        = Math.abs(this.distX);
28688        absDistY        = Math.abs(this.distY);
28689
28690        // We need to move at least 10 pixels for the scrolling to initiate
28691        if ( timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10) ) {
28692            return;
28693        }
28694
28695        // If you are scrolling in one direction lock the other
28696        if ( !this.directionLocked && !this.options.freeScroll ) {
28697            if ( absDistX > absDistY + this.options.directionLockThreshold ) {
vendor: 6,057 bytes, lines 28698-28884
28698                this.directionLocked = 'h';     // lock horizontally
28699            } else if ( absDistY >= absDistX + this.options.directionLockThreshold ) {
28700                this.directionLocked = 'v';     // lock vertically
28701            } else {
28702                this.directionLocked = 'n';     // no lock
28703            }
28704        }
28705
28706        if ( this.directionLocked == 'h' ) {
28707            if ( this.options.eventPassthrough == 'vertical' ) {
28708                e.preventDefault();
28709            } else if ( this.options.eventPassthrough == 'horizontal' ) {
28710                this.initiated = false;
28711                return;
28712            }
28713
28714            deltaY = 0;
28715        } else if ( this.directionLocked == 'v' ) {
28716            if ( this.options.eventPassthrough == 'horizontal' ) {
28717                e.preventDefault();
28718            } else if ( this.options.eventPassthrough == 'vertical' ) {
28719                this.initiated = false;
28720                return;
28721            }
28722
28723            deltaX = 0;
28724        }
28725
28726        deltaX = this.hasHorizontalScroll ? deltaX : 0;
28727        deltaY = this.hasVerticalScroll ? deltaY : 0;
28728
28729        newX = this.x + deltaX;
28730        newY = this.y + deltaY;
28731
28732        // Slow down if outside of the boundaries
28733        if ( newX > 0 || newX < this.maxScrollX ) {
28734            newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX;
28735        }
28736        if ( newY > 0 || newY < this.maxScrollY ) {
28737            newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY;
28738        }
28739
28740        this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0;
28741        this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0;
28742
28743        if ( !this.moved ) {
28744            this._execEvent('scrollStart');
28745        }
28746
28747        this.moved = true;
28748
28749        this._translate(newX, newY);
28750
28751/* REPLACE START: _move */
28752
28753        if ( timestamp - this.startTime > 300 ) {
28754            this.startTime = timestamp;
28755            this.startX = this.x;
28756            this.startY = this.y;
28757        }
28758
28759/* REPLACE END: _move */
28760
28761    },
28762
28763    _end: function (e) {
28764        if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
28765            return;
28766        }
28767
28768        if ( this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {
28769            e.preventDefault();
28770        }
28771
28772        var point = e.changedTouches ? e.changedTouches[0] : e,
28773            momentumX,
28774            momentumY,
28775            duration = utils.getTime() - this.startTime,
28776            newX = Math.round(this.x),
28777            newY = Math.round(this.y),
28778            distanceX = Math.abs(newX - this.startX),
28779            distanceY = Math.abs(newY - this.startY),
28780            time = 0,
28781            easing = '';
28782
28783        this.isInTransition = 0;
28784        this.initiated = 0;
28785        this.endTime = utils.getTime();
28786
28787        // reset if we are outside of the boundaries
28788        if ( this.resetPosition(this.options.bounceTime) ) {
28789            return;
28790        }
28791
28792        this.scrollTo(newX, newY);  // ensures that the last position is rounded
28793
28794        // we scrolled less than 10 pixels
28795        if ( !this.moved ) {
28796            if ( this.options.tap ) {
28797                utils.tap(e, this.options.tap);
28798            }
28799
28800            if ( this.options.click ) {
28801                utils.click(e);
28802            }
28803
28804            this._execEvent('scrollCancel');
28805            return;
28806        }
28807
28808        if ( this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100 ) {
28809            this._execEvent('flick');
28810            return;
28811        }
28812
28813        // start momentum animation if needed
28814        if ( this.options.momentum && duration < 300 ) {
28815            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 };
28816            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 };
28817            newX = momentumX.destination;
28818            newY = momentumY.destination;
28819            time = Math.max(momentumX.duration, momentumY.duration);
28820            this.isInTransition = 1;
28821        }
28822
28823
28824        if ( this.options.snap ) {
28825            var snap = this._nearestSnap(newX, newY);
28826            this.currentPage = snap;
28827            time = this.options.snapSpeed || Math.max(
28828                    Math.max(
28829                        Math.min(Math.abs(newX - snap.x), 1000),
28830                        Math.min(Math.abs(newY - snap.y), 1000)
28831                    ), 300);
28832            newX = snap.x;
28833            newY = snap.y;
28834
28835            this.directionX = 0;
28836            this.directionY = 0;
28837            easing = this.options.bounceEasing;
28838        }
28839
28840// INSERT POINT: _end
28841
28842        if ( newX != this.x || newY != this.y ) {
28843            // change easing function when scroller goes out of the boundaries
28844            if ( newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY ) {
28845                easing = utils.ease.quadratic;
28846            }
28847
28848            this.scrollTo(newX, newY, time, easing);
28849            return;
28850        }
28851
28852        this._execEvent('scrollEnd');
28853    },
28854
28855    _resize: function () {
28856        var that = this;
28857
28858        clearTimeout(this.resizeTimeout);
28859
28860        this.resizeTimeout = setTimeout(function () {
28861            that.refresh();
28862        }, this.options.resizePolling);
28863    },
28864
28865    resetPosition: function (time) {
28866        var x = this.x,
28867            y = this.y;
28868
28869        time = time || 0;
28870
28871        if ( !this.hasHorizontalScroll || this.x > 0 ) {
28872            x = 0;
28873        } else if ( this.x < this.maxScrollX ) {
28874            x = this.maxScrollX;
28875        }
28876
28877        if ( !this.hasVerticalScroll || this.y > 0 ) {
28878            y = 0;
28879        } else if ( this.y < this.maxScrollY ) {
28880            y = this.maxScrollY;
28881        }
28882
28883        if ( x == this.x && y == this.y ) {
28884            return false;
vendor: 5,509 bytes, lines 28885-29089
28885        }
28886
28887        this.scrollTo(x, y, time, this.options.bounceEasing);
28888
28889        return true;
28890    },
28891
28892    disable: function () {
28893        this.enabled = false;
28894    },
28895
28896    enable: function () {
28897        this.enabled = true;
28898    },
28899
28900    refresh: function () {
28901        var rf = this.wrapper.offsetHeight;     // Force reflow
28902
28903        this.wrapperWidth   = this.wrapper.clientWidth;
28904        this.wrapperHeight  = this.wrapper.clientHeight;
28905
28906/* REPLACE START: refresh */
28907
28908        this.scrollerWidth  = this.scroller.offsetWidth;
28909        this.scrollerHeight = this.scroller.offsetHeight;
28910
28911        this.maxScrollX     = this.wrapperWidth - this.scrollerWidth;
28912        this.maxScrollY     = this.wrapperHeight - this.scrollerHeight;
28913
28914/* REPLACE END: refresh */
28915
28916        this.hasHorizontalScroll    = this.options.scrollX && this.maxScrollX < 0;
28917        this.hasVerticalScroll      = this.options.scrollY && this.maxScrollY < 0;
28918
28919        if ( !this.hasHorizontalScroll ) {
28920            this.maxScrollX = 0;
28921            this.scrollerWidth = this.wrapperWidth;
28922        }
28923
28924        if ( !this.hasVerticalScroll ) {
28925            this.maxScrollY = 0;
28926            this.scrollerHeight = this.wrapperHeight;
28927        }
28928
28929        this.endTime = 0;
28930        this.directionX = 0;
28931        this.directionY = 0;
28932
28933        this.wrapperOffset = utils.offset(this.wrapper);
28934
28935        this._execEvent('refresh');
28936
28937        this.resetPosition();
28938
28939// INSERT POINT: _refresh
28940
28941    },
28942
28943
28944    on: function (type, fn) {
28945        if ( !this._events[type] ) {
28946            this._events[type] = [];
28947        }
28948
28949        this._events[type].push(fn);
28950    },
28951
28952    off: function (type, fn) {
28953        if ( !this._events[type] ) {
28954            return;
28955        }
28956
28957        var index = this._events[type].indexOf(fn);
28958
28959        if ( index > -1 ) {
28960            this._events[type].splice(index, 1);
28961        }
28962    },
28963
28964    _execEvent: function (type) {
28965        if ( !this._events[type] ) {
28966            return;
28967        }
28968
28969        var i = 0,
28970            l = this._events[type].length;
28971
28972        if ( !l ) {
28973            return;
28974        }
28975
28976        for ( ; i < l; i++ ) {
28977            this._events[type][i].apply(this, [].slice.call(arguments, 1));
28978        }
28979    },
28980
28981    scrollBy: function (x, y, time, easing) {
28982        x = this.x + x;
28983        y = this.y + y;
28984        time = time || 0;
28985
28986        this.scrollTo(x, y, time, easing);
28987    },
28988
28989    scrollTo: function (x, y, time, easing) {
28990        easing = easing || utils.ease.circular;
28991
28992        this.isInTransition = this.options.useTransition && time > 0;
28993        var transitionType = this.options.useTransition && easing.style;
28994        if ( !time || transitionType ) {
28995                if(transitionType) {
28996                    this._transitionTimingFunction(easing.style);
28997                    this._transitionTime(time);
28998                }
28999            this._translate(x, y);
29000        } else {
29001            this._animate(x, y, time, easing.fn);
29002        }
29003    },
29004
29005    scrollToElement: function (el, time, offsetX, offsetY, easing) {
29006        el = el.nodeType ? el : this.scroller.querySelector(el);
29007
29008        if ( !el ) {
29009            return;
29010        }
29011
29012        var pos = utils.offset(el);
29013
29014        pos.left -= this.wrapperOffset.left;
29015        pos.top  -= this.wrapperOffset.top;
29016
29017        // if offsetX/Y are true we center the element to the screen
29018        if ( offsetX === true ) {
29019            offsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2);
29020        }
29021        if ( offsetY === true ) {
29022            offsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2);
29023        }
29024
29025        pos.left -= offsetX || 0;
29026        pos.top  -= offsetY || 0;
29027
29028        pos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left;
29029        pos.top  = pos.top  > 0 ? 0 : pos.top  < this.maxScrollY ? this.maxScrollY : pos.top;
29030
29031        time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x-pos.left), Math.abs(this.y-pos.top)) : time;
29032
29033        this.scrollTo(pos.left, pos.top, time, easing);
29034    },
29035
29036    _transitionTime: function (time) {
29037        if (!this.options.useTransition) {
29038            return;
29039        }
29040        time = time || 0;
29041        var durationProp = utils.style.transitionDuration;
29042        if(!durationProp) {
29043            return;
29044        }
29045
29046        this.scrollerStyle[durationProp] = time + 'ms';
29047
29048        if ( !time && utils.isBadAndroid ) {
29049            this.scrollerStyle[durationProp] = '0.0001ms';
29050            // remove 0.0001ms
29051            var self = this;
29052            rAF(function() {
29053                if(self.scrollerStyle[durationProp] === '0.0001ms') {
29054                    self.scrollerStyle[durationProp] = '0s';
29055                }
29056            });
29057        }
29058
29059
29060        if ( this.indicators ) {
29061            for ( var i = this.indicators.length; i--; ) {
29062                this.indicators[i].transitionTime(time);
29063            }
29064        }
29065
29066
29067// INSERT POINT: _transitionTime
29068
29069    },
29070
29071    _transitionTimingFunction: function (easing) {
29072        this.scrollerStyle[utils.style.transitionTimingFunction] = easing;
29073
29074
29075        if ( this.indicators ) {
29076            for ( var i = this.indicators.length; i--; ) {
29077                this.indicators[i].transitionTimingFunction(easing);
29078            }
29079        }
29080
29081
29082// INSERT POINT: _transitionTimingFunction
29083
29084    },
29085
29086    _translate: function (x, y) {
29087        //Uncode addition
29088        if ( (" " + this.wrapper.className + " ").replace(/[\n\t]/g, " ").indexOf(" no-scrolloverflow ") > -1 )
29089            return false;
vendor: 9,939 bytes, lines 29090-29401
29090
29091        if ( this.options.useTransform ) {
29092
29093/* REPLACE START: _translate */
29094
29095            this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ;
29096
29097/* REPLACE END: _translate */
29098
29099        } else {
29100            x = Math.round(x);
29101            y = Math.round(y);
29102            this.scrollerStyle.left = x + 'px';
29103            this.scrollerStyle.top = y + 'px';
29104        }
29105
29106        this.x = x;
29107        this.y = y;
29108
29109
29110        if ( this.indicators ) {
29111            for ( var i = this.indicators.length; i--; ) {
29112                this.indicators[i].updatePosition();
29113            }
29114        }
29115
29116        //Uncode addition
29117        var uncodevent = new CustomEvent('fp-slide-scroll');
29118        window.dispatchEvent(uncodevent);
29119
29120// INSERT POINT: _translate
29121
29122    },
29123
29124    _initEvents: function (remove) {
29125        var eventType = remove ? utils.removeEvent : utils.addEvent,
29126            target = this.options.bindToWrapper ? this.wrapper : window;
29127
29128        eventType(window, 'orientationchange', this);
29129        eventType(window, 'resize', this);
29130
29131        if ( this.options.click ) {
29132            eventType(this.wrapper, 'click', this, true);
29133        }
29134
29135        if ( !this.options.disableMouse ) {
29136            eventType(this.wrapper, 'mousedown', this);
29137            eventType(target, 'mousemove', this);
29138            eventType(target, 'mousecancel', this);
29139            eventType(target, 'mouseup', this);
29140        }
29141
29142        if ( utils.hasPointer && !this.options.disablePointer ) {
29143            eventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this);
29144            eventType(target, utils.prefixPointerEvent('pointermove'), this);
29145            eventType(target, utils.prefixPointerEvent('pointercancel'), this);
29146            eventType(target, utils.prefixPointerEvent('pointerup'), this);
29147        }
29148
29149        if ( utils.hasTouch && !this.options.disableTouch ) {
29150            eventType(this.wrapper, 'touchstart', this);
29151            eventType(target, 'touchmove', this);
29152            eventType(target, 'touchcancel', this);
29153            eventType(target, 'touchend', this);
29154        }
29155
29156        eventType(this.scroller, 'transitionend', this);
29157        eventType(this.scroller, 'webkitTransitionEnd', this);
29158        eventType(this.scroller, 'oTransitionEnd', this);
29159        eventType(this.scroller, 'MSTransitionEnd', this);
29160    },
29161
29162    getComputedPosition: function () {
29163        var matrix = window.getComputedStyle(this.scroller, null),
29164            x, y;
29165
29166        if ( this.options.useTransform ) {
29167            matrix = matrix[utils.style.transform].split(')')[0].split(', ');
29168            x = +(matrix[12] || matrix[4]);
29169            y = +(matrix[13] || matrix[5]);
29170        } else {
29171            x = +matrix.left.replace(/[^-\d.]/g, '');
29172            y = +matrix.top.replace(/[^-\d.]/g, '');
29173        }
29174
29175        return { x: x, y: y };
29176    },
29177    _initIndicators: function () {
29178        var interactive = this.options.interactiveScrollbars,
29179            customStyle = typeof this.options.scrollbars != 'string',
29180            indicators = [],
29181            indicator;
29182
29183        var that = this;
29184
29185        this.indicators = [];
29186
29187        if ( this.options.scrollbars ) {
29188            // Vertical scrollbar
29189            if ( this.options.scrollY ) {
29190                indicator = {
29191                    el: createDefaultScrollbar('v', interactive, this.options.scrollbars),
29192                    interactive: interactive,
29193                    defaultScrollbars: true,
29194                    customStyle: customStyle,
29195                    resize: this.options.resizeScrollbars,
29196                    shrink: this.options.shrinkScrollbars,
29197                    fade: this.options.fadeScrollbars,
29198                    listenX: false
29199                };
29200
29201                this.wrapper.appendChild(indicator.el);
29202                indicators.push(indicator);
29203            }
29204
29205            // Horizontal scrollbar
29206            if ( this.options.scrollX ) {
29207                indicator = {
29208                    el: createDefaultScrollbar('h', interactive, this.options.scrollbars),
29209                    interactive: interactive,
29210                    defaultScrollbars: true,
29211                    customStyle: customStyle,
29212                    resize: this.options.resizeScrollbars,
29213                    shrink: this.options.shrinkScrollbars,
29214                    fade: this.options.fadeScrollbars,
29215                    listenY: false
29216                };
29217
29218                this.wrapper.appendChild(indicator.el);
29219                indicators.push(indicator);
29220            }
29221        }
29222
29223        if ( this.options.indicators ) {
29224            // TODO: check concat compatibility
29225            indicators = indicators.concat(this.options.indicators);
29226        }
29227
29228        for ( var i = indicators.length; i--; ) {
29229            this.indicators.push( new Indicator(this, indicators[i]) );
29230        }
29231
29232        // TODO: check if we can use array.map (wide compatibility and performance issues)
29233        function _indicatorsMap (fn) {
29234            if (that.indicators) {
29235                for ( var i = that.indicators.length; i--; ) {
29236                    fn.call(that.indicators[i]);
29237                }
29238            }
29239        }
29240
29241        if ( this.options.fadeScrollbars ) {
29242            this.on('scrollEnd', function () {
29243                _indicatorsMap(function () {
29244                    this.fade();
29245                });
29246            });
29247
29248            this.on('scrollCancel', function () {
29249                _indicatorsMap(function () {
29250                    this.fade();
29251                });
29252            });
29253
29254            this.on('scrollStart', function () {
29255                _indicatorsMap(function () {
29256                    this.fade(1);
29257                });
29258            });
29259
29260            this.on('beforeScrollStart', function () {
29261                _indicatorsMap(function () {
29262                    this.fade(1, true);
29263                });
29264            });
29265        }
29266
29267
29268        this.on('refresh', function () {
29269            _indicatorsMap(function () {
29270                this.refresh();
29271            });
29272        });
29273
29274        this.on('destroy', function () {
29275            _indicatorsMap(function () {
29276                this.destroy();
29277            });
29278
29279            delete this.indicators;
29280        });
29281    },
29282
29283    _initWheel: function () {
29284        utils.addEvent(this.wrapper, 'wheel', this);
29285        utils.addEvent(this.wrapper, 'mousewheel', this);
29286        utils.addEvent(this.wrapper, 'DOMMouseScroll', this);
29287
29288        this.on('destroy', function () {
29289            clearTimeout(this.wheelTimeout);
29290            this.wheelTimeout = null;
29291            utils.removeEvent(this.wrapper, 'wheel', this);
29292            utils.removeEvent(this.wrapper, 'mousewheel', this);
29293            utils.removeEvent(this.wrapper, 'DOMMouseScroll', this);
29294        });
29295    },
29296
29297    _wheel: function (e) {
29298        if ( !this.enabled ) {
29299            return;
29300        }
29301
29302        var wheelDeltaX, wheelDeltaY,
29303            newX, newY,
29304            that = this;
29305
29306        if ( this.wheelTimeout === undefined ) {
29307            that._execEvent('scrollStart');
29308        }
29309
29310        // Execute the scrollEnd event after 400ms the wheel stopped scrolling
29311        clearTimeout(this.wheelTimeout);
29312        this.wheelTimeout = setTimeout(function () {
29313            if(!that.options.snap) {
29314                that._execEvent('scrollEnd');
29315            }
29316            that.wheelTimeout = undefined;
29317        }, 400);
29318
29319        if ( 'deltaX' in e ) {
29320            if (e.deltaMode === 1) {
29321                wheelDeltaX = -e.deltaX * this.options.mouseWheelSpeed;
29322                wheelDeltaY = -e.deltaY * this.options.mouseWheelSpeed;
29323            } else {
29324                wheelDeltaX = -e.deltaX;
29325                wheelDeltaY = -e.deltaY;
29326            }
29327        } else if ( 'wheelDeltaX' in e ) {
29328            wheelDeltaX = e.wheelDeltaX / 120 * this.options.mouseWheelSpeed;
29329            wheelDeltaY = e.wheelDeltaY / 120 * this.options.mouseWheelSpeed;
29330        } else if ( 'wheelDelta' in e ) {
29331            wheelDeltaX = wheelDeltaY = e.wheelDelta / 120 * this.options.mouseWheelSpeed;
29332        } else if ( 'detail' in e ) {
29333            wheelDeltaX = wheelDeltaY = -e.detail / 3 * this.options.mouseWheelSpeed;
29334        } else {
29335            return;
29336        }
29337
29338        wheelDeltaX *= this.options.invertWheelDirection;
29339        wheelDeltaY *= this.options.invertWheelDirection;
29340
29341        if ( !this.hasVerticalScroll ) {
29342            wheelDeltaX = wheelDeltaY;
29343            wheelDeltaY = 0;
29344        }
29345
29346        if ( this.options.snap ) {
29347            newX = this.currentPage.pageX;
29348            newY = this.currentPage.pageY;
29349
29350            if ( wheelDeltaX > 0 ) {
29351                newX--;
29352            } else if ( wheelDeltaX < 0 ) {
29353                newX++;
29354            }
29355
29356            if ( wheelDeltaY > 0 ) {
29357                newY--;
29358            } else if ( wheelDeltaY < 0 ) {
29359                newY++;
29360            }
29361
29362            this.goToPage(newX, newY);
29363
29364            return;
29365        }
29366
29367        newX = this.x + Math.round(this.hasHorizontalScroll ? wheelDeltaX : 0);
29368        newY = this.y + Math.round(this.hasVerticalScroll ? wheelDeltaY : 0);
29369
29370        this.directionX = wheelDeltaX > 0 ? -1 : wheelDeltaX < 0 ? 1 : 0;
29371        this.directionY = wheelDeltaY > 0 ? -1 : wheelDeltaY < 0 ? 1 : 0;
29372
29373        if ( newX > 0 ) {
29374            newX = 0;
29375        } else if ( newX < this.maxScrollX ) {
29376            newX = this.maxScrollX;
29377        }
29378
29379        if ( newY > 0 ) {
29380            newY = 0;
29381        } else if ( newY < this.maxScrollY ) {
29382            newY = this.maxScrollY;
29383        }
29384
29385        this.scrollTo(newX, newY, 0);
29386
29387// INSERT POINT: _wheel
29388    },
29389
29390    _initSnap: function () {
29391        this.currentPage = {};
29392
29393        if ( typeof this.options.snap == 'string' ) {
29394            this.options.snap = this.scroller.querySelectorAll(this.options.snap);
29395        }
29396
29397        this.on('refresh', function () {
29398            var i = 0, l,
29399                m = 0, n,
29400                cx, cy,
29401                x = 0, y,
vendor: 7,339 bytes, lines 29402-29655
29402                stepX = this.options.snapStepX || this.wrapperWidth,
29403                stepY = this.options.snapStepY || this.wrapperHeight,
29404                el;
29405
29406            this.pages = [];
29407
29408            if ( !this.wrapperWidth || !this.wrapperHeight || !this.scrollerWidth || !this.scrollerHeight ) {
29409                return;
29410            }
29411
29412            if ( this.options.snap === true ) {
29413                cx = Math.round( stepX / 2 );
29414                cy = Math.round( stepY / 2 );
29415
29416                while ( x > -this.scrollerWidth ) {
29417                    this.pages[i] = [];
29418                    l = 0;
29419                    y = 0;
29420
29421                    while ( y > -this.scrollerHeight ) {
29422                        this.pages[i][l] = {
29423                            x: Math.max(x, this.maxScrollX),
29424                            y: Math.max(y, this.maxScrollY),
29425                            width: stepX,
29426                            height: stepY,
29427                            cx: x - cx,
29428                            cy: y - cy
29429                        };
29430
29431                        y -= stepY;
29432                        l++;
29433                    }
29434
29435                    x -= stepX;
29436                    i++;
29437                }
29438            } else {
29439                el = this.options.snap;
29440                l = el.length;
29441                n = -1;
29442
29443                for ( ; i < l; i++ ) {
29444                    if ( i === 0 || el[i].offsetLeft <= el[i-1].offsetLeft ) {
29445                        m = 0;
29446                        n++;
29447                    }
29448
29449                    if ( !this.pages[m] ) {
29450                        this.pages[m] = [];
29451                    }
29452
29453                    x = Math.max(-el[i].offsetLeft, this.maxScrollX);
29454                    y = Math.max(-el[i].offsetTop, this.maxScrollY);
29455                    cx = x - Math.round(el[i].offsetWidth / 2);
29456                    cy = y - Math.round(el[i].offsetHeight / 2);
29457
29458                    this.pages[m][n] = {
29459                        x: x,
29460                        y: y,
29461                        width: el[i].offsetWidth,
29462                        height: el[i].offsetHeight,
29463                        cx: cx,
29464                        cy: cy
29465                    };
29466
29467                    if ( x > this.maxScrollX ) {
29468                        m++;
29469                    }
29470                }
29471            }
29472
29473            this.goToPage(this.currentPage.pageX || 0, this.currentPage.pageY || 0, 0);
29474
29475            // Update snap threshold if needed
29476            if ( this.options.snapThreshold % 1 === 0 ) {
29477                this.snapThresholdX = this.options.snapThreshold;
29478                this.snapThresholdY = this.options.snapThreshold;
29479            } else {
29480                this.snapThresholdX = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].width * this.options.snapThreshold);
29481                this.snapThresholdY = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].height * this.options.snapThreshold);
29482            }
29483        });
29484
29485        this.on('flick', function () {
29486            var time = this.options.snapSpeed || Math.max(
29487                    Math.max(
29488                        Math.min(Math.abs(this.x - this.startX), 1000),
29489                        Math.min(Math.abs(this.y - this.startY), 1000)
29490                    ), 300);
29491
29492            this.goToPage(
29493                this.currentPage.pageX + this.directionX,
29494                this.currentPage.pageY + this.directionY,
29495                time
29496            );
29497        });
29498    },
29499
29500    _nearestSnap: function (x, y) {
29501        if ( !this.pages.length ) {
29502            return { x: 0, y: 0, pageX: 0, pageY: 0 };
29503        }
29504
29505        var i = 0,
29506            l = this.pages.length,
29507            m = 0;
29508
29509        // Check if we exceeded the snap threshold
29510        if ( Math.abs(x - this.absStartX) < this.snapThresholdX &&
29511            Math.abs(y - this.absStartY) < this.snapThresholdY ) {
29512            return this.currentPage;
29513        }
29514
29515        if ( x > 0 ) {
29516            x = 0;
29517        } else if ( x < this.maxScrollX ) {
29518            x = this.maxScrollX;
29519        }
29520
29521        if ( y > 0 ) {
29522            y = 0;
29523        } else if ( y < this.maxScrollY ) {
29524            y = this.maxScrollY;
29525        }
29526
29527        for ( ; i < l; i++ ) {
29528            if ( x >= this.pages[i][0].cx ) {
29529                x = this.pages[i][0].x;
29530                break;
29531            }
29532        }
29533
29534        l = this.pages[i].length;
29535
29536        for ( ; m < l; m++ ) {
29537            if ( y >= this.pages[0][m].cy ) {
29538                y = this.pages[0][m].y;
29539                break;
29540            }
29541        }
29542
29543        if ( i == this.currentPage.pageX ) {
29544            i += this.directionX;
29545
29546            if ( i < 0 ) {
29547                i = 0;
29548            } else if ( i >= this.pages.length ) {
29549                i = this.pages.length - 1;
29550            }
29551
29552            x = this.pages[i][0].x;
29553        }
29554
29555        if ( m == this.currentPage.pageY ) {
29556            m += this.directionY;
29557
29558            if ( m < 0 ) {
29559                m = 0;
29560            } else if ( m >= this.pages[0].length ) {
29561                m = this.pages[0].length - 1;
29562            }
29563
29564            y = this.pages[0][m].y;
29565        }
29566
29567        return {
29568            x: x,
29569            y: y,
29570            pageX: i,
29571            pageY: m
29572        };
29573    },
29574
29575    goToPage: function (x, y, time, easing) {
29576        easing = easing || this.options.bounceEasing;
29577
29578        if ( x >= this.pages.length ) {
29579            x = this.pages.length - 1;
29580        } else if ( x < 0 ) {
29581            x = 0;
29582        }
29583
29584        if ( y >= this.pages[x].length ) {
29585            y = this.pages[x].length - 1;
29586        } else if ( y < 0 ) {
29587            y = 0;
29588        }
29589
29590        var posX = this.pages[x][y].x,
29591            posY = this.pages[x][y].y;
29592
29593        time = time === undefined ? this.options.snapSpeed || Math.max(
29594            Math.max(
29595                Math.min(Math.abs(posX - this.x), 1000),
29596                Math.min(Math.abs(posY - this.y), 1000)
29597            ), 300) : time;
29598
29599        this.currentPage = {
29600            x: posX,
29601            y: posY,
29602            pageX: x,
29603            pageY: y
29604        };
29605
29606        this.scrollTo(posX, posY, time, easing);
29607    },
29608
29609    next: function (time, easing) {
29610        var x = this.currentPage.pageX,
29611            y = this.currentPage.pageY;
29612
29613        x++;
29614
29615        if ( x >= this.pages.length && this.hasVerticalScroll ) {
29616            x = 0;
29617            y++;
29618        }
29619
29620        this.goToPage(x, y, time, easing);
29621    },
29622
29623    prev: function (time, easing) {
29624        var x = this.currentPage.pageX,
29625            y = this.currentPage.pageY;
29626
29627        x--;
29628
29629        if ( x < 0 && this.hasVerticalScroll ) {
29630            x = 0;
29631            y--;
29632        }
29633
29634        this.goToPage(x, y, time, easing);
29635    },
29636
29637    _initKeys: function (e) {
29638        // default key bindings
29639        var keys = {
29640            pageUp: 33,
29641            pageDown: 34,
29642            end: 35,
29643            home: 36,
29644            left: 37,
29645            up: 38,
29646            right: 39,
29647            down: 40
29648        };
29649        var i;
29650
29651        // if you give me characters I give you keycode
29652        if ( typeof this.options.keyBindings == 'object' ) {
29653            for ( i in this.options.keyBindings ) {
29654                if ( typeof this.options.keyBindings[i] == 'string' ) {
29655                    this.options.keyBindings[i] = this.options.keyBindings[i].toUpperCase().charCo
vendor: 11,097 bytes, lines 29655-30008
29655deAt(0);
29656                }
29657            }
29658        } else {
29659            this.options.keyBindings = {};
29660        }
29661
29662        for ( i in keys ) {
29663            this.options.keyBindings[i] = this.options.keyBindings[i] || keys[i];
29664        }
29665
29666        utils.addEvent(window, 'keydown', this);
29667
29668        this.on('destroy', function () {
29669            utils.removeEvent(window, 'keydown', this);
29670        });
29671    },
29672
29673    _key: function (e) {
29674        if ( !this.enabled ) {
29675            return;
29676        }
29677
29678        var snap = this.options.snap,   // we are using this alot, better to cache it
29679            newX = snap ? this.currentPage.pageX : this.x,
29680            newY = snap ? this.currentPage.pageY : this.y,
29681            now = utils.getTime(),
29682            prevTime = this.keyTime || 0,
29683            acceleration = 0.250,
29684            pos;
29685
29686        if ( this.options.useTransition && this.isInTransition ) {
29687            pos = this.getComputedPosition();
29688
29689            this._translate(Math.round(pos.x), Math.round(pos.y));
29690            this.isInTransition = false;
29691        }
29692
29693        this.keyAcceleration = now - prevTime < 200 ? Math.min(this.keyAcceleration + acceleration, 50) : 0;
29694
29695        switch ( e.keyCode ) {
29696            case this.options.keyBindings.pageUp:
29697                if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {
29698                    newX += snap ? 1 : this.wrapperWidth;
29699                } else {
29700                    newY += snap ? 1 : this.wrapperHeight;
29701                }
29702                break;
29703            case this.options.keyBindings.pageDown:
29704                if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {
29705                    newX -= snap ? 1 : this.wrapperWidth;
29706                } else {
29707                    newY -= snap ? 1 : this.wrapperHeight;
29708                }
29709                break;
29710            case this.options.keyBindings.end:
29711                newX = snap ? this.pages.length-1 : this.maxScrollX;
29712                newY = snap ? this.pages[0].length-1 : this.maxScrollY;
29713                break;
29714            case this.options.keyBindings.home:
29715                newX = 0;
29716                newY = 0;
29717                break;
29718            case this.options.keyBindings.left:
29719                newX += snap ? -1 : 5 + this.keyAcceleration>>0;
29720                break;
29721            case this.options.keyBindings.up:
29722                newY += snap ? 1 : 5 + this.keyAcceleration>>0;
29723                break;
29724            case this.options.keyBindings.right:
29725                newX -= snap ? -1 : 5 + this.keyAcceleration>>0;
29726                break;
29727            case this.options.keyBindings.down:
29728                newY -= snap ? 1 : 5 + this.keyAcceleration>>0;
29729                break;
29730            default:
29731                return;
29732        }
29733
29734        if ( snap ) {
29735            this.goToPage(newX, newY);
29736            return;
29737        }
29738
29739        if ( newX > 0 ) {
29740            newX = 0;
29741            this.keyAcceleration = 0;
29742        } else if ( newX < this.maxScrollX ) {
29743            newX = this.maxScrollX;
29744            this.keyAcceleration = 0;
29745        }
29746
29747        if ( newY > 0 ) {
29748            newY = 0;
29749            this.keyAcceleration = 0;
29750        } else if ( newY < this.maxScrollY ) {
29751            newY = this.maxScrollY;
29752            this.keyAcceleration = 0;
29753        }
29754
29755        this.scrollTo(newX, newY, 0);
29756
29757        this.keyTime = now;
29758    },
29759
29760    _animate: function (destX, destY, duration, easingFn) {
29761        var that = this,
29762            startX = this.x,
29763            startY = this.y,
29764            startTime = utils.getTime(),
29765            destTime = startTime + duration;
29766
29767        function step () {
29768            var now = utils.getTime(),
29769                newX, newY,
29770                easing;
29771
29772            if ( now >= destTime ) {
29773                that.isAnimating = false;
29774                that._translate(destX, destY);
29775
29776                if ( !that.resetPosition(that.options.bounceTime) ) {
29777                    that._execEvent('scrollEnd');
29778                }
29779
29780                return;
29781            }
29782
29783            now = ( now - startTime ) / duration;
29784            easing = easingFn(now);
29785            newX = ( destX - startX ) * easing + startX;
29786            newY = ( destY - startY ) * easing + startY;
29787            that._translate(newX, newY);
29788
29789            if ( that.isAnimating ) {
29790                rAF(step);
29791            }
29792        }
29793
29794        this.isAnimating = true;
29795        step();
29796    },
29797    handleEvent: function (e) {
29798        switch ( e.type ) {
29799            case 'touchstart':
29800            case 'pointerdown':
29801            case 'MSPointerDown':
29802            case 'mousedown':
29803                this._start(e);
29804                break;
29805            case 'touchmove':
29806            case 'pointermove':
29807            case 'MSPointerMove':
29808            case 'mousemove':
29809                this._move(e);
29810                break;
29811            case 'touchend':
29812            case 'pointerup':
29813            case 'MSPointerUp':
29814            case 'mouseup':
29815            case 'touchcancel':
29816            case 'pointercancel':
29817            case 'MSPointerCancel':
29818            case 'mousecancel':
29819                this._end(e);
29820                break;
29821            case 'orientationchange':
29822            case 'resize':
29823                this._resize();
29824                break;
29825            case 'transitionend':
29826            case 'webkitTransitionEnd':
29827            case 'oTransitionEnd':
29828            case 'MSTransitionEnd':
29829                this._transitionEnd(e);
29830                break;
29831            case 'wheel':
29832            case 'DOMMouseScroll':
29833            case 'mousewheel':
29834                this._wheel(e);
29835                break;
29836            case 'keydown':
29837                this._key(e);
29838                break;
29839            case 'click':
29840                if ( this.enabled && !e._constructed ) {
29841                    e.preventDefault();
29842                    e.stopPropagation();
29843                }
29844                break;
29845        }
29846    }
29847};
29848function createDefaultScrollbar (direction, interactive, type) {
29849    var scrollbar = document.createElement('div'),
29850        indicator = document.createElement('div');
29851
29852    if ( type === true ) {
29853        scrollbar.style.cssText = 'position:absolute;z-index:9999';
29854        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';
29855    }
29856
29857    indicator.className = 'iScrollIndicator';
29858
29859    if ( direction == 'h' ) {
29860        if ( type === true ) {
29861            scrollbar.style.cssText += ';height:7px;left:2px;right:2px;bottom:0';
29862            indicator.style.height = '100%';
29863        }
29864        scrollbar.className = 'iScrollHorizontalScrollbar';
29865    } else {
29866        if ( type === true ) {
29867            scrollbar.style.cssText += ';width:7px;bottom:2px;top:2px;right:1px';
29868            indicator.style.width = '100%';
29869        }
29870        scrollbar.className = 'iScrollVerticalScrollbar';
29871    }
29872
29873    scrollbar.style.cssText += ';overflow:hidden';
29874
29875    if ( !interactive ) {
29876        scrollbar.style.pointerEvents = 'none';
29877    }
29878
29879    scrollbar.appendChild(indicator);
29880
29881    return scrollbar;
29882}
29883
29884function Indicator (scroller, options) {
29885    this.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el;
29886    this.wrapperStyle = this.wrapper.style;
29887    this.indicator = this.wrapper.children[0];
29888    this.indicatorStyle = this.indicator.style;
29889    this.scroller = scroller;
29890
29891    this.options = {
29892        listenX: true,
29893        listenY: true,
29894        interactive: false,
29895        resize: true,
29896        defaultScrollbars: false,
29897        shrink: false,
29898        fade: false,
29899        speedRatioX: 0,
29900        speedRatioY: 0
29901    };
29902
29903    for ( var i in options ) {
29904        this.options[i] = options[i];
29905    }
29906
29907    this.sizeRatioX = 1;
29908    this.sizeRatioY = 1;
29909    this.maxPosX = 0;
29910    this.maxPosY = 0;
29911
29912    if ( this.options.interactive ) {
29913        if ( !this.options.disableTouch ) {
29914            utils.addEvent(this.indicator, 'touchstart', this);
29915            utils.addEvent(window, 'touchend', this);
29916        }
29917        if ( !this.options.disablePointer ) {
29918            utils.addEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);
29919            utils.addEvent(window, utils.prefixPointerEvent('pointerup'), this);
29920        }
29921        if ( !this.options.disableMouse ) {
29922            utils.addEvent(this.indicator, 'mousedown', this);
29923            utils.addEvent(window, 'mouseup', this);
29924        }
29925    }
29926
29927    if ( this.options.fade ) {
29928        this.wrapperStyle[utils.style.transform] = this.scroller.translateZ;
29929        var durationProp = utils.style.transitionDuration;
29930        if(!durationProp) {
29931            return;
29932        }
29933        this.wrapperStyle[durationProp] = utils.isBadAndroid ? '0.0001ms' : '0ms';
29934        // remove 0.0001ms
29935        var self = this;
29936        if(utils.isBadAndroid) {
29937            rAF(function() {
29938                if(self.wrapperStyle[durationProp] === '0.0001ms') {
29939                    self.wrapperStyle[durationProp] = '0s';
29940                }
29941            });
29942        }
29943        this.wrapperStyle.opacity = '0';
29944    }
29945}
29946
29947Indicator.prototype = {
29948    handleEvent: function (e) {
29949        switch ( e.type ) {
29950            case 'touchstart':
29951            case 'pointerdown':
29952            case 'MSPointerDown':
29953            case 'mousedown':
29954                this._start(e);
29955                break;
29956            case 'touchmove':
29957            case 'pointermove':
29958            case 'MSPointerMove':
29959            case 'mousemove':
29960                this._move(e);
29961                break;
29962            case 'touchend':
29963            case 'pointerup':
29964            case 'MSPointerUp':
29965            case 'mouseup':
29966            case 'touchcancel':
29967            case 'pointercancel':
29968            case 'MSPointerCancel':
29969            case 'mousecancel':
29970                this._end(e);
29971                break;
29972        }
29973    },
29974
29975    destroy: function () {
29976        if ( this.options.fadeScrollbars ) {
29977            clearTimeout(this.fadeTimeout);
29978            this.fadeTimeout = null;
29979        }
29980        if ( this.options.interactive ) {
29981            utils.removeEvent(this.indicator, 'touchstart', this);
29982            utils.removeEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);
29983            utils.removeEvent(this.indicator, 'mousedown', this);
29984
29985            utils.removeEvent(window, 'touchmove', this);
29986            utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);
29987            utils.removeEvent(window, 'mousemove', this);
29988
29989            utils.removeEvent(window, 'touchend', this);
29990            utils.removeEvent(window, utils.prefixPointerEvent('pointerup'), this);
29991            utils.removeEvent(window, 'mouseup', this);
29992        }
29993
29994        if ( this.options.defaultScrollbars ) {
29995            this.wrapper.parentNode.removeChild(this.wrapper);
29996        }
29997    },
29998
29999    _start: function (e) {
30000        var point = e.touches ? e.touches[0] : e;
30001
30002        e.preventDefault();
30003        e.stopPropagation();
30004
30005        this.transitionTime();
30006
30007        this.initiated = true;
30008        this.moved = false;
vendor: 9,615 bytes, lines 30009-30267
30009        this.lastPointX = point.pageX;
30010        this.lastPointY = point.pageY;
30011
30012        this.startTime  = utils.getTime();
30013
30014        if ( !this.options.disableTouch ) {
30015            utils.addEvent(window, 'touchmove', this);
30016        }
30017        if ( !this.options.disablePointer ) {
30018            utils.addEvent(window, utils.prefixPointerEvent('pointermove'), this);
30019        }
30020        if ( !this.options.disableMouse ) {
30021            utils.addEvent(window, 'mousemove', this);
30022        }
30023
30024        this.scroller._execEvent('beforeScrollStart');
30025    },
30026
30027    _move: function (e) {
30028        var point = e.touches ? e.touches[0] : e,
30029            deltaX, deltaY,
30030            newX, newY,
30031            timestamp = utils.getTime();
30032
30033        if ( !this.moved ) {
30034            this.scroller._execEvent('scrollStart');
30035        }
30036
30037        this.moved = true;
30038
30039        deltaX = point.pageX - this.lastPointX;
30040        this.lastPointX = point.pageX;
30041
30042        deltaY = point.pageY - this.lastPointY;
30043        this.lastPointY = point.pageY;
30044
30045        newX = this.x + deltaX;
30046        newY = this.y + deltaY;
30047
30048        this._pos(newX, newY);
30049
30050// INSERT POINT: indicator._move
30051
30052        e.preventDefault();
30053        e.stopPropagation();
30054    },
30055
30056    _end: function (e) {
30057        if ( !this.initiated ) {
30058            return;
30059        }
30060
30061        this.initiated = false;
30062
30063        e.preventDefault();
30064        e.stopPropagation();
30065
30066        utils.removeEvent(window, 'touchmove', this);
30067        utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);
30068        utils.removeEvent(window, 'mousemove', this);
30069
30070        if ( this.scroller.options.snap ) {
30071            var snap = this.scroller._nearestSnap(this.scroller.x, this.scroller.y);
30072
30073            var time = this.options.snapSpeed || Math.max(
30074                    Math.max(
30075                        Math.min(Math.abs(this.scroller.x - snap.x), 1000),
30076                        Math.min(Math.abs(this.scroller.y - snap.y), 1000)
30077                    ), 300);
30078
30079            if ( this.scroller.x != snap.x || this.scroller.y != snap.y ) {
30080                this.scroller.directionX = 0;
30081                this.scroller.directionY = 0;
30082                this.scroller.currentPage = snap;
30083                this.scroller.scrollTo(snap.x, snap.y, time, this.scroller.options.bounceEasing);
30084            }
30085        }
30086
30087        if ( this.moved ) {
30088            this.scroller._execEvent('scrollEnd');
30089        }
30090    },
30091
30092    transitionTime: function (time) {
30093        time = time || 0;
30094        var durationProp = utils.style.transitionDuration;
30095        if(!durationProp) {
30096            return;
30097        }
30098
30099        this.indicatorStyle[durationProp] = time + 'ms';
30100
30101        if ( !time && utils.isBadAndroid ) {
30102            this.indicatorStyle[durationProp] = '0.0001ms';
30103            // remove 0.0001ms
30104            var self = this;
30105            rAF(function() {
30106                if(self.indicatorStyle[durationProp] === '0.0001ms') {
30107                    self.indicatorStyle[durationProp] = '0s';
30108                }
30109            });
30110        }
30111    },
30112
30113    transitionTimingFunction: function (easing) {
30114        this.indicatorStyle[utils.style.transitionTimingFunction] = easing;
30115    },
30116
30117    refresh: function () {
30118        this.transitionTime();
30119
30120        if ( this.options.listenX && !this.options.listenY ) {
30121            this.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none';
30122        } else if ( this.options.listenY && !this.options.listenX ) {
30123            this.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none';
30124        } else {
30125            this.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none';
30126        }
30127
30128        if ( this.scroller.hasHorizontalScroll && this.scroller.hasVerticalScroll ) {
30129            utils.addClass(this.wrapper, 'iScrollBothScrollbars');
30130            utils.removeClass(this.wrapper, 'iScrollLoneScrollbar');
30131
30132            if ( this.options.defaultScrollbars && this.options.customStyle ) {
30133                if ( this.options.listenX ) {
30134                    this.wrapper.style.right = '8px';
30135                } else {
30136                    this.wrapper.style.bottom = '8px';
30137                }
30138            }
30139        } else {
30140            utils.removeClass(this.wrapper, 'iScrollBothScrollbars');
30141            utils.addClass(this.wrapper, 'iScrollLoneScrollbar');
30142
30143            if ( this.options.defaultScrollbars && this.options.customStyle ) {
30144                if ( this.options.listenX ) {
30145                    this.wrapper.style.right = '2px';
30146                } else {
30147                    this.wrapper.style.bottom = '2px';
30148                }
30149            }
30150        }
30151
30152        var r = this.wrapper.offsetHeight;  // force refresh
30153
30154        if ( this.options.listenX ) {
30155            this.wrapperWidth = this.wrapper.clientWidth;
30156            if ( this.options.resize ) {
30157                this.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / (this.scroller.scrollerWidth || this.wrapperWidth || 1)), 8);
30158                this.indicatorStyle.width = this.indicatorWidth + 'px';
30159            } else {
30160                this.indicatorWidth = this.indicator.clientWidth;
30161            }
30162
30163            this.maxPosX = this.wrapperWidth - this.indicatorWidth;
30164
30165            if ( this.options.shrink == 'clip' ) {
30166                this.minBoundaryX = -this.indicatorWidth + 8;
30167                this.maxBoundaryX = this.wrapperWidth - 8;
30168            } else {
30169                this.minBoundaryX = 0;
30170                this.maxBoundaryX = this.maxPosX;
30171            }
30172
30173            this.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX));
30174        }
30175
30176        if ( this.options.listenY ) {
30177            this.wrapperHeight = this.wrapper.clientHeight;
30178            if ( this.options.resize ) {
30179                this.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / (this.scroller.scrollerHeight || this.wrapperHeight || 1)), 8);
30180                this.indicatorStyle.height = this.indicatorHeight + 'px';
30181            } else {
30182                this.indicatorHeight = this.indicator.clientHeight;
30183            }
30184
30185            this.maxPosY = this.wrapperHeight - this.indicatorHeight;
30186
30187            if ( this.options.shrink == 'clip' ) {
30188                this.minBoundaryY = -this.indicatorHeight + 8;
30189                this.maxBoundaryY = this.wrapperHeight - 8;
30190            } else {
30191                this.minBoundaryY = 0;
30192                this.maxBoundaryY = this.maxPosY;
30193            }
30194
30195            this.maxPosY = this.wrapperHeight - this.indicatorHeight;
30196            this.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY));
30197        }
30198
30199        this.updatePosition();
30200    },
30201
30202    updatePosition: function () {
30203        var x = this.options.listenX && Math.round(this.sizeRatioX * this.scroller.x) || 0,
30204            y = this.options.listenY && Math.round(this.sizeRatioY * this.scroller.y) || 0;
30205
30206        if ( !this.options.ignoreBoundaries ) {
30207            if ( x < this.minBoundaryX ) {
30208                if ( this.options.shrink == 'scale' ) {
30209                    this.width = Math.max(this.indicatorWidth + x, 8);
30210                    this.indicatorStyle.width = this.width + 'px';
30211                }
30212                x = this.minBoundaryX;
30213            } else if ( x > this.maxBoundaryX ) {
30214                if ( this.options.shrink == 'scale' ) {
30215                    this.width = Math.max(this.indicatorWidth - (x - this.maxPosX), 8);
30216                    this.indicatorStyle.width = this.width + 'px';
30217                    x = this.maxPosX + this.indicatorWidth - this.width;
30218                } else {
30219                    x = this.maxBoundaryX;
30220                }
30221            } else if ( this.options.shrink == 'scale' && this.width != this.indicatorWidth ) {
30222                this.width = this.indicatorWidth;
30223                this.indicatorStyle.width = this.width + 'px';
30224            }
30225
30226            if ( y < this.minBoundaryY ) {
30227                if ( this.options.shrink == 'scale' ) {
30228                    this.height = Math.max(this.indicatorHeight + y * 3, 8);
30229                    this.indicatorStyle.height = this.height + 'px';
30230                }
30231                y = this.minBoundaryY;
30232            } else if ( y > this.maxBoundaryY ) {
30233                if ( this.options.shrink == 'scale' ) {
30234                    this.height = Math.max(this.indicatorHeight - (y - this.maxPosY) * 3, 8);
30235                    this.indicatorStyle.height = this.height + 'px';
30236                    y = this.maxPosY + this.indicatorHeight - this.height;
30237                } else {
30238                    y = this.maxBoundaryY;
30239                }
30240            } else if ( this.options.shrink == 'scale' && this.height != this.indicatorHeight ) {
30241                this.height = this.indicatorHeight;
30242                this.indicatorStyle.height = this.height + 'px';
30243            }
30244        }
30245
30246        this.x = x;
30247        this.y = y;
30248
30249        if ( this.scroller.options.useTransform ) {
30250            this.indicatorStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.scroller.translateZ;
30251        } else {
30252            this.indicatorStyle.left = x + 'px';
30253            this.indicatorStyle.top = y + 'px';
30254        }
30255    },
30256
30257    _pos: function (x, y) {
30258        if ( x < 0 ) {
30259            x = 0;
30260        } else if ( x > this.maxPosX ) {
30261            x = this.maxPosX;
30262        }
30263
30264        if ( y < 0 ) {
30265            y = 0;
30266        } else if ( y > this.maxPosY ) {
30267            y = this.maxPosY;
30268        }
30269
30270        x = this.options.listenX ? Math.round(x / this.sizeRatioX) : this.scroller.x;
30271        y = this.options.listenY ? Math.round(y / this.sizeRatioY) : this.scroller.y;
30272
30273        this.scroller.scrollTo(x, y);
30274    },
30275
30276    fade: function (val, hold) {
30277        if ( hold && !this.visible ) {
30278            return;
30279        }
30280
30281        clearTimeout(this.fadeTimeout);
30282        this.fadeTimeout = null;
30283
30284        var time = val ? 250 : 500,
30285            delay = val ? 0 : 300;
30286
30287        val = val ? '1' : '0';
30288
30289        this.wrapperStyle[utils.style.transitionDuration] = time + 'ms';
30290
30291        this.fadeTimeout = setTimeout((function (val) {
30292            this.wrapperStyle.opacity = val;
30293            this.visible = +val;
30294        }).bind(this, val), delay);
30295    }
30296};
30297
30298IScroll.utils = utils;
30299
30300if ( typeof module != 'undefined' && module.exports ) {
30301    module.exports = IScroll;
30302} else if ( typeof define == 'function' && define.amd ) {
30303        define( function () { return IScroll; } );
30304} else {
30305    window.IScroll = IScroll;
30306}
30307
30308})(window, document, Math);
30309/*!
30310 * fullPage 2.9.4
30311 * https://github.com/alvarotrigo/fullPage.js
30312 * @license MIT licensed
30313 *
30314 * Copyright (C) 2015 alvarotrigo.com - A project by Alvaro Trigo
30315 */
30316(function(global, factory) {
30317    'use strict';
30318    if (typeof define === 'function' && define.amd) {
30319        define(['jquery'], function($) {
30320          return factory($, global, global.document, global.Math);
30321        });
30322    } else if (typeof exports === "object" && exports) {
30323        module.exports = factory(require('jquery'), global, global.document, global.Math);
30324    } else {
30325        factory(jQuery, global, global.document, global.Math);
30326    }
30327})(typeof window !== 'undefined' ? window : this, function($, window, document, Math, undefined) {
30328    'use strict';
30329
30330    // keeping central set of classnames and selectors
30331    var WRAPPER =               'fullpage-wrapper';
30332    var WRAPPER_SEL =           '.' + WRAPPER;
30333
30334    // slimscroll
30335    var SCROLLABLE =            'fp-scrollable';
30336    var SCROLLABLE_SEL =        '.' + SCROLLABLE;
30337
30338    // util
30339    var RESPONSIVE =            'fp-responsive';
30340    var NO_TRANSITION =         'fp-notransition';
30341    var DESTROYED =             'fp-destroyed';
30342    var ENABLED =               'fp-enabled';
30343    var VIEWING_PREFIX =        'fp-viewing';
30344    var ACTIVE =                'active';
30345    var ACTIVE_SEL =            '.' + ACTIVE;
30346    var COMPLETELY =            'fp-completely';
30347    var COMPLETELY_SEL =        '.' + COMPLETELY;
30348
30349    // section
30350    var SECTION_DEFAULT_SEL =   '.section';
30351    var SECTION =               'fp-section';
30352    var SECTION_SEL =           '.' + SECTION;
30353    var SECTION_ACTIVE_SEL =    SECTION_SEL + ACTIVE_SEL;
30354    var SECTION_FIRST_SEL =     SECTION_SEL + ':first';
30355    var SECTION_LAST_SEL =      SECTION_SEL + ':last';
30356    var TABLE_CELL =            'fp-tableCell';
30357    var TABLE_CELL_SEL =        '.' + TABLE_CELL;
30358    var AUTO_HEIGHT =           'fp-auto-height';
30359    var AUTO_HEIGHT_SEL =       '.fp-auto-height';
30360    var NORMAL_SCROLL =         'fp-normal-scroll';
30361    var NORMAL_SCROLL_SEL =     '.fp-normal-scroll';
30362
30363    // section nav
30364    var SECTION_NAV =           'fp-nav';
30365    var SECTION_NAV_SEL =       '#' + SECTION_NAV;
30366    var SECTION_NAV_TOOLTIP =   'fp-tooltip';
30367    var SECTION_NAV_TOOLTIP_SEL='.'+SECTION_NAV_TOOLTIP;
30368    var SHOW_ACTIVE_TOOLTIP =   'fp-show-active';
30369
30370    // slide
30371    var SLIDE_DEFAULT_SEL =     '.slide';
30372    var SLIDE =                 'fp-slide';
30373    var SLIDE_SEL =             '.' + SLIDE;
30374    var SLIDE_ACTIVE_SEL =      SLIDE_SEL + ACTIVE_SEL;
30375    var SLIDES_WRAPPER =        'fp-slides';
30376    var SLIDES_WRAPPER_SEL =    '.' + SLIDES_WRAPPER;
30377    var SLIDES_CONTAINER =      'fp-slidesContainer';
30378    var SLIDES_CONTAINER_SEL =  '.' + SLIDES_CONTAINER;
30379    var TABLE =                 'fp-table';
30380
30381    // slide nav
30382    var SLIDES_NAV =            'fp-slidesNav';
30383    var SLIDES_NAV_SEL =        '.' + SLIDES_NAV;
30384    var SLIDES_NAV_LINK_SEL =   SLIDES_NAV_SEL + ' a';
30385    var SLIDES_ARROW =          'fp-controlArrow';
30386    var SLIDES_ARROW_SEL =      '.' + SLIDES_ARROW;
30387    var SLIDES_PREV =           'fp-prev';
30388    var SLIDES_PREV_SEL =       '.' + SLIDES_PREV;
30389    var SLIDES_ARROW_PREV =     SLIDES_ARROW + ' ' + SLIDES_PREV;
30390    var SLIDES_ARROW_PREV_SEL = SLIDES_ARROW_SEL + SLIDES_PREV_SEL;
30391    var SLIDES_NEXT =           'fp-next';
30392    var SLIDES_NEXT_SEL =       '.' + SLIDES_NEXT;
30393    var SLIDES_ARROW_NEXT =     SLIDES_ARROW + ' ' + SLIDES_NEXT;
30394    var SLIDES_ARROW_NEXT_SEL = SLIDES_ARROW_SEL + SLIDES_NEXT_SEL;
30395
30396    var $window = $(window);
30397    var $document = $(document);
30398
30399    // Default options for iScroll.js used when using scrollOverflow
30400    var iscrollOptions = {
30401        scrollbars: true,
30402        mouseWheel: true,
30403        hideScrollbars: false,
30404        fadeScrollbars: false,
30405        disableMouse: true,
30406        interactiveScrollbars: true,
30407        bounce: false,
30408    };
30409
30410    $.fn.fullpage = function(options) {
30411        //only once my friend!
30412        if($('html').hasClass(ENABLED)){ displayWarnings(); return; }
30413
30414        // common jQuery objects
30415        var $htmlBody = $('html, body');
30416        var $body = $('body');
30417
30418        var FP = $.fn.fullpage;
30419
30420        // Creating some defaults, extending them with any options that were provided
30421        options = $.extend({
30422            //navigation
30423            menu: false,
30424            anchors:[],
30425            lockAnchors: false,
30426            navigation: false,
30427            navigationPosition: 'right',
30428            navigationTooltips: [],
30429            showActiveTooltip: false,
30430            slidesNavigation: false,
30431            slidesNavPosition: 'bottom',
30432            scrollBar: false,
30433            hybrid: false,
30434
30435            //scrolling
30436            css3: true,
30437            scrollingSpeed: 700,
30438            autoScrolling: true,
30439            fitToSection: true,
30440            fitToSectionDelay: 1000,
30441            easing: 'easeInOutCubic',
30442            easingcss3: 'ease',
30443            loopBottom: false,
30444            loopTop: false,
30445            loopHorizontal: true,
30446            continuousVertical: false,
30447            continuousHorizontal: false,
30448            scrollHorizontally: false,
30449            interlockedSlides: false,
30450            dragAndMove: false,
30451            offsetSections: false,
30452            resetSliders: false,
30453            fadingEffect: false,
30454            normalScrollElements: null,
30455            scrollOverflow: false,
30456            scrollOverflowReset: false,
30457            scrollOverflowHandler: iscrollHandler,
30458            scrollOverflowOptions: null,
30459            touchSensitivity: 5,
30460            normalScrollElementTouchThreshold: 5,
30461            bigSectionsDestination: null,
30462
30463            //Accessibility
30464            keyboardScrolling: true,
30465            animateAnchor: true,
30466            recordHistory: true,
30467
30468            //design
30469            controlArrows: true,
30470            controlArrowColor: '#fff',
30471            verticalCentered: true,
30472            sectionsColor : [],
30473            paddingTop: 0,
30474            paddingBottom: 0,
30475            fixedElements: null,
30476            responsive: 0, //backwards compabitility with responsiveWiddth
30477            responsiveWidth: 0,
30478            responsiveHeight: 0,
30479            responsiveSlides: false,
30480            parallax: false,
30481            parallaxOptions: {
30482                type: 'reveal',
30483                percentage: 62,
30484                property: 'translate'
30485            },
30486
30487            //Custom selectors
30488            sectionSelector: SECTION_DEFAULT_SEL,
30489            slideSelector: SLIDE_DEFAULT_SEL,
30490
30491            //events
30492            afterLoad: null,
30493            onLeave: null,
30494            afterRender: null,
30495            afterResize: null,
30496            afterReBuild: null,
30497            afterSlideLoad: null,
30498            onSlideLeave: null,
30499            afterResponsive: null,
30500
30501            lazyLoading: true
30502        }, options);
30503
30504        //flag to avoid very fast sliding for landscape sliders
30505        var slideMoving = false;
30506
30507        var isTouchDevice = navigator.userAgent.match(/(iPhone|iPod|iPad|Android|playbook|silk|BlackBerry|BB10|Windows Phone|Tizen|Bada|webOS|IEMobile|Opera Mini)/);
30508        var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0) || (navigator.maxTouchPoints));
30509        var container = $(this);
30510        var windowsHeight = $window.height();
30511        var isResizing = false;
30512        var isWindowFocused = true;
30513        var lastScrolledDestiny;
30514        var lastScrolledSlide;
30515        var canScroll = true;
30516        var scrollings = [];
30517        var controlPressed;
30518        var startingSection;
30519        var isScrollAllowed = {};
30520        isScrollAllowed.m = {  'up':true, 'down':true, 'left':true, 'right':true };
30521        isScrollAllowed.k = $.extend(true,{}, isScrollAllowed.m);
30522        var MSPointer = getMSPointer();
30523        var events = {
30524            touchmove: 'ontouchmove' in window ? 'touchmove' :  MSPointer.move,
30525            touchstart: 'ontouchstart' in window ? 'touchstart' :  MSPointer.down
30526        };
30527
30528        //cheks for passive event support
30529        //added by Uncode from new fullPage updates
30530        var g_supportsPassive = false;
30531        try {
30532          var opts = Object.defineProperty({}, 'passive', {
30533            get: function() {
30534              g_supportsPassive = true;
30535            }
30536          });
30537          window.addEventListener("testPassive", null, opts);
30538          window.removeEventListener("testPassive", null, opts);
30539        } catch (e) {}
30540
30541        //timeouts
30542        var resizeId;
30543        var afterSectionLoadsId;
30544        var afterSlideLoadsId;
30545        var scrollId;
30546        var scrollId2;
30547        var keydownId;
30548        var originals = $.extend(true, {}, options); //deep copy
30549
30550        //Uncode addition
30551        var $masthead = $('#masthead');
30552        var hideMenu = !$('body').hasClass('vmenu') && $('body').hasClass('uncode-fp-menu-hide') ? true : false;
30553        var menuHeight = $masthead.hasClass('menu-transparent') || hideMenu ? 0 : UNCODE.menuHeight;
30554        var bodyBorder = UNCODE.bodyBorder;
30555        var adminBarHeight = UNCODE.adminBarHeight;
30556
30557        displayWarnings();
30558
30559        //fixing bug in iScroll with links: https://github.com/cubiq/iscroll/issues/783
30560        iscrollOptions.click = isTouch; // see #2035
30561
30562        //extending iScroll options with the user custom ones
30563        iscrollOptions = $.extend(iscrollOptions, options.scrollOverflowOptions);
30564
30565        //easeInOutCubic animation included in the plugin
30566        $.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;}});
30567
30568        /**
30569        * Sets the autoScroll option.
30570        * It changes the scroll bar visibility and the history of the site as a result.
30571        */
30572        function setAutoScrolling(value, type){
30573            //removing the transformation
30574            if(!value){
30575                silentScroll(0);
30576            }
30577
30578            setVariableState('autoScrolling', value, type);
30579
30580            var element = $(SECTION_ACTIVE_SEL);
30581
30582            if(options.autoScrolling && !options.scrollBar){
30583                $htmlBody.css({
30584                    'overflow' : 'hidden !important',
30585                    'height' : '100%'
30586                });
30587
30588                //Uncode addition
30589                //setRecordHistory(originals.recordHistory, 'internal');
30590
30591                //for IE touch devices
30592                container.css({
30593                    '-ms-touch-action': 'none',
30594                    'touch-action': 'none'
30595                });
30596
30597                if(element.length){
30598                    //moving the container up
30599                    silentScroll(element.position().top);
30600                }
30601
30602            }else{
30603                $htmlBody.css({
30604                    'overflow' : 'visible !important',
30605                    'height' : 'initial'
30606                });
30607
30608                //Uncode addition
30609                //setRecordHistory(false, 'internal');
30610
30611                //for IE touch devices
30612                container.css({
30613                    '-ms-touch-action': '',
30614                    'touch-action': ''
30615                });
30616
30617                //scrolling the page to the section with no animation
30618                if (element.length) {
30619                    $htmlBody.scrollTop(element.position().top);
30620                }
30621            }
30622        }
30623
30624        /**
30625        * Defines wheter to record the history for each hash change in the URL.
30626        */
30627        function setRecordHistory(value, type){
30628            setVariableState('recordHistory', value, type);
30629        }
30630
30631        /**
30632        * Defines the scrolling speed
30633        */
30634        function setScrollingSpeed(value, type){
30635            setVariableState('scrollingSpeed', value, type);
30636        }
30637
30638        /**
30639        * Sets fitToSection
30640        */
30641        function setFitToSection(value, type){
30642            setVariableState('fitToSection', value, type);
30643        }
30644
30645        /**
30646        * Sets lockAnchors
30647        */
30648        function setLockAnchors(value){
30649            options.lockAnchors = value;
30650        }
30651
30652        /**
30653        * Adds or remove the possiblity of scrolling through sections by using the mouse wheel or the trackpad.
30654        */
30655        function setMouseWheelScrolling(value){
30656            if(value){
30657                addMouseWheelHandler();
30658                addMiddleWheelHandler();
30659            }else{
30660                removeMouseWheelHandler();
30661                removeMiddleWheelHandler();
30662            }
30663        }
30664
30665        /**
30666        * Adds or remove the possibility of scrolling through sections by using the mouse wheel/trackpad or touch gestures.
30667        * Optionally a second parameter can be used to specify the direction for which the action will be applied.
30668        *
30669        * @param directions string containing the direction or directions separated by comma.
30670        */
30671        function setAllowScrolling(value, directions){
30672            if(typeof directions !== 'undefined'){
30673                directions = directions.replace(/ /g,'').split(',');
30674
30675                $.each(directions, function (index, direction){
30676                    setIsScrollAllowed(value, direction, 'm');
30677                });
30678            }
30679            else if(value){
30680                setMouseWheelScrolling(true);
30681                addTouchHandler();
30682            }else{
30683                setMouseWheelScrolling(false);
30684                removeTouchHandler();
30685            }
30686        }
30687
30688        /**
30689        * Adds or remove the possibility of scrolling through sections by using the keyboard arrow keys
30690        */
30691        function setKeyboardScrolling(value, directions){
30692            if(typeof directions !== 'undefined'){
30693                directions = directions.replace(/ /g,'').split(',');
30694
30695                $.each(directions, function (index, direction){
30696                    setIsScrollAllowed(value, direction, 'k');
30697                });
30698            }else{
30699                options.keyboardScrolling = value;
30700            }
30701        }
30702
30703        /**
30704        * Moves the page up one section.
30705        */
30706        function moveSectionUp(){
30707            var prev = $(SECTION_ACTIVE_SEL).prev(SECTION_SEL);
30708
30709            //looping to the bottom if there's no more sections above
30710            if (!prev.length && (options.loopTop || options.continuousVertical)) {
30711                prev = $(SECTION_SEL).last();
30712            }
30713
30714            if (prev.length) {
30715                scrollPage(prev, null, true);
30716            }
30717        }
30718
30719        /**
30720        * Moves the page down one section.
30721        */
30722        function moveSectionDown(){
30723            var next = $(SECTION_ACTIVE_SEL).next(SECTION_SEL);
30724
30725            //looping to the top if there's no more sections below
30726            if(!next.length &&
30727                (options.loopBottom || options.continuousVertical)){
30728                next = $(SECTION_SEL).first();
30729            }
30730
30731            if(next.length){
30732                scrollPage(next, null, false);
30733            }
30734        }
30735
30736        /**
30737        * Moves the page to the given section and slide with no animation.
30738        * Anchors or index positions can be used as params.
30739        */
30740        function silentMoveTo(sectionAnchor, slideAnchor){
30741            setScrollingSpeed (0, 'internal');
30742            moveTo(sectionAnchor, slideAnchor);
30743            setScrollingSpeed (originals.scrollingSpeed, 'internal');
30744        }
30745
30746        /**
30747        * Moves the page to the given section and slide.
30748        * Anchors or index positions can be used as params.
30749        */
30750        function moveTo(sectionAnchor, slideAnchor){
30751            var destiny = getSectionByAnchor(sectionAnchor);
30752
30753            if (typeof slideAnchor !== 'undefined'){
30754                scrollPageAndSlide(sectionAnchor, slideAnchor);
30755            }else if(destiny.length > 0){
30756                scrollPage(destiny);
30757            }
30758        }
30759
30760        /**
30761        * Slides right the slider of the active section.
30762        * Optional `section` param.
30763        */
30764        function moveSlideRight(section){
30765            moveSlide('right', section);
30766        }
30767
30768        /**
30769        * Slides left the slider of the active section.
30770        * Optional `section` param.
30771        */
30772        function moveSlideLeft(section){
30773            moveSlide('left', section);
30774        }
30775
30776        /**
30777         * When resizing is finished, we adjust the slides sizes and positions
30778         */
30779        function reBuild(resizing){
30780            if(container.hasClass(DESTROYED)){ return; }  //nothing to do if the plugin was destroyed
30781
30782            isResizing = true;
30783
30784            windowsHeight = $window.height();  //updating global var
30785
30786            $(SECTION_SEL).each(function(){
30787                var slidesWrap = $(this).find(SLIDES_WRAPPER_SEL);
30788                var slides = $(this).find(SLIDE_SEL);
30789
30790                //adjusting the height of the table-cell for IE and Firefox
30791                if(options.verticalCentered){
30792                    $(this).find(TABLE_CELL_SEL).css('height', getTableHeight($(this)) + 'px');
30793                }
30794
30795                $(this).css('height', windowsHeight + 'px');
30796
30797                //resizing the scrolling divs
30798                if(options.scrollOverflow){
30799                    if(slides.length){
30800                        slides.each(function(){
30801                            createScrollBar($(this));
30802                        });
30803                    }else{
30804                        createScrollBar($(this));
30805                    }
30806                }
30807
30808                //adjusting the position fo the FULL WIDTH slides...
30809                if (slides.length > 1) {
30810                    landscapeScroll(slidesWrap, slidesWrap.find(SLIDE_ACTIVE_SEL));
30811                }
30812            });
30813
30814            var activeSection = $(SECTION_ACTIVE_SEL);
30815            var sectionIndex = activeSection.index(SECTION_SEL);
30816
30817            //isn't it the first section?
30818            if(sectionIndex){
30819                //adjusting the position for the current section
30820                silentMoveTo(sectionIndex + 1);
30821            }
30822
30823            isResizing = false;
30824            // Uncode change
30825            // $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container);
30826            $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container, getTableHeight());
30827            $.isFunction( options.afterReBuild ) && !resizing && options.afterReBuild.call(container);
30828        }
30829
30830        /**
30831        * Turns fullPage.js to normal scrolling mode when the viewport `width` or `height`
30832        * are smaller than the set limit values.
30833        */
30834        function setResponsive(active){
30835            var isResponsive = $body.hasClass(RESPONSIVE);
30836
30837            if(active){
30838                if(!isResponsive){
30839                    setAutoScrolling(false, 'internal');
30840                    setFitToSection(false, 'internal');
30841                    $(SECTION_NAV_SEL).hide();
30842                    $body.addClass(RESPONSIVE);
30843                    $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active);
30844                }
30845            }
30846            else if(isResponsive){
30847                setAutoScrolling(originals.autoScrolling, 'internal');
30848                setFitToSection(originals.autoScrolling, 'internal');
30849                $(SECTION_NAV_SEL).show();
30850                $body.removeClass(RESPONSIVE);
30851                $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active);
30852            }
30853        }
30854
30855        if($(this).length){
30856            //public functions
30857            FP.setAutoScrolling = setAutoScrolling;
30858            FP.setRecordHistory = setRecordHistory;
30859            FP.setScrollingSpeed = setScrollingSpeed;
30860            FP.setFitToSection = setFitToSection;
30861            FP.setLockAnchors = setLockAnchors;
30862            FP.setMouseWheelScrolling = setMouseWheelScrolling;
30863            FP.setAllowScrolling = setAllowScrolling;
30864            FP.setKeyboardScrolling = setKeyboardScrolling;
30865            FP.moveSectionUp = moveSectionUp;
30866            FP.moveSectionDown = moveSectionDown;
30867            FP.silentMoveTo = silentMoveTo;
30868            FP.moveTo = moveTo;
30869            FP.moveSlideRight = moveSlideRight;
30870            FP.moveSlideLeft = moveSlideLeft;
30871            FP.fitToSection = fitToSection;
30872            FP.reBuild = reBuild;
30873            FP.setResponsive = setResponsive;
30874            FP.destroy = destroy;
30875
30876            init();
30877
30878            bindEvents();
30879        }
30880
30881        function init(){
30882            //if css3 is not supported, it will use jQuery animations
30883            if(options.css3){
30884                options.css3 = support3d();
30885            }
30886
30887            options.scrollBar = options.scrollBar || options.hybrid;
30888
30889            setOptionsFromDOM();
30890            prepareDom();
30891            setAllowScrolling(true);
30892            setAutoScrolling(options.autoScrolling, 'internal');
30893            responsive();
30894
30895            //setting the class for the body element
30896            setBodyClass();
30897
30898            //Uncode addition
30899            // if(document.readyState === 'complete'){
30900            //     scrollToAnchor();
30901            // }
30902            // $window.on('load', scrollToAnchor);
30903        }
30904
30905        function bindEvents(){
30906            $window
30907                //when scrolling...
30908                //.on('scroll', scrollHandler)
30909
30910                //detecting any change on the URL to scroll to the given anchor link
30911                //(a way to detect back history button as we play with the hashes on the URL)
30912                .on('hashchange', hashChangeHandler)
30913
30914                //when opening a new tab (ctrl + t), `control` won't be pressed when coming back.
30915                .blur(blurHandler)
30916
30917                //when resizing the site, we adjust the heights of the sections, slimScroll...
30918                .resize(resizeHandler);
30919
30920            $document
30921                //Sliding with arrow keys, both, vertical and horizontal
30922                .keydown(keydownHandler)
30923
30924                //to prevent scrolling while zooming
30925                .keyup(keyUpHandler)
30926
30927                //Scrolls to the section when clicking the navigation bullet
30928                .on('click touchstart', SECTION_NAV_SEL + ' a', sectionBulletHandler)
30929
30930                //Scrolls the slider to the given slide destination for the given section
30931                .on('click touchstart', SLIDES_NAV_LINK_SEL, slideBulletHandler)
30932
30933                .on('click', SECTION_NAV_TOOLTIP_SEL, tooltipTextHandler);
30934
30935            //Scrolling horizontally when clicking on the slider controls.
30936            $(SECTION_SEL).on('click touchstart', SLIDES_ARROW_SEL, slideArrowHandler);
30937
30938            /**
30939            * Applying normalScroll elements.
30940            * Ignoring the scrolls over the specified selectors.
30941            */
30942            if(options.normalScrollElements){
30943                $document.on('mouseenter', options.normalScrollElements, function () {
30944                    setMouseWheelScrolling(false);
30945                });
30946
30947                $document.on('mouseleave', options.normalScrollElements, function(){
30948                    setMouseWheelScrolling(true);
30949                });
30950            }
30951        }
30952
30953        /**
30954        * Setting options from DOM elements if they are not provided.
30955        */
30956        function setOptionsFromDOM(){
30957            var sections = container.find(options.sectionSelector);
30958
30959            //no anchors option? Checking for them in the DOM attributes
30960            if(!options.anchors.length){
30961                options.anchors = sections.filter('[data-anchor]').map(function(){
30962                    return $(this).data('anchor').toString();
30963                }).get();
30964            }
30965
30966            //no tooltips option? Checking for them in the DOM attributes
30967            if(!options.navigationTooltips.length){
30968                options.navigationTooltips = sections.filter('[data-tooltip]').map(function(){
30969                    return $(this).data('tooltip').toString();
30970                }).get();
30971            }
30972        }
30973
30974        /**
30975        * Works over the DOM structure to set it up for the current fullpage options.
30976        */
30977        function prepareDom(){
30978            container.css({
30979                'height': '100%',
30980                'position': 'relative'
30981            });
30982
30983            //adding a class to recognize the container internally in the code
30984            container.addClass(WRAPPER);
30985            $('html').addClass(ENABLED);
30986
30987            windowsHeight = $window.height();
30988
30989            container.removeClass(DESTROYED); //in case it was destroyed before initializing it again
30990
30991            addInternalSelectors();
30992
30993             //styling the sections / slides / menu
30994            $(SECTION_SEL).each(function(index){
30995                var section = $(this);
30996                var slides = section.find(SLIDE_SEL);
30997                var numSlides = slides.length;
30998
30999                styleSection(section, index);
31000                styleMenu(section, index);
31001
31002                // if there's any slide
31003                if (numSlides > 0) {
31004                    styleSlides(section, slides, numSlides);
31005                }else{
31006                    if(options.verticalCentered){
31007                        addTableClass(section);
31008                    }
31009                }
31010            });
31011
31012            //fixed elements need to be moved out of the plugin container due to problems with CSS3.
31013            if(options.fixedElements && options.css3){
31014                $(options.fixedElements).appendTo($body);
31015            }
31016
31017            //vertical centered of the navigation + active bullet
31018            if(options.navigation){
31019                addVerticalNavigation();
31020            }
31021
31022            enableYoutubeAPI();
31023
31024            if(options.scrollOverflow){
31025                if(document.readyState === 'complete'){
31026                    createScrollBarHandler();
31027                }
31028                //after DOM and images are loaded
31029                $window.on('load', createScrollBarHandler);
31030            }else{
31031                afterRenderActions();
31032            }
31033        }
31034
31035        /**
31036        * Styles the horizontal slides for a section.
31037        */
31038        function styleSlides(section, slides, numSlides){
31039            var sliderWidth = numSlides * 100;
31040            var slideWidth = 100 / numSlides;
31041
31042            slides.wrapAll('<div class="' + SLIDES_CONTAINER + '" />');
31043            slides.parent().wrap('<div class="' + SLIDES_WRAPPER + '" />');
31044
31045            section.find(SLIDES_CONTAINER_SEL).css('width', sliderWidth + '%');
31046
31047            if(numSlides > 1){
31048                if(options.controlArrows){
31049                    createSlideArrows(section);
31050                }
31051
31052                if(options.slidesNavigation){
31053                    addSlidesNavigation(section, numSlides);
31054                }
31055            }
31056
31057            slides.each(function(index) {
31058                $(this).css('width', slideWidth + '%');
31059
31060                if(options.verticalCentered){
31061                    addTableClass($(this));
31062                }
31063            });
31064
31065            var startingSlide = section.find(SLIDE_ACTIVE_SEL);
31066
31067            //if the slide won't be an starting point, the default will be the first one
31068            //the active section isn't the first one? Is not the first slide of the first section? Then we load that section/sl
31068ide by default.
31069            if( startingSlide.length &&  ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) !== 0 || ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) === 0 && startingSlide.index() !== 0))){
31070                silentLandscapeScroll(startingSlide, 'internal');
31071            }else{
31072                slides.eq(0).addClass(ACTIVE);
31073            }
31074        }
31075
31076        /**
31077        * Styling vertical sections
31078        */
31079        function styleSection(section, index){
31080            //if no active section is defined, the 1st one will be the default one
31081            if(!index && $(SECTION_ACTIVE_SEL).length === 0) {
31082                section.addClass(ACTIVE);
31083            }
31084            startingSection = $(SECTION_ACTIVE_SEL);
31085
31086            section.css('height', windowsHeight + 'px');
31087
31088            if(options.paddingTop){
31089                section.css('padding-top', options.paddingTop);
31090            }
31091
31092            if(options.paddingBottom){
31093                section.css('padding-bottom', options.paddingBottom);
31094            }
31095
31096            if (typeof options.sectionsColor[index] !==  'undefined') {
31097                section.css('background-color', options.sectionsColor[index]);
31098            }
31099
31100            if (typeof options.anchors[index] !== 'undefined') {
31101                section.attr('data-anchor', options.anchors[index]);
31102            }
31103        }
31104
31105        /**
31106        * Sets the data-anchor attributes to the menu elements and activates the current one.
31107        */
31108        function styleMenu(section, index){
31109            if (typeof options.anchors[index] !== 'undefined') {
31110                //activating the menu / nav element on load
31111                if(section.hasClass(ACTIVE)){
31112                    activateMenuAndNav(options.anchors[index], index);
31113                }
31114            }
31115
31116            //moving the menu outside the main container if it is inside (avoid problems with fixed positions when using CSS3 tranforms)
31117            if(options.menu && options.css3 && $(options.menu).closest(WRAPPER_SEL).length){
31118                $(options.menu).appendTo($body);
31119            }
31120        }
31121
31122        /**
31123        * Adds internal classes to be able to provide customizable selectors
31124        * keeping the link with the style sheet.
31125        */
31126        function addInternalSelectors(){
31127            container.find(options.sectionSelector).addClass(SECTION);
31128            container.find(options.slideSelector).addClass(SLIDE);
31129        }
31130
31131        /**
31132        * Creates the control arrows for the given section
31133        */
31134        function createSlideArrows(section){
31135            section.find(SLIDES_WRAPPER_SEL).after('<div class="' + SLIDES_ARROW_PREV + '"></div><div class="' + SLIDES_ARROW_NEXT + '"></div>');
31136
31137            if(options.controlArrowColor!='#fff'){
31138                section.find(SLIDES_ARROW_NEXT_SEL).css('border-color', 'transparent transparent transparent '+options.controlArrowColor);
31139                section.find(SLIDES_ARROW_PREV_SEL).css('border-color', 'transparent '+ options.controlArrowColor + ' transparent transparent');
31140            }
31141
31142            if(!options.loopHorizontal){
31143                section.find(SLIDES_ARROW_PREV_SEL).hide();
31144            }
31145        }
31146
31147        /**
31148        * Creates a vertical navigation bar.
31149        */
31150        function addVerticalNavigation(){
31151            $body.append('<div id="' + SECTION_NAV + '"><ul></ul></div>');
31152            var nav = $(SECTION_NAV_SEL);
31153
31154            nav.addClass(function() {
31155                return options.showActiveTooltip ? SHOW_ACTIVE_TOOLTIP + ' ' + options.navigationPosition : options.navigationPosition;
31156            });
31157
31158            for (var i = 0; i < $(SECTION_SEL).length; i++) {
31159                var link = '';
31160                if (options.anchors.length) {
31161                    link = options.anchors[i];
31162                }
31163
31164                var li = '<li><a href="#' + link + '"><span></span></a>';
31165
31166                // Only add tooltip if needed (defined by user)
31167                var tooltip = options.navigationTooltips[i];
31168
31169                if (typeof tooltip !== 'undefined' && tooltip !== '') {
31170                    li += '<div class="' + SECTION_NAV_TOOLTIP + ' ' + options.navigationPosition + '">' + tooltip + '</div>';
31171                }
31172
31173                li += '</li>';
31174
31175                nav.find('ul').append(li);
31176            }
31177
31178            //centering it vertically
31179            $(SECTION_NAV_SEL).css('margin-top', '-' + ($(SECTION_NAV_SEL).height()/2) + 'px');
31180
31181            //activating the current active section
31182            $(SECTION_NAV_SEL).find('li').eq($(SECTION_ACTIVE_SEL).index(SECTION_SEL)).find('a').addClass(ACTIVE);
31183        }
31184
31185        /**
31186        * Creates the slim scroll scrollbar for the sections and slides inside them.
31187        */
31188        function createScrollBarHandler(){
31189            $(SECTION_SEL).each(function(){
31190                var slides = $(this).find(SLIDE_SEL);
31191
31192                if(slides.length){
31193                    slides.each(function(){
31194                        createScrollBar($(this));
31195                    });
31196                }else{
31197                    createScrollBar($(this));
31198                }
31199
31200            });
31201            afterRenderActions();
31202        }
31203
31204        /*
31205        * Enables the Youtube videos API so we can control their flow if necessary.
31206        */
31207        function enableYoutubeAPI(){
31208            container.find('iframe[src*="youtube.com/embed/"]').each(function(){
31209                addURLParam($(this), 'enablejsapi=1');
31210            });
31211        }
31212
31213        /**
31214        * Adds a new parameter and its value to the `src` of a given element
31215        */
31216        function addURLParam(element, newParam){
31217            var originalSrc = element.attr('src');
31218            element.attr('src', originalSrc + getUrlParamSign(originalSrc) + newParam);
31219        }
31220
31221        /*
31222        * Returns the prefix sign to use for a new parameter in an existen URL.
31223        *
31224        * @return {String}  ? | &
31225        */
31226        function getUrlParamSign(url){
31227            return ( !/\?/.test( url ) ) ? '?' : '&';
31228        }
31229
31230        /**
31231        * Actions and callbacks to fire afterRender
31232        */
31233        function afterRenderActions(){
31234            var section = $(SECTION_ACTIVE_SEL);
31235
31236            section.addClass(COMPLETELY);
31237
31238            if(options.scrollOverflowHandler.afterRender){
31239                options.scrollOverflowHandler.afterRender(section);
31240            }
31241            lazyLoad(section);
31242            playMedia(section);
31243            options.scrollOverflowHandler.afterLoad();
31244
31245            if(isDestinyTheStartingSection()){
31246                $.isFunction( options.afterLoad ) && options.afterLoad.call(section, section.data('anchor'), (section.index(SECTION_SEL) + 1));
31247            }
31248
31249            // Uncode change
31250            // $.isFunction( options.afterRender ) && options.afterRender.call(container);
31251            $.isFunction( options.afterRender ) && options.afterRender.call(container, getTableHeight());
31252        }
31253
31254        /**
31255        * Determines if the URL anchor destiny is the starting section (the one using 'active' class before initialization)
31256        */
31257        function isDestinyTheStartingSection(){
31258            var anchors =  window.location.hash.replace('#', '').split('/');
31259            var destinationSection = getSectionByAnchor(decodeURIComponent(anchors[0]));
31260
31261            return !destinationSection.length || destinationSection.length && destinationSection.index() === startingSection.index();
31262        }
31263
31264
31265        var isScrolling = false;
31266        var lastScroll = 0;
31267
31268        //when scrolling...
31269        function scrollHandler(){
31270            var currentSection;
31271
31272            if(!options.autoScrolling || options.scrollBar){
31273                var currentScroll = $window.scrollTop();
31274                var scrollDirection = getScrollDirection(currentScroll);
31275                var visibleSectionIndex = 0;
31276                var screen_mid = currentScroll + ($window.height() / 2.0);
31277                var isAtBottom = $body.height() - $window.height() === currentScroll;
31278                var sections =  document.querySelectorAll(SECTION_SEL);
31279
31280                //when using `auto-height` for a small last section it won't be centered in the viewport
31281                if(isAtBottom){
31282                    visibleSectionIndex = sections.length - 1;
31283                }
31284                //is at top? when using `auto-height` for a small first section it won't be centered in the viewport
31285                else if(!currentScroll){
31286                    visibleSectionIndex = 0;
31287                }
31288
31289                //taking the section which is showing more content in the viewport
31290                else{
31291                    for (var i = 0; i < sections.length; ++i) {
31292                        var section = sections[i];
31293
31294                        // Pick the the last section which passes the middle line of the screen.
31295                        if (section.offsetTop <= screen_mid)
31296                        {
31297                            visibleSectionIndex = i;
31298                        }
31299                    }
31300                }
31301
31302                if(isCompletelyInViewPort(scrollDirection)){
31303                    if(!$(SECTION_ACTIVE_SEL).hasClass(COMPLETELY)){
31304                        $(SECTION_ACTIVE_SEL).addClass(COMPLETELY).siblings().removeClass(COMPLETELY);
31305                    }
31306                }
31307
31308                //geting the last one, the current one on the screen
31309                currentSection = $(sections).eq(visibleSectionIndex);
31310
31311                //setting the visible section as active when manually scrolling
31312                //executing only once the first time we reach the section
31313                if(!currentSection.hasClass(ACTIVE)){
31314                    isScrolling = true;
31315                    var leavingSection = $(SECTION_ACTIVE_SEL);
31316                    var leavingSectionIndex = leavingSection.index(SECTION_SEL) + 1;
31317                    var yMovement = getYmovement(currentSection);
31318                    var anchorLink  = currentSection.data('anchor');
31319                    var sectionIndex = currentSection.index(SECTION_SEL) + 1;
31320                    var activeSlide = currentSection.find(SLIDE_ACTIVE_SEL);
31321                    var slideIndex;
31322                    var slideAnchorLink;
31323
31324                    if(activeSlide.length){
31325                        slideAnchorLink = activeSlide.data('anchor');
31326                        slideIndex = activeSlide.index();
31327                    }
31328
31329                    if(canScroll){
31330                        currentSection.addClass(ACTIVE).siblings().removeClass(ACTIVE);
31331
31332                        $.isFunction( options.onLeave ) && options.onLeave.call( leavingSection, leavingSectionIndex, sectionIndex, yMovement);
31333                        $.isFunction( options.afterLoad ) && options.afterLoad.call( currentSection, anchorLink, sectionIndex);
31334
31335                        stopMedia(leavingSection);
31336                        lazyLoad(currentSection);
31337                        playMedia(currentSection);
31338
31339                        activateMenuAndNav(anchorLink, sectionIndex - 1);
31340
31341                        if(options.anchors.length){
31342                            //needed to enter in hashChange event when using the menu with anchor links
31343                            lastScrolledDestiny = anchorLink;
31344                        }
31345                        setState(slideIndex, slideAnchorLink, anchorLink, sectionIndex);
31346                    }
31347
31348                    //small timeout in order to avoid entering in hashChange event when scrolling is not finished yet
31349                    clearTimeout(scrollId);
31350                    scrollId = setTimeout(function(){
31351                        isScrolling = false;
31352                    }, 100);
31353                }
31354
31355                if(options.fitToSection){
31356                    //for the auto adjust of the viewport to fit a whole section
31357                    clearTimeout(scrollId2);
31358
31359                    scrollId2 = setTimeout(function(){
31360                        //checking it again in case it changed during the delay
31361                        if(options.fitToSection){
31362                            fitToSection();
31363                        }
31364                    }, options.fitToSectionDelay);
31365                }
31366            }
31367        }
31368
31369        /**
31370        * Fits the site to the nearest active section
31371        */
31372        function fitToSection(){
31373            //checking fitToSection again in case it was set to false before the timeout delay
31374            if(canScroll){
31375                //allows to scroll to an active section and
31376                //if the section is already active, we prevent firing callbacks
31377                isResizing = true;
31378
31379                scrollPage($(SECTION_ACTIVE_SEL));
31380                isResizing = false;
31381            }
31382        }
31383
31384        /**
31385        * Determines whether the active section has seen in its whole or not.
31386        */
31387        function isCompletelyInViewPort(movement){
31388            var top = $(SECTION_ACTIVE_SEL).position().top;
31389            var bottom = top + $window.height();
31390
31391            if(movement == 'up'){
31392                return bottom >= ($window.scrollTop() + $window.height());
31393            }
31394            return top <= $window.scrollTop();
31395        }
31396
31397        /**
31398        * Gets the directon of the the scrolling fired by the scroll event.
31399        */
31400        function getScrollDirection(currentScroll){
31401            var direction = currentScroll > lastScroll ? 'down' : 'up';
31402
31403            lastScroll = currentScroll;
31404
31405            //needed for auto-height sections to determine if we want to scroll to the top or bottom of the destination
31406            previousDestTop = currentScroll;
31407
31408            return direction;
31409        }
31410
31411        /**
31412        * Determines the way of scrolling up or down:
31413        * by 'automatically' scrolling a section or by using the default and normal scrolling.
31414        */
31415        function scrolling(type, scrollable){
31416            if (!isScrollAllowed.m[type]){
31417                return;
31418            }
31419            var check = (type === 'down') ? 'bottom' : 'top';
31420            var scrollSection = (type === 'down') ? moveSectionDown : moveSectionUp;
31421
31422            if(scrollable.length > 0 ){
31423                //is the scrollbar at the start/end of the scroll?
31424                if(options.scrollOverflowHandler.isScrolled(check, scrollable)){
31425                    scrollSection();
31426                }else{
31427                    return true;
31428                }
31429            }else{
31430                // moved up/down
31431                scrollSection();
31432            }
31433        }
31434
31435        /*
31436        * Preventing bouncing in iOS #2285
31437        */
31438        function preventBouncing(event){
31439            var e = event.originalEvent;
31440            if(!checkParentForNormalScrollElement(event.target) && options.autoScrolling && isReallyTouch(e) && isScrollAllowed.m.up){
31441                //preventing the easing on iOS devices
31442                event.preventDefault();
31443            }
31444        }
31445
31446        var touchStartY = 0;
31447        var touchStartX = 0;
31448        var touchEndY = 0;
31449        var touchEndX = 0;
31450
31451        /* Detecting touch events
31452
31453        * As we are changing the top property of the page on scrolling, we can not use the traditional way to detect it.
31454        * This way, the touchstart and the touch moves shows an small difference between them which is the
31455        * used one to determine the direction.
31456        */
31457        function touchMoveHandler(event){
31458            var e = event.originalEvent;
31459            var activeSection = $(e.target).closest(SECTION_SEL);
31460
31461            // additional: if one of the normalScrollElements isn't within options.normalScrollElementTouchThreshold hops up the DOM chain
31462            if (!checkParentForNormalScrollElement(event.target) && isReallyTouch(e) ) {
31463
31464                if(options.autoScrolling){
31465                    //preventing the easing on iOS devices
31466                    event.preventDefault();
31467                }
31468
31469                var scrollable = options.scrollOverflowHandler.scrollable(activeSection);
31470                var touchEvents = getEventsPage(e);
31471
31472                touchEndY = touchEvents.y;
31473                touchEndX = touchEvents.x;
31474
31475                //if movement in the X axys is greater than in the Y and the currect section has slides...
31476                if (activeSection.find(SLIDES_WRAPPER_SEL).length && Math.abs(touchStartX - touchEndX) > (Math.abs(touchStartY - touchEndY))) {
31477
31478                    //is the movement greater than the minimum resistance to scroll?
31479                    if (!slideMoving && Math.abs(touchStartX - touchEndX) > ($window.outerWidth() / 100 * options.touchSensitivity)) {
31480                        if (touchStartX > touchEndX) {
31481                            if(isScrollAllowed.m.right){
31482                                moveSlideRight(activeSection); //next
31483                            }
31484                        } else {
31485                            if(isScrollAllowed.m.left){
31486                                moveSlideLeft(activeSection); //prev
31487                            }
31488                        }
31489                    }
31490                }
31491
31492                //vertical scrolling (only when autoScrolling is enabled)
31493                else if(options.autoScrolling && canScroll){
31494
31495                    //is the movement greater than the minimum resistance to scroll?
31496                    if (Math.abs(touchStartY - touchEndY) > ($window.height() / 100 * options.touchSensitivity)) {
31497                        if (touchStartY > touchEndY) {
31498                            scrolling('down', scrollable);
31499                        } else if (touchEndY > touchStartY) {
31500                            scrolling('up', scrollable);
31501                        }
31502                    }
31503                }
31504            }
31505        }
31506
31507        /**
31508         * recursive function to loop up the parent nodes to check if one of them exists in options.normalScrollElements
31509         * Currently works well for iOS - Android might need some testing
31510         * @param  {Element} el  target element / jquery selector (in subsequent nodes)
31511         * @param  {int}     hop current hop compared to options.normalScrollElementTouchThreshold
31512         * @return {boolean} true if there is a match to options.normalScrollElements
31513         */
31514        function checkParentForNormalScrollElement (el, hop) {
31515            hop = hop || 0;
31516            var parent = $(el).parent();
31517
31518            if (hop < options.normalScrollElementTouchThreshold &&
31519                parent.is(options.normalScrollElements) ) {
31520                return true;
31521            } else if (hop == options.normalScrollElementTouchThreshold) {
31522                return false;
31523            } else {
31524                return checkParentForNormalScrollElement(parent, ++hop);
31525            }
31526        }
31527
31528        /**
31529        * As IE >= 10 fires both touch and mouse events when using a mouse in a touchscreen
31530        * this way we make sure that is really a touch event what IE is detecting.
31531        */
31532        function isReallyTouch(e){
31533            //if is not IE   ||  IE is detecting `touch` or `pen`
31534            return typeof e.pointerType === 'undefined' || e.pointerType != 'mouse';
31535        }
31536
31537        /**
31538        * Handler for the touch start event.
31539        */
31540        function touchStartHandler(event){
31541            var e = event.originalEvent;
31542
31543            //stopping the auto scroll to adjust to a section
31544            if(options.fitToSection){
31545                $htmlBody.stop();
31546            }
31547
31548            if(isReallyTouch(e)){
31549                var touchEvents = getEventsPage(e);
31550                touchStartY = touchEvents.y;
31551                touchStartX = touchEvents.x;
31552            }
31553        }
31554
31555        /**
31556        * Gets the average of the last `number` elements of the given array.
31557        */
31558        function getAverage(elements, number){
31559            var sum = 0;
31560
31561            //taking `number` elements from the end to make the average, if there are not enought, 1
31562            var lastElements = elements.slice(Math.max(elements.length - number, 1));
31563
31564            for(var i = 0; i < lastElements.length; i++){
31565                sum = sum + lastElements[i];
31566            }
31567
31568            return Math.ceil(sum/number);
31569        }
31570
31571        /**
31572         * Detecting mousewheel scrolling
31573         *
31574         * http://blogs.sitepointstatic.com/examples/tech/mouse-wheel/index.html
31575         * http://www.sitepoint.com/html5-javascript-mouse-wheel/
31576         */
31577        var prevTime = new Date().getTime();
31578
31579        function MouseWheelHandler(e) {
31580            var curTime = new Date().getTime();
31581            var isNormalScroll = $(COMPLETELY_SEL).hasClass(NORMAL_SCROLL);
31582
31583            //autoscrolling and not zooming?
31584            if(options.autoScrolling && !controlPressed && !isNormalScroll){
31585                // cross-browser wheel delta
31586                e = e || window.event;
31587                var value = e.wheelDelta || -e.deltaY || -e.detail;
31588                var delta = Math.max(-1, Math.min(1, value));
31589
31590                var horizontalDetection = typeof e.wheelDeltaX !== 'undefined' || typeof e.deltaX !== 'undefined';
31591                var isScrollingVertically = (Math.abs(e.wheelDeltaX) < Math.abs(e.wheelDelta)) || (Math.abs(e.deltaX ) < Math.abs(e.deltaY) || !horizontalDetection);
31592
31593                //Limiting the array to 150 (lets not waste memory!)
31594                if(scrollings.length > 149){
31595                    scrollings.shift();
31596                }
31597
31598                //keeping record of the previous scrollings
31599                scrollings.push(Math.abs(value));
31600
31601                //preventing to scroll the site on mouse wheel when scrollbar is present
31602                if(options.scrollBar){
31603                    e.preventDefault ? e.preventDefault() : e.returnValue = false;
31604                }
31605
31606                var activeSection = $(SECTION_ACTIVE_SEL);
31607                var scrollable = options.scrollOverflowHandler.scrollable(activeSection);
31608
31609                //time difference between the last scroll and the current one
31610                var timeDiff = curTime-prevTime;
31611                prevTime = curTime;
31612
31613                //haven't they scrolled in a while?
31614                //(enough to be consider a different scrolling action to scroll another section)
31615                if(timeDiff > 200){
31616                    //emptying the array, we dont care about old scrollings for our averages
31617                    scrollings = [];
31618                }
31619
31620                if(canScroll){
31621                    var averageEnd = getAverage(scrollings, 10);
31622                    var averageMiddle = getAverage(scrollings, 70);
31623                    var isAccelerating = averageEnd >= averageMiddle;
31624
31625                    //to avoid double swipes...
31626                    if(isAccelerating && isScrollingVertically){
31627                        //scrolling down?
31628                        if (delta < 0) {
31629                            scrolling('down', scrollable);
31630
31631                        //scrolling up?
31632                        }else {
31633                            scrolling('up', scrollable);
31634                        }
31635                    }
31636                }
31637
31638                return false;
31639            }
31640
31641            if(options.fitToSection){
31642                //stopping the auto scroll to adjust to a section
31643                $htmlBody.stop();
31644            }
31645        }
31646
31647        /**
31648        * Slides a slider to the given direction.
31649        * Optional `section` param.
31650        */
31651        function moveSlide(direction, section){
31652            var activeSection = typeof section === 'undefined' ? $(SECTION_ACTIVE_SEL) : section;
31653            var slides = activeSection.find(SLIDES_WRAPPER_SEL);
31654            var numSlides = slides.find(SLIDE_SEL).length;
31655
31656            // more than one slide needed and nothing should be sliding
31657            if (!slides.length || slideMoving || numSlides < 2) {
31658                return;
31659            }
31660
31661            var currentSlide = slides.find(SLIDE_ACTIVE_SEL);
31662            var destiny = null;
31663
31664            if(direction === 'left'){
31665                destiny = currentSlide.prev(SLIDE_SEL);
31666            }else{
31667                destiny = currentSlide.next(SLIDE_SEL);
31668            }
31669
31670            //isn't there a next slide in the secuence?
31671            if(!destiny.length){
31672                //respect loopHorizontal settin
31673                if (!options.loopHorizontal) return;
31674
31675                if(direction === 'left'){
31676                    destiny = currentSlide.siblings(':last');
31677                }else{
31678                    destiny = currentSlide.siblings(':first');
31679                }
31680            }
31681
31682            slideMoving = true;
31683
31684            landscapeScroll(slides, destiny, direction);
31685        }
31686
31687        /**
31688        * Maintains the active slides in the viewport
31689        * (Because the `scroll` animation might get lost with some actions, such as when using continuousVertical)
31690        */
31691        function keepSlidesPosition(){
31692            $(SLIDE_ACTIVE_SEL).each(function(){
31693                silentLandscapeScroll($(this), 'internal');
31694            });
31695        }
31696
31697        var previousDestTop = 0;
31698        /**
31699        * Returns the destination Y position based on the scrolling direction and
31700        * the height of the section.
31701        */
31702        function getDestinationPosition(element){
31703            var elemPosition = element.position();
31704
31705            //top of the desination will be at the top of the viewport
31706            var position = elemPosition.top;
31707            var isScrollingDown =  elemPosition.top > previousDestTop;
31708            var sectionBottom = position - windowsHeight + element.outerHeight();
31709            var bigSectionsDestination = options.bigSectionsDestination;
31710
31711            //Uncode addition
31712            var containerH = container.outerHeight();
31713            var containerPosition = container.offset();
31714
31715            //########### Commented by Uncode - START ###########
31716            //is the destination element bigger than the viewport?
31717            // if(element.outerHeight() > windowsHeight){
31718            //     //scrolling up?
31719            //     if(!isScrollingDown && !bigSectionsDestination || bigSectionsDestination === 'bottom' ){
31720            //         position = sectionBottom;
31721            //     }
31722            // }
31723
31724            // //sections equal or smaller than the viewport height && scrolling down? ||  is resizing and its in the last section
31725            // else if(isScrollingDown || (isResizing && element.is(':last-child')) ){
31726            //     //The bottom of the destination will be at the bottom of the viewport
31727            //     position = sectionBottom;
31728            // }
31729            //########### Commented by Uncode - END ###########
31730
31731            //Uncode addition
31732            if ( !$masthead.hasClass('menu-transparent') && $('body').hasClass('uncode-fp-menu-shrink') && !element.is(':first-child') )
31733                position += 18;
31734            if ( ( containerH + menuHeight + bodyBorder + adminBarHeight - windowsHeight ) < position || ( isResizing && element.is(':last-child') ) ) {
31735                position = sectionBottom + menuHeight + bodyBorder*2 + adminBarHeight;
31736            }
31737
31738            /*
31739            Keeping record of the last scrolled position to determine the scrolling direction.
31740            No conventional methods can be used as the scroll bar might not be present
31741            AND the section might not be active if it is auto-height and didnt reach the middle
31742            of the viewport.
31743            */
31744            previousDestTop = position;
31745            return position;
31746        }
31747
31748        /**
31749        * Scrolls the site to the given element and scrolls to the slide if a callback is given.
31750        */
31751        function scrollPage(element, callback, isMovementUp){
31752            if(typeof element === 'undefined'){ return; } //there's no element to scroll, leaving the function
31753
31754            var dtop = getDestinationPosition(element);
31755            var slideAnchorLink;
31756            var slideIndex;
31757
31758            //local variables
31759            var v = {
31760                element: element,
31761                callback: callback,
31762                isMovementUp: isMovementUp,
31763                dtop: dtop,
31764                yMovement: getYmovement(element),
31765                anchorLink: element.data('anchor'),
31766                sectionIndex: element.index(SECTION_SEL),
31767                activeSlide: element.find(SLIDE_ACTIVE_SEL),
31768                activeSection: $(SECTION_ACTIVE_SEL),
31769                leavingSection: $(SECTION_ACTIVE_SEL).index(SECTION_SEL) + 1,
31770
31771                //caching the value of isResizing at the momment the function is called
31772                //because it will be checked later inside a setTimeout and the value might change
31773                localIsResizing: isResizing
31774            };
31775
31776            //quiting when destination scroll is the same as the current one
31777            if((v.activeSection.is(element) && !isResizing) || (options.scrollBar && $window.scrollTop() === v.dtop && !element.hasClass(AUTO_HEIGHT) )){ return; }
31778
31779            if(v.activeSlide.length){
31780                slideAnchorLink = v.activeSlide.data('anchor');
31781                slideIndex = v.activeSlide.index();
31782            }
31783
31784            // If continuousVertical && we need to wrap around
31785            if (options.autoScrolling && options.continuousVertical && typeof (v.isMovementUp) !== "undefined" &&
31786                ((!v.isMovementUp && v.yMovement == 'up') || // Intending to scroll down but about to go up or
31787                (v.isMovementUp && v.yMovement == 'down'))) { // intending to scroll up but about to go down
31788
31789                v = createInfiniteSections(v);
31790            }
31791
31792            //callback (onLeave) if the site is not just resizing and readjusting the slides
31793            if($.isFunction(options.onLeave) && !v.localIsResizing){
31794                if(options.onLeave.call(v.activeSection, v.leavingSection, (v.sectionIndex + 1), v.yMovement) === false){
31795                    return;
31796                }
31797            }
31798
31799            //pausing media of the leaving section (if we are not just resizing, as destinatino will be the same one)
31800            if(!v.localIsResizing){
31801                stopMedia(v.activeSection);
31802            }
31803
31804            options.scrollOverflowHandler.beforeLeave();
31805            element.addClass(ACTIVE).siblings().removeClass(ACTIVE);
31806            lazyLoad(element);
31807            options.scrollOverflowHandler.onLeave();
31808
31809
31810            //preventing from activating the MouseWheelHandler event
31811            //more than once if the page is scrolling
31812            canScroll = false;
31813
31814            setState(slideIndex, slideAnchorLink, v.anchorLink, v.sectionIndex);
31815
31816            performMovement(v);
31817
31818            //flag to avoid callingn `scrollPage()` twice in case of using anchor links
31819            lastScrolledDestiny = v.anchorLink;
31820
31821            //avoid firing it twice (as it does also on scroll)
31822            activateMenuAndNav(v.anchorLink, v.sectionIndex);
31823        }
31824
31825        /**
31826        * Performs the vertical movement (by CSS3 or by jQuery)
31827        */
31828        function performMovement(v){
31829            // using CSS3 translate functionality
31830            if (options.css3 && options.autoScrolling && !options.scrollBar) {
31831
31832                // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625
31833                // that's why we round it to 0.
31834                var translate3d = 'translate3d(0px, -' + Math.round(v.dtop) + 'px, 0px)';
31835                transformContainer(translate3d, true);
31836
31837                //even when the scrollingSpeed is 0 there's a little delay, which might cause the
31838                //scrollingSpeed to change in case of using silentMoveTo();
31839                if(options.scrollingSpeed){
31840                    clearTimeout(afterSectionLoadsId);
31841                    afterSectionLoadsId = setTimeout(function () {
31842                        afterSectionLoads(v);
31843                    }, options.scrollingSpeed);
31844                }else{
31845                    afterSectionLoads(v);
31846                }
31847            }
31848
31849            // using jQuery animate
31850            else{
31851                var scrollSettings = getScrollSettings(v);
31852
31853                $(scrollSettings.element).animate(
31854                    scrollSettings.options,
31855                options.scrollingSpeed, options.easing).promise().done(function () { //only one single callback in case of animating  `html, body`
31856                    if(options.scrollBar){
31857
31858                        /* Hack!
31859                        The timeout prevents setting the most dominant section in the viewport as "active" when the user
31860                        scrolled to a smaller section by using the mousewheel (auto scrolling) rather than draging the scroll bar.
31861
31862                        When using scrollBar:true It seems like the scroll events still getting propagated even after the scrolling animation has finished.
31863                        */
31864                        setTimeout(function(){
31865                            afterSectionLoads(v);
31866                        },30);
31867                    }else{
31868                        afterSectionLoads(v);
31869                    }
31870                });
31871            }
31872        }
31873
31874        /**
31875        * Gets the scrolling settings depending on the plugin autoScrolling option
31876        */
31877        function getScrollSettings(v){
31878            var scroll = {};
31879
31880            if(options.autoScrolling && !options.scrollBar){
31881                scroll.options = { 'top': -v.dtop};
31882                scroll.element = WRAPPER_SEL;
31883            }else{
31884                scroll.options = { 'scrollTop': v.dtop};
31885                scroll.element = 'html, body';
31886            }
31887
31888            return scroll;
31889        }
31890
31891        /**
31892        * Adds sections before or after the current one to create the infinite effect.
31893        */
31894        function createInfiniteSections(v){
31895            // Scrolling down
31896            if (!v.isMovementUp) {
31897                // Move all previous sections to after the active section
31898                $(SECTION_ACTIVE_SEL).after(v.activeSection.prevAll(SECTION_SEL).get().reverse());
31899            }
31900            else { // Scrolling up
31901                // Move all next sections to before the active section
31902                $(SECTION_ACTIVE_SEL).before(v.activeSection.nextAll(SECTION_SEL));
31903            }
31904
31905            // Maintain the displayed position (now that we changed the element order)
31906            silentScroll($(SECTION_ACTIVE_SEL).position().top);
31907
31908            // Maintain the active slides visible in the viewport
31909            keepSlidesPosition();
31910
31911            // save for later the elements that still need to be reordered
31912            v.wrapAroundElements = v.activeSection;
31913
31914            // Recalculate animation variables
31915            v.dtop = v.element.position().top;
31916            v.yMovement = getYmovement(v.element);
31917
31918            return v;
31919        }
31920
31921        /**
31922        * Fix section order after continuousVertical changes have been animated
31923        */
31924        function continuousVerticalFixSectionOrder (v) {
31925            // If continuousVertical is in effect (and autoScrolling would also be in effect then),
31926            // finish moving the elements around so the direct navigation will function more simply
31927            if (!v.wrapAroundElements || !v.wrapAroundElements.length) {
31928                return;
31929            }
31930
31931            if (v.isMovementUp) {
31932                $(SECTION_FIRST_SEL).before(v.wrapAroundElements);
31933            }
31934            else {
31935                $(SECTION_LAST_SEL).after(v.wrapAroundElements);
31936            }
31937
31938            silentScroll($(SECTION_ACTIVE_SEL).position().top);
31939
31940            // Maintain the active slides visible in the viewport
31941            keepSlidesPosition();
31942        }
31943
31944
31945        /**
31946        * Actions to do once the section is loaded.
31947        */
31948        function afterSectionLoads (v){
31949            continuousVerticalFixSectionOrder(v);
31950
31951            //callback (afterLoad) if the site is not just resizing and readjusting the slides
31952            $.isFunction(options.afterLoad) && !v.localIsResizing && options.afterLoad.call(v.element, v.anchorLink, (v.sectionIndex + 1));
31953            options.scrollOverflowHandler.afterLoad();
31954
31955            if(!v.localIsResizing){
31956                playMedia(v.element);
31957            }
31958
31959            v.element.addClass(COMPLETELY).siblings().removeClass(COMPLETELY);
31960
31961            canScroll = true;
31962
31963            $.isFunction(v.callback) && v.callback.call(this);
31964        }
31965
31966        /**
31967        * Sets the value for the given attribute from the `data-` attribute with the same suffix
31968        * ie: data-srcset ==> srcset  |  data-src ==> src
31969        */
31970        function setSrc(element, attribute){
31971            element
31972                .attr(attribute, element.data(attribute))
31973                .removeAttr('data-' + attribute);
31974        }
31975
31976        /**
31977        * Lazy loads image, video and audio elements.
31978        */
31979        function lazyLoad(destiny){
31980            if (!options.lazyLoading){
31981                return;
31982            }
31983
31984            var panel = getSlideOrSection(destiny);
31985            var element;
31986
31987            panel.find('img[data-src], img[data-srcset], source[data-src], audio[data-src], iframe[data-src]').each(function(){
31988                element = $(this);
31989
31990                $.each(['src', 'srcset'], function(index, type){
31991                    var attribute = element.attr('data-' + type);
31992                    if(typeof attribute !== 'undefined' && attribute){
31993                        setSrc(element, type);
31994                    }
31995                });
31996
31997                if(element.is('source')){
31998                    element.closest('video').get(0).load();
31999                }
32000            });
32001        }
32002
32003        /**
32004        * Plays video and audio elements.
32005        */
32006        function playMedia(destiny){
32007            var panel = getSlideOrSection(destiny);
32008
32009            //playing HTML5 media elements
32010            panel.find('video, audio').each(function(){
32011                var element = $(this).get(0);
32012
32013                if( element.hasAttribute('data-autoplay') && typeof element.play === 'function' ) {
32014                    element.play();
32015                }
32016            });
32017
32018            //youtube videos
32019            panel.find('iframe[src*="youtube.com/embed/"]').each(function(){
32020                var element = $(this).get(0);
32021
32022                if ( element.hasAttribute('data-autoplay') ){
32023                    playYoutube(element);
32024                }
32025
32026                //in case the URL was not loaded yet. On page load we need time for the new URL (with the API string) to load.
32027                element.onload = function() {
32028                    if ( element.hasAttribute('data-autoplay') ){
32029                        playYoutube(element);
32030                    }
32031                };
32032            });
32033        }
32034
32035        /**
32036        * Plays a youtube video
32037        */
32038        function playYoutube(element){
32039            element.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*');
32040        }
32041
32042        /**
32043        * Stops video and audio elements.
32044        */
32045        function stopMedia(destiny){
32046            var panel = getSlideOrSection(destiny);
32047
32048            //stopping HTML5 media elements
32049            panel.find('video, audio').each(function(){
32050                var element = $(this).get(0);
32051
32052                if( !element.hasAttribute('data-keepplaying') && typeof element.pause === 'function' ) {
32053                    element.pause();
32054                }
32055            });
32056
32057            //youtube videos
32058            panel.find('iframe[src*="youtube.com/embed/"]').each(function(){
32059                var element = $(this).get(0);
32060
32061                if( /youtube\.com\/embed\//.test($(this).attr('src')) && !element.hasAttribute('data-keepplaying')){
32062                    $(this).get(0).contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}','*');
32063                }
32064            });
32065        }
32066
32067        /**
32068        * Gets the active slide (or section) for the given section
32069        */
32070        function getSlideOrSection(destiny){
32071            var slide = destiny.find(SLIDE_ACTIVE_SEL);
32072            if( slide.length ) {
32073                destiny = $(slide);
32074            }
32075
32076            return destiny;
32077        }
32078
32079        /**
32080        * Scrolls to the anchor in the URL when loading the site
32081        */
32082        function scrollToAnchor(){
32083            //getting the anchor link in the URL and deleting the `#`
32084            var value =  window.location.hash.replace('#', '').split('/');
32085            var sectionAnchor = decodeURIComponent(value[0]);
32086            var slideAnchor = decodeURIComponent(value[1]);
32087
32088            if(sectionAnchor){  //if theres any #
32089                if(options.animateAnchor){
32090                    scrollPageAndSlide(sectionAnchor, slideAnchor);
32091                }else{
32092                    silentMoveTo(sectionAnchor, slideAnchor);
32093                }
32094            }
32095        }
32096
32097        /**
32098        * Detecting any change on the URL to scroll to the given anchor link
32099        * (a way to detect back history button as we play with the hashes on the URL)
32100        */
32101        function hashChangeHandler(){
32102            if(!isScrolling && !options.lockAnchors){
32103                var value =  window.location.hash.replace('#', '').split('/');
32104                var sectionAnchor = decodeURIComponent(value[0]);
32105                var slideAnchor = decodeURIComponent(value[1]);
32106
32107                    //when moving to a slide in the first section for the first time (first time to add an anchor to the URL)
32108                    var isFirstSlideMove =  (typeof lastScrolledDestiny === 'undefined');
32109                    var isFirstScrollMove = (typeof lastScrolledDestiny === 'undefined' && typeof slideAnchor === 'undefined' && !slideMoving);
32110
32111
32112                if(sectionAnchor.length){
32113                    /*in order to call scrollpage() only once for each destination at a time
32114                    It is called twice for each scroll otherwise, as in case of using anchorlinks `hashChange`
32115                    event is fired on every scroll too.*/
32116                    if ((sectionAnchor && sectionAnchor !== lastScrolledDestiny) && !isFirstSlideMove || isFirstScrollMove || (!slideMoving && lastScrolledSlide != slideAnchor ))  {
32117                        scrollPageAndSlide(sectionAnchor, slideAnchor);
32118                    }
32119                }
32120            }
32121        }
32122
32123        //Sliding with arrow keys, both, vertical and horizontal
32124        function keydownHandler(e) {
32125
32126            clearTimeout(keydownId);
32127
32128            var activeElement = $(':focus');
32129
32130            if(!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select') &&
32131                activeElement.attr('contentEditable') !== "true" && activeElement.attr('contentEditable') !== '' &&
32132                options.keyboardScrolling && options.autoScrolling){
32133                var keyCode = e.which;
32134
32135                //preventing the scroll with arrow keys & spacebar & Page Up & Down keys
32136                var keyControls = [40, 38, 32, 33, 34];
32137                if($.inArray(keyCode, keyControls) > -1){
32138                    e.preventDefault();
32139                }
32140
32141                controlPressed = e.ctrlKey;
32142
32143                keydownId = setTimeout(function(){
32144                    onkeydown(e);
32145                },150);
32146            }
32147        }
32148
32149        function tooltipTextHandler(){
32150            $(this).prev().trigger('click');
32151        }
32152
32153        //to prevent scrolling while zooming
32154        function keyUpHandler(e){
32155            if(isWindowFocused){ //the keyup gets fired on new tab ctrl + t in Firefox
32156                controlPressed = e.ctrlKey;
32157            }
32158        }
32159
32160        //binding the mousemove when the mouse's middle button is released
32161        function mouseDownHandler(e){
32162            //middle button
32163            if (e.which == 2){
32164                oldPageY = e.pageY;
32165                container.on('mousemove', mouseMoveHandler);
32166            }
32167        }
32168
32169        //unbinding the mousemove when the mouse's middle button is released
32170        function mouseUpHandler(e){
32171            //middle button
32172            if (e.which == 2){
32173                container.off('mousemove');
32174            }
32175        }
32176
32177        //Scrolling horizontally when clicking on the slider controls.
32178        function slideArrowHandler(){
32179            var section = $(this).closest(SECTION_SEL);
32180
32181            if ($(this).hasClass(SLIDES_PREV)) {
32182                if(isScrollAllowed.m.left){
32183                    moveSlideLeft(section);
32184                }
32185            } else {
32186                if(isScrollAllowed.m.right){
32187                    moveSlideRight(section);
32188                }
32189            }
32190        }
32191
32192        //when opening a new tab (ctrl + t), `control` won't be pressed when coming back.
32193        function blurHandler(){
32194            isWindowFocused = false;
32195            controlPressed = false;
32196        }
32197
32198        //Scrolls to the section when clicking the navigation bullet
32199        function sectionBulletHandler(e){
32200            e.preventDefault();
32201            var index = $(this).parent().index();
32202            scrollPage($(SECTION_SEL).eq(index));
32203        }
32204
32205        //Scrolls the slider to the given slide destination for the given section
32206        function slideBulletHandler(e){
32207            e.preventDefault();
32208            var slides = $(this).closest(SECTION_SEL).find(SLIDES_WRAPPER_SEL);
32209            var destiny = slides.find(SLIDE_SEL).eq($(this).closest('li').index());
32210
32211            landscapeScroll(slides, destiny);
32212        }
32213
32214        /**
32215        * Keydown event
32216        */
32217        function onkeydown(e){
32218            var shiftPressed = e.shiftKey;
32219
32220            //do nothing if we can not scroll or we are not using horizotnal key arrows.
32221            if(!canScroll && [37,39].indexOf(e.which) < 0){
32222                return;
32223            }
32224
32225            switch (e.which) {
32226                //up
32227                case 38:
32228                case 33:
32229                    if(isScrollAllowed.k.up){
32230                        moveSectionUp();
32231                    }
32232                    break;
32233
32234                //down
32235                case 32: //spacebar
32236                    if(shiftPressed && isScrollAllowed.k.up){
32237                        moveSectionUp();
32238                        break;
32239                    }
32240                /* falls through */
32241                case 40:
32242                case 34:
32243                    if(isScrollAllowed.k.down){
32244                        moveSectionDown();
32245                    }
32246                    break;
32247
32248                //Home
32249                case 36:
32250                    if(isScrollAllowed.k.up){
32251                        moveTo(1);
32252                    }
32253                    break;
32254
32255                //End
32256                case 35:
32257                     if(isScrollAllowed.k.down){
32258                        moveTo( $(SECTION_SEL).length );
32259                    }
32260                    break;
32261
32262                //left
32263                case 37:
32264                    if(isScrollAllowed.k.left){
32265                        moveSlideLeft();
32266                    }
32267                    break;
32268
32269                //right
32270                case 39:
32271                    if(isScrollAllowed.k.right){
32272                        moveSlideRight();
32273                    }
32274                    break;
32275
32276                default:
32277                    return; // exit this handler for other keys
32278            }
32279        }
32280
32281        /**
32282        * Detecting the direction of the mouse movement.
32283        * Used only for the middle button of the mouse.
32284        */
32285        var oldPageY = 0;
32286        function mouseMoveHandler(e){
32287            if(canScroll){
32288                // moving up
32289                if (e.pageY < oldPageY && isScrollAllowed.m.up){
32290                    moveSectionUp();
32291                }
32292
32293                // moving down
32294                else if(e.pageY > oldPageY && isScrollAllowed.m.down){
32295                    moveSectionDown();
32296                }
32297            }
32298            oldPageY = e.pageY;
32299        }
32300
32301        /**
32302        * Scrolls horizontal sliders.
32303        */
32304        function landscapeScroll(slides, destiny, direction){
32305            var section = slides.closest(SECTION_SEL);
32306            var v = {
32307                slides: slides,
32308                destiny: destiny,
32309                direction: direction,
32310                destinyPos: destiny.position(),
32311                slideIndex: destiny.index(),
32312                section: section,
32313                sectionIndex: section.index(SECTION_SEL),
32314                anchorLink: section.data('anchor'),
32315                slidesNav: section.find(SLIDES_NAV_SEL),
32316                slideAnchor:  getAnchor(destiny),
32317                prevSlide: section.find(SLIDE_ACTIVE_SEL),
32318                prevSlideIndex: section.find(SLIDE_ACTIVE_SEL).index(),
32319
32320                //caching the value of isResizing at the momment the function is called
32321                //because it will be checked later inside a setTimeout and the value might change
32322                localIsResizing: isResizing
32323            };
32324            v.xMovement = getXmovement(v.prevSlideIndex, v.slideIndex);
32325            v.direction = v.direction ? v.direction : v.xMovement;
32326
32327            //important!! Only do it when not resizing
32328            if(!v.localIsResizing){
32329                //preventing from scrolling to the next/prev section when using scrollHorizontally
32330                canScroll = false;
32331            }
32332
32333            if(options.onSlideLeave){
32334
32335                //if the site is not just resizing and readjusting the slides
32336                if(!v.localIsResizing && v.xMovement!=='none'){
32337                    if($.isFunction( options.onSlideLeave )){
32338                        if(options.onSlideLeave.call( v.prevSlide, v.anchorLink, (v.sectionIndex + 1), v.prevSlideIndex, v.xMovement, v.slideIndex ) === false){
32339                            slideMoving = false;
32340                            return;
32341                        }
32342                    }
32343                }
32344            }
32345
32346            destiny.addClass(ACTIVE).siblings().removeClass(ACTIVE);
32347
32348            if(!v.localIsResizing){
32349                stopMedia(v.prevSlide);
32350                lazyLoad(destiny);
32351            }
32352
32353            if(!options.loopHorizontal && options.controlArrows){
32354                //hidding it for the fist slide, showing for the rest
32355                section.find(SLIDES_ARROW_PREV_SEL).toggle(v.slideIndex!==0);
32356
32357                //hidding it for the last slide, showing for the rest
32358                section.find(SLIDES_ARROW_NEXT_SEL).toggle(!destiny.is(':last-child'));
32359            }
32360
32361            //only changing the URL if the slides are in the current section (not for resize re-adjusting)
32362            if(section.hasClass(ACTIVE) && !v.localIsResizing){
32363                setState(v.slideIndex, v.slideAnchor, v.anchorLink, v.sectionIndex);
32364            }
32365
32366            performHorizontalMove(slides, v, true);
32367        }
32368
32369
32370        function afterSlideLoads(v){
32371            activeSlidesNavigation(v.slidesNav, v.slideIndex);
32372
32373            //if the site is not just resizing and readjusting the slides
32374            if(!v.localIsResizing){
32375                $.isFunction( options.afterSlideLoad ) && options.afterSlideLoad.call( v.destiny, v.anchorLink, (v.sectionIndex + 1), v.slideAnchor, v.slideIndex);
32376
32377                //needs to be inside the condition to prevent problems with continuousVertical and scrollHorizontally
32378                //and to prevent double scroll right after a windows resize
32379                canScroll = true;
32380
32381                playMedia(v.destiny);
32382            }
32383
32384            //letting them slide again
32385            slideMoving = false;
32386        }
32387
32388        /**
32389        * Performs the horizontal movement. (CSS3 or jQuery)
32390        *
32391        * @param fireCallback {Bool} - determines whether or not to fire the callback
32392        */
32393        function performHorizontalMove(slides, v, fireCallback){
32394            var destinyPos = v.destinyPos;
32395
32396            if(options.css3){
32397                var translate3d = 'translate3d(-' + Math.round(destinyPos.left) + 'px, 0px, 0px)';
32398
32399                addAnimation(slides.find(SLIDES_CONTAINER_SEL)).css(getTransforms(translate3d), v);
32400
32401                afterSlideLoadsId = setTimeout(function(){
32402                    fireCallback && afterSlideLoads(v);
32403                }, options.scrollingSpeed, options.easing);
32404            }else{
32405                slides.animate({
32406                    scrollLeft : Math.round(destinyPos.left)
32407                }, options.scrollingSpeed, options.easing, function() {
32408
32409                    fireCallback && afterSlideLoads(v);
32410                });
32411            }
32412        }
32413
32414        /**
32415        * Sets the state for the horizontal bullet navigations.
32416        */
32417        function activeSlidesNavigation(slidesNav, slideIndex){
32418            slidesNav.find(ACTIVE_SEL).removeClass(ACTIVE);
32419            slidesNav.find('li').eq(slideIndex).find('a').addClass(ACTIVE);
32420        }
32421
32422        var previousHeight = windowsHeight;
32423
32424        //when resizing the site, we adjust the heights of the sections, slimScroll...
32425        function resizeHandler(){
32426            //checking if it needs to get responsive
32427            responsive();
32428
32429            // rebuild immediately on touch devices
32430            if (isTouchDevice) {
32431                var activeElement = $(document.activeElement);
32432
32433                //if the keyboard is NOT visible
32434                if (!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select')) {
32435                    var currentHeight = $window.height();
32436
32437                    //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)
32438                    if( Math.abs(currentHeight - previousHeight) > (20 * Math.max(previousHeight, currentHeight) / 100) ){
32439                        reBuild(true);
32440                        previousHeight = currentHeight;
32441                    }
32442                }
32443            }else{
32444                //in order to call the functions only when the resize is finished
32445                //http://stackoverflow.com/questions/4298612/jquery-how-to-call-resize-event-only-once-its-finished-resizing
32446                clearTimeout(resizeId);
32447
32448                resizeId = setTimeout(function(){
32449                    reBuild(true);
32450                }, 350);
32451            }
32452        }
32453
32454        /**
32455        * Checks if the site needs to get responsive and disables autoScrolling if so.
32456        * A class `fp-responsive` is added to the plugin's container in case the user wants to use it for his own responsive CSS.
32457        */
32458        function responsive(){
32459            var widthLimit = options.responsive || options.responsiveWidth; //backwards compatiblity
32460            var heightLimit = options.responsiveHeight;
32461
32462            //only calculating what we need. Remember its called on the resize event.
32463            var isBreakingPointWidth = widthLimit && $window.outerWidth() < widthLimit;
32464            var isBreakingPointHeight = heightLimit && $window.height() < heightLimit;
32465
32466            if(widthLimit && heightLimit){
32467                setResponsive(isBreakingPointWidth || isBreakingPointHeight);
32468            }
32469            else if(widthLimit){
32470                setResponsive(isBreakingPointWidth);
32471            }
32472            else if(heightLimit){
32473                setResponsive(isBreakingPointHeight);
32474            }
32475        }
32476
32477        /**
32478        * Adds transition animations for the given element
32479        */
32480        function addAnimation(container, element){
32481            var transition = 'all ' + options.scrollingSpeed + 'ms ' + options.easingcss3;
32482
32483            container.removeClass(NO_TRANSITION);
32484            return container.css({
32485                '-webkit-transition': transition,
32486                'transition': transition
32487            });
32488        }
32489
32490        /**
32491        * Remove transition animations for the given element
32492        */
32493        function removeAnimation(element){
32494            return element.addClass(NO_TRANSITION);
32495        }
32496
32497        /**
32498        * Activating the vertical navigation bullets according to the given slide name.
32499        */
32500        function activateNavDots(name, sectionIndex){
32501            if(options.navigation){
32502                $(SECTION_NAV_SEL).find(ACTIVE_SEL).removeClass(ACTIVE);
32503                if(name){
32504                    $(SECTION_NAV_SEL).find('a[href="#' + name + '"]').addClass(ACTIVE);
32505                }else{
32506                    $(SECTION_NAV_SEL).find('li').eq(sectionIndex).find('a').addClass(ACTIVE);
32507                }
32508            }
32509        }
32510
32511        /**
32512        * Activating the website main menu elements according to the given slide name.
32513        */
32514        function activateMenuElement(name){
32515            if(options.menu){
32516                $(options.menu).find(ACTIVE_SEL).removeClass(ACTIVE);
32517                $(options.menu).find('[data-menuanchor="'+name+'"]').addClass(ACTIVE);
32518            }
32519        }
32520
32521        /**
32522        * Sets to active the current menu and vertical nav items.
32523        */
32524        function activateMenuAndNav(anchor, index){
32525            activateMenuElement(anchor);
32526            activateNavDots(anchor, index);
32527        }
32528
32529        /**
32530        * Retuns `up` or `down` depending on the scrolling movement to reach its destination
32531        * from the current section.
32532        */
32533        function getYmovement(destiny){
32534            var fromIndex = $(SECTION_ACTIVE_SEL).index(SECTION_SEL);
32535            var toIndex = destiny.index(SECTION_SEL);
32536            if( fromIndex == toIndex){
32537                return 'none';
32538            }
32539            if(fromIndex > toIndex){
32540                return 'up';
32541            }
32542            return 'down';
32543        }
32544
32545        /**
32546        * Retuns `right` or `left` depending on the scrolling movement to reach its destination
32547        * from the current slide.
32548        */
32549        function getXmovement(fromIndex, toIndex){
32550            if( fromIndex == toIndex){
32551                return 'none';
32552            }
32553            if(fromIndex > toIndex){
32554                return 'left';
32555            }
32556            return 'right';
32557        }
32558
32559        /**
32560        * Checks if the element needs scrollbar and if the user wants to apply it.
32561        * If so it creates it.
32562        *
32563        * @param {Object} element   jQuery object of the section or slide
32564        */
32565        function createScrollBar(element){
32566            //User doesn't want scrollbar here? Sayonara baby!
32567            if(element.hasClass('fp-noscroll')) return;
32568
32569            //needed to make `scrollHeight` work under Opera 12
32570            element.css('overflow', 'hidden');
32571
32572            var scrollOverflowHandler = options.scrollOverflowHandler;
32573            var wrap = scrollOverflowHandler.wrapContent();
32574            //in case element is a slide
32575            var section = element.closest(SECTION_SEL);
32576            var scrollable = scrollOverflowHandler.scrollable(element);
32577            var contentHeight;
32578
32579            //if there was scroll, the contentHeight will be the one in the scrollable section
32580            if(scrollable.length){
32581                contentHeight = scrollOverflowHandler.scrollHeight(element);
32582            }else{
32583                contentHeight = element.get(0).scrollHeight;
32584                if(options.verticalCentered){
32585                    contentHeight = element.find(TABLE_CELL_SEL).get(0).scrollHeight;
32586                }
32587            }
32588
32589            var scrollHeight = windowsHeight - parseInt(section.css('padding-bottom')) - parseInt(section.css('padding-top'));
32590
32591            //needs scroll?
32592            if ( contentHeight > scrollHeight) {
32593                //did we already have an scrollbar ? Updating it
32594                if(scrollable.length){
32595                    scrollOverflowHandler.update(element, scrollHeight);
32596                }
32597                //creating the scrolling
32598                else{
32599                    if(options.verticalCentered){
32600                        element.find(TABLE_CELL_SEL).wrapInner(wrap);
32601                    }else{
32602                        element.wrapInner(wrap);
32603                    }
32604                    scrollOverflowHandler.create(element, scrollHeight);
32605                }
32606            }
32607            //removing the scrolling when it is not necessary anymore
32608            else{
32609                scrollOverflowHandler.remove(element);
32610            }
32611
32612            //undo
32613            element.css('overflow', '');
32614        }
32615
32616        function addTableClass(element){
32617            //In case we are styling for the 2nd time as in with reponsiveSlides
32618            if(!element.hasClass(TABLE)){
32619                element.addClass(TABLE).wrapInner('<div class="' + TABLE_CELL + '" style="height:' + getTableHeight(element) + 'px;" />');
32620            }
32621        }
32622
32623        function getTableHeight(element){
32624            var sectionHeight = windowsHeight;
32625
32626            if(options.paddingTop || options.paddingBottom){
32627                var section = element;
32628                if(!section.hasClass(SECTION)){
32629                    section = element.closest(SECTION_SEL);
32630                }
32631
32632                var paddings = parseInt(section.css('padding-top')) + parseInt(section.css('padding-bottom'));
32633                sectionHeight = (windowsHeight - paddings);
32634            }
32635
32636            return sectionHeight;
32637        }
32638
32639        /**
32640        * Adds a css3 transform property to the container class with or without animation depending on the animated param.
32641        */
32642        function transformContainer(translate3d, animated){
32643            if(animated){
32644                addAnimation(container);
32645            }else{
32646                removeAnimation(container);
32647            }
32648
32649            container.css(getTransforms(translate3d));
32650
32651            //syncronously removing the class after the animation has been applied.
32652            setTimeout(function(){
32653                container.removeClass(NO_TRANSITION);
32654            },10);
32655        }
32656
32657        /**
32658        * Gets a section by its anchor / index
32659        */
32660        function getSectionByAnchor(sectionAnchor){
32661            if(!sectionAnchor) return [];
32662
32663            var section = container.find(SECTION_SEL + '[data-anchor="'+sectionAnchor+'"]');
32664            if(!section.length){
32665                section = $(SECTION_SEL).eq( sectionAnchor -1);
32666            }
32667
32668            return section;
32669        }
32670
32671        /**
32672        * Gets a slide inside a given section by its anchor / index
32673        */
32674        function getSlideByAnchor(slideAnchor, section){
32675            var slides = section.find(SLIDES_WRAPPER_SEL);
32676            var slide =  slides.find(SLIDE_SEL + '[data-anchor="'+slideAnchor+'"]');
32677
32678            if(!slide.length){
32679                slide = slides.find(SLIDE_SEL).eq(slideAnchor);
32680            }
32681
32682            return slide;
32683        }
32684
32685        /**
32686        * Scrolls to the given section and slide anchors
32687        */
32688        function scrollPageAndSlide(destiny, slide){
32689            var section = getSectionByAnchor(destiny);
32690
32691            //do nothing if there's no section with the given anchor name
32692            if(!section.length) return;
32693
32694            //default slide
32695            if (typeof slide === 'undefined') {
32696                slide = 0;
32697            }
32698
32699            //we need to scroll to the section and then to the slide
32700            if (destiny !== lastScrolledDestiny && !section.hasClass(ACTIVE)){
32701                scrollPage(section, function(){
32702                    scrollSlider(section, slide);
32703                });
32704            }
32705            //if we were already in the section
32706            else{
32707                scrollSlider(section, slide);
32708            }
32709        }
32710
32711        /**
32712        * Scrolls the slider to the given slide destination for the given section
32713        */
32714        function scrollSlider(section, slideAnchor){
32715            if(typeof slideAnchor !== 'undefined'){
32716                var slides = section.find(SLIDES_WRAPPER_SEL);
32717                var destiny =  getSlideByAnchor(slideAnchor, section);
32718
32719                if(destiny.length){
32720                    landscapeScroll(slides, destiny);
32721                }
32722            }
32723        }
32724
32725        /**
32726        * Creates a landscape navigation bar with dots for horizontal sliders.
32727        */
32728        function addSlidesNavigation(section, numSlides){
32729            section.append('<div class="' + SLIDES_NAV + '"><ul></ul></div>');
32730            var nav = section.find(SLIDES_NAV_SEL);
32731
32732            //top or bottom
32733            nav.addClass(options.slidesNavPosition);
32734
32735            for(var i=0; i< numSlides; i++){
32736                nav.find('ul').append('<li><a href="#"><span></span></a></li>');
32737            }
32738
32739            //centering it
32740            nav.css('margin-left', '-' + (nav.width()/2) + 'px');
32741
32742            nav.find('li').first().find('a').addClass(ACTIVE);
32743        }
32744
32745
32746        /**
32747        * Sets the state of the website depending on the active section/slide.
32748        * It changes the URL hash when needed and updates the body class.
32749        */
32750        function setState(slideIndex, slideAnchor, anchorLink, sectionIndex){
32751            var sectionHash = '';
32752
32753            if(options.anchors.length && !options.lockAnchors){
32754
32755                //isn't it the first slide?
32756                if(slideIndex){
32757                    if(typeof anchorLink !== 'undefined'){
32758                        sectionHash = anchorLink;
32759                    }
32760
32761                    //slide without anchor link? We take the index instead.
32762                    if(typeof slideAnchor === 'undefined'){
32763                        slideAnchor = slideIndex;
32764                    }
32765
32766                    lastScrolledSlide = slideAnchor;
32767                    setUrlHash(sectionHash + '/' + slideAnchor);
32768
32769                //first slide won't have slide anchor, just the section one
32770                }else if(typeof slideIndex !== 'undefined'){
32771                    lastScrolledSlide = slideAnchor;
32772                    setUrlHash(anchorLink);
32773                }
32774
32775                //section without slides
32776                else{
32777                    setUrlHash(anchorLink);
32778                }
32779            }
32780
32781            setBodyClass();
32782        }
32783
32784        /**
32785        * Sets the URL hash.
32786        */
32787        function setUrlHash(url){
32788            //Uncode addition
32789            if ( typeof SiteParameters.slide_footer != 'undefined' && url == SiteParameters.slide_footer )
32790                return false;
32791
32792            if(options.recordHistory){
32793                location.hash = url;
32794            }else{
32795                //Uncode addition
32796                //Mobile Chrome doesn't work the normal way, so... lets use HTML5 for phones :)
32797                // if(isTouchDevice || isTouch){
32798                //     window.history.replaceState(undefined, undefined, '#' + url);
32799                // }else{
32800                //     var baseUrl = window.location.href.split('#')[0];
32801                //     window.location.replace( baseUrl + '#' + url );
32802                // }
32803                return false;
32804            }
32805        }
32806
32807        /**
32808        * Gets the anchor for the given slide / section. Its index will be used if there's none.
32809        */
32810        function getAnchor(element){
32811            var anchor = element.data('anchor');
32812            var index = element.index();
32813
32814            //Slide without anchor link? We take the index instead.
32815            if(typeof anchor === 'undefined'){
32816                anchor = index;
32817            }
32818
32819            return anchor;
32820        }
32821
32822        /**
32823        * Sets a class for the body of the page depending on the active section / slide
32824        */
32825        function setBodyClass(){
32826            var section = $(SECTION_ACTIVE_SEL);
32827            var slide = section.find(SLIDE_ACTIVE_SEL);
32828
32829            var sectionAnchor = getAnchor(section);
32830            var slideAnchor = getAnchor(slide);
32831
32832            var text = String(sectionAnchor);
32833
32834            if(slide.length){
32835                text = text + '-' + slideAnchor;
32836            }
32837
32838            //changing slash for dash to make it a valid CSS style
32839            text = text.replace('/', '-').replace('#','');
32840
32841            //removing previous anchor classes
32842            var classRe = new RegExp('\\b\\s?' + VIEWING_PREFIX + '-[^\\s]+\\b', "g");
32843            $body[0].className = $body[0].className.replace(classRe, '');
32844
32845            //adding the current anchor
32846            $body.addClass(VIEWING_PREFIX + '-' + text);
32847        }
32848
32849        /**
32850        * Checks for translate3d support
32851        * @return boolean
32852        * http://stackoverflow.com/questions/5661671/detecting-transform-translate3d-support
32853        */
32854        function support3d() {
32855            var el = document.createElement('p'),
32856                has3d,
32857                transforms = {
32858                    'webkitTransform':'-webkit-transform',
32859                    'OTransform':'-o-transform',
32860                    'msTransform':'-ms-transform',
32861                    'MozTransform':'-moz-transform',
32862                    'transform':'transform'
32863                };
32864
32865            // Add it to the body to get the computed style.
32866            document.body.insertBefore(el, null);
32867
32868            for (var t in transforms) {
32869                if (el.style[t] !== undefined) {
32870                    el.style[t] = 'translate3d(1px,1px,1px)';
32871                    has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]);
32872                }
32873            }
32874
32875            document.body.removeChild(el);
32876
32877            return (has3d !== undefined && has3d.length > 0 && has3d !== 'none');
32878        }
32879
32880        /**
32881        * Removes the auto scrolling action fired by the mouse wheel and trackpad.
32882        * After this function is called, the mousewheel and trackpad movements won't scroll through sections.
32883        */
32884        function removeMouseWheelHandler(){
32885            if (document.addEventListener) {
32886                document.removeEventListener('mousewheel', MouseWheelHandler, false); //IE9, Chrome, Safari, Oper
32887                document.removeEventListener('wheel', MouseWheelHandler, false); //Firefox
32888                document.removeEventListener('MozMousePixelScroll', MouseWheelHandler, false); //old Firefox
32889            } else {
32890                document.detachEvent('onmousewheel', MouseWheelHandler); //IE 6/7/8
32891            }
32892        }
32893
32894        /**
32895        * Adds the auto scrolling action for the mouse wheel and trackpad.
32896        * After this function is called, the mousewheel and trackpad movements will scroll through sections
32897        * https://developer.mozilla.org/en-US/docs/Web/Events/wheel
32898        */
32899        function addMouseWheelHandler(){
32900            var prefix = '';
32901            var _addEventListener;
32902
32903            if (window.addEventListener){
32904                _addEventListener = "addEventListener";
32905            }else{
32906                _addEventListener = "attachEvent";
32907                prefix = 'on';
32908            }
32909
32910             // detect available wheel event
32911            var support = 'onwheel' in document.createElement('div') ? 'wheel' : // Modern browsers support "wheel"
32912                      document.onmousewheel !== undefined ? 'mousewheel' : // Webkit and IE support at least "mousewheel"
32913                      'DOMMouseScroll'; // let's assume that remaining browsers are older Firefox
32914            var passiveEvent = g_supportsPassive ? {passive: false }
32914: false;
32915
32916
32917            if(support == 'DOMMouseScroll'){
32918                document[ _addEventListener ](prefix + 'MozMousePixelScroll', MouseWheelHandler, passiveEvent);
32919            }
32920
32921            //handle MozMousePixelScroll in older Firefox
32922            else{
32923                document[ _addEventListener ](prefix + support, MouseWheelHandler, passiveEvent);
32924            }
32925        }
32926
32927        /**
32928        * Binding the mousemove when the mouse's middle button is pressed
32929        */
32930        function addMiddleWheelHandler(){
32931            container
32932                .on('mousedown', mouseDownHandler)
32933                .on('mouseup', mouseUpHandler);
32934        }
32935
32936        /**
32937        * Unbinding the mousemove when the mouse's middle button is released
32938        */
32939        function removeMiddleWheelHandler(){
32940            container
32941                .off('mousedown', mouseDownHandler)
32942                .off('mouseup', mouseUpHandler);
32943        }
32944
32945        /**
32946        * Adds the possibility to auto scroll through sections on touch devices.
32947        */
32948        function addTouchHandler(){
32949            if(isTouchDevice || isTouch){
32950                if(options.autoScrolling){
32951                    $body.off(events.touchmove).on(events.touchmove, preventBouncing);
32952                }
32953
32954                $(WRAPPER_SEL)
32955                    .off(events.touchstart).on(events.touchstart, touchStartHandler)
32956                    .off(events.touchmove).on(events.touchmove, touchMoveHandler);
32957            }
32958        }
32959
32960        /**
32961        * Removes the auto scrolling for touch devices.
32962        */
32963        function removeTouchHandler(){
32964            if(isTouchDevice || isTouch){
32965                $(WRAPPER_SEL)
32966                    .off(events.touchstart)
32967                    .off(events.touchmove);
32968            }
32969        }
32970
32971        /*
32972        * Returns and object with Microsoft pointers (for IE<11 and for IE >= 11)
32973        * http://msdn.microsoft.com/en-us/library/ie/dn304886(v=vs.85).aspx
32974        */
32975        function getMSPointer(){
32976            var pointer;
32977
32978            //IE >= 11 & rest of browsers
32979            if(window.PointerEvent){
32980                pointer = { down: 'pointerdown', move: 'pointermove'};
32981            }
32982
32983            //IE < 11
32984            else{
32985                pointer = { down: 'MSPointerDown', move: 'MSPointerMove'};
32986            }
32987
32988            return pointer;
32989        }
32990
32991        /**
32992        * Gets the pageX and pageY properties depending on the browser.
32993        * https://github.com/alvarotrigo/fullPage.js/issues/194#issuecomment-34069854
32994        */
32995        function getEventsPage(e){
32996            var events = [];
32997
32998            events.y = (typeof e.pageY !== 'undefined' && (e.pageY || e.pageX) ? e.pageY : e.touches[0].pageY);
32999            events.x = (typeof e.pageX !== 'undefined' && (e.pageY || e.pageX) ? e.pageX : e.touches[0].pageX);
33000
33001            //in touch devices with scrollBar:true, e.pageY is detected, but we have to deal with touch events. #1008
33002            if(isTouch && isReallyTouch(e) && options.scrollBar){
33003                events.y = e.touches[0].pageY;
33004                events.x = e.touches[0].pageX;
33005            }
33006
33007            return events;
33008        }
33009
33010        /**
33011        * Slides silently (with no animation) the active slider to the given slide.
33012        * @param noCallback {bool} true or defined -> no callbacks
33013        */
33014        function silentLandscapeScroll(activeSlide, noCallbacks){
33015            setScrollingSpeed (0, 'internal');
33016
33017            if(typeof noCallbacks !== 'undefined'){
33018                //preventing firing callbacks afterSlideLoad etc.
33019                isResizing = true;
33020            }
33021
33022            landscapeScroll(activeSlide.closest(SLIDES_WRAPPER_SEL), activeSlide);
33023
33024            if(typeof noCallbacks !== 'undefined'){
33025                isResizing = false;
33026            }
33027
33028            setScrollingSpeed(originals.scrollingSpeed, 'internal');
33029        }
33030
33031        /**
33032        * Scrolls silently (with no animation) the page to the given Y position.
33033        */
33034        function silentScroll(top){
33035            // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625
33036            // that's why we round it to 0.
33037            var roundedTop = Math.round(top);
33038
33039            if (options.css3 && options.autoScrolling && !options.scrollBar){
33040                var translate3d = 'translate3d(0px, -' + roundedTop + 'px, 0px)';
33041                transformContainer(translate3d, false);
33042            }
33043            else if(options.autoScrolling && !options.scrollBar){
33044                container.css('top', -roundedTop);
33045            }
33046            else{
33047                $htmlBody.scrollTop(roundedTop);
33048            }
33049        }
33050
33051        /**
33052        * Returns the cross-browser transform string.
33053        */
33054        function getTransforms(translate3d){
33055            return {
33056                '-webkit-transform': translate3d,
33057                '-moz-transform': translate3d,
33058                '-ms-transform':translate3d,
33059                'transform': translate3d
33060            };
33061        }
33062
33063        /**
33064        * Allowing or disallowing the mouse/swipe scroll in a given direction. (not for keyboard)
33065        * @type  m (mouse) or k (keyboard)
33066        */
33067        function setIsScrollAllowed(value, direction, type){
33068            switch (direction){
33069                case 'up': isScrollAllowed[type].up = value; break;
33070                case 'down': isScrollAllowed[type].down = value; break;
33071                case 'left': isScrollAllowed[type].left = value; break;
33072                case 'right': isScrollAllowed[type].right = value; break;
33073                case 'all':
33074                    if(type == 'm'){
33075                        setAllowScrolling(value);
33076                    }else{
33077                        setKeyboardScrolling(value);
33078                    }
33079            }
33080        }
33081
33082        /*
33083        * Destroys fullpage.js plugin events and optinally its html markup and styles
33084        */
33085        function destroy(all){
33086            setAutoScrolling(false, 'internal');
33087            setAllowScrolling(false);
33088            setKeyboardScrolling(false);
33089            container.addClass(DESTROYED);
33090
33091            clearTimeout(afterSlideLoadsId);
33092            clearTimeout(afterSectionLoadsId);
33093            clearTimeout(resizeId);
33094            clearTimeout(scrollId);
33095            clearTimeout(scrollId2);
33096
33097            $window
33098                .off('scroll', scrollHandler)
33099                .off('hashchange', hashChangeHandler)
33100                .off('resize', resizeHandler);
33101
33102            $document
33103                .off('click touchstart', SECTION_NAV_SEL + ' a')
33104                .off('mouseenter', SECTION_NAV_SEL + ' li')
33105                .off('mouseleave', SECTION_NAV_SEL + ' li')
33106                .off('click touchstart', SLIDES_NAV_LINK_SEL)
33107                .off('mouseover', options.normalScrollElements)
33108                .off('mouseout', options.normalScrollElements);
33109
33110            $(SECTION_SEL)
33111                .off('click touchstart', SLIDES_ARROW_SEL);
33112
33113            clearTimeout(afterSlideLoadsId);
33114            clearTimeout(afterSectionLoadsId);
33115
33116            //lets make a mess!
33117            if(all){
33118                destroyStructure();
33119            }
33120        }
33121
33122        /*
33123        * Removes inline styles added by fullpage.js
33124        */
33125        function destroyStructure(){
33126            //reseting the `top` or `translate` properties to 0
33127            silentScroll(0);
33128
33129            //loading all the lazy load content
33130            container.find('img[data-src], source[data-src], audio[data-src], iframe[data-src]').each(function(){
33131                setSrc($(this), 'src');
33132            });
33133
33134            container.find('img[data-srcset]').each(function(){
33135                setSrc($(this), 'srcset');
33136            });
33137
33138            $(SECTION_NAV_SEL + ', ' + SLIDES_NAV_SEL +  ', ' + SLIDES_ARROW_SEL).remove();
33139
33140            //removing inline styles
33141            $(SECTION_SEL).css( {
33142                'height': '',
33143                'background-color' : '',
33144                'padding': ''
33145            });
33146
33147            $(SLIDE_SEL).css( {
33148                'width': ''
33149            });
33150
33151            container.css({
33152                'height': '',
33153                'position': '',
33154                '-ms-touch-action': '',
33155                'touch-action': ''
33156            });
33157
33158            $htmlBody.css({
33159                'overflow': '',
33160                'height': ''
33161            });
33162
33163            // remove .fp-enabled class
33164            $('html').removeClass(ENABLED);
33165
33166            // remove .fp-responsive class
33167            $body.removeClass(RESPONSIVE);
33168
33169            // remove all of the .fp-viewing- classes
33170            $.each($body.get(0).className.split(/\s+/), function (index, className) {
33171                if (className.indexOf(VIEWING_PREFIX) === 0) {
33172                    $body.removeClass(className);
33173                }
33174            });
33175
33176            //removing added classes
33177            $(SECTION_SEL + ', ' + SLIDE_SEL).each(function(){
33178                options.scrollOverflowHandler.remove($(this));
33179                $(this).removeClass(TABLE + ' ' + ACTIVE);
33180            });
33181
33182            removeAnimation(container);
33183
33184            //Unwrapping content
33185            container.find(TABLE_CELL_SEL + ', ' + SLIDES_CONTAINER_SEL + ', ' + SLIDES_WRAPPER_SEL).each(function(){
33186                //unwrap not being use in case there's no child element inside and its just text
33187                $(this).replaceWith(this.childNodes);
33188            });
33189
33190            //removing the applied transition from the fullpage wrapper
33191            container.css({
33192                '-webkit-transition': 'none',
33193                'transition': 'none'
33194            });
33195
33196            //scrolling the page to the top with no animation
33197            $htmlBody.scrollTop(0);
33198
33199            //removing selectors
33200            var usedSelectors = [SECTION, SLIDE, SLIDES_CONTAINER];
33201            $.each(usedSelectors, function(index, value){
33202                $('.' + value).removeClass(value);
33203            });
33204        }
33205
33206        /*
33207        * Sets the state for a variable with multiple states (original, and temporal)
33208        * Some variables such as `autoScrolling` or `recordHistory` might change automatically its state when using `responsive` or `autoScrolling:false`.
33209        * This function is used to keep track of both states, the original and the temporal one.
33210        * If type is not 'internal', then we assume the user is globally changing the variable.
33211        */
33212        function setVariableState(variable, value, type){
33213            options[variable] = value;
33214            if(type !== 'internal'){
33215                originals[variable] = value;
33216            }
33217        }
33218
33219        /**
33220        * Displays warnings
33221        */
33222        function displayWarnings(){
33223            var extensions = ['fadingEffect', 'continuousHorizontal', 'scrollHorizontally', 'interlockedSlides', 'resetSliders', 'responsiveSlides', 'offsetSections', 'dragAndMove', 'scrollOverflowReset', 'parallax'];
33224            //UNCODE.addition
33225            // if($('html').hasClass(ENABLED)){
33226            //     showError('error', 'Fullpage.js can only be initialized once and you are doing it multiple times!');
33227            //     return;
33228            // }
33229
33230            // Disable mutually exclusive settings
33231            //UNCODE.addition
33232            // if (options.continuousVertical &&
33233            //     (options.loopTop || options.loopBottom)) {
33234            //     options.continuousVertical = false;
33235            //     showError('warn', 'Option `loopTop/loopBottom` is mutually exclusive with `continuousVertical`; `continuousVertical` disabled');
33236            // }
33237
33238            // if(options.scrollBar && options.scrollOverflow){
33239            //     showError('warn', 'Option `scrollBar` is mutually exclusive with `scrollOverflow`. Sections with scrollOverflow might not work well in Firefox');
33240            // }
33241
33242            // if(options.continuousVertical && (options.scrollBar || !options.autoScrolling)){
33243            //     options.continuousVertical = false;
33244            //     showError('warn', 'Scroll bars (`scrollBar:true` or `autoScrolling:false`) are mutually exclusive with `continuousVertical`; `continuousVertical` disabled');
33245            // }
33246
33247            //using extensions? Wrong file!
33248            $.each(extensions, function(index, extension){
33249                //is the option set to true?
33250                if(options[extension]){
33251                    showError('warn', 'fullpage.js extensions require jquery.fullpage.extensions.min.js file instead of the usual jquery.fullpage.js. Requested: '+ extension);
33252                }
33253            });
33254
33255            //anchors can not have the same value as any element ID or NAME
33256            $.each(options.anchors, function(index, name){
33257
33258                //case insensitive selectors (http://stackoverflow.com/a/19465187/1081396)
33259                var nameAttr = $document.find('[name]').filter(function() {
33260                    return $(this).attr('name') && $(this).attr('name').toLowerCase() == name.toLowerCase();
33261                });
33262
33263                var idAttr = $document.find('[id]').filter(function() {
33264                    return $(this).attr('id') && $(this).attr('id').toLowerCase() == name.toLowerCase();
33265                });
33266
33267                if(idAttr.length || nameAttr.length ){
33268                    showError('error', 'data-anchor tags can not have the same value as any `id` element on the site (or `name` element for IE).');
33269                    idAttr.length && showError('error', '"' + name + '" is is being used by another element `id` property');
33270                    nameAttr.length && showError('error', '"' + name + '" is is being used by another element `name` property');
33271                }
33272            });
33273        }
33274
33275        /**
33276        * Shows a message in the console of the given type.
33277        */
33278        function showError(type, text){
33279            console && console[type] && console[type]('fullPage: ' + text);
33280        }
33281
33282    }; //end of $.fn.fullpage
33283
33284    if(typeof IScroll !== 'undefined'){
33285        /*
33286        * Turns iScroll `mousewheel` option off dynamically
33287        * https://github.com/cubiq/iscroll/issues/1036
33288        */
33289        IScroll.prototype.wheelOn = function () {
33290            this.wrapper.addEventListener('wheel', this);
33291            this.wrapper.addEventListener('mousewheel', this);
33292            this.wrapper.addEventListener('DOMMouseScroll', this);
33293        };
33294
33295        /*
33296        * Turns iScroll `mousewheel` option on dynamically
33297        * https://github.com/cubiq/iscroll/issues/1036
33298        */
33299        IScroll.prototype.wheelOff = function () {
33300            this.wrapper.removeEventListener('wheel', this);
33301            this.wrapper.removeEventListener('mousewheel', this);
33302            this.wrapper.removeEventListener('DOMMouseScroll', this);
33303        };
33304    }
33305
33306    /**
33307     * An object to handle overflow scrolling.
33308     * This uses jquery.slimScroll to accomplish overflow scrolling.
33309     * It is possible to pass in an alternate scrollOverflowHandler
33310     * to the fullpage.js option that implements the same functions
33311     * as this handler.
33312     *
33313     * @type {Object}
33314     */
33315    var iscrollHandler = {
33316        refreshId: null,
33317        iScrollInstances: [],
33318
33319        // Enables or disables the mouse wheel for the active section or all slides in it
33320        toggleWheel: function(value){
33321            var scrollable = $(SECTION_ACTIVE_SEL).find(SCROLLABLE_SEL);
33322            scrollable.each(function(){
33323                var iScrollInstance = $(this).data('iscrollInstance');
33324                if(typeof iScrollInstance !== 'undefined' && iScrollInstance){
33325                    if(value){
33326                        iScrollInstance.wheelOn();
33327                    }
33328                    else{
33329                        iScrollInstance.wheelOff();
33330                    }
33331                }
33332            });
33333        },
33334
33335        /**
33336        * Turns off iScroll for the destination section.
33337        * When scrolling very fast on some trackpads (and Apple laptops) the inertial scrolling would
33338        * scroll the destination section/slide before the sections animations ends.
33339        */
33340        onLeave: function(){
33341            iscrollHandler.toggleWheel(false);
33342        },
33343
33344        // Turns off iScroll for the leaving section
33345        beforeLeave: function(){
33346            iscrollHandler.onLeave()
33347        },
33348
33349        // Turns on iScroll on section load
33350        afterLoad: function(){
33351            iscrollHandler.toggleWheel(true);
33352        },
33353
33354        /**
33355         * Called when overflow scrolling is needed for a section.
33356         *
33357         * @param  {Object} element      jQuery object containing current section
33358         * @param  {Number} scrollHeight Current window height in pixels
33359         */
33360        create: function(element, scrollHeight) {
33361            var scrollable = element.find(SCROLLABLE_SEL);
33362
33363            scrollable.height(scrollHeight);
33364            scrollable.each(function() {
33365                var $this = $(this);
33366                var iScrollInstance = $this.data('iscrollInstance');
33367                if (iScrollInstance) {
33368                    $.each(iscrollHandler.iScrollInstances, function(){
33369                        $(this).destroy();
33370                    });
33371                }
33372
33373                iScrollInstance = new IScroll($this.get(0), iscrollOptions);
33374                iscrollHandler.iScrollInstances.push(iScrollInstance);
33375
33376                //off by default until the section gets active
33377                iScrollInstance.wheelOff();
33378
33379                $this.data('iscrollInstance', iScrollInstance);
33380            });
33381        },
33382
33383        /**
33384         * Return a boolean depending on whether the scrollable element is a
33385         * the end or at the start of the scrolling depending on the given type.
33386         *
33387         * @param  {String}  type       Either 'top' or 'bottom'
33388         * @param  {Object}  scrollable jQuery object for the scrollable element
33389         * @return {Boolean}
33390         */
33391        isScrolled: function(type, scrollable) {
33392            var scroller = scrollable.data('iscrollInstance');
33393
33394            //no scroller?
33395            if (!scroller) {
33396                return true;
33397            }
33398
33399            //Uncode addition
33400            var uncode_body_borders = parseFloat($('.body-borders').attr('data-border')) || 0;
33401            //End Uncode addition
33402
33403            if (type === 'top') {
33404                return scroller.y >= 0 && !scrollable.scrollTop();
33405            } else if (type === 'bottom') {
33406                //Uncode change
33407                // return (0 - scroller.y) + scrollable.scrollTop() + 1 + scrollable.innerHeight() >= scrollable[0].scrollHeight;
33408                return (0 - scroller.y) + scrollable.scrollTop() + 1 + ( uncode_body_borders * 2 ) + scrollable.innerHeight() >= scrollable[0].scrollHeight;
33409                //End Uncode change
33410            }
33411        },
33412
33413        /**
33414         * Returns the scrollable element for the given section.
33415         * If there are landscape slides, will only return a scrollable element
33416         * if it is in the active slide.
33417         *
33418         * @param  {Object}  activeSection jQuery object containing current section
33419         * @return {Boolean}
33420         */
33421        scrollable: function(activeSection){
33422            // if there are landscape slides, we check if the scrolling bar is in the current one or not
33423            if (activeSection.find(SLIDES_WRAPPER_SEL).length) {
33424                return activeSection.find(SLIDE_ACTIVE_SEL).find(SCROLLABLE_SEL);
33425            }
33426            return activeSection.find(SCROLLABLE_SEL);
33427        },
33428
33429        /**
33430         * Returns the scroll height of the wrapped content.
33431         * If this is larger than the window height minus section padding,
33432         * overflow scrolling is needed.
33433         *
33434         * @param  {Object} element jQuery object containing current section
33435         * @return {Number}
33436         */
33437        scrollHeight: function(element) {
33438            return element.find(SCROLLABLE_SEL).children().first().get(0).scrollHeight;
33439        },
33440
33441        /**
33442         * Called when overflow scrolling is no longer needed for a section.
33443         *
33444         * @param  {Object}
33444 element      jQuery object containing current section
33445         */
33446        remove: function(element) {
33447            var scrollable = element.find(SCROLLABLE_SEL);
33448            if (scrollable.length) {
33449                var iScrollInstance = scrollable.data('iscrollInstance');
33450                iScrollInstance.destroy();
33451
33452                scrollable.data('iscrollInstance', null);
33453            }
33454            element.find(SCROLLABLE_SEL).children().first().children().first().unwrap().unwrap();
33455        },
33456
33457        /**
33458         * Called when overflow scrolling has already been setup but the
33459         * window height has potentially changed.
33460         *
33461         * @param  {Object} element      jQuery object containing current section
33462         * @param  {Number} scrollHeight Current window height in pixels
33463         */
33464        update: function(element, scrollHeight) {
33465            //using a timeout in order to execute the refresh function only once when `update` is called multiple times in a
33466            //short period of time.
33467            //it also comes on handy because iScroll requires the use of timeout when using `refresh`.
33468            clearTimeout(iscrollHandler.refreshId);
33469            iscrollHandler.refreshId = setTimeout(function(){
33470                $.each(iscrollHandler.iScrollInstances, function(){
33471                    $(this).get(0).refresh();
33472                });
33473            }, 150);
33474
33475            //updating the wrappers height
33476            element.find(SCROLLABLE_SEL).css('height', scrollHeight + 'px').parent().css('height', scrollHeight + 'px');
33477        },
33478
33479        /**
33480         * Called to get any additional elements needed to wrap the section
33481         * content in order to facilitate overflow scrolling.
33482         *
33483         * @return {String|Object} Can be a string containing HTML,
33484         *                         a DOM element, or jQuery object.
33485         */
33486        wrapContent: function() {
33487            return '<div class="' + SCROLLABLE + '"><div class="fp-scroller"></div></div>';
33488        }
33489    };
33490});
33491
33492(function (global, factory) {
33493	typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
33494	typeof define === 'function' && define.amd ? define(['exports'], factory) :
33495	(global = global || self, factory(global.window = global.window || {}));
33496}(this, (function (exports) { 'use strict';
33497
33498	/*!
33499	 * ScrollTrigger 3.8.0
33500	 * https://greensock.com
33501	 *
33502	 * @license Copyright 2008-2021, GreenSock. All rights reserved.
33503	 * Subject to the terms at https://greensock.com/standard-license or for
33504	 * Club GreenSock members, the agreement issued with that membership.
33505	 * @author: Jack Doyle, [email protected]
33506	*/
33507	var gsap,
33508	    _coreInitted,
33509	    _win,
33510	    _doc,
33511	    _docEl,
33512	    _body,
33513	    _root,
33514	    _resizeDelay,
33515	    _raf,
33516	    _request,
33517	    _toArray,
33518	    _clamp,
33519	    _time2,
33520	    _syncInterval,
33521	    _refreshing,
33522	    _pointerIsDown,
33523	    _transformProp,
33524	    _i,
33525	    _prevWidth,
33526	    _prevHeight,
33527	    _autoRefresh,
33528	    _sort,
33529	    _suppressOverwrites,
33530	    _ignoreResize,
33531	    _limitCallbacks,
33532	    _startup = 1,
33533	    _proxies = [],
33534	    _scrollers = [],
33535	    _getTime = Date.now,
33536	    _time1 = _getTime(),
33537	    _lastScrollTime = 0,
33538	    _enabled = 1,
33539	    _passThrough = function _passThrough(v) {
33540	  return v;
33541	},
33542	    _getTarget = function _getTarget(t) {
33543	  return _toArray(t)[0] || (_isString(t) ? console.warn("Element not found:", t) : null);
33544	},
33545	    _round = function _round(value) {
33546	  return Math.round(value * 100000) / 100000 || 0;
33547	},
33548	    _windowExists = function _windowExists() {
33549	  return typeof window !== "undefined";
33550	},
33551	    _getGSAP = function _getGSAP() {
33552	  return gsap || _windowExists() && (gsap = window.gsap) && gsap.registerPlugin && gsap;
33553	},
33554	    _isViewport = function _isViewport(e) {
33555	  return !!~_root.indexOf(e);
33556	},
33557	    _getProxyProp = function _getProxyProp(element, property) {
33558	  return ~_proxies.indexOf(element) && _proxies[_proxies.indexOf(element) + 1][property];
33559	},
33560	    _getScrollFunc = function _getScrollFunc(element, _ref) {
33561	  var s = _ref.s,
33562	      sc = _ref.sc;
33563
33564	  var i = _scrollers.indexOf(element),
33565	      offset = sc === _vertical.sc ? 1 : 2;
33566
33567	  !~i && (i = _scrollers.push(element) - 1);
33568	  return _scrollers[i + offset] || (_scrollers[i + offset] = _getProxyProp(element, s) || (_isViewport(element) ? sc : function (value) {
33569	    return arguments.length ? element[s] = value : element[s];
33570	  }));
33571	},
33572	    _getBoundsFunc = function _getBoundsFunc(element) {
33573	  return _getProxyProp(element, "getBoundingClientRect") || (_isViewport(element) ? function () {
33574	    _winOffsets.width = _win.innerWidth;
33575	    _winOffsets.height = _win.innerHeight;
33576	    return _winOffsets;
33577	  } : function () {
33578	    return _getBounds(element);
33579	  });
33580	},
33581	    _getSizeFunc = function _getSizeFunc(scroller, isViewport, _ref2) {
33582	  var d = _ref2.d,
33583	      d2 = _ref2.d2,
33584	      a = _ref2.a;
33585	  return (a = _getProxyProp(scroller, "getBoundingClientRect")) ? function () {
33586	    return a()[d];
33587	  } : function () {
33588	    return (isViewport ? _win["inner" + d2] : scroller["client" + d2]) || 0;
33589	  };
33590	},
33591	    _getOffsetsFunc = function _getOffsetsFunc(element, isViewport) {
33592	  return !isViewport || ~_proxies.indexOf(element) ? _getBoundsFunc(element) : function () {
33593	    return _winOffsets;
33594	  };
33595	},
33596	    _maxScroll = function _maxScroll(element, _ref3) {
33597	  var s = _ref3.s,
33598	      d2 = _ref3.d2,
33599	      d = _ref3.d,
33600	      a = _ref3.a;
33601	  return (s = "scroll" + d2) && (a = _getProxyProp(element, s)) ? a() - _getBoundsFunc(element)()[d] : _isViewport(element) ? (_body[s] || _docEl[s]) - (_win["inner" + d2] || _docEl["client" + d2] || _body["client" + d2]) : element[s] - element["offset" + d2];
33602	},
33603	    _iterateAutoRefresh = function _iterateAutoRefresh(func, events) {
33604	  for (var i = 0; i < _autoRefresh.length; i += 3) {
vendor: 5,689 bytes, lines 33605-33809
33605	    (!events || ~events.indexOf(_autoRefresh[i + 1])) && func(_autoRefresh[i], _autoRefresh[i + 1], _autoRefresh[i + 2]);
33606	  }
33607	},
33608	    _isString = function _isString(value) {
33609	  return typeof value === "string";
33610	},
33611	    _isFunction = function _isFunction(value) {
33612	  return typeof value === "function";
33613	},
33614	    _isNumber = function _isNumber(value) {
33615	  return typeof value === "number";
33616	},
33617	    _isObject = function _isObject(value) {
33618	  return typeof value === "object";
33619	},
33620	    _callIfFunc = function _callIfFunc(value) {
33621	  return _isFunction(value) && value();
33622	},
33623	    _combineFunc = function _combineFunc(f1, f2) {
33624	  return function () {
33625	    var result1 = _callIfFunc(f1),
33626	        result2 = _callIfFunc(f2);
33627
33628	    return function () {
33629	      _callIfFunc(result1);
33630
33631	      _callIfFunc(result2);
33632	    };
33633	  };
33634	},
33635	    _endAnimation = function _endAnimation(animation, reversed, pause) {
33636	  return animation && animation.progress(reversed ? 0 : 1) && pause && animation.pause();
33637	},
33638	    _callback = function _callback(self, func) {
33639	  var result = func(self);
33640	  result && result.totalTime && (self.callbackAnimation = result);
33641	},
33642	    _abs = Math.abs,
33643	    _scrollLeft = "scrollLeft",
33644	    _scrollTop = "scrollTop",
33645	    _left = "left",
33646	    _top = "top",
33647	    _right = "right",
33648	    _bottom = "bottom",
33649	    _width = "width",
33650	    _height = "height",
33651	    _Right = "Right",
33652	    _Left = "Left",
33653	    _Top = "Top",
33654	    _Bottom = "Bottom",
33655	    _padding = "padding",
33656	    _margin = "margin",
33657	    _Width = "Width",
33658	    _Height = "Height",
33659	    _px = "px",
33660	    _horizontal = {
33661	  s: _scrollLeft,
33662	  p: _left,
33663	  p2: _Left,
33664	  os: _right,
33665	  os2: _Right,
33666	  d: _width,
33667	  d2: _Width,
33668	  a: "x",
33669	  sc: function sc(value) {
33670	    return arguments.length ? _win.scrollTo(value, _vertical.sc()) : _win.pageXOffset || _doc[_scrollLeft] || _docEl[_scrollLeft] || _body[_scrollLeft] || 0;
33671	  }
33672	},
33673	    _vertical = {
33674	  s: _scrollTop,
33675	  p: _top,
33676	  p2: _Top,
33677	  os: _bottom,
33678	  os2: _Bottom,
33679	  d: _height,
33680	  d2: _Height,
33681	  a: "y",
33682	  op: _horizontal,
33683	  sc: function sc(value) {
33684	    return arguments.length ? _win.scrollTo(_horizontal.sc(), value) : _win.pageYOffset || _doc[_scrollTop] || _docEl[_scrollTop] || _body[_scrollTop] || 0;
33685	  }
33686	},
33687	    _getComputedStyle = function _getComputedStyle(element) {
33688	  return _win.getComputedStyle(element);
33689	},
33690	    _makePositionable = function _makePositionable(element) {
33691	  var position = _getComputedStyle(element).position;
33692
33693	  element.style.position = position === "absolute" || position === "fixed" ? position : "relative";
33694	},
33695	    _setDefaults = function _setDefaults(obj, defaults) {
33696	  for (var p in defaults) {
33697	    p in obj || (obj[p] = defaults[p]);
33698	  }
33699
33700	  return obj;
33701	},
33702	    _getBounds = function _getBounds(element, withoutTransforms) {
33703	  var tween = withoutTransforms && _getComputedStyle(element)[_transformProp] !== "matrix(1, 0, 0, 1, 0, 0)" && gsap.to(element, {
33704	    x: 0,
33705	    y: 0,
33706	    xPercent: 0,
33707	    yPercent: 0,
33708	    rotation: 0,
33709	    rotationX: 0,
33710	    rotationY: 0,
33711	    scale: 1,
33712	    skewX: 0,
33713	    skewY: 0
33714	  }).progress(1),
33715	      bounds = element.getBoundingClientRect();
33716	  tween && tween.progress(0).kill();
33717	  return bounds;
33718	},
33719	    _getSize = function _getSize(element, _ref4) {
33720	  var d2 = _ref4.d2;
33721	  return element["offset" + d2] || element["client" + d2] || 0;
33722	},
33723	    _getLabelRatioArray = function _getLabelRatioArray(timeline) {
33724	  var a = [],
33725	      labels = timeline.labels,
33726	      duration = timeline.duration(),
33727	      p;
33728
33729	  for (p in labels) {
33730	    a.push(labels[p] / duration);
33731	  }
33732
33733	  return a;
33734	},
33735	    _getClosestLabel = function _getClosestLabel(animation) {
33736	  return function (value) {
33737	    return gsap.utils.snap(_getLabelRatioArray(animation), value);
33738	  };
33739	},
33740	    _snapDirectional = function _snapDirectional(snapIncrementOrArray) {
33741	  var snap = gsap.utils.snap(snapIncrementOrArray),
33742	      a = Array.isArray(snapIncrementOrArray) && snapIncrementOrArray.slice(0).sort(function (a, b) {
33743	    return a - b;
33744	  });
33745	  return a ? function (value, direction) {
33746	    var i;
33747
33748	    if (!direction) {
33749	      return snap(value);
33750	    }
33751
33752	    if (direction > 0) {
33753	      value -= 1e-4;
33754
33755	      for (i = 0; i < a.length; i++) {
33756	        if (a[i] >= value) {
33757	          return a[i];
33758	        }
33759	      }
33760
33761	      return a[i - 1];
33762	    } else {
33763	      i = a.length;
33764	      value += 1e-4;
33765
33766	      while (i--) {
33767	        if (a[i] <= value) {
33768	          return a[i];
33769	        }
33770	      }
33771	    }
33772
33773	    return a[0];
33774	  } : function (value, direction) {
33775	    var snapped = snap(value);
33776	    return !direction || Math.abs(snapped - value) < 0.001 || snapped - value < 0 === direction < 0 ? snapped : snap(direction < 0 ? value - snapIncrementOrArray : value + snapIncrementOrArray);
33777	  };
33778	},
33779	    _getLabelAtDirection = function _getLabelAtDirection(timeline) {
33780	  return function (value, st) {
33781	    return _snapDirectional(_getLabelRatioArray(timeline))(value, st.direction);
33782	  };
33783	},
33784	    _multiListener = function _multiListener(func, element, types, callback) {
33785	  return types.split(",").forEach(function (type) {
33786	    return func(element, type, callback);
33787	  });
33788	},
33789	    _addListener = function _addListener(element, type, func) {
33790	  return element.addEventListener(type, func, {
33791	    passive: true
33792	  });
33793	},
33794	    _removeListener = function _removeListener(element, type, func) {
33795	  return element.removeEventListener(type, func);
33796	},
33797	    _markerDefaults = {
33798	  startColor: "green",
33799	  endColor: "red",
33800	  indent: 0,
33801	  fontSize: "16px",
33802	  fontWeight: "normal"
33803	},
33804	    _defaults = {
33805	  toggleActions: "play",
33806	  anticipatePin: 0
33807	},
33808	    _keywords = {
33809	  top: 0,
33810	  left: 0,
33811	  center: 0.5,
33812	  bottom: 1,
33813	  right: 1
33814	},
33815	    _offsetToPx = function _offsetToPx(value, size) {
33816	  if (_isString(value)) {
33817	    var eqIndex = value.indexOf("="),
33818	        relative = ~eqIndex ? +(value.charAt(eqIndex - 1) + 1) * parseFloat(value.substr(eqIndex + 1)) : 0;
33819
33820	    if (~eqIndex) {
33821	      value.indexOf("%") > eqIndex && (relative *= size / 100);
33822	      value = value.substr(0, eqIndex - 1);
33823	    }
33824
33825	    value = relative + (value in _keywords ? _keywords[value] * size : ~value.indexOf("%") ? parseFloat(value) * size / 100 : parseFloat(value) || 0);
33826	  }
33827
33828	  return value;
33829	},
33830	    _createMarker = function _createMarker(type, name, container, direction, _ref5, offset, matchWidthEl, containerAnimation) {
33831	  var startColor = _ref5.startColor,
33832	      endColor = _ref5.endColor,
33833	      fontSize = _ref5.fontSize,
33834	      indent = _ref5.indent,
33835	      fontWeight = _ref5.fontWeight;
33836
33837	  var e = _doc.createElement("div"),
33838	      useFixedPosition = _isViewport(container) || _getProxyProp(container, "pinType") === "fixed",
33839	      isScroller = type.indexOf("scroller") !== -1,
33840	      parent = useFixedPosition ? _body : container,
33841	      isStart = type.indexOf("start") !== -1,
33842	      color = isStart ? startColor : endColor,
33843	      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;";
33844
33845	  css += "position:" + ((isScroller || containerAnimation) && useFixedPosition ? "fixed;" : "absolute;");
33846	  (isScroller || containerAnimation || !useFixedPosition) && (css += (direction === _vertical ? _right : _bottom) + ":" + (offset + parseFloat(indent)) + "px;");
33847	  matchWidthEl && (css += "box-sizing:border-box;text-align:left;width:" + matchWidthEl.offsetWidth + "px;");
33848	  e._isStart = isStart;
33849	  e.setAttribute("class", "gsap-marker-" + type + (name ? " marker-" + name : ""));
33850	  e.style.cssText = css;
33851	  e.innerText = name || name === 0 ? type + "-" + name : type;
33852	  parent.children[0] ? parent.insertBefore(e, parent.children[0]) : parent.appendChild(e);
33853	  e._offset = e["offset" + direction.op.d2];
33854
33855	  _positionMarker(e, 0, direction, isStart);
33856
33857	  return e;
33858	},
33859	    _positionMarker = function _positionMarker(marker, start, direction, flipped) {
33860	  var vars = {
33861	    display: "block"
33862	  },
33863	      side = direction[flipped ? "os2" : "p2"],
33864	      oppositeSide = direction[flipped ? "p2" : "os2"];
33865	  marker._isFlipped = flipped;
33866	  vars[direction.a + "Percent"] = flipped ? -100 : 0;
33867	  vars[direction.a] = flipped ? "1px" : 0;
33868	  vars["border" + side + _Width] = 1;
33869	  vars["border" + oppositeSide + _Width] = 0;
33870	  vars[direction.p] = start + "px";
33871	  gsap.set(marker, vars);
33872	},
33873	    _triggers = [],
33874	    _ids = {},
33875	    _sync = function _sync() {
33876	  return _getTime() - _lastScrollTime > 20 && _updateAll();
33877	},
33878	    _onScroll = function _onScroll() {
33879	  var time = _getTime();
33880
33881	  if (_lastScrollTime !== time) {
33882	    _updateAll();
33883
33884	    _lastScrollTime || _dispatch("scrollStart");
33885	    _lastScrollTime = time;
33886	  } else if (!_request) {
33887	    _request = _raf(_updateAll);
33888	  }
33889	},
33890	    _onResize = function _onResize() {
33891	  return !_refreshing && !_ignoreResize && !_doc.fullscreenElement && _resizeDelay.restart(true);
33892	},
33893	    _listeners = {},
33894	    _emptyArray = [],
33895	    _media = [],
33896	    _creatingMedia,
33897	    _lastMediaTick,
33898	    _onMediaChange = function _onMediaChange(e) {
33899	  var tick = gsap.ticker.frame,
33900	      matches = [],
33901	      i = 0,
33902	      index;
33903
33904	  if (_lastMediaTick !== tick || _startup) {
33905	    _revertAll();
33906
33907	    for (; i < _media.length; i += 4) {
33908	      index = _win.matchMedia(_media[i]).matches;
33909
33910	      if (index !== _media[i + 3]) {
33911	        _media[i + 3] = index;
33912	        index ? matches.push(i) : _revertAll(1, _media[i]) || _isFunction(_media[i + 2]) && _media[i + 2]();
33913	      }
33914	    }
33915
33916	    _revertRecorded();
33917
33918	    for (i = 0; i < matches.length; i++) {
33919	      index = matches[i];
33920	      _creatingMedia = _media[index];
33921	      _media[index + 2] = _media[index + 1](e);
33922	    }
33923
33924	    _creatingMedia = 0;
33925	    _coreInitted && _refreshAll(0, 1);
33926	    _lastMediaTick = tick;
33927
33928	    _dispatch("matchMedia");
33929	  }
33930	},
33931	    _softRefresh = function _softRefresh() {
33932	  return _removeListener(ScrollTrigger, "scrollEnd", _softRefresh) || _refreshAll(true);
33933	},
33934	    _dispatch = function _dispatch(type) {
33935	  return _listeners[type] && _listeners[type].map(function (f) {
33936	    return f();
33937	  }) || _emptyArray;
33938	},
33939	    _savedStyles = [],
33940	    _revertRecorded = function _revertRecorded(media) {
33941	  for (var i = 0; i < _savedStyles.length; i += 5) {
33942	    if (!media || _savedStyles[i + 4] === media) {
33943	      _savedStyles[i].style.cssText = _savedStyles[i + 1];
33944	      _savedStyles[i].getBBox && _savedStyles[i].setAttribute("transform", _savedStyles[i + 2] || "");
33945	      _savedStyles[i + 3].uncache = 1;
33946	    }
33947	  }
33948	},
33949	    _revertAll = function _revertAll(kill, media) {
33950	  var trigger;
33951
33952	  for (_i = 0; _i < _triggers.length; _i++) {
33953	    trigger = _triggers[_i];
33954
33955	    if (!media || trigger.media === media) {
33956	      if (kill) {
33957	        trigger.kill(1);
33958	      } else {
33959	        trigger.revert();
33960	      }
33961	    }
33962	  }
33963
33964	  media && _revertRecorded(media);
33965	  media || _dispatch("revert");
33966	},
33967	    _clearScrollMemory = function _clearScrollMemory() {
vendor: 10,266 bytes, lines 33968-34302
33968	  return _scrollers.forEach(function (obj) {
33969	    return typeof obj === "function" && (obj.rec = 0);
33970	  });
33971	},
33972	    _refreshingAll,
33973	    _refreshAll = function _refreshAll(force, skipRevert) {
33974	  if (_lastScrollTime && !force) {
33975	    _addListener(ScrollTrigger, "scrollEnd", _softRefresh);
33976
33977	    return;
33978	  }
33979
33980	  _refreshingAll = true;
33981
33982	  var refreshInits = _dispatch("refreshInit");
33983
33984	  _sort && ScrollTrigger.sort();
33985	  skipRevert || _revertAll();
33986
33987	  _triggers.forEach(function (t) {
33988	    return t.refresh();
33989	  });
33990
33991	  refreshInits.forEach(function (result) {
33992	    return result && result.render && result.render(-1);
33993	  });
33994
33995	  _clearScrollMemory();
33996
33997	  _resizeDelay.pause();
33998
33999	  _refreshingAll = false;
34000
34001	  _dispatch("refresh");
34002	},
34003	    _lastScroll = 0,
34004	    _direction = 1,
34005	    _updateAll = function _updateAll() {
34006	  if (!_refreshingAll) {
34007	    var l = _triggers.length,
34008	        time = _getTime(),
34009	        recordVelocity = time - _time1 >= 50,
34010	        scroll = l && _triggers[0].scroll();
34011
34012	    _direction = _lastScroll > scroll ? -1 : 1;
34013	    _lastScroll = scroll;
34014
34015	    if (recordVelocity) {
34016	      if (_lastScrollTime && !_pointerIsDown && time - _lastScrollTime > 200) {
34017	        _lastScrollTime = 0;
34018
34019	        _dispatch("scrollEnd");
34020	      }
34021
34022	      _time2 = _time1;
34023	      _time1 = time;
34024	    }
34025
34026	    if (_direction < 0) {
34027	      _i = l;
34028
34029	      while (_i-- > 0) {
34030	        _triggers[_i] && _triggers[_i].update(0, recordVelocity);
34031	      }
34032
34033	      _direction = 1;
34034	    } else {
34035	      for (_i = 0; _i < l; _i++) {
34036	        _triggers[_i] && _triggers[_i].update(0, recordVelocity);
34037	      }
34038	    }
34039
34040	    _request = 0;
34041	  }
34042	},
34043	    _propNamesToCopy = [_left, _top, _bottom, _right, _margin + _Bottom, _margin + _Right, _margin + _Top, _margin + _Left, "display", "flexShrink", "float", "zIndex", "grid-column-start", "grid-column-end", "grid-row-start", "grid-row-end", "grid-area", "justify-self", "align-self", "place-self"],
34044	    _stateProps = _propNamesToCopy.concat([_width, _height, "boxSizing", "max" + _Width, "max" + _Height, "position", _margin, _padding, _padding + _Top, _padding + _Right, _padding + _Bottom, _padding + _Left]),
34045	    _swapPinOut = function _swapPinOut(pin, spacer, state) {
34046	  _setState(state);
34047
34048	  var cache = pin._gsap;
34049
34050	  if (cache.spacerIsNative) {
34051	    _setState(cache.spacerState);
34052	  } else if (pin.parentNode === spacer) {
34053	    var parent = spacer.parentNode;
34054
34055	    if (parent) {
34056	      parent.insertBefore(pin, spacer);
34057	      parent.removeChild(spacer);
34058	    }
34059	  }
34060	},
34061	    _swapPinIn = function _swapPinIn(pin, spacer, cs, spacerState) {
34062	  if (pin.parentNode !== spacer) {
34063	    var i = _propNamesToCopy.length,
34064	        spacerStyle = spacer.style,
34065	        pinStyle = pin.style,
34066	        p;
34067
34068	    while (i--) {
34069	      p = _propNamesToCopy[i];
34070	      spacerStyle[p] = cs[p];
34071	    }
34072
34073	    spacerStyle.position = cs.position === "absolute" ? "absolute" : "relative";
34074	    cs.display === "inline" && (spacerStyle.display = "inline-block");
34075	    pinStyle[_bottom] = pinStyle[_right] = "auto";
34076	    spacerStyle.overflow = "visible";
34077	    spacerStyle.boxSizing = "border-box";
34078	    spacerStyle[_width] = _getSize(pin, _horizontal) + _px;
34079	    spacerStyle[_height] = _getSize(pin, _vertical) + _px;
34080	    spacerStyle[_padding] = pinStyle[_margin] = pinStyle[_top] = pinStyle[_left] = "0";
34081
34082	    _setState(spacerState);
34083
34084	    pinStyle[_width] = pinStyle["max" + _Width] = cs[_width];
34085	    pinStyle[_height] = pinStyle["max" + _Height] = cs[_height];
34086	    pinStyle[_padding] = cs[_padding];
34087	    pin.parentNode.insertBefore(spacer, pin);
34088	    spacer.appendChild(pin);
34089	  }
34090	},
34091	    _capsExp = /([A-Z])/g,
34092	    _setState = function _setState(state) {
34093	  if (state) {
34094	    var style = state.t.style,
34095	        l = state.length,
34096	        i = 0,
34097	        p,
34098	        value;
34099	    (state.t._gsap || gsap.core.getCache(state.t)).uncache = 1;
34100
34101	    for (; i < l; i += 2) {
34102	      value = state[i + 1];
34103	      p = state[i];
34104
34105	      if (value) {
34106	        style[p] = value;
34107	      } else if (style[p]) {
34108	        style.removeProperty(p.replace(_capsExp, "-$1").toLowerCase());
34109	      }
34110	    }
34111	  }
34112	},
34113	    _getState = function _getState(element) {
34114	  var l = _stateProps.length,
34115	      style = element.style,
34116	      state = [],
34117	      i = 0;
34118
34119	  for (; i < l; i++) {
34120	    state.push(_stateProps[i], style[_stateProps[i]]);
34121	  }
34122
34123	  state.t = element;
34124	  return state;
34125	},
34126	    _copyState = function _copyState(state, override, omitOffsets) {
34127	  var result = [],
34128	      l = state.length,
34129	      i = omitOffsets ? 8 : 0,
34130	      p;
34131
34132	  for (; i < l; i += 2) {
34133	    p = state[i];
34134	    result.push(p, p in override ? override[p] : state[i + 1]);
34135	  }
34136
34137	  result.t = state.t;
34138	  return result;
34139	},
34140	    _winOffsets = {
34141	  left: 0,
34142	  top: 0
34143	},
34144	    _parsePosition = function _parsePosition(value, trigger, scrollerSize, direction, scroll, marker, markerScroller, self, scrollerBounds, borderWidth, useFixedPosition, scrollerMax, containerAnimation) {
34145	  _isFunction(value) && (value = value(self));
34146
34147	  if (_isString(value) && value.substr(0, 3) === "max") {
34148	    value = scrollerMax + (value.charAt(4) === "=" ? _offsetToPx("0" + value.substr(3), scrollerSize) : 0);
34149	  }
34150
34151	  var time = containerAnimation ? containerAnimation.time() : 0,
34152	      p1,
34153	      p2,
34154	      element;
34155	  containerAnimation && containerAnimation.seek(0);
34156
34157	  if (!_isNumber(value)) {
34158	    _isFunction(trigger) && (trigger = trigger(self));
34159	    var offsets = value.split(" "),
34160	        bounds,
34161	        localOffset,
34162	        globalOffset,
34163	        display;
34164	    element = _getTarget(trigger) || _body;
34165	    bounds = _getBounds(element) || {};
34166
34167	    if ((!bounds || !bounds.left && !bounds.top) && _getComputedStyle(element).display === "none") {
34168	      display = element.style.display;
34169	      element.style.display = "block";
34170	      bounds = _getBounds(element);
34171	      display ? element.style.display = display : element.style.removeProperty("display");
34172	    }
34173
34174	    localOffset = _offsetToPx(offsets[0], bounds[direction.d]);
34175	    globalOffset = _offsetToPx(offsets[1] || "0", scrollerSize);
34176	    value = bounds[direction.p] - scrollerBounds[direction.p] - borderWidth + localOffset + scroll - globalOffset;
34177	    markerScroller && _positionMarker(markerScroller, globalOffset, direction, scrollerSize - globalOffset < 20 || markerScroller._isStart && globalOffset > 20);
34178	    scrollerSize -= scrollerSize - globalOffset;
34179	  } else if (markerScroller) {
34180	    _positionMarker(markerScroller, scrollerSize, direction, true);
34181	  }
34182
34183	  if (marker) {
34184	    var position = value + scrollerSize,
34185	        isStart = marker._isStart;
34186	    p1 = "scroll" + direction.d2;
34187
34188	    _positionMarker(marker, position, direction, isStart && position > 20 || !isStart && (useFixedPosition ? Math.max(_body[p1], _docEl[p1]) : marker.parentNode[p1]) <= position + 1);
34189
34190	    if (useFixedPosition) {
34191	      scrollerBounds = _getBounds(markerScroller);
34192	      useFixedPosition && (marker.style[direction.op.p] = scrollerBounds[direction.op.p] - direction.op.m - marker._offset + _px);
34193	    }
34194	  }
34195
34196	  if (containerAnimation && element) {
34197	    p1 = _getBounds(element);
34198	    containerAnimation.seek(scrollerMax);
34199	    p2 = _getBounds(element);
34200	    containerAnimation._caScrollDist = p1[direction.p] - p2[direction.p];
34201	    value = value / containerAnimation._caScrollDist * scrollerMax;
34202	  }
34203
34204	  containerAnimation && containerAnimation.seek(time);
34205	  return containerAnimation ? value : Math.round(value);
34206	},
34207	    _prefixExp = /(?:webkit|moz|length|cssText|inset)/i,
34208	    _reparent = function _reparent(element, parent, top, left) {
34209	  if (element.parentNode !== parent) {
34210	    var style = element.style,
34211	        p,
34212	        cs;
34213
34214	    if (parent === _body) {
34215	      element._stOrig = style.cssText;
34216	      cs = _getComputedStyle(element);
34217
34218	      for (p in cs) {
34219	        if (!+p && !_prefixExp.test(p) && cs[p] && typeof style[p] === "string" && p !== "0") {
34220	          style[p] = cs[p];
34221	        }
34222	      }
34223
34224	      style.top = top;
34225	      style.left = left;
34226	    } else {
34227	      style.cssText = element._stOrig;
34228	    }
34229
34230	    gsap.core.getCache(element).uncache = 1;
34231	    parent.appendChild(element);
34232	  }
34233	},
34234	    _getTweenCreator = function _getTweenCreator(scroller, direction) {
34235	  var getScroll = _getScrollFunc(scroller, direction),
34236	      prop = "_scroll" + direction.p2,
34237	      lastScroll1,
34238	      lastScroll2,
34239	      getTween = function getTween(scrollTo, vars, initialValue, change1, change2) {
34240	    var tween = getTween.tween,
34241	        onComplete = vars.onComplete,
34242	        modifiers = {};
34243	    tween && tween.kill();
34244	    lastScroll1 = Math.round(initialValue);
34245	    vars[prop] = scrollTo;
34246	    vars.modifiers = modifiers;
34247
34248	    modifiers[prop] = function (value) {
34249	      value = _round(getScroll());
34250
34251	      if (value !== lastScroll1 && value !== lastScroll2 && Math.abs(value - lastScroll1) > 2) {
34252	        tween.kill();
34253	        getTween.tween = 0;
34254	      } else {
34255	        value = initialValue + change1 * tween.ratio + change2 * tween.ratio * tween.ratio;
34256	      }
34257
34258	      lastScroll2 = lastScroll1;
34259	      return lastScroll1 = _round(value);
34260	    };
34261
34262	    vars.onComplete = function () {
34263	      getTween.tween = 0;
34264	      onComplete && onComplete.call(tween);
34265	    };
34266
34267	    tween = getTween.tween = gsap.to(scroller, vars);
34268	    return tween;
34269	  };
34270
34271	  scroller[prop] = getScroll;
34272	  scroller.addEventListener("wheel", function () {
34273	    return getTween.tween && getTween.tween.kill() && (getTween.tween = 0);
34274	  }, {
34275	    passive: true
34276	  });
34277	  return getTween;
34278	};
34279
34280	_horizontal.op = _vertical;
34281	var ScrollTrigger = function () {
34282	  function ScrollTrigger(vars, animation) {
34283	    _coreInitted || ScrollTrigger.register(gsap) || console.warn("Please gsap.registerPlugin(ScrollTrigger)");
34284	    this.init(vars, animation);
34285	  }
34286
34287	  var _proto = ScrollTrigger.prototype;
34288
34289	  _proto.init = function init(vars, animation) {
34290	    this.progress = this.start = 0;
34291	    this.vars && this.kill(1);
34292
34293	    if (!_enabled) {
34294	      this.update = this.refresh = this.kill = _passThrough;
34295	      return;
34296	    }
34297
34298	    vars = _setDefaults(_isString(vars) || _isNumber(vars) || vars.nodeType ? {
34299	      trigger: vars
34300	    } : vars, _defaults);
34301
34302	    var _vars = vars,
34303	        onUpdate = _vars.onUpdate,
34304	        toggleClass = _vars.toggleClass,
34305	        id = _vars.id,
34306	        onToggle = _vars.onToggle,
34307	        onRefresh = _vars.onRefresh,
34308	        scrub = _vars.scrub,
34309	        trigger = _vars.trigger,
34310	        pin = _vars.pin,
34311	        pinSpacing = _vars.pinSpacing,
34312	        invalidateOnRefresh = _vars.invalidateOnRefresh,
34313	        anticipatePin = _vars.anticipatePin,
34314	        onScrubComplete = _vars.onScrubComplete,
34315	        onSnapComplete = _vars.onSnapComplete,
34316	        once = _vars.once,
34317	        snap = _vars.snap,
34318	        pinReparent = _vars.pinReparent,
34319	        pinSpacer = _vars.pinSpacer,
34320	        containerAnimation = _vars.containerAnimation,
34321	        fastScrollEnd = _vars.fastScrollEnd,
34322	        preventOverlaps = _vars.preventOverlaps,
34323	        direction = vars.horizontal || vars.containerAnimation && vars.horizontal !== false ? _horizontal : _vertical,
34324	        isToggle = !scrub && scrub !== 0,
34325	        scroller = _getTarget(vars.scroller || _win),
34326	        scrollerCache = gsap.core.getCache(scroller),
34327	        isViewport = _isViewport(scroller),
34328	        useFixedPosition = ("pinType" in vars ? vars.pinType : _getProxyProp(scroller, "pinType") || isViewport && "fixed") === "fixed",
34329	        callbacks = [vars.onEnter, vars.onLeave, vars.onEnterBack, vars.onLeaveBack],
34330	        toggleActions = isToggle && vars.toggleActions.split(" "),
34331	        markers = "markers" in vars ? vars.markers : _defaults.markers,
34332	        borderWidth = isViewport ? 0 : parseFloat(_getComputedStyle(scroller)["border" + direction.p2 + _Width]) || 0,
34333	        self = this,
34334	        onRefreshInit = vars.onRefreshInit && function () {
34335	      return vars.onRefreshInit(self);
34336	    },
34337	        getScrollerSize = _getSizeFunc(scroller, isViewport, direction),
34338	        getScrollerOffsets = _getOffsetsFunc(scroller, isViewport),
34339	        lastSnap = 0,
34340	        scrollFunc = _getScrollFunc(scroller, direction),
34341	        tweenTo,
34342	        pinCache,
34343	        snapFunc,
34344	        scroll1,
34345	        scroll2,
34346	        start,
34347	        end,
34348	        markerStart,
34349	        markerEnd,
34350	        markerStartTrigger,
34351	        markerEndTrigger,
34352	        markerVars,
34353	        change,
34354	        pinOriginalState,
34355	        pinActiveState,
34356	        pinState,
34357	        spacer,
34358	        offset,
34359	        pinGetter,
34360	        pinSetter,
34361	        pinStart,
34362	        pinChange,
34363	        spacingStart,
34364	        spacerState,
34365	        markerStartSetter,
34366	        markerEndSetter,
34367	        cs,
34368	        snap1,
34369	        snap2,
34370	        scrubTween,
34371	        scrubSmooth,
34372	        snapDurClamp,
34373	        snapDelayedCall,
34374	        prevProgress,
34375	        prevScroll,
34376	        prevAnimProgress,
34377	        caMarkerSetter;
34378
34379	    self.media = _creatingMedia;
34380	    anticipatePin *= 45;
34381	    self.scroller = scroller;
34382	    self.scroll = containerAnimation ? containerAnimation.time.bind(containerAnimation) : scrollFunc;
34383	    scroll1 = scrollFunc();
34384	    self.vars = vars;
34385	    animation = animation || vars.animation;
34386	    "refreshPriority" in vars && (_sort = 1);
34387	    scrollerCache.tweenScroll = scrollerCache.tweenScroll || {
34388	      top: _getTweenCreator(scroller, _vertical),
34389	      left: _getTweenCreator(scroller, _horizontal)
34390	    };
34391	    self.tweenTo = tweenTo = scrollerCache.tweenScroll[direction.p];
34392
34393	    if (animation) {
34394	      animation.vars.lazy = false;
34395	      animation._initted || animation.vars.immediateRender !== false && vars.immediateRender !== false && animation.render(0, true, true);
34396	      self.animation = animation.pause();
34397	      animation.scrollTrigger = self;
34398	      scrubSmooth = _isNumber(scrub) && scrub;
34399	      scrubSmooth && (scrubTween = gsap.to(animation, {
34400	        ease: "power3",
34401	        duration: scrubSmooth,
34402	        onComplete: function onComplete() {
34403	          return onScrubComplete && onScrubComplete(self);
34404	        }
34405	      }));
34406	      snap1 = 0;
34407	      id || (id = animation.vars.id);
34408	    }
34409
34410	    _triggers.push(self);
34411
34412	    if (snap) {
34413	      if (!_isObject(snap) || snap.push) {
34414	        snap = {
34415	          snapTo: snap
34416	        };
34417	      }
34418
34419	      "scrollBehavior" in _body.style && gsap.set(isViewport ? [_body, _docEl] : scroller, {
34420	        scrollBehavior: "auto"
34421	      });
34422	      snapFunc = _isFunction(snap.snapTo) ? snap.snapTo : snap.snapTo === "labels" ? _getClosestLabel(animation) : snap.snapTo === "labelsDirectional" ? _getLabelAtDirection(animation) : snap.directional !== false ? function (value, st) {
34423	        return _snapDirectional(snap.snapTo)(value, st.direction);
34424	      } : gsap.utils.snap(snap.snapTo);
34425	      snapDurClamp = snap.duration || {
34426	        min: 0.1,
34427	        max: 2
34428	      };
34429	      snapDurClamp = _isObject(snapDurClamp) ? _clamp(snapDurClamp.min, snapDurClamp.max) : _clamp(snapDurClamp, snapDurClamp);
34430	      snapDelayedCall = gsap.delayedCall(snap.delay || scrubSmooth / 2 || 0.1, function () {
34431	        if (Math.abs(self.getVelocity()) < 10 && !_pointerIsDown && lastSnap !== scrollFunc()) {
34432	          var totalProgress = animation && !isToggle ? animation.totalProgress() : self.progress,
34433	              velocity = (totalProgress - snap2) / (_getTime() - _time2) * 1000 || 0,
34434	              change1 = gsap.utils.clamp(-self.progress, 1 - self.progress, _abs(velocity / 2) * velocity / 0.185),
34435	              naturalEnd = self.progress + (snap.inertia === false ? 0 : change1),
34436	              endValue = _clamp(0, 1, snapFunc(naturalEnd, self)),
34437	              scroll = scrollFunc(),
34438	              endScroll = Math.round(start + endValue * change),
34439	              _snap = snap,
34440	              onStart = _snap.onStart,
34441	              _onInterrupt = _snap.onInterrupt,
34442	              _onComplete = _snap.onComplete,
34443	              tween = tweenTo.tween;
34444
34445	          if (scroll <= end && scroll >= start && endScroll !== scroll) {
34446	            if (tween && !tween._initted && tween.data <= _abs(endScroll - scroll)) {
34447	              return;
34448	            }
34449
34450	            if (snap.inertia === false) {
34451	              change1 = endValue - self.progress;
34452	            }
34453
34454	            tweenTo(endScroll, {
34455	              duration: snapDurClamp(_abs(Math.max(_abs(naturalEnd - totalProgress), _abs(endValue - totalProgress)) * 0.185 / velocity / 0.05 || 0)),
34456	              ease: snap.ease || "power3",
34457	              data: _abs(endScroll - scroll),
34458	              onInterrupt: function onInterrupt() {
34459	                return snapDelayedCall.restart(true) && _onInterrupt && _onInterrupt(self);
34460	              },
34461	              onComplete: function onComplete() {
34462	                lastSnap = scrollFunc();
34463	                snap1 = snap2 = animation && !isToggle ? animation.totalProgress() : self.progress;
34464	                onSnapComplete && onSnapComplete(self);
34465	                _onComplete && _onComplete(self);
34466	              }
34467	            }, scroll, change1 * change, endScroll - scroll - change1 * change);
34468	            onStart && onStart(self, tweenTo.tween);
34469	          }
34470	        } else if (self.isActive) {
34471	          snapDelayedCall.restart(true);
34472	        }
34473	      }).pause();
34474	    }
34475
34476	    id && (_ids[id] = self);
34477	    trigger = self.trigger = _getTarget(trigger || pin);
34478	    pin = pin === true ? trigger : _getTarget(pin);
34479	    _isString(toggleClass) && (toggleClass = {
34480	      targets: trigger,
34481	      className: toggleClass
34482	    });
34483
34484	    if (pin) {
34485	      pinSpacing === false || pinSpacing === _margin || (pinSpacing = !pinSpacing && _getComputedStyle(pin.parentNode).display === "flex" ? false : _padding);
34486	      self.pin = pin;
34487	      vars.force3D !== false && gsap.set(pin, {
34488	        force3D: true
34489	      });
34490	      pinCache = gsap.core.getCache(pin);
34491
34492	      if (!pinCache.spacer) {
34493	        if (pinSpacer) {
34494	          pinSpacer = _getTarget(pinSpacer);
34495	          pinSpacer && !pinSpacer.nodeType && (pinSpacer = pinSpacer.current || pinSpacer.nativeElement);
34496	          pinCache.spacerIsNative = !!pinSpacer;
34497	          pinSpacer && (pinCache.spacerState = _getState(pinSpacer));
34498	        }
34499
34500	        pinCache.spacer = spacer = pinSpacer || _doc.createElement("div");
34501	        spacer.classList.add("pin-spacer");
34502	        id && spacer.classList.add("pin-spacer-" + id);
34503	        pinCache.pinState = pinOriginalState = _getState(pin);
34504	      } else {
34505	        pinOriginalState = pinCache.pinState;
34506	      }
34507
34508	      self.spacer = spacer = pinCache.spacer;
34509	      cs = _getComputedStyle(pin);
34510	      spacingStart = cs[pinSpacing + direction.os2];
34511	      pinGetter = gsap.getProperty(pin);
34512	      pinSetter = gsap.quickSetter(pin, direction.a, _px);
34513
34514	      _swapPinIn(pin, spacer, cs);
34515
34516	      pinState = _getState(pin);
34517	    }
34518
34519	    if (markers) {
34520	      markerVars = _isObject(markers) ? _setDefaults(markers, _markerDefaults) : _markerDefaults;
34521	      markerStartTrigger = _createMarker("scroller-start", id, scroller, direction, markerVars, 0);
34522	      markerEndTrigger = _createMarker("scroller-end", id, scroller, direction, markerVars, 0, markerStartTrigger);
34523	      offset = markerStartTrigger["offset" + direction.op.d2];
34524	      markerStart = _createMarker("start", id, scroller, direction, markerVars, offset, 0, containerAnimation);
34525	      markerEnd = _createMarker("end", id, scroller, direction, markerVars, offset, 0, containerAnimation);
34526	      containerAnimation && (caMarkerSetter = gsap.quickSetter([markerStart, markerEnd], direction.a, _px));
34527
34528	      if (!useFixedPosition && !(_proxies.length && _getProxyProp(scroller, "fixedMarkers") === true)) {
34529	        _makePositionable(isViewport ? _body : scroller);
34530
34531	        gsap.set([markerStartTrigger, markerEndTrigger], {
34532	          force3D: true
34533	        });
34534	        markerStartSetter = gsap.quickSetter(markerStartTrigger, direction.a, _px);
34535	        markerEndSetter = gsap.quickSetter(markerEndTrigger, direction.a, _px);
34536	      }
34537	    }
34538
34539	    if (containerAnimation) {
34540	      var oldOnUpdate = containerAnimation.vars.onUpdate,
34541	          oldParams = containerAnimation.vars.onUpdateParams;
34542	      containerAnimation.eventCallback("onUpdate", function () {
34543	        self.update(0, 0, 1);
34544	        oldOnUpdate && oldOnUpdate.apply(oldParams || []);
34545	      });
34546	    }
34547
34548	    self.previous = function () {
34549	      return _triggers[_triggers.indexOf(self) - 1];
34550	    };
34551
34552	    self.next = function () {
34553	      return _triggers[_triggers.indexOf(self) + 1];
34554	    };
34555
34556	    self.revert = function (revert) {
34557	      var r = revert !== false || !self.enabled,
34558	          prevRefreshing = _refreshing;
34559
34560	      if (r !== self.isReverted) {
34561	        if (r) {
34562	          self.scroll.rec || (self.scroll.rec = scrollFunc());
34563	          prevScroll = Math.max(scrollFunc(), self.scroll.rec || 0);
34564	          prevProgress = self.progress;
34565	          prevAnimProgress = animation && animation.progress();
34566	        }
34567
34568	        markerStart && [markerStart, markerEnd, markerStartTrigger, markerEndTrigger].forEach(function (m) {
34569	          return m.style.display = r ? "none" : "block";
34570	        });
34571	        r && (_refreshing = 1);
34572	        self.update(r);
34573	        _refreshing = prevRefreshing;
34574	        pin && (r ? _swapPinOut(pin, spacer, pinOriginalState) : (!pinReparent || !self.isActive) && _swapPinIn(pin, spacer, _getComputedStyle(pin), spacerState));
34575	        self.isReverted = r;
34576	      }
34577	    };
34578
34579	    self.refresh = function (soft, force) {
34580	      if ((_refreshing || !self.enabled) && !force) {
34581	        return;
34582	      }
34583
34584	      if (pin && soft && _lastScrollTime) {
34585	        _addListener(ScrollTrigger, "scrollEnd", _softRefresh);
34586
34587	        return;
34588	      }
34589
34590	      _refreshing = 1;
34591	      scrubTween && scrubTween.pause();
34592	      invalidateOnRefresh && animation && animation.progress(0).invalidate();
34593	      self.isReverted || self.revert();
34594
34595	      var size = getScrollerSize(),
34596	          scrollerBounds = getScrollerOffsets(),
34597	          max = containerAnimation ? containerAnimation.duration() : _maxScroll(scroller, direction),
34598	          offset = 0,
34599	          otherPinOffset = 0,
34600	          parsedEnd = vars.end,
34601	          parsedEndTrigger = vars.endTrigger || trigger,
34602	          parsedStart = vars.start || (vars.start === 0 || !trigger ? 0 : pin ? "0 0" : "0 100%"),
34603	          pinnedContainer = vars.pinnedContainer && _getTarget(vars.pinnedContainer),
34604	          triggerIndex = trigger && Math.max(0, _triggers.indexOf(self)) || 0,
34605	          i = triggerIndex,
34606	          cs,
34607	          bounds,
34608	          scroll,
34609	          isVertical,
34610	          override,
34611	          curTrigger,
34612	          curPin,
34613	          oppositeScroll,
34614	          initted,
34615	          revertedPins;
34616
34617	      while (i--) {
34618	        curTrigger = _triggers[i];
34619	        curTrigger.end || curTrigger.refresh(0, 1) || (_refreshing = 1);
34620	        curPin = curTrigger.pin;
34621
34622	        if (curPin && (curPin === trigger || curPin === pin) && !curTrigger.isReverted) {
34623	          revertedPins || (revertedPins = []);
34624	          revertedPins.unshift(curTrigger);
34625	          curTrigger.revert();
34626	        }
34627	      }
34628
34629	      _isFunction(parsedStart) && (parsedStart = parsedStart(self));
34630	      start = _parsePosition(parsedStart, trigger, size, direction, scrollFunc(), markerStart, markerStartTrigger, self, scrollerBounds, borderWidth, useFixedPosition, max, containerAnimation) || (pin ? -0.001 : 0);
34631	      _isFunction(parsedEnd) && (parsedEnd = parsedEnd(self));
34632
34633	      if (_isString(parsedEnd) && !parsedEnd.indexOf("+=")) {
34634	        if (~parsedEnd.indexOf(" ")) {
34635	          parsedEnd = (_isString(parsedStart) ? parsedStart.split(" ")[0] : "") + parsedEnd;
34636	        } else {
34637	          offset = _offsetToPx(parsedEnd.substr(2), size);
34638	          parsedEnd = _isString(parsedStart) ? parsedStart : start + offset;
34639	          parsedEndTrigger = trigger;
34640	        }
34641	      }
34642
34643	      end = Math.max(start, _parsePosition(parsedEnd || (parsedEndTrigger ? "100% 0" : max), parsedEndTrigger, size, direction, scrollFunc() + offset, markerEnd, markerEndTrigger, self, scrollerBounds, borderWidth, useFixedPosition, max, containerAnimation)) || -0.001;
34644	      change = end - start || (start -= 0.01) && 0.001;
34645	      offset = 0;
34646	      i = triggerIndex;
34647
34648	      while (i--) {
34649	        curTrigger = _triggers[i];
34650	        curPin = curTrigger.pin;
34651
34652	        if (curPin && curTrigger.start - curTrigger._pinPush < start && !containerAnimation) {
34653	          cs = curTrigger.end - curTrigger.start;
34654	          (curPin === trigger || curPin === pinnedContainer) && !_isNumber(parsedStart) && (offset += cs);
34655	          curPin === pin && (otherPinOffset += cs);
34656	        }
34657	      }
34658
34659	      start += offset;
34660	      end += offset;
34661	      self._pinPush = otherPinOffset;
34662
34663	      if (markerStart && offset) {
34664	        cs = {};
34665	        cs[direction.a] = "+=" + offset;
34666	        pinnedContainer && (cs[direction.p] = "-=" + scrollFunc());
34667	        gsap.set([markerStart, markerEnd], cs);
34668	      }
34669
34670	      if (pin) {
34671	        cs = _getComputedStyle(pin);
34672	        isVertical = direction === _vertical;
34673	        scroll = scrollFunc();
34674	        pinStart = parseFloat(pinGetter(direction.a)) + otherPinOffset;
34675	        !max && end > 1 && ((isViewport ? _body : scroller).style["overflow-" + direction.a] = "scroll");
34676
34677	        _swapPinIn(pin, spacer, cs);
34678
34679	        pinState = _getState(pin);
34680	        bounds = _getBounds(pin, true);
34681	        oppositeScroll = useFixedPosition && _getScrollFunc(scroller, isVertical ? _horizontal : _vertical)();
34682
34683	        if (pinSpacing) {
34684	          spacerState = [pinSpacing + direction.os2, change + otherPinOffset + _px];
34685	          spacerState.t = spacer;
34686	          i = pinSpacing === _padding ? _getSize(pin, direction) + change + otherPinOffset : 0;
34687	          i && spacerState.push(direction.d, i + _px);
34688
34689	          _setState(spacerState);
34690
34691	          useFixedPosition && scrollFunc(prevScroll);
34692	        }
34693
34694	        if (useFixedPosition) {
34695	          override = {
34696	            top: bounds.top + (isVertical ? scroll - start : oppositeScroll) + _px,
34697	            left: bounds.left + (isVertical ? oppositeScroll : scroll - start) + _px,
34698	            boxSizing: "border-box",
34699	            position: "fixed"
34700	          };
34701	          override[_width] = override["max" + _Width] = Math.ceil(bounds.width) + _px;
34702	          override[_height] = override["max" + _Height] = Math.ceil(bounds.height) + _px;
34703	          override[_margin] = override[_margin + _Top] = override[_margin + _Right] = override[_margin + _Bottom] = override[_margin + _Left] = "0";
34704	          override[_padding] = cs[_padding];
34705	          override[_padding + _Top] = cs[_padding + _Top];
34706	          override[_padding + _Right] = cs[_padding + _Right];
34707	          override[_padding + _Bottom] = cs[_padding + _Bottom];
34708	          override[_padding + _Left] = cs[_padding + _Left];
34709	          pinActiveState = _copyState(pinOriginalState, override, pinReparent);
34710	        }
34711
34712	        if (animation) {
34713	          initted = animation._initted;
34714
34715	          _suppressOverwrites(1);
34716
34717	          animation.render(animation.duration(), true, true);
34718	          pinChange = pinGetter(direction.a) - pinStart + change + otherPinOffset;
34719	          change !== pinChange && pinActiveState.splice(pinActiveState.length - 2, 2);
34720	          animation.render(0, true, true);
34721	          initted || animation.invalidate();
34722
34723	          _suppressOverwrites(0);
34724	        } else {
34725	          pinChange = change;
34726	        }
34727	      } else if (trigger && scrollFunc() && !containerAnimation) {
34728	        bounds = trigger.parentNode;
34729
34730	        while (bounds && bounds !== _body) {
34731	          if (bounds._pinOffset) {
34732	            start -= bounds._pinOffset;
34733	            end -= bounds._pinOffset;
34734	          }
34735
34736	          bounds = bounds.parentNode;
34737	        }
34738	      }
34739
34740	      revertedPins && revertedPins.forEach(function (t) {
34741	        return t.revert(false);
34742	      });
34743	      self.start = start;
34744	      self.end = end;
34745	      scroll1 = scroll2 = scrollFunc();
34746
34747	      if (!containerAnimation) {
34748	        scroll1 < prevScroll && scrollFunc(prevScroll);
34749	        self.scroll.rec = 0;
34750	      }
34751
34752	      self.revert(false);
34753	      _refreshing = 0;
34754	      animation && isToggle && animation._initted && animation.progress() !== prevAnimProgress && animation.progress(prevAnimProgress, true).render(animation.time(), true, true);
34755
34756	      if (prevProgress !== self.progress) {
34757	        animation && !isToggle && animation.totalProgress(prevProgress, true);
34758	        self.progress = prevProgress;
34759	        self.update(0, 0, 1);
34760	      }
34761
34762	      pin && pinSpacing && (spacer._pinOffset = Math.round(self.progress * pinChange));
34763	      onRefresh && onRefresh(self);
34764	    };
34765
34766	    self.getVelocity = function () {
34767	      return (scrollFunc() - scroll2) / (_getTime() - _time2) * 1000 || 0;
34768	    };
34769
34770	    self.endAnimation = function () {
vendor: 8,601 bytes, lines 34771-35009
34771	      _endAnimation(self.callbackAnimation);
34772
34773	      if (animation) {
34774	        scrubTween ? scrubTween.progress(1) : !animation.paused() ? _endAnimation(animation, animation.reversed()) : isToggle || _endAnimation(animation, self.direction < 0, 1);
34775	      }
34776	    };
34777
34778	    self.getTrailing = function (name) {
34779	      var i = _triggers.indexOf(self),
34780	          a = self.direction > 0 ? _triggers.slice(0, i).reverse() : _triggers.slice(i + 1);
34781
34782	      return _isString(name) ? a.filter(function (t) {
34783	        return t.vars.preventOverlaps === name;
34784	      }) : a;
34785	    };
34786
34787	    self.update = function (reset, recordVelocity, forceFake) {
34788	      if (containerAnimation && !forceFake && !reset) {
34789	        return;
34790	      }
34791
34792	      var scroll = self.scroll(),
34793	          p = reset ? 0 : (scroll - start) / change,
34794	          clipped = p < 0 ? 0 : p > 1 ? 1 : p || 0,
34795	          prevProgress = self.progress,
34796	          isActive,
34797	          wasActive,
34798	          toggleState,
34799	          action,
34800	          stateChanged,
34801	          toggled,
34802	          isAtMax,
34803	          isTakingAction;
34804
34805	      if (recordVelocity) {
34806	        scroll2 = scroll1;
34807	        scroll1 = containerAnimation ? scrollFunc() : scroll;
34808
34809	        if (snap) {
34810	          snap2 = snap1;
34811	          snap1 = animation && !isToggle ? animation.totalProgress() : clipped;
34812	        }
34813	      }
34814
34815	      anticipatePin && !clipped && pin && !_refreshing && !_startup && _lastScrollTime && start < scroll + (scroll - scroll2) / (_getTime() - _time2) * anticipatePin && (clipped = 0.0001);
34816
34817	      if (clipped !== prevProgress && self.enabled) {
34818	        isActive = self.isActive = !!clipped && clipped < 1;
34819	        wasActive = !!prevProgress && prevProgress < 1;
34820	        toggled = isActive !== wasActive;
34821	        stateChanged = toggled || !!clipped !== !!prevProgress;
34822	        self.direction = clipped > prevProgress ? 1 : -1;
34823	        self.progress = clipped;
34824
34825	        if (stateChanged && !_refreshing) {
34826	          toggleState = clipped && !prevProgress ? 0 : clipped === 1 ? 1 : prevProgress === 1 ? 2 : 3;
34827
34828	          if (isToggle) {
34829	            action = !toggled && toggleActions[toggleState + 1] !== "none" && toggleActions[toggleState + 1] || toggleActions[toggleState];
34830	            isTakingAction = animation && (action === "complete" || action === "reset" || action in animation);
34831	          }
34832	        }
34833
34834	        preventOverlaps && toggled && (isTakingAction || scrub || !animation) && (_isFunction(preventOverlaps) ? preventOverlaps(self) : self.getTrailing(preventOverlaps).forEach(function (t) {
34835	          return t.endAnimation();
34836	        }));
34837
34838	        if (!isToggle) {
34839	          if (scrubTween && !_refreshing && !_startup) {
34840	            scrubTween.vars.totalProgress = clipped;
34841	            scrubTween.invalidate().restart();
34842	          } else if (animation) {
34843	            animation.totalProgress(clipped, !!_refreshing);
34844	          }
34845	        }
34846
34847	        if (pin) {
34848	          reset && pinSpacing && (spacer.style[pinSpacing + direction.os2] = spacingStart);
34849
34850	          if (!useFixedPosition) {
34851	            pinSetter(pinStart + pinChange * clipped);
34852	          } else if (stateChanged) {
34853	            isAtMax = !reset && clipped > prevProgress && end + 1 > scroll && scroll + 1 >= _maxScroll(scroller, direction);
34854
34855	            if (pinReparent) {
34856	              if (!reset && (isActive || isAtMax)) {
34857	                var bounds = _getBounds(pin, true),
34858	                    _offset = scroll - start;
34859
34860	                _reparent(pin, _body, bounds.top + (direction === _vertical ? _offset : 0) + _px, bounds.left + (direction === _vertical ? 0 : _offset) + _px);
34861	              } else {
34862	                _reparent(pin, spacer);
34863	              }
34864	            }
34865
34866	            _setState(isActive || isAtMax ? pinActiveState : pinState);
34867
34868	            pinChange !== change && clipped < 1 && isActive || pinSetter(pinStart + (clipped === 1 && !isAtMax ? pinChange : 0));
34869	          }
34870	        }
34871
34872	        snap && !tweenTo.tween && !_refreshing && !_startup && snapDelayedCall.restart(true);
34873	        toggleClass && (toggled || once && clipped && (clipped < 1 || !_limitCallbacks)) && _toArray(toggleClass.targets).forEach(function (el) {
34874	          return el.classList[isActive || once ? "add" : "remove"](toggleClass.className);
34875	        });
34876	        onUpdate && !isToggle && !reset && onUpdate(self);
34877
34878	        if (stateChanged && !_refreshing) {
34879	          if (isToggle) {
34880	            if (isTakingAction) {
34881	              if (action === "complete") {
34882	                animation.pause().totalProgress(1);
34883	              } else if (action === "reset") {
34884	                animation.restart(true).pause();
34885	              } else if (action === "restart") {
34886	                animation.restart(true);
34887	              } else {
34888	                animation[action]();
34889	              }
34890	            }
34891
34892	            onUpdate && onUpdate(self);
34893	          }
34894
34895	          if (toggled || !_limitCallbacks) {
34896	            onToggle && toggled && _callback(self, onToggle);
34897	            callbacks[toggleState] && _callback(self, callbacks[toggleState]);
34898	            once && (clipped === 1 ? self.kill(false, 1) : callbacks[toggleState] = 0);
34899
34900	            if (!toggled) {
34901	              toggleState = clipped === 1 ? 1 : 3;
34902	              callbacks[toggleState] && _callback(self, callbacks[toggleState]);
34903	            }
34904	          }
34905
34906	          if (fastScrollEnd && !isActive && Math.abs(self.getVelocity()) > (_isNumber(fastScrollEnd) ? fastScrollEnd : 2500)) {
34907	            _endAnimation(self.callbackAnimation);
34908
34909	            scrubTween ? scrubTween.progress(1) : _endAnimation(animation, !clipped, 1);
34910	          }
34911	        } else if (isToggle && onUpdate && !_refreshing) {
34912	          onUpdate(self);
34913	        }
34914	      }
34915
34916	      if (markerEndSetter) {
34917	        var n = containerAnimation ? scroll / containerAnimation.duration() * (containerAnimation._caScrollDist || 0) : scroll;
34918	        markerStartSetter(n + (markerStartTrigger._isFlipped ? 1 : 0));
34919	        markerEndSetter(n);
34920	      }
34921
34922	      caMarkerSetter && caMarkerSetter(-scroll / containerAnimation.duration() * (containerAnimation._caScrollDist || 0));
34923	    };
34924
34925	    self.enable = function (reset, refresh) {
34926	      if (!self.enabled) {
34927	        self.enabled = true;
34928
34929	        _addListener(scroller, "resize", _onResize);
34930
34931	        _addListener(scroller, "scroll", _onScroll);
34932
34933	        onRefreshInit && _addListener(ScrollTrigger, "refreshInit", onRefreshInit);
34934
34935	        if (reset !== false) {
34936	          self.progress = prevProgress = 0;
34937	          scroll1 = scroll2 = lastSnap = scrollFunc();
34938	        }
34939
34940	        refresh !== false && self.refresh();
34941	      }
34942	    };
34943
34944	    self.getTween = function (snap) {
34945	      return snap && tweenTo ? tweenTo.tween : scrubTween;
34946	    };
34947
34948	    self.disable = function (reset, allowAnimation) {
34949	      if (self.enabled) {
34950	        reset !== false && self.revert();
34951	        self.enabled = self.isActive = false;
34952	        allowAnimation || scrubTween && scrubTween.pause();
34953	        prevScroll = 0;
34954	        pinCache && (pinCache.uncache = 1);
34955	        onRefreshInit && _removeListener(ScrollTrigger, "refreshInit", onRefreshInit);
34956
34957	        if (snapDelayedCall) {
34958	          snapDelayedCall.pause();
34959	          tweenTo.tween && tweenTo.tween.kill() && (tweenTo.tween = 0);
34960	        }
34961
34962	        if (!isViewport) {
34963	          var i = _triggers.length;
34964
34965	          while (i--) {
34966	            if (_triggers[i].scroller === scroller && _triggers[i] !== self) {
34967	              return;
34968	            }
34969	          }
34970
34971	          _removeListener(scroller, "resize", _onResize);
34972
34973	          _removeListener(scroller, "scroll", _onScroll);
34974	        }
34975	      }
34976	    };
34977
34978	    self.kill = function (revert, allowAnimation) {
34979	      self.disable(revert, allowAnimation);
34980	      scrubTween && scrubTween.kill();
34981	      id && delete _ids[id];
34982
34983	      var i = _triggers.indexOf(self);
34984
34985	      _triggers.splice(i, 1);
34986
34987	      i === _i && _direction > 0 && _i--;
34988	      i = 0;
34989
34990	      _triggers.forEach(function (t) {
34991	        return t.scroller === self.scroller && (i = 1);
34992	      });
34993
34994	      i || (self.scroll.rec = 0);
34995
34996	      if (animation) {
34997	        animation.scrollTrigger = null;
34998	        revert && animation.render(-1);
34999	        allowAnimation || animation.kill();
35000	      }
35001
35002	      markerStart && [markerStart, markerEnd, markerStartTrigger, markerEndTrigger].forEach(function (m) {
35003	        return m.parentNode && m.parentNode.removeChild(m);
35004	      });
35005
35006	      if (pin) {
35007	        pinCache && (pinCache.uncache = 1);
35008	        i = 0;
35009
35010	        _triggers.forEach(function (t) {
35011	          return t.pin === pin && i++;
35012	        });
35013
35014	        i || (pinCache.spacer = 0);
35015	      }
35016	    };
35017
35018	    self.enable(false, false);
35019	    !animation || !animation.add || change ? self.refresh() : gsap.delayedCall(0.01, function () {
35020	      return start || end || self.refresh();
35021	    }) && (change = 0.01) && (start = end = 0);
35022	  };
35023
35024	  ScrollTrigger.register = function register(core) {
35025	    if (!_coreInitted) {
35026	      gsap = core || _getGSAP();
35027
35028	      if (_windowExists() && window.document) {
35029	        _win = window;
35030	        _doc = document;
35031	        _docEl = _doc.documentElement;
35032	        _body = _doc.body;
35033	      }
35034
35035	      if (gsap) {
35036	        _toArray = gsap.utils.toArray;
35037	        _clamp = gsap.utils.clamp;
35038	        _suppressOverwrites = gsap.core.suppressOverwrites || _passThrough;
35039	        gsap.core.globals("ScrollTrigger", ScrollTrigger);
35040
35041	        if (_body) {
35042	          _raf = _win.requestAnimationFrame || function (f) {
35043	            return setTimeout(f, 16);
35044	          };
35045
35046	          _addListener(_win, "wheel", _onScroll);
35047
35048	          _root = [_win, _doc, _docEl, _body];
35049
35050	          _addListener(_doc, "scroll", _onScroll);
35051
35052	          var bodyStyle = _body.style,
35053	              border = bodyStyle.borderTopStyle,
35054	              bounds;
35055	          bodyStyle.borderTopStyle = "solid";
35056	          bounds = _getBounds(_body);
35057	          _vertical.m = Math.round(bounds.top + _vertical.sc()) || 0;
35058	          _horizontal.m = Math.round(bounds.left + _horizontal.sc()) || 0;
35059	          border ? bodyStyle.borderTopStyle = border : bodyStyle.removeProperty("border-top-style");
35060	          _syncInterval = setInterval(_sync, 200);
35061	          gsap.delayedCall(0.5, function () {
35062	            return _startup = 0;
35063	          });
35064
35065	          _addListener(_doc, "touchcancel", _passThrough);
35066
35067	          _addListener(_body, "touchstart", _passThrough);
35068
35069	          _multiListener(_addListener, _doc, "pointerdown,touchstart,mousedown", function () {
35070	            return _pointerIsDown = 1;
35071	          });
35072
35073	          _multiListener(_addListener, _doc, "pointerup,touchend,mouseup", function () {
35074	            return _pointerIsDown = 0;
35075	          });
35076
35077	          _transformProp = gsap.utils.checkPrefix("transform");
35078
35079	          _stateProps.push(_transformProp);
35080
35081	          _coreInitted = _getTime();
35082	          _resizeDelay = gsap.delayedCall(0.2, _refreshAll).pause();
35083	          _autoRefresh = [_doc, "visibilitychange", function () {
35084	            var w = _win.innerWidth,
35085	                h = _win.innerHeight;
35086
35087	            if (_doc.hidden) {
35088	              _prevWidth = w;
35089	              _prevHeight = h;
35090	            } else if (_prevWidth !== w || _prevHeight !== h) {
35091	              _onResize();
35092	            }
35093	          }, _doc, "DOMContentLoaded", _refreshAll, _win, "load", function () {
35094	            return _lastScrollTime || _refreshAll();
35095	          }, _win, "resize", _onResize];
35096
35097	          _iterateAutoRefresh(_addListener);
35098	        }
35099	      }
35100	    }
35101
35102	    return _coreInitted;
35103	  };
35104
35105	  ScrollTrigger.defaults = function defaults(config) {
35106	    for (var p in config) {
35107	      _defaults[p] = config[p];
35108	    }
35109	  };
35110
35111	  ScrollTrigger.kill = function kill() {
35112	    _enabled = 0;
35113
35114	    _triggers.slice(0).forEach(function (trigger) {
35115	      return trigger.kill(1);
35116	    });
35117	  };
35118
35119	  ScrollTrigger.config = function config(vars) {
35120	    "limitCallbacks" in vars && (_limitCallbacks = !!vars.limitCallbacks);
35121	    var ms = vars.syncInterval;
35122	    ms && clearInterval(_syncInterval) || (_syncInterval = ms) && setInterval(_sync, ms);
35123
35124	    if ("autoRefreshEvents" in vars) {
35125	      _iterateAutoRefresh(_removeListener) || _iterateAutoRefresh(_addListener, vars.autoRefreshEvents || "none");
35126	      _ignoreResize = (vars.autoRefreshEvents + "").indexOf("resize") === -1;
35127	    }
35128	  };
35129
35130	  ScrollTrigger.scrollerProxy = function scrollerProxy(target, vars) {
35131	    var t = _getTarget(target),
35132	        i = _scrollers.indexOf(t),
35133	        isViewport = _isViewport(t);
35134
35135	    if (~i) {
35136	      _scrollers.splice(i, isViewport ? 6 : 2);
35137	    }
35138
35139	    isViewport ? _proxies.unshift(_win, vars, _body, vars, _docEl, vars) : _proxies.unshift(t, vars);
35140	  };
35141
35142	  ScrollTrigger.matchMedia = function matchMedia(vars) {
35143	    var mq, p, i, func, result;
35144
35145	    for (p in vars) {
35146	      i = _media.indexOf(p);
35147	      func = vars[p];
35148	      _creatingMedia = p;
35149
35150	      if (p === "all") {
35151	        func();
35152	      } else {
35153	        mq = _win.matchMedia(p);
35154
35155	        if (mq) {
35156	          mq.matches && (result = func());
35157
35158	          if (~i) {
35159	            _media[i + 1] = _combineFunc(_media[i + 1], func);
35160	            _media[i + 2] = _combineFunc(_media[i + 2], result);
35161	          } else {
35162	            i = _media.length;
35163
35164	            _media.push(p, func, result);
35165
35166	            mq.addListener ? mq.addListener(_onMediaChange) : mq.addEventListener("change", _onMediaChange);
35167	          }
35168
35169	          _media[i + 3] = mq.matches;
35170	        }
35171	      }
35172
35173	      _creatingMedia = 0;
35174	    }
35175
35176	    return _media;
35177	  };
35178
35179	  ScrollTrigger.clearMatchMedia = function clearMatchMedia(query) {
35180	    query || (_media.length = 0);
35181	    query = _media.indexOf(query);
35182	    query >= 0 && _media.splice(query, 4);
35183	  };
35184
35185	  ScrollTrigger.isInViewport = function isInViewport(element, ratio, horizontal) {
35186	    var bounds = (_isString(element) ? _getTarget(element) : element).getBoundingClientRect(),
35187	        offset = bounds[horizontal ? _width : _height] * ratio || 0;
35188	    return horizontal ? bounds.right - offset > 0 && bounds.left + offset < _win.innerWidth : bounds.bottom - offset > 0 && bounds.top + offset < _win.innerHeight;
35189	  };
35190
35191	  ScrollTrigger.positionInViewport = function positionInViewport(element, referencePoint, horizontal) {
35192	    _isString(element) && (element = _getTarget(element));
35193	    var bounds = element.getBoundingClientRect(),
35194	        size = bounds[horizontal ? _width : _height],
35195	        offset = referencePoint == null ? size / 2 : referencePoint in _keywords ? _keywords[referencePoint] * size : ~referencePoint.indexOf("%") ? parseFloat(referencePoint) * size / 100 : parseFloat(referencePoint) || 0;
35196	    return horizontal ? (bounds.left + offset) / _win.innerWidth : (bounds.top + offset) / _win.innerHeight;
35197	  };
35198
35199	  return ScrollTrigger;
35200	}();
35201	ScrollTrigger.version = "3.8.0";
35202
35203	ScrollTrigger.saveStyles = function (targets) {
35204	  return targets ? _toArray(targets).forEach(function (target) {
35205	    if (target && target.style) {
35206	      var i = _savedStyles.indexOf(target);
35207
35208	      i >= 0 && _savedStyles.splice(i, 5);
35209
35210	      _savedStyles.push(target, target.style.cssText, target.getBBox && target.getAttribute("transform"), gsap.core.getCache(target), _creatingMedia);
35211	    }
35212	  }) : _savedStyles;
35213	};
35214
35215	ScrollTrigger.revert = function (soft, media) {
35216	  return _revertAll(!soft, media);
35217	};
35218
35219	ScrollTrigger.create = function (vars, animation) {
35220	  return new ScrollTrigger(vars, animation);
35221	};
35222
35223	ScrollTrigger.refresh = function (safe) {
35224	  return safe ? _onResize() : (_coreInitted || ScrollTrigger.register()) && _refreshAll(true);
35225	};
35226
35227	ScrollTrigger.update = _updateAll;
35228	ScrollTrigger.clearScrollMemory = _clearScrollMemory;
35229
35230	ScrollTrigger.maxScroll = function (element, horizontal) {
35231	  return _maxScroll(element, horizontal ? _horizontal : _vertical);
35232	};
35233
35234	ScrollTrigger.getScrollFunc = function (element, horizontal) {
35235	  return _getScrollFunc(_getTarget(element), horizontal ? _horizontal : _vertical);
35236	};
35237
35238	ScrollTrigger.getById = function (id) {
35239	  return _ids[id];
35240	};
35241
35242	ScrollTrigger.getAll = function () {
35243	  return _triggers.slice(0);
35244	};
35245
35246	ScrollTrigger.isScrolling = function () {
35247	  return !!_lastScrollTime;
35248	};
35249
35250	ScrollTrigger.snapDirectional = _snapDirectional;
35251
35252	ScrollTrigger.addEventListener = function (type, callback) {
35253	  var a = _listeners[type] || (_listeners[type] = []);
35254	  ~a.indexOf(callback) || a.push(callback);
35255	};
35256
35257	ScrollTrigger.removeEventListener = function (type, callback) {
35258	  var a = _listeners[type],
35259	      i = a && a.indexOf(callback);
35260	  i >= 0 && a.splice(i, 1);
35261	};
35262
35263	ScrollTrigger.batch = function (targets, vars) {
35264	  var result = [],
35265	      varsCopy = {},
35266	      interval = vars.interval || 0.016,
35267	      batchMax = vars.batchMax || 1e9,
35268	      proxyCallback = function proxyCallback(type, callback) {
35269	    var elements = [],
35270	        triggers = [],
35271	        delay = gsap.delayedCall(interval, function () {
35272	      callback(elements, triggers);
35273	      elements = [];
35274	      triggers = [];
35275	    }).pause();
35276	    return function (self) {
35277	      elements.length || delay.restart(true);
35278	      elements.push(self.trigger);
35279	      triggers.push(self);
35280	      batchMax <= elements.length && delay.progress(1);
35281	    };
35282	  },
35283	      p;
35284
35285	  for (p in vars) {
35286	    varsCopy[p] = p.substr(0, 2) === "on" && _isFunction(vars[p]) && p !== "onRefreshInit" ? proxyCallback(p, vars[p]) : vars[p];
35287	  }
35288
35289	  if (_isFunction(batchMax)) {
35290	    batchMax = batchMax();
35291
35292	    _addListener(ScrollTrigger, "refresh", function () {
35293	      return batchMax = vars.batchMax();
35294	    });
35295	  }
35296
35297	  _toArray(targets).forEach(function (target) {
35298	    var config = {};
35299
35300	    for (p in varsCopy) {
35301	      config[p] = varsCopy[p];
35302	    }
35303
35304	    config.trigger = target;
35305	    result.push(ScrollTrigger.create(config));
35306	  });
35307
35308	  return result;
35309	};
35310
35311	ScrollTrigger.sort = function (func) {
35312	  return _triggers.sort(func || function (a, b) {
35313	    return (a.vars.refreshPriority || 0) * -1e6 + a.start - (b.start + (b.vars.refreshPriority || 0) * -1e6);
35314	  });
35315	};
35316
35317	_getGSAP() && gsap.registerPlugin(ScrollTrigger);
35318
35319	exports.ScrollTrigger = ScrollTrigger;
35320	exports.default = ScrollTrigger;
35321
35322	Object.defineProperty(exports, '__esModule', { value: true });
35323
35324})));
35325
35326/* ========================================================================
35327 * Bootstrap: collapse.js v3.1.1
35328 * http://getbootstrap.com/javascript/#collapse
35329 * ========================================================================
35330 * Copyright 2011-2014 Twitter, Inc.
35331 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
35332 * ======================================================================== */
35333
35334
35335+function ($) {
35336	'use strict';
35337
35338	// COLLAPSE PUBLIC CLASS DEFINITION
35339	// ================================
35340
35341	var Collapse = function (element, options) {
35342		this.$element      = $(element)
35343		this.options       = $.extend({}, Collapse.DEFAULTS, options)
35344		this.transitioning = null
35345
35346		if (this.options.parent) this.$parent = $(this.options.parent)
35347		if (this.options.toggle) this.toggle()
35348	}
35349
35350	Collapse.DEFAULTS = {
35351		toggle: true
35352	}
35353
35354	Collapse.prototype.dimension = function () {
35355		var hasWidth = this.$element.hasClass('width')
35356		return hasWidth ? 'width' : 'height'
35357	}
35358
35359	Collapse.prototype.show = function () {
35360		if (this.transitioning || this.$element.hasClass('in')) return
35361
35362		var startEvent = $.Event('show.bs.collapse')
35363		this.$element.trigger(startEvent)
35364		if (startEvent.isDefaultPrevented()) return
35365
35366		var actives = this.$parent && this.$parent.find('> .panel > .in')
35367
35368		if (actives && actives.length) {
35369			var hasData = actives.data('bs.collapse')
35370			if (hasData && hasData.transitioning) return
35371			actives.collapse('hide')
35372			hasData || actives.data('bs.collapse', null)
35373		}
35374
35375		var dimension = this.dimension()
35376
35377		this.$element
35378			.removeClass('collapse')
35379			.addClass('collapsing')[dimension](0)
35380
35381		this.transitioning = 1
35382
35383		var complete = function (e) {
35384			if (e && e.target != this.$element[0]) return
35385			this.$element
35386				.removeClass('collapsing')
35387				.addClass('collapse in')[dimension]('auto')
35388			this.transitioning = 0
35389			this.$element.trigger('shown.bs.collapse')
35390		}
35391
35392		if (!$.support.transition) return complete.call(this)
35393
35394		var scrollSize = $.camelCase(['scroll', dimension].join('-'))
35395
35396		this.$element
35397			.one($.support.transition.end, $.proxy(complete, this))
35398			.emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize])
35399	}
35400
35401	Collapse.prototype.hide = function () {
35402		if (this.transitioning || !this.$element.hasClass('in')) return
35403
35404		var startEvent = $.Event('hide.bs.collapse')
35405		this.$element.trigger(startEvent)
35406		if (startEvent.isDefaultPrevented()) return
35407
35408		var dimension = this.dimension()
35409
35410		this.$element[dimension](this.$element[dimension]())[0].offsetHeight
35411
35412		this.$element
35413			.addClass('collapsing')
35414			.removeClass('collapse')
35415			.removeClass('in')
35416
35417		this.transitioning = 1
35418
35419		var complete = function (e) {
35420			if (e && e.target != this.$element[0]) return
35421			this.transitioning = 0
35422			this.$element
35423				.trigger('hidden.bs.collapse')
35424				.removeClass('collapsing')
35425				.addClass('collapse')
35426		}
35427
35428		if (!$.support.transition) return complete.call(this)
35429
35430		this.$element
35431			[dimension](0)
35432			.one($.support.transition.end, $.proxy(complete, this))
35433			.emulateTransitionEnd(350)
35434	}
35435
35436	Collapse.prototype.toggle = function () {
35437		this[this.$element.hasClass('in') ? 'hide' : 'show']()
35438	}
35439
35440
35441	// COLLAPSE PLUGIN DEFINITION
35442	// ==========================
35443
35444	var old = $.fn.collapse
35445
35446	$.fn.collapse = function (option) {
35447		return this.each(function () {
35448			var $this   = $(this)
35449			var data    = $this.data('bs.collapse')
35450			var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
35451
35452			if (!data && options.toggle && option == 'show') option = !option
35453			if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
35454			if (typeof option == 'string') data[option]()
35455		})
35456	}
35457
35458	$.fn.collapse.Constructor = Collapse
35459
35460
35461	// COLLAPSE NO CONFLICT
35462	// ====================
35463
35464	$.fn.collapse.noConflict = function () {
35465		$.fn.collapse = old
35466		return this
35467	}
35468
35469
35470	// COLLAPSE DATA-API
35471	// =================
35472
35473	$(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
35474		var $this   = $(this), href
35475		var target  = $this.attr('data-target')
35476				|| e.preventDefault()
35477				|| (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
35478		//Edited by Uncode to replace ID in panel [START]
35479		var _target = href.replace(/^#/, "");
35480		if ( $('[data-id="' + _target + '"]').length ) {
35481			var $target = $('[data-id="' + _target + '"]')
35482		} else {
35483			var $target = $(target)
35484		}
35485		//Edited by Uncode to replace ID in panel [END]
35486		var data    = $target.data('bs.collapse')
35487		var option  = data ? 'toggle' : $this.data()
35488		var parent  = $this.attr('data-parent')
35489		var $parent = parent && $(parent)
35490
35491		if (!data || !data.transitioning) {
35492			if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed')
35493			$this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
35494		}
35495
35496		$target.collapse(option)
35497	})
35498
35499}(jQuery);
35500
35501/* ========================================================================
35502 * Bootstrap: tab.js v3.1.1
35503 * http://getbootstrap.com/javascript/#tabs
35504 * ========================================================================
35505 * Copyright 2011-2014 Twitter, Inc.
35506 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
35507 * ======================================================================== */
35508
35509
35510+function ($) {
35511  'use strict';
35512
35513  // TAB CLASS DEFINITION
35514  // ====================
35515
35516  var Tab = function (element) {
35517    this.element = $(element)
35518  }
35519
35520  Tab.prototype.show = function () {
35521    var $this    = this.element
35522    var $ul      = $this.closest('ul:not(.dropdown-menu)')
35523    var selector = $this.data('target')
35524
35525    if (!selector) {
35526      selector = $this.attr('href')
35527      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
35528    }
35529
35530    if ($this.parent('li').hasClass('active')) return
35531
35532    var previous = $ul.find('.active:last a')[0]
35533    var e        = $.Event('show.bs.tab', {
35534      relatedTarget: previous
35535    })
35536
35537    $this.trigger(e)
35538
35539    if (e.isDefaultPrevented()) return
35540
35541    //Edited by Uncode to replace ID in panel [START]
35542    var _target = selector.replace(/^#/, "");
35543    if ( $('[data-id="' + _target + '"]').length )
35544      var $target = $('[data-id="' + _target + '"]')
35545    else
35546      var $target = $(selector)
35547    //Edited by Uncode to replace ID in panel [END]
35548
35549    this.activate($this.parent('li'), $ul)
35550    this.activate($target, $target.parent(), function () {
35551      $this.trigger({
35552        type: 'shown.bs.tab',
35553        relatedTarget: previous
35554      })
35555    })
35556  }
35557
35558  Tab.prototype.activate = function (element, container, callback) {
35559    var $active    = container.find('> .active')
35560    var transition = callback
35561      && $.support.transition
35562      && $active.hasClass('fade')
35563
35564    function next() {
35565      $active
35566        .removeClass('active')
35567        .find('> .dropdown-menu > .active')
35568        .removeClass('active')
35569
35570      element.addClass('active')
35571
35572      if (transition) {
35573        element[0].offsetWidth // reflow for transition
35574        element.addClass('in')
35575      } else {
35576        element.removeClass('fade')
35577      }
35578
35579      if (element.parent('.dropdown-menu')) {
35580        element.closest('li.dropdown').addClass('active')
35581      }
35582
35583      callback && callback()
35584    }
35585
35586    transition ?
35587      $active
35588        .one($.support.transition.end, next)
35589        .emulateTransitionEnd(150) :
35590      next()
35591
35592    $active.removeClass('in')
35593  }
35594
35595
35596  // TAB PLUGIN DEFINITION
35597  // =====================
35598
35599  var old = $.fn.tab
35600
35601  $.fn.tab = function ( option ) {
35602    return this.each(function () {
35603      var $this = $(this)
35604      var data  = $this.data('bs.tab')
35605
35606      if (!data) $this.data('bs.tab', (data = new Tab(this)))
35607      if (typeof option == 'string') data[option]()
35608    })
35609  }
35610
35611  $.fn.tab.Constructor = Tab
35612
35613
35614  // TAB NO CONFLICT
35615  // ===============
35616
35617  $.fn.tab.noConflict = function () {
35618    $.fn.tab = old
35619    return this
35620  }
35621
35622
35623  // TAB DATA-API
35624  // ============
35625
35626  $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
35627    e.preventDefault()
35628    $(this).tab('show')
35629  })
35630
35631}(jQuery);
35632
35633/* ========================================================================
35634 * Bootstrap: tooltip.js v3.1.1
35635 * http://getbootstrap.com/javascript/#tooltip
35636 * Inspired by the original jQuery.tipsy by Jason Frame
35637 * ========================================================================
35638 * Copyright 2011-2014 Twitter, Inc.
35639 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
35640 * ======================================================================== */
35641
35642
35643+function ($) {
35644  'use strict';
35645
35646  // TOOLTIP PUBLIC CLASS DEFINITION
35647  // ===============================
35648
35649  var Tooltip = function (element, options) {
35650    this.type       =
35651    this.options    =
35652    this.enabled    =
35653    this.timeout    =
35654    this.hoverState =
35655    this.$element   = null
35656
35657    this.init('tooltip', element, options)
35658  }
35659
35660  Tooltip.DEFAULTS = {
35661    animation: true,
35662    placement: 'top',
35663    selector: false,
35664    template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
35665    trigger: 'hover focus',
35666    title: '',
35667    delay: 0,
35668    html: false,
35669    container: false,
35670    viewport: {
35671      selector: 'body',
35672      padding: 0
35673    }
35674  }
35675
35676  Tooltip.prototype.init = function (type, element, options) {
35677    this.enabled   = true
35678    this.type      = type
35679    this.$element  = $(element)
35680    this.options   = this.getOptions(options)
35681    this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
35682
35683    var triggers = this.options.trigger.split(' ')
35684
35685    for (var i = triggers.length; i--;) {
35686      var trigger = triggers[i]
35687
35688      if (trigger == 'click') {
35689        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
35690      } else if (trigger != 'manual') {
35691        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin'
35692        var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
35693
35694        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
35695        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
35696      }
35697    }
35698
35699    this.options.selector ?
35700      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
35701      this.fixTitle()
35702  }
35703
35704  Tooltip.prototype.getDefaults = function () {
35705    return Tooltip.DEFAULTS
35706  }
35707
35708  Tooltip.prototype.getOptions = function (options) {
35709    options = $.extend({}, this.getDefaults(), this.$element.data(), options)
35710
35711    if (options.delay && typeof options.delay == 'number') {
35712      options.delay = {
35713        show: options.delay,
35714        hide: options.delay
35715      }
35716    }
35717
35718    return options
35719  }
35720
35721  Tooltip.prototype.getDelegateOptions = function () {
35722    var options  = {}
35723    var defaults = this.getDefaults()
35724
35725    this._options && $.each(this._options, function (key, value) {
35726      if (defaults[key] != value) options[key] = value
35727    })
35728
35729    return options
35730  }
35731
35732  Tooltip.prototype.enter = function (obj) {
35733    var self = obj instanceof this.constructor ?
35734      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
35735
35736    clearTimeout(self.timeout)
35737
35738    self.hoverState = 'in'
35739
35740    if (!self.options.delay || !self.options.delay.show) return self.show()
35741
35742    self.timeout = setTimeout(function () {
35743      if (self.hoverState == 'in') self.show()
35744    }, self.options.delay.show)
35745  }
35746
35747  Tooltip.prototype.leave = function (obj) {
35748    var self = obj instanceof this.constructor ?
35749      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
35750
35751    clearTimeout(self.timeout)
35752
35753    self.hoverState = 'out'
35754
35755    if (!self.options.delay || !self.options.delay.hide) return self.hide()
35756
35757    self.timeout = setTimeout(function () {
35758      if (self.hoverState == 'out') self.hide()
35759    }, self.options.delay.hide)
35760  }
35761
35762  Tooltip.prototype.show = function () {
35763    var e = $.Event('show.bs.' + this.type)
35764
35765    if (this.hasContent() && this.enabled) {
35766      this.$element.trigger(e)
35767
35768      if (e.isDefaultPrevented()) return
35769      var that = this;
35770
35771      var $tip = this.tip()
35772
35773      this.setContent()
35774
35775      if (this.options.animation) $tip.addClass('fade')
35776
35777      var placement = typeof this.options.placement == 'function' ?
35778        this.options.placement.call(this, $tip[0], this.$element[0]) :
35779        this.options.placement
35780
35781      var autoToken = /\s?auto?\s?/i
35782      var autoPlace = autoToken.test(placement)
35783      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
35784
35785      $tip
35786        .detach()
35787        .css({ top: 0, left: 0, display: 'block' })
35788        .addClass(placement)
35789
35790      this.options.container ? $tip.appendTo($(document).find(this.options.container)) : $tip.insertAfter(this.$element)
35791
35792      var pos          = this.getPosition()
35793      var actualWidth  = $tip[0].offsetWidth
35794      var act
35794ualHeight = $tip[0].offsetHeight
35795
35796      if (autoPlace) {
35797        var orgPlacement = placement
35798        var $parent      = this.$element.parent()
35799        var parentDim    = this.getPosition($parent)
35800
35801        placement = placement == 'bottom' && pos.top   + pos.height       + actualHeight - parentDim.scroll > parentDim.height ? 'top'    :
35802                    placement == 'top'    && pos.top   - parentDim.scroll - actualHeight < 0                                   ? 'bottom' :
35803                    placement == 'right'  && pos.right + actualWidth      > parentDim.width                                    ? 'left'   :
35804                    placement == 'left'   && pos.left  - actualWidth      < parentDim.left                                     ? 'right'  :
35805                    placement
35806
35807        $tip
35808          .removeClass(orgPlacement)
35809          .addClass(placement)
35810      }
35811
35812      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
35813
35814      this.applyPlacement(calculatedOffset, placement)
35815      this.hoverState = null
35816
35817      var complete = function() {
35818        that.$element.trigger('shown.bs.' + that.type)
35819      }
35820
35821      $.support.transition && this.$tip.hasClass('fade') ?
35822        $tip
35823          .one($.support.transition.end, complete)
35824          .emulateTransitionEnd(150) :
35825        complete()
35826    }
35827  }
35828
35829  Tooltip.prototype.applyPlacement = function (offset, placement) {
35830    var $tip   = this.tip()
35831    var width  = $tip[0].offsetWidth
35832    var height = $tip[0].offsetHeight
35833
35834    // manually read margins because getBoundingClientRect includes difference
35835    var marginTop = parseInt($tip.css('margin-top'), 10)
35836    var marginLeft = parseInt($tip.css('margin-left'), 10)
35837
35838    // we must check for NaN for ie 8/9
35839    if (isNaN(marginTop))  marginTop  = 0
35840    if (isNaN(marginLeft)) marginLeft = 0
35841
35842    offset.top  = offset.top  + marginTop
35843    offset.left = offset.left + marginLeft
35844
35845    // $.fn.offset doesn't round pixel values
35846    // so we use setOffset directly with our own function B-0
35847    $.offset.setOffset($tip[0], $.extend({
35848      using: function (props) {
35849        $tip.css({
35850          top: Math.round(props.top),
35851          left: Math.round(props.left)
35852        })
35853      }
35854    }, offset), 0)
35855
35856    $tip.addClass('in')
35857
35858    // check to see if placing tip in new offset caused the tip to resize itself
35859    var actualWidth  = $tip[0].offsetWidth
35860    var actualHeight = $tip[0].offsetHeight
35861
35862    if (placement == 'top' && actualHeight != height) {
35863      offset.top = offset.top + height - actualHeight
35864    }
35865
35866    var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
35867
35868    if (delta.left) offset.left += delta.left
35869    else offset.top += delta.top
35870
35871    var arrowDelta          = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
35872    var arrowPosition       = delta.left ? 'left'        : 'top'
35873    var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight'
35874
35875    $tip.offset(offset)
35876    this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition)
35877  }
35878
35879  Tooltip.prototype.replaceArrow = function (delta, dimension, position) {
35880    this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '')
35881  }
35882
35883  Tooltip.prototype.setContent = function () {
35884    var $tip  = this.tip()
35885    var title = this.getTitle()
35886
35887    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
35888    $tip.removeClass('fade in top bottom left right')
35889  }
35890
35891  Tooltip.prototype.hide = function () {
35892    var that = this
35893    var $tip = this.tip()
35894    var e    = $.Event('hide.bs.' + this.type)
35895
35896    function complete() {
35897      if (that.hoverState != 'in') $tip.detach()
35898      that.$element.trigger('hidden.bs.' + that.type)
35899    }
35900
35901    this.$element.trigger(e)
35902
35903    if (e.isDefaultPrevented()) return
35904
35905    $tip.removeClass('in')
35906
35907    $.support.transition && this.$tip.hasClass('fade') ?
35908      $tip
35909        .one($.support.transition.end, complete)
35910        .emulateTransitionEnd(150) :
35911      complete()
35912
35913    this.hoverState = null
35914
35915    return this
35916  }
35917
35918  Tooltip.prototype.fixTitle = function () {
35919    var $e = this.$element
35920    if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
35921      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
35922    }
35923  }
35924
35925  Tooltip.prototype.hasContent = function () {
35926    return this.getTitle()
35927  }
35928
35929  Tooltip.prototype.getPosition = function ($element) {
35930    $element   = $element || this.$element
35931    var el     = $element[0]
35932    var isBody = el.tagName == 'BODY'
35933    return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, {
35934      scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(),
35935      width:  isBody ? $(window).width()  : $element.outerWidth(),
35936      height: isBody ? $(window).height() : $element.outerHeight()
35937    }, isBody ? {top: 0, left: 0} : $element.offset())
35938  }
35939
35940  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
35941    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2  } :
35942           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2  } :
35943           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
35944        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width   }
35945
35946  }
35947
35948  Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
35949    var delta = { top: 0, left: 0 }
35950    if (!this.$viewport) return delta
35951
35952    var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
35953    var viewportDimensions = this.getPosition(this.$viewport)
35954
35955    if (/right|left/.test(placement)) {
35956      var topEdgeOffset    = pos.top - viewportPadding - viewportDimensions.scroll
35957      var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
35958      if (topEdgeOffset < viewportDimensions.top) { // top overflow
35959        delta.top = viewportDimensions.top - topEdgeOffset
35960      } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
35961        delta.top = viewportDimensions.top + viewportDimensions.height - bottom
35961EdgeOffset
35962      }
35963    } else {
35964      var leftEdgeOffset  = pos.left - viewportPadding
35965      var rightEdgeOffset = pos.left + viewportPadding + actualWidth
35966      if (leftEdgeOffset < viewportDimensions.left) { // left overflow
35967        delta.left = viewportDimensions.left - leftEdgeOffset
35968      } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
35969        delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
35970      }
35971    }
35972
35973    return delta
35974  }
35975
35976  Tooltip.prototype.getTitle = function () {
35977    var title
35978    var $e = this.$element
35979    var o  = this.options
35980
35981    title = $e.attr('data-original-title')
35982      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
35983
35984    return title
35985  }
35986
35987  Tooltip.prototype.tip = function () {
35988    return this.$tip = this.$tip || $(this.options.template)
35989  }
35990
35991  Tooltip.prototype.arrow = function () {
35992    return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')
35993  }
35994
35995  Tooltip.prototype.validate = function () {
35996    if (!this.$element[0].parentNode) {
35997      this.hide()
35998      this.$element = null
35999      this.options  = null
36000    }
36001  }
36002
36003  Tooltip.prototype.enable = function () {
36004    this.enabled = true
36005  }
36006
36007  Tooltip.prototype.disable = function () {
36008    this.enabled = false
36009  }
36010
36011  Tooltip.prototype.toggleEnabled = function () {
36012    this.enabled = !this.enabled
36013  }
36014
36015  Tooltip.prototype.toggle = function (e) {
36016    var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this
36017    self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
36018  }
36019
36020  Tooltip.prototype.destroy = function () {
36021    clearTimeout(this.timeout)
36022    this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
36023  }
36024
36025
36026  // TOOLTIP PLUGIN DEFINITION
36027  // =========================
36028
36029  var old = $.fn.tooltip
36030
36031  $.fn.tooltip = function (option) {
36032    return this.each(function () {
36033      var $this   = $(this)
36034      var data    = $this.data('bs.tooltip')
36035      var options = typeof option == 'object' && option
36036
36037      if (!data && option == 'destroy') return
36038      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
36039      if (typeof option == 'string') data[option]()
36040    })
36041  }
36042
36043  $.fn.tooltip.Constructor = Tooltip
36044
36045
36046  // TOOLTIP NO CONFLICT
36047  // ===================
36048
36049  $.fn.tooltip.noConflict = function () {
36050    $.fn.tooltip = old
36051    return this
36052  }
36053
36054}(jQuery);
36055
36056/* ========================================================================
36057 * Bootstrap: transition.js v3.1.1
36058 * http://getbootstrap.com/javascript/#transitions
36059 * ========================================================================
36060 * Copyright 2011-2014 Twitter, Inc.
36061 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
36062 * ======================================================================== */
36063
36064
36065+function ($) {
36066  'use strict';
36067
36068  // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
36069  // ============================================================
36070
36071  function transitionEnd() {
36072    var el = document.createElement('bootstrap')
36073
36074    var transEndEventNames = {
36075      WebkitTransition : 'webkitTransitionEnd',
36076      MozTransition    : 'transitionend',
36077      OTransition      : 'oTransitionEnd otransitionend',
36078      transition       : 'transitionend'
36079    }
36080
36081    for (var name in transEndEventNames) {
36082      if (el.style[name] !== undefined) {
36083        return { end: transEndEventNames[name] }
36084      }
36085    }
36086
36087    return false // explicit for ie8 (  ._.)
36088  }
36089
36090  // http://blog.alexmaccaw.com/css-transitions
36091  $.fn.emulateTransitionEnd = function (duration) {
36092    var called = false, $el = this
36093    $(this).one($.support.transition.end, function () { called = true })
36094    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
36095    setTimeout(callback, duration)
36096    return this
36097  }
36098
36099  $(function () {
36100    $.support.transition = transitionEnd()
36101  })
36102
36103}(jQuery);
36104
36105
36106// ------------------------------------------
36107// Rellax.js
36108// Buttery smooth parallax library
36109// Copyright (c) 2016 Moe Amaya (@moeamaya)
36110// MIT license
36111//
36112// Thanks to Paraxify.js and Jaime Cabllero
36113// for parallax concepts
36114// ------------------------------------------
36115
36116(function (root, factory) {
36117	if (typeof define === 'function' && define.amd) {
36118		// AMD. Register as an anonymous module.
36119		define([], factory);
36120	} else if (typeof module === 'object' && module.exports) {
36121		// Node. Does not work with strict CommonJS, but
36122		// only CommonJS-like environments that support module.exports,
36123		// like Node.
36124		module.exports = factory();
36125	} else {
36126		// Browser globals (root is window)
36127		root.Rellax = factory();
36128	}
36129}(typeof window !== "undefined" ? window : global, function () {
36130	var Rellax = function(el, options){
36131		"use strict";
36132
36133		var self = Object.create(Rellax.prototype);
36134
36135		var posY = 0;
36136		var screenY = 0;
36137		var posX = 0;
36138		var screenX = 0;
36139		var blocks = [];
36140		var pause = true;
36141
36142		// check what requestAnimationFrame to use, and if
36143		// it's not supported, use the onscroll event
36144		var loop = window.requestAnimationFrame ||
36145			window.webkitRequestAnimationFrame ||
36146			window.mozRequestAnimationFrame ||
36147			window.msRequestAnimationFrame ||
36148			window.oRequestAnimationFrame ||
36149			function(callback){ return setTimeout(callback, 1000 / 60); };
36150
36151		// store the id for later use
36152		var loopId = null;
36153
36154		// Test via a getter in the options object to see if the passive property is accessed
36155		var supportsPassive = false;
vendor: 10,724 bytes, lines 36156-36457
36156		try {
36157			var opts = Object.defineProperty({}, 'passive', {
36158				get: function() {
36159					supportsPassive = true;
36160				}
36161			});
36162			window.addEventListener("testPassive", null, opts);
36163			window.removeEventListener("testPassive", null, opts);
36164		} catch (e) {}
36165
36166		// check what cancelAnimation method to use
36167		var clearLoop = window.cancelAnimationFrame || window.mozCancelAnimationFrame || clearTimeout;
36168
36169		// check which transform property to use
36170		var transformProp = window.transformProp || (function(){
36171				var testEl = document.createElement('div');
36172				if (testEl.style.transform === null) {
36173					var vendors = ['Webkit', 'Moz', 'ms'];
36174					for (var vendor in vendors) {
36175						if (testEl.style[ vendors[vendor] + 'Transform' ] !== undefined) {
36176							return vendors[vendor] + 'Transform';
36177						}
36178					}
36179				}
36180				return 'transform';
36181			})();
36182
36183		// Default Settings
36184		self.options = {
36185			speed: -2,
36186			verticalSpeed: null,
36187			horizontalSpeed: null,
36188			breakpoints: [576, 768, 1201],
36189			center: false,
36190			wrapper: null,
36191			relativeToWrapper: false,
36192			round: true,
36193			vertical: true,
36194			horizontal: false,
36195			verticalScrollAxis: "y",
36196			horizontalScrollAxis: "x",
36197			callback: function() {},
36198		};
36199
36200		// User defined options (might have more in the future)
36201		if (options){
36202			Object.keys(options).forEach(function(key){
36203				self.options[key] = options[key];
36204			});
36205		}
36206
36207		function validateCustomBreakpoints () {
36208			if (self.options.breakpoints.length === 3 && Array.isArray(self.options.breakpoints)) {
36209				var isAscending = true;
36210				var isNumerical = true;
36211				var lastVal;
36212				self.options.breakpoints.forEach(function (i) {
36213					if (typeof i !== 'number') isNumerical = false;
36214					if (lastVal !== null) {
36215						if (i < lastVal) isAscending = false;
36216					}
36217					lastVal = i;
36218				});
36219				if (isAscending && isNumerical) return;
36220			}
36221			// revert defaults if set incorrectly
36222			self.options.breakpoints = [576, 768, 1201];
36223			console.warn("Rellax: You must pass an array of 3 numbers in ascending order to the breakpoints option. Defaults reverted");
36224		}
36225
36226		if (options && options.breakpoints) {
36227			validateCustomBreakpoints();
36228		}
36229
36230		// By default, rellax class
36231		if (!el) {
36232			el = '.rellax';
36233		}
36234
36235		// check if el is a className or a node
36236		var elements = typeof el === 'string' ? document.querySelectorAll(el) : [el];
36237
36238		// Now query selector
36239		if (elements.length > 0) {
36240			self.elems = elements;
36241		}
36242
36243		// The elements don't exist
36244		else {
36245			console.warn("Rellax: The elements you're trying to select don't exist.");
36246			return;
36247		}
36248
36249		// Has a wrapper and it exists
36250		if (self.options.wrapper) {
36251			if (!self.options.wrapper.nodeType) {
36252				var wrapper = document.querySelector(self.options.wrapper);
36253
36254				if (wrapper) {
36255					self.options.wrapper = wrapper;
36256				} else {
36257					console.warn("Rellax: The wrapper you're trying to use doesn't exist.");
36258					return;
36259				}
36260			}
36261		}
36262
36263		// set a placeholder for the current breakpoint
36264		var currentBreakpoint;
36265
36266		// helper to determine current breakpoint
36267		var getCurrentBreakpoint = function (w) {
36268			var bp = self.options.breakpoints;
36269			if (w < bp[0]) return 'xs';
36270			if (w >= bp[0] && w < bp[1]) return 'sm';
36271			if (w >= bp[1] && w < bp[2]) return 'md';
36272			return 'lg';
36273		};
36274
36275		// Get and cache initial position of all elements
36276		var cacheBlocks = function() {
36277			for (var i = 0; i < self.elems.length; i++){
36278				var block = createBlock(self.elems[i]);
36279				blocks.push(block);
36280			}
36281		};
36282
36283
36284		// Let's kick this script off
36285		// Build array for cached element values
36286		var init = function() {
36287			for (var i = 0; i < blocks.length; i++){
36288				self.elems[i].style.cssText = blocks[i].style;
36289			}
36290
36291			blocks = [];
36292
36293			screenY = window.innerHeight;
36294			screenX = window.innerWidth;
36295			currentBreakpoint = getCurrentBreakpoint(screenX);
36296
36297			setPosition();
36298
36299			cacheBlocks();
36300
36301			animate();
36302
36303			// If paused, unpause and set listener for window resizing events
36304			if (pause) {
36305				window.addEventListener('resize', init);
36306				pause = false;
36307				// Start the loop
36308				update();
36309			}
36310		};
36311
36312		// We want to cache the parallax blocks'
36313		// values: base, top, height, speed
36314		// el: is dom object, return: el cache values
36315		var createBlock = function(el) {
36316			var dataPercentage = el.getAttribute( 'data-rellax-percentage' );
36317			var dataSpeed = el.getAttribute( 'data-rellax-speed' );
36318			var dataXsSpeed = el.getAttribute( 'data-rellax-xs-speed' );
36319			var dataMobileSpeed = el.getAttribute( 'data-rellax-mobile-speed' );
36320			var dataTabletSpeed = el.getAttribute( 'data-rellax-tablet-speed' );
36321			var dataDesktopSpeed = el.getAttribute( 'data-rellax-desktop-speed' );
36322			var dataVerticalSpeed = el.getAttribute('data-rellax-vertical-speed');
36323			var dataHorizontalSpeed = el.getAttribute('data-rellax-horizontal-speed');
36324			var dataVericalScrollAxis = el.getAttribute('data-rellax-vertical-scroll-axis');
36325			var dataHorizontalScrollAxis = el.getAttribute('data-rellax-horizontal-scroll-axis');
36326			var dataZindex = el.getAttribute( 'data-rellax-zindex' ) || 0;
36327			var dataMin = el.getAttribute( 'data-rellax-min' );
36328			var dataMax = el.getAttribute( 'data-rellax-max' );
36329			var dataMinX = el.getAttribute('data-rellax-min-x');
36330			var dataMaxX = el.getAttribute('data-rellax-max-x');
36331			var dataMinY = el.getAttribute('data-rellax-min-y');
36332			var dataMaxY = el.getAttribute('data-rellax-max-y');
36333			var mapBreakpoints;
36334			var breakpoints = true;
36335
36336			if (!dataXsSpeed && !dataMobileSpeed && !dataTabletSpeed && !dataDesktopSpeed) {
36337				breakpoints = false;
36338			} else {
36339				mapBreakpoints = {
36340					'xs': dataXsSpeed,
36341					'sm': dataMobileSpeed,
36342					'md': dataTabletSpeed,
36343					'lg': dataDesktopSpeed
36344				};
36345			}
36346
36347			// initializing at scrollY = 0 (top of browser), scrollX = 0 (left of browser)
36348			// ensures elements are positioned based on HTML layout.
36349			//
36350			// If the element has the percentage attribute, the posY and posX needs to be
36351			// the current scroll position's value, so that the elements are still positioned based on HTML layout
36352			var wrapperPosY = self.options.wrapper ? self.options.wrapper.scrollTop : (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
36353			// If the option relativeToWrapper is true, use the wrappers offset to top, subtracted from the current page scroll.
36354			if (self.options.relativeToWrapper) {
36355				var scrollPosY = (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
36356				wrapperPosY = scrollPosY - self.options.wrapper.offsetTop;
36357			}
36358			var posY = self.options.vertical ? ( dataPercentage || self.options.center ? wrapperPosY : 0 ) : 0;
36359			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;
36360
36361			var blockTop = posY + el.getBoundingClientRect().top;
36362			var blockHeight = el.clientHeight || el.offsetHeight || el.scrollHeight;
36363
36364			var blockLeft = posX + el.getBoundingClientRect().left;
36365			var blockWidth = el.clientWidth || el.offsetWidth || el.scrollWidth;
36366
36367			// apparently parallax equation everyone uses
36368			var percentageY = dataPercentage ? dataPercentage : (posY - blockTop + screenY) / (blockHeight + screenY);
36369			var percentageX = dataPercentage ? dataPercentage : (posX - blockLeft + screenX) / (blockWidth + screenX);
36370			if(self.options.center){ percentageX = 0.5; percentageY = 0.5; }
36371
36372			// Optional individual block speed as data attr, otherwise global speed
36373			var speed = (breakpoints && mapBreakpoints[currentBreakpoint] !== null) ? Number(mapBreakpoints[currentBreakpoint]) : (dataSpeed ? dataSpeed : self.options.speed);
36374			var verticalSpeed = dataVerticalSpeed ? dataVerticalSpeed : self.options.verticalSpeed;
36375			var horizontalSpeed = dataHorizontalSpeed ? dataHorizontalSpeed : self.options.horizontalSpeed;
36376
36377			// Optional individual block movement axis direction as data attr, otherwise global movement direction
36378			var verticalScrollAxis = dataVericalScrollAxis ? dataVericalScrollAxis : self.options.verticalScrollAxis;
36379			var horizontalScrollAxis = dataHorizontalScrollAxis ? dataHorizontalScrollAxis : self.options.horizontalScrollAxis;
36380
36381			var bases = updatePosition(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed);
36382
36383			// ~~Store non-translate3d transforms~~
36384			// Store inline styles and extract transforms
36385			var style = el.style.cssText;
36386			var transform = '';
36387
36388			// Check if there's an inline styled transform
36389			var searchResult = /transform\s*:/i.exec(style);
36390			if (searchResult) {
36391				// Get the index of the transform
36392				var index = searchResult.index;
36393
36394				// Trim the style to the transform point and get the following semi-colon index
36395				var trimmedStyle = style.slice(index);
36396				var delimiter = trimmedStyle.indexOf(';');
36397
36398				// Remove "transform" string and save the attribute
36399				if (delimiter) {
36400					transform = " " + trimmedStyle.slice(11, delimiter).replace(/\s/g,'');
36401				} else {
36402					transform = " " + trimmedStyle.slice(11).replace(/\s/g,'');
36403				}
36404			}
36405
36406			return {
36407				baseX: bases.x,
36408				baseY: bases.y,
36409				top: blockTop,
36410				left: blockLeft,
36411				height: blockHeight,
36412				width: blockWidth,
36413				speed: speed,
36414				verticalSpeed: verticalSpeed,
36415				horizontalSpeed: horizontalSpeed,
36416				verticalScrollAxis: verticalScrollAxis,
36417				horizontalScrollAxis: horizontalScrollAxis,
36418				style: style,
36419				transform: transform,
36420				zindex: dataZindex,
36421				min: dataMin,
36422				max: dataMax,
36423				minX: dataMinX,
36424				maxX: dataMaxX,
36425				minY: dataMinY,
36426				maxY: dataMaxY
36427			};
36428		};
36429
36430		// set scroll position (posY, posX)
36431		// side effect method is not ideal, but okay for now
36432		// returns true if the scroll changed, false if nothing happened
36433		var setPosition = function() {
36434			var oldY = posY;
36435			var oldX = posX;
36436
36437			posY = self.options.wrapper ? self.options.wrapper.scrollTop : (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset;
36438			posX = self.options.wrapper ? self.options.wrapper.scrollLeft : (document.documentElement || document.body.parentNode || document.body).scrollLeft || window.pageXOffset;
36439			// If option relativeToWrapper is true, use relative wrapper value instead.
36440			if (self.options.relativeToWrapper) {
36441				var scrollPosY = (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset;
36442				posY = scrollPosY - self.options.wrapper.offsetTop;
36443			}
36444
36445
36446			if (oldY != posY && self.options.vertical) {
36447				// scroll changed, return true
36448				return true;
36449			}
36450
36451			if (oldX != posX && self.options.horizontal) {
36452				// scroll changed, return true
36453				return true;
36454			}
36455
36456			// scroll did not change
36457			return false;
36458		};
36459
36460		// Ahh a pure function, gets new transform value
36461		// based on scrollPosition and speed
36462		// Allow for decimal pixel values
36463		var updatePosition = function(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed) {
36464			var result = {};
36465			var valueX = ((horizontalSpeed ? horizontalSpeed : speed) * (100 * (1 - percentageX)));
36466			var valueY = ((verticalSpeed ? verticalSpeed : speed) * (100 * (1 - percentageY)));
36467
36468			result.x = self.options.round ? Math.round(valueX) : Math.round(valueX * 100) / 100;
36469			result.y = self.options.round ? Math.round(valueY) : Math.round(valueY * 100) / 100;
36470
36471			return result;
36472		};
36473
36474		// Remove event listeners and loop again
36475		var deferredUpdate = function() {
36476			window.removeEventListener('resize', deferredUpdate);
36477			window.removeEventListener('orientationchange', deferredUpdate);
36478			(self.options.wrapper ? self.options.wrapper : window).removeEventListener('scroll', deferredUpdate);
36479			(self.options.wrapper ? self.options.wrapper : document).removeEventListener('touchmove', deferredUpdate);
36480
36481			// loop again
36482			loopId = loop(update);
36483		};
36484
36485		// Loop
36486		var update = function() {
36487			if (setPosition() && pause === false) {
36488				animate();
36489
36490				// loop again
36491				loopId = loop(update);
36492			} else {
36493				loopId = null;
36494
36495				// Don't animate until we get a position updating event
36496				window.addEventListener('resize', deferredUpdate);
36497				window.addEventListener('orientationchange', deferredUpdate);
36498				(self.options.wrapper ? self.options.wrapper : window).addEventListener('scroll', deferredUpdate, supportsPassive ? { passive: true } : false);
36499				(self.options.wrapper ? self.options.wrapper : document).addEventListener('touchmove', deferredUpdate, supportsPassive ? { passive: true } : false);
36500			}
36501		};
36502
36503		// Transform3d on parallax element
36504		var animate = function() {
36505			var positions;
36506			for (var i = 0; i < self.elems.length; i++){
36507				// Determine relevant movement directions
36508				var verticalScrollAxis = blocks[i].verticalScrollAxis.toLowerCase();
36509				var horizontalScrollAxis = blocks[i].horizontalScrollAxis.toLowerCase();
36510				var verticalScrollX = verticalScrollAxis.indexOf("x") != -1 ? posY : 0;
36511				var verticalScrollY = verticalScrollAxis.indexOf("y") != -1 ? posY : 0;
36512				var horizontalScrollX = horizontalScrollAxis.indexOf("x") != -1 ? posX : 0;
36513				var horizontalScrollY = horizontalScrollAxis.indexOf("y") != -1 ? posX : 0;
36514
36515				var percentageY = ((verticalScrollY + horizontalScrollY - blocks[i].top + screenY) / (blocks[i].height + screenY));
36516				var percentageX = ((verticalScrollX + horizontalScrollX - blocks[i].left + screenX) / (blocks[i].width + screenX));
36517
36518				// Subtracting initialize value, so element stays in same spot as HTML
36519				positions = updatePosition(percentageX, percentageY, blocks[i].speed, blocks[i].verticalSpeed, blocks[i].horizontalSpeed);
36520				var positionY = positions.y - blocks[i].baseY;
36521				var positionX = positions.x - blocks[i].baseX;
36522
36523				// The next two "if" blocks go like this:
36524				// Check if a limit is defined (first "min", then "max");
36525				// Check if we need to change the Y or the X
36526				// (Currently working only if just one of the axes is enabled)
36527				// Then, check if the new position is inside the allowed limit
36528				// If so, use new position. If not, set position to limit.
36529
36530				// Check if a min limit is defined
36531				if (blocks[i].min !== null) {
36532					if (self.options.vertical && !self.options.horizontal) {
36533						positionY = positionY <= blocks[i].min ? blocks[i].min : positionY;
36534					}
36535					if (self.options.horizontal && !self.options.vertical) {
36536						positionX = positionX <= blocks[i].min ? blocks[i].min : positionX;
36537					}
36538				}
36539
36540				// Check if directional min limits are defined
36541				if (blocks[i].minY != null) {
36542						positionY = positionY <= blocks[i].minY ? blocks[i].minY : positionY;
36543				}
36544				if (blocks[i].minX != null) {
36545						positionX = positionX <= blocks[i].minX ? blocks[i].minX : positionX;
36546				}
36547
36548				// Check if a max limit is defined
36549				if (blocks[i].max !== null) {
36550					if (self.options.vertical && !self.options.horizontal) {
36551						positionY = positionY >= blocks[i].max ? blocks[i].max : positionY;
36552					}
36553					if (self.options.horizontal && !self.options.vertical) {
36554						positionX = positionX >= blocks[i].max ? blocks[i].max : positionX;
36555					}
36556				}
36557
36558				// Check if directional max limits are defined
36559				if (blocks[i].maxY != null) {
36560						positionY = positionY >= blocks[i].maxY ? blocks[i].maxY : positionY;
36561				}
36562				if (blocks[i].maxX != null) {
36563						positionX = positionX >= blocks[i].maxX ? blocks[i].maxX : positionX;
36564				}
36565
36566				var zindex = blocks[i].zindex;
36567
36568				// Move that element
36569				// (Set the new translation and append initial inline transforms.)
36570				var translate = 'translate3d(' + (self.options.horizontal ? positionX : '0') + 'px,' + (self.options.vertical ? positionY : '0') + 'px,' + zindex + 'px) ' + blocks[i].transform;
36571				self.elems[i].style[transformProp] = translate;
36572			}
36573			self.options.callback(positions);
36574		};
36575
36576		self.destroy = function() {
36577			for (var i = 0; i < self.elems.length; i++){
36578				self.elems[i].style.cssText = blocks[i].style;
36579			}
36580
36581			// Remove resize event listener if not pause, and pause
36582			if (!pause) {
36583				window.removeEventListener('resize', init);
36584				pause = true;
36585			}
36586
36587			// Clear the animation loop to prevent possible memory leak
36588			clearLoop(loopId);
36589			loopId = null;
36590		};
36591
36592		// Init
36593		init();
36594
36595		// Allow to recalculate the initial values whenever we want
36596		self.refresh = init;
36597
36598		return self;
36599	};
36600	return Rellax;
36601}));
36602
36603/*
36604 * OKVideo by OKFocus v2.3.2
36605 * http://okfoc.us
36606 *
36607 * Copyright 2014, OKFocus
36608 * Licensed under the MIT license.
36609 *
36610 */
36611var player, OKEvents, options, videoWidth, videoHeight, YTplayers, youtubePlayers = new Array();
36612// youtube player ready
36613function onYouTubeIframeAPIReady() {
36614	YTplayers = new Array();
36615	jQuery('.no-touch .uncode-video-container.video').each(function() {
36616		var playerY;
36617		if (jQuery(this).attr('data-provider') == 'youtube') {
36618			var id = jQuery(this).attr('data-id'),
36619				start = jQuery(this).attr('data-start'),
36620				end = jQuery(this).attr('data-end');
36621			start = typeof start && start !== null ? start : 0;
36622			end = typeof end && end !== null ? end : 0;
36623			options = jQuery(window).data('okoptions-' + id);
36624			options.time = jQuery(this).attr('data-t');
36625			playerY = new YT.Player('okplayer-' + id, {
36626				videoId: options.video ? options.video.id : null,
36627				playerVars: {
36628					'autohide': 1,
36629					'autoplay': 0, //options.autoplay,
36630					'disablekb': 1,
36631					'cc_load_policy': options.captions,
36632					'controls': 0,
36633					'enablejsapi': 1,
36634					'fs': 0,
36635					'modestbranding': 1,
36636					'origin': window.location.origin || (window.location.protocol + '//' + window.location.hostname),
36637					'iv_load_policy': options.annotations,
36638					'loop': options.loop,
36639					'showinfo': 0,
36640					'rel': 0,
36641					'wmode': 'opaque',
36642					'hd': options.hd,
36643					'mute': 1,
36644					'start': start,
36645					'end': end
36646				},
36647				events: {
36648					'onReady': OKEvents.yt.ready,
36649					'onStateChange': OKEvents.yt.onStateChange,
36650					'onError': OKEvents.yt.error
36651				}
36652			});
36653			YTplayers[id] = playerY;
36654			playerY.videoId = id;
36655		}
36656
36657	});
36658}
36659// vimeo player ready
36660function vimeoPlayerReady(id) {
36661	options = jQuery(window).data('okoptions-' + id);
36662	var jIframe = options.jobject,
36663		iframe = jIframe[0];
36664
36665	jIframe.attr('src', jIframe.data('src'));
36666	var playerV = new Vimeo.Player(iframe);
36667	// hide player until Vimeo hides controls...
36668	playerV.on('loaded', function(e) {
36669		OKEvents.v.onReady(iframe);
36670		var carouselContainer = jQuery(iframe).closest('.owl-carousel');
36671		if (carouselContainer.length) {
36672			UNCODE.owlPlayVideo(carouselContainer);
36673		}
36674		// "Do not try to add listeners or call functions before receiving this event."
36675		if (OKEvents.utils.isMobile()) {
36676			// mobile devices cannot listen for play event
36677			OKEvents.v.onPlay(playerV);
36678		} else {
36679			playerV.on('play', function(){
36680				OKEvents.v.onPlay(playerV);
36681			});
36682			playerV.on('pause', function(){
36683				OKEvents.v.onPause;
36684			});
36685			playerV.on('ended', function(){
36686				OKEvents.v.onFinish
36687			});
36688		}
36689		if (options.time != null) {
36690			var optsTimeStr = (options.time).replace('t=', ''),
36691				timeV = '';
36692
36693			if ( /[a-zA-Z]/g.test(optsTimeStr) ) {
36694				var timeArr = optsTimeStr.split(/([^\d.-])/);
36695				for ( var i = 0; i < timeArr.length; i++ ) {
36696					if ( timeArr[i] === 'h' ) {
36697						timeV += parseFloat(timeArr[i-1]) * 3600;
36698					} else if ( timeArr[i] === 'm' ) {
36699						timeV += parseFloat(timeArr[i-1]) * 60;
36700					} else if ( timeArr[i] === 's' ) {
36701						timeV += parseFloat(timeArr[i-1]);
36702					}
36703				}
36704			} else {
36705				timeV = optsTimeStr;
36706			}
36707
36708			playerV.setCurrentTime(timeV);
36709		}
36710
36711		playerV.setVolume(0);
36712		playerV.play();
36713		jQuery(iframe).css({
36714			visibility: 'visible',
36715			opacity: 1
36716		});
36717		jQuery(iframe).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1');
36718		jQuery(iframe).closest('#page-header').addClass('video-started');
36719		jQuery(iframe).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1');
36720
36721	});
36722}
36723OKEvents = {
36724	yt: {
36725		ready: function(event) {
36726			var id = event.target.videoId;
36727			youtubePlayers[id] = event.target;
36728			event.target.setVolume(options.volume);
36729			if (options.autoplay === 1) {
36730				if (options.playlist.list) {
36731					player.loadPlaylist(options.playlist.list, options.playlist.index, options.playlist.startSeconds, options.playlist.suggestedQuality);
36732				} else {
36733					var inCarousel = jQuery('#okplayer-' + id).closest('.owl-item');
36734					if (!inCarousel.length || (inCarousel.length && inCarousel.hasClass('active'))) {
36735						if (options.time != null) {
36736							event.target.seekTo(parseInt(options.time));
36737						}
36738						event.target.playVideo();
36739					} else {
36740						event.target.pauseVideo();
36741					}
36742				}
36743			}
36744			OKEvents.utils.isFunction(options.onReady) && options.onReady(event.target);
36745
36746			jQuery('#okplayer-' + id).closest('[data-provider]').on('uncode-resume', function(){
36747				if (options.time != null) {
36748					event.target.seekTo(parseInt(options.time)).playVideo();
36749				} else {
36750					event.target.seekTo(0).playVideo();
36751				}
36752			});
36753
36754			jQuery('#okplayer-' + id).closest('[data-provider]').on('uncode-pause', function(){
36755				if (options.time != null) {
36756					event.target.seekTo(parseInt(options.time)).pauseVideo();
36757				} else {
36758					event.target.seekTo(0).pauseVideo();
36759				}
36760			});
36761		},
36762		onStateChange: function(event) {
36763			var id = event.target.videoId;
36764			switch (event.data) {
36765				case -1:
36766					OKEvents.utils.isFunction(options.unstarted) && options.unstarted();
36767					break;
36768				case 0:
36769					OKEvents.utils.isFunction(options.onFinished) && options.onFinished();
36770					options.loop && event.target.playVideo();
36771					break;
36772				case 1:
36773					OKEvents.utils.isFunction(options.onPlay) && options.onPlay();
36774					setTimeout(function() {
36775						UNCODE.initVideoComponent(document.body, '.uncode-video-container.video:not(.drop-move), .uncode-video-container.self-video:not(.drop-move)');
36776						jQuery('#okplayer-' + id).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1');
36777						jQuery('#okplayer-' + id).closest('#page-header').addClass('video-started');
36778						jQuery('#okplayer-' + id).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1');
36779					}, 300);
36780					break;
36781				case 2:
36782					OKEvents.utils.isFunction(options.onPause) && options.onPause();
36783					break;
36784				case 3:
36785					OKEvents.utils.isFunction(options.buffering) && options.buffering();
36786					break;
36787				case 5:
36788					OKEvents.utils.isFunction(options.cued) && options.cued();
36789					break;
36790				default:
36791					throw "OKVideo: received invalid data from YT player.";
36792			}
36793		},
36794		error: function(event) {
36795			throw event;
36796		}
36797	},
36798	v: {
36799		onReady: function(target) {
36800			OKEvents.utils.isFunction(options.onReady) && options.onReady(target);
36801		},
36802		onPlay: function(player) {
36803			if (!OKEvents.utils.isMobile()) player.setVolume(options.volume);
36804			OKEvents.utils.isFunction(options.onPlay) && options.onPlay();
36805			jQuery(player.element).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1');
36806			jQuery(player.element).closest('#page-header').addClass('video-started');
36807			jQuery(player.element).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1');
36808		},
36809		onPause: function() {
36810			OKEvents.utils.isFunction(options.onPause) && options.onPause();
36811		},
36812		onFinish: function() {
36813			OKEvents.utils.isFunction(options.onFinish) && options.onFinish();
36814		}
36815	},
36816	utils: {
36817		isFunction: function(func) {
36818			if (typeof func === 'function') {
36819				return true;
36820			} else {
36821				return false;
36822			}
36823		},
36824		isMobile: function() {
36825			if (navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry)/)) {
36826				return true;
36827			} else {
36828				return false;
36829			}
36830		}
36831	}
36832};
36833
36834/**
36835 * vivus - JavaScript library to make drawing animation on SVG
36836 * @version v0.4.4
36837 * @link https://github.com/maxwellito/vivus
36838 * @license MIT
36839 */
36840
36841'use strict';
36842
36843(function () {
36844
36845  'use strict';
36846
36847/**
36848 * Pathformer
36849 * Beta version
36850 *
36851 * Take any SVG version 1.1 and transform
36852 * child elements to 'path' elements
36853 *
36854 * This code is purely forked from
36855 * https://github.com/Waest/SVGPathConverter
36856 */
36857
36858/**
36859 * Class constructor
36860 *
36861 * @param {DOM|String} element Dom element of the SVG or id of it
36862 */
36863function Pathformer(element) {
36864  // Test params
36865  if (typeof element === 'undefined') {
36866	throw new Error('Pathformer [constructor]: "element" parameter is required');
36867  }
36868
36869  // Set the element
36870  if (element.constructor === String) {
36871	element = document.getElementById(element);
36872	if (!element) {
36873	  throw new Error('Pathformer [constructor]: "element" parameter is not related to an existing ID');
36874	}
36875  }
36876  if (element instanceof window.SVGElement ||
36877	  element instanceof window.SVGGElement ||
36878	  /^svg$/i.test(element.nodeName)) {
36879	this.el = element;
36880  } else {
36881	throw new Error('Pathformer [constructor]: "element" parameter must be a string or a SVGelement');
36882  }
36883
36884  // Start
36885  this.scan(element);
36886}
36887
36888/**
36889 * List of tags which can be transformed
36890 * to path elements
36891 *
36892 * @type {Array}
36893 */
36894Pathformer.prototype.TYPES = ['line', 'ellipse', 'circle', 'polygon', 'polyline', 'rect'];
36895
36896/**
36897 * List of attribute names which contain
36898 * data. This array list them to check if
36899 * they contain bad values, like percentage.
36900 *
36901 * @type {Array}
36902 */
36903Pathformer.prototype.ATTR_WATCH = ['cx', 'cy', 'points', 'r', 'rx', 'ry', 'x', 'x1', 'x2', 'y', '
vendor: 24,640 bytes, lines 36903-37701
36903y1', 'y2'];
36904
36905/**
36906 * Finds the elements compatible for transform
36907 * and apply the liked method
36908 *
36909 * @param  {object} options Object from the constructor
36910 */
36911Pathformer.prototype.scan = function (svg) {
36912  var fn, element, pathData, pathDom,
36913	  elements = svg.querySelectorAll(this.TYPES.join(','));
36914
36915  for (var i = 0; i < elements.length; i++) {
36916	element = elements[i];
36917	fn = this[element.tagName.toLowerCase() + 'ToPath'];
36918	pathData = fn(this.parseAttr(element.attributes));
36919	pathDom = this.pathMaker(element, pathData);
36920	element.parentNode.replaceChild(pathDom, element);
36921  }
36922};
36923
36924
36925/**
36926 * Read `line` element to extract and transform
36927 * data, to make it ready for a `path` object.
36928 *
36929 * @param  {DOMelement} element Line element to transform
36930 * @return {object}			 Data for a `path` element
36931 */
36932Pathformer.prototype.lineToPath = function (element) {
36933  var newElement = {},
36934	  x1 = element.x1 || 0,
36935	  y1 = element.y1 || 0,
36936	  x2 = element.x2 || 0,
36937	  y2 = element.y2 || 0;
36938
36939  newElement.d = 'M' + x1 + ',' + y1 + 'L' + x2 + ',' + y2;
36940  return newElement;
36941};
36942
36943/**
36944 * Read `rect` element to extract and transform
36945 * data, to make it ready for a `path` object.
36946 * The radius-border is not taken in charge yet.
36947 * (your help is more than welcomed)
36948 *
36949 * @param  {DOMelement} element Rect element to transform
36950 * @return {object}             Data for a `path` element
36951 */
36952Pathformer.prototype.rectToPath = function (element) {
36953  var newElement = {},
36954      x      = parseFloat(element.x)      || 0,
36955      y      = parseFloat(element.y)      || 0,
36956      width  = parseFloat(element.width)  || 0,
36957      height = parseFloat(element.height) || 0;
36958
36959  if (element.rx || element.ry) {
36960    var rx = parseInt(element.rx, 10) || -1,
36961        ry = parseInt(element.ry, 10) || -1;
36962    rx = Math.min(Math.max(rx < 0 ? ry : rx, 0), width/2);
36963    ry = Math.min(Math.max(ry < 0 ? rx : ry, 0), height/2);
36964
36965    newElement.d = 'M ' + (x + rx) + ',' + y + ' ' +
36966                   'L ' + (x + width - rx) + ',' + y + ' ' +
36967                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + width) + ',' + (y + ry) + ' ' +
36968                   'L ' + (x + width) + ',' + (y + height - ry) + ' ' +
36969                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + width - rx) + ',' + (y + height) + ' ' +
36970                   'L ' + (x + rx) + ',' + (y + height) + ' ' +
36971                   'A ' + rx + ',' + ry + ',0,0,1,' + x + ',' + (y + height - ry) + ' ' +
36972                   'L ' + x + ',' + (y + ry) + ' ' +
36973                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + rx) + ',' + y;
36974  }
36975  else {
36976    newElement.d = 'M' + x + ' ' + y + ' ' +
36977                   'L' + (x + width) + ' ' + y + ' ' +
36978                   'L' + (x + width) + ' ' + (y + height) + ' ' +
36979                   'L' + x + ' ' + (y + height) + ' Z';
36980  }
36981  return newElement;
36982};
36983
36984/**
36985 * Read `polyline` element to extract and transform
36986 * data, to make it ready for a `path` object.
36987 *
36988 * @param  {DOMelement} element Polyline element to transform
36989 * @return {object}             Data for a `path` element
36990 */
36991Pathformer.prototype.polylineToPath = function (element) {
36992  var newElement = {},
36993      points = element.points.trim().split(' '),
36994      i, path;
36995
36996  // Reformatting if points are defined without commas
36997  if (element.points.indexOf(',') === -1) {
36998    var formattedPoints = [];
36999    for (i = 0; i < points.length; i+=2) {
37000      formattedPoints.push(points[i] + ',' + points[i+1]);
37001    }
37002    points = formattedPoints;
37003  }
37004
37005  // Generate the path.d value
37006  path = 'M' + points[0];
37007  for(i = 1; i < points.length; i++) {
37008    if (points[i].indexOf(',') !== -1) {
37009      path += 'L' + points[i];
37010    }
37011  }
37012  newElement.d = path;
37013  return newElement;
37014};
37015
37016/**
37017 * Read `polygon` element to extract and transform
37018 * data, to make it ready for a `path` object.
37019 * This method rely on polylineToPath, because the
37020 * logic is similar. The path created is just closed,
37021 * so it needs an 'Z' at the end.
37022 *
37023 * @param  {DOMelement} element Polygon element to transform
37024 * @return {object}             Data for a `path` element
37025 */
37026Pathformer.prototype.polygonToPath = function (element) {
37027  var newElement = Pathformer.prototype.polylineToPath(element);
37028
37029  newElement.d += 'Z';
37030  return newElement;
37031};
37032
37033/**
37034 * Read `ellipse` element to extract and transform
37035 * data, to make it ready for a `path` object.
37036 *
37037 * @param  {DOMelement} element ellipse element to transform
37038 * @return {object}             Data for a `path` element
37039 */
37040Pathformer.prototype.ellipseToPath = function (element) {
37041  var newElement = {},
37042      rx = parseFloat(element.rx) || 0,
37043      ry = parseFloat(element.ry) || 0,
37044      cx = parseFloat(element.cx) || 0,
37045      cy = parseFloat(element.cy) || 0,
37046      startX = cx - rx,
37047      startY = cy,
37048      endX = parseFloat(cx) + parseFloat(rx),
37049      endY = cy;
37050
37051  newElement.d = 'M' + startX + ',' + startY +
37052                 'A' + rx + ',' + ry + ' 0,1,1 ' + endX + ',' + endY +
37053                 'A' + rx + ',' + ry + ' 0,1,1 ' + startX + ',' + endY;
37054  return newElement;
37055};
37056
37057/**
37058 * Read `circle` element to extract and transform
37059 * data, to make it ready for a `path` object.
37060 *
37061 * @param  {DOMelement} element Circle element to transform
37062 * @return {object}             Data for a `path` element
37063 */
37064Pathformer.prototype.circleToPath = function (element) {
37065  var newElement = {},
37066      r  = parseFloat(element.r)  || 0,
37067      cx = parseFloat(element.cx) || 0,
37068      cy = parseFloat(element.cy) || 0,
37069      startX = cx - r,
37070      startY = cy,
37071      endX = parseFloat(cx) + parseFloat(r),
37072      endY = cy;
37073
37074  newElement.d =  'M' + startX + ',' + startY +
37075                  'A' + r + ',' + r + ' 0,1,1 ' + endX + ',' + endY +
37076                  'A' + r + ',' + r + ' 0,1,1 ' + startX + ',' + endY;
37077  return newElement;
37078};
37079
37080/**
37081 * Create `path` elements form original element
37082 * and prepared objects
37083 *
37084 * @param  {DOMelement} element  Original element to transform
37085 * @param  {object} pathData     Path data (from `toPath` methods)
37086 * @return {DOMelement}          Path element
37087 */
37088Pathformer.prototype.pathMaker = function (element, pathData) {
37089  var i, attr, pathTag = document.createElementNS('http://www.w3.org/2000/svg','path');
37090  for(i = 0; i < element.attributes.length; i++) {
37091    attr = element.attributes[i];
37092    if (this.ATTR_WATCH.indexOf(attr.name) === -1) {
37093      pathTag.setAttribute(attr.name, attr.value);
37094    }
37095  }
37096  for(i in pathData) {
37097    pathTag.setAttribute(i, pathData[i]);
37098  }
37099  return pathTag;
37100};
37101
37102/**
37103 * Parse attributes of a DOM element to
37104 * get an object of attribute => value
37105 *
37106 * @param  {NamedNodeMap} attributes Attributes object from DOM element to parse
37107 * @return {object}                  Object of attributes
37108 */
37109Pathformer.prototype.parseAttr = function (element) {
37110  var attr, output = {};
37111  for (var i = 0; i < element.length; i++) {
37112    attr = element[i];
37113    // Check if no data attribute contains '%', or the transformation is impossible
37114    if (this.ATTR_WATCH.indexOf(attr.name) !== -1 && attr.value.indexOf('%') !== -1) {
37115      throw new Error('Pathformer [parseAttr]: a SVG shape got values in percentage. This cannot be transformed into \'path\' tags. Please use \'viewBox\'.');
37116    }
37117    output[attr.name] = attr.value;
37118  }
37119  return output;
37120};
37121
37122  'use strict';
37123
37124var setupEnv, requestAnimFrame, cancelAnimFrame, parsePositiveInt;
37125
37126/**
37127 * Vivus
37128 * Beta version
37129 *
37130 * Take any SVG and make the animation
37131 * to give give the impression of live drawing
37132 *
37133 * This in more than just inspired from codrops
37134 * At that point, it's a pure fork.
37135 */
37136
37137/**
37138 * Class constructor
37139 * option structure
37140 *   type: 'delayed'|'sync'|'oneByOne'|'script' (to know if the items must be drawn synchronously or not, default: delayed)
37141 *   duration: <int> (in frames)
37142 *   start: 'inViewport'|'manual'|'autostart' (start automatically the animation, default: inViewport)
37143 *   delay: <int> (delay between the drawing of first and last path)
37144 *   dashGap <integer> whitespace extra margin between dashes
37145 *   pathTimingFunction <function> timing animation function for each path element of the SVG
37146 *   animTimingFunction <function> timing animation function for the complete SVG
37147 *   forceRender <boolean> force the browser to re-render all updated path items
37148 *   selfDestroy <boolean> removes all extra styling on the SVG, and leaves it as original
37149 *
37150 * The attribute 'type' is by default on 'delayed'.
37151 *  - 'delayed'
37152 *    all paths are draw at the same time but with a
37153 *    little delay between them before start
37154 *  - 'sync'
37155 *    all path are start and finish at the same time
37156 *  - 'oneByOne'
37157 *    only one path is draw at the time
37158 *    the end of the first one will trigger the draw
37159 *    of the next one
37160 *
37161 * All these values can be overwritten individually
37162 * for each path item in the SVG
37163 * The value of frames will always take the advantage of
37164 * the duration value.
37165 * If you fail somewhere, an error will be thrown.
37166 * Good luck.
37167 *
37168 * @constructor
37169 * @this {Vivus}
37170 * @param {DOM|String}   element  Dom element of the SVG or id of it
37171 * @param {Object}       options  Options about the animation
37172 * @param {Function}     callback Callback for the end of the animation
37173 */
37174function Vivus (element, options, callback) {
37175
37176  setupEnv();
37177
37178  // Setup
37179  this.isReady = false;
37180  this.setElement(element, options);
37181  this.setOptions(options);
37182  this.setCallback(callback);
37183
37184  if (this.isReady) {
37185    this.init();
37186  }
37187}
37188
37189/**
37190 * Timing functions
37191 **************************************
37192 *
37193 * Default functions to help developers.
37194 * It always take a number as parameter (between 0 to 1) then
37195 * return a number (between 0 and 1)
37196 */
37197Vivus.LINEAR          = function (x) {return x;};
37198Vivus.EASE            = function (x) {return -Math.cos(x * Math.PI) / 2 + 0.5;};
37199Vivus.EASE_OUT        = function (x) {return 1 - Math.pow(1-x, 3);};
37200Vivus.EASE_IN         = function (x) {return Math.pow(x, 3);};
37201Vivus.EASE_OUT_BOUNCE = function (x) {
37202  var base = -Math.cos(x * (0.5 * Math.PI)) + 1,
37203    rate = Math.pow(base,1.5),
37204    rateR = Math.pow(1 - x, 2),
37205    progress = -Math.abs(Math.cos(rate * (2.5 * Math.PI) )) + 1;
37206  return (1- rateR) + (progress * rateR);
37207};
37208
37209
37210/**
37211 * Setters
37212 **************************************
37213 */
37214
37215/**
37216 * Check and set the element in the instance
37217 * The method will not return anything, but will throw an
37218 * error if the parameter is invalid
37219 *
37220 * @param {DOM|String}   element  SVG Dom element or id of it
37221 */
37222Vivus.prototype.setElement = function (element, options) {
37223  var onLoad, self;
37224
37225  // Basic check
37226  if (typeof element === 'undefined') {
37227    throw new Error('Vivus [constructor]: "element" parameter is required');
37228  }
37229
37230  // Set the element
37231  if (element.constructor === String) {
37232    element = document.getElementById(element);
37233    if (!element) {
37234      throw new Error('Vivus [constructor]: "element" parameter is not related to an existing ID');
37235    }
37236  }
37237  this.parentEl = element;
37238
37239  // Load the SVG with XMLHttpRequest and extract the SVG
37240  if (options && options.file) {
37241    var self = this;
37242    onLoad = function (e) {
37243      var domSandbox = document.createElement('div');
37244      domSandbox.innerHTML = this.responseText;
37245
37246      var svgTag = domSandbox.querySelector('svg');
37247      if (!svgTag) {
37248        throw new Error('Vivus [load]: Cannot find the SVG in the loaded file : ' + options.file);
37249      }
37250
37251      self.el = svgTag
37252      self.el.setAttribute('width', '100%');
37253      self.el.setAttribute('height', '100%');
37254      self.parentEl.appendChild(self.el)
37255      self.isReady = true;
37256      self.init();
37257      self = null;
37258    }
37259
37260    var oReq = new window.XMLHttpRequest();
37261    oReq.addEventListener('load', onLoad);
37262    oReq.open('GET', options.file);
37263    oReq.send();
37264    return;
37265  }
37266
37267  switch (element.constructor) {
37268  case window.SVGSVGElement:
37269  case window.SVGElement:
37270  case window.SVGGElement:
37271    this.el = element;
37272    this.isReady = true;
37273    break;
37274
37275  case window.HTMLObjectElement:
37276    self = this;
37277    onLoad = function (e) {
37278      if (self.isReady) {
37279        return;
37280      }
37281      self.el = element.contentDocument && element.contentDocument.querySelector('svg');
37282      if (!self.el && e) {
37283        throw new Error('Vivus [constructor]: object loaded does not contain any SVG');
37284      }
37285      else if (self.el) {
37286        if (element.getAttribute('built-by-vivus')) {
37287          self.parentEl.insertBefore(self.el, element);
37288          self.parentEl.removeChild(element);
37289          self.el.setAttribute('width', '100%');
37290          self.el.setAttribute('height', '100%');
37291        }
37292        self.isReady = true;
37293        self.init();
37294        self = null;
37295      }
37296    };
37297
37298    if (!onLoad()) {
37299      element.addEventListener('load', onLoad);
37300    }
37301    break;
37302
37303  default:
37304    throw new Error('Vivus [constructor]: "element" parameter is not valid (or miss the "file" attribute)');
37305  }
37306};
37307
37308/**
37309 * Set up user option to the instance
37310 * The method will not return anything, but will throw an
37311 * error if the parameter is invalid
37312 *
37313 * @param  {object} options Object from the constructor
37314 */
37315Vivus.prototype.setOptions = function (options) {
37316  var allowedTypes = ['delayed', 'sync', 'async', 'nsync', 'oneByOne', 'scenario', 'scenario-sync'];
37317  var allowedStarts =  ['inViewport', 'manual', 'autostart'];
37318
37319  // Basic check
37320  if (options !== undefined && options.constructor !== Object) {
37321    throw new Error('Vivus [constructor]: "options" parameter must be an object');
37322  }
37323  else {
37324    options = options || {};
37325  }
37326
37327  // Set the animation type
37328  if (options.type && allowedTypes.indexOf(options.type) === -1) {
37329    throw new Error('Vivus [constructor]: ' + options.type + ' is not an existing animation `type`');
37330  }
37331  else {
37332    this.type = options.type || allowedTypes[0];
37333  }
37334
37335  // Set the start type
37336  if (options.start && allowedStarts.indexOf(options.start) === -1) {
37337    throw new Error('Vivus [constructor]: ' + options.start + ' is not an existing `start` option');
37338  }
37339  else {
37340    this.start = options.start || allowedStarts[0];
37341  }
37342
37343  this.isIE         = (window.navigator.userAgent.indexOf('MSIE') !== -1 || window.navigator.userAgent.indexOf('Trident/') !== -1 || window.navigator.userAgent.indexOf('Edge/') !== -1 );
37344  this.duration     = parsePositiveInt(options.duration, 120);
37345  this.delay        = parsePositiveInt(options.delay, null);
37346  //Uncode addition
37347  this.delayStart   = parsePositiveInt(options.delayStart, null);
37348  //#END
37349  this.dashGap      = parsePositiveInt(options.dashGap, 1);
37350  this.forceRender  = options.hasOwnProperty('forceRender') ? !!options.forceRender : this.isIE;
37351  this.reverseStack = !!options.reverseStack;
37352  this.selfDestroy  = !!options.selfDestroy;
37353  this.onReady      = options.onReady;
37354  this.map          = [];
37355  this.frameLength  = this.currentFrame = this.delayUnit = this.speed = this.handle = null;
37356
37357  this.ignoreInvisible = options.hasOwnProperty('ignoreInvisible') ? !!options.ignoreInvisible : false;
37358
37359  this.animTimingFunction = options.animTimingFunction || Vivus.LINEAR;
37360  this.pathTimingFunction = options.pathTimingFunction || Vivus.LINEAR;
37361
37362  if (this.delay >= this.duration) {
37363    throw new Error('Vivus [constructor]: delay must be shorter than duration');
37364  }
37365};
37366
37367/**
37368 * Set up callback to the instance
37369 * The method will not return enything, but will throw an
37370 * error if the parameter is invalid
37371 *
37372 * @param  {Function} callback Callback for the animation end
37373 */
37374Vivus.prototype.setCallback = function (callback) {
37375  // Basic check
37376  if (!!callback && callback.constructor !== Function) {
37377    throw new Error('Vivus [constructor]: "callback" parameter must be a function');
37378  }
37379  this.callback = callback || function () {};
37380};
37381
37382
37383/**
37384 * Core
37385 **************************************
37386 */
37387
37388/**
37389 * Map the svg, path by path.
37390 * The method return nothing, it just fill the
37391 * `map` array. Each item in this array represent
37392 * a path element from the SVG, with informations for
37393 * the animation.
37394 *
37395 * ```
37396 * [
37397 *   {
37398 *     el: <DOMobj> the path element
37399 *     length: <number> length of the path line
37400 *     startAt: <number> time start of the path animation (in frames)
37401 *     duration: <number> path animation duration (in frames)
37402 *   },
37403 *   ...
37404 * ]
37405 * ```
37406 *
37407 */
37408Vivus.prototype.mapping = function () {
37409  var i, paths, path, pAttrs, pathObj, totalLength, lengthMeter, timePoint;
37410  timePoint = totalLength = lengthMeter = 0;
37411  paths = this.el.querySelectorAll('path');
37412
37413  for (i = 0; i < paths.length; i++) {
37414    path = paths[i];
37415    if (this.isInvisible(path)) {
37416      continue;
37417    }
37418    pathObj = {
37419      el: path,
37420      length: Math.ceil(path.getTotalLength())
37421    };
37422    // Test if the path length is correct
37423    if (isNaN(pathObj.length)) {
37424      if (window.console && console.warn) {
37425        console.warn('Vivus [mapping]: cannot retrieve a path element length', path);
37426      }
37427      continue;
37428    }
37429    this.map.push(pathObj);
37430    path.style.strokeDasharray  = pathObj.length + ' ' + (pathObj.length + this.dashGap * 2);
37431    path.style.strokeDashoffset = pathObj.length + this.dashGap;
37432    pathObj.length += this.dashGap;
37433    totalLength += pathObj.length;
37434
37435    this.renderPath(i);
37436  }
37437
37438  totalLength = totalLength === 0 ? 1 : totalLength;
37439  this.delay = this.delay === null ? this.duration / 3 : this.delay;
37440  this.delayUnit = this.delay / (paths.length > 1 ? paths.length - 1 : 1);
37441
37442  // Reverse stack if asked
37443  if (this.reverseStack) {
37444    this.map.reverse();
37445  }
37446
37447  for (i = 0; i < this.map.length; i++) {
37448    pathObj = this.map[i];
37449
37450    switch (this.type) {
37451    case 'delayed':
37452      pathObj.startAt = this.delayUnit * i;
37453      pathObj.duration = this.duration - this.delay;
37454      break;
37455
37456    case 'oneByOne':
37457      pathObj.startAt = lengthMeter / totalLength * this.duration;
37458      pathObj.duration = pathObj.length / totalLength * this.duration;
37459      break;
37460
37461    case 'sync':
37462    case 'async':
37463    case 'nsync':
37464      pathObj.startAt = 0;
37465      pathObj.duration = this.duration;
37466      break;
37467
37468    case 'scenario-sync':
37469      path = pathObj.el;
37470      pAttrs = this.parseAttr(path);
37471      pathObj.startAt = timePoint + (parsePositiveInt(pAttrs['data-delay'], this.delayUnit) || 0);
37472      pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration);
37473      timePoint = pAttrs['data-async'] !== undefined ? pathObj.startAt : pathObj.startAt + pathObj.duration;
37474      this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration));
37475      break;
37476
37477    case 'scenario':
37478      path = pathObj.el;
37479      pAttrs = this.parseAttr(path);
37480      pathObj.startAt = parsePositiveInt(pAttrs['data-start'], this.delayUnit) || 0;
37481      pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration);
37482      this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration));
37483      break;
37484    }
37485    lengthMeter += pathObj.length;
37486    this.frameLength = this.frameLength || this.duration;
37487  }
37488};
37489
37490/**
37491 * Interval method to draw the SVG from current
37492 * position of the animation. It update the value of
37493 * `currentFrame` and re-trace the SVG.
37494 *
37495 * It use this.handle to store the requestAnimationFrame
37496 * and clear it one the animation is stopped. So this
37497 * attribute can be used to know if the animation is
37498 * playing.
37499 *
37500 * Once the animation at the end, this method will
37501 * trigger the Vivus callback.
37502 *
37503 */
37504Vivus.prototype.drawer = function () {
37505  var self = this;
37506  this.currentFrame += this.speed;
37507
37508  if (this.currentFrame <= 0) {
37509    this.stop();
37510    this.reset();
37511  } else if (this.currentFrame >= this.frameLength) {
37512    this.stop();
37513    this.currentFrame = this.frameLength;
37514    this.trace();
37515    if (this.selfDestroy) {
37516      this.destroy();
37517    }
37518  } else {
37519    this.trace();
37520    this.handle = requestAnimFrame(function () {
37521      self.drawer();
37522    });
37523    return;
37524  }
37525
37526  this.callback(this);
37527  if (this.instanceCallback) {
37528    this.instanceCallback(this);
37529    this.instanceCallback = null;
37530  }
37531};
37532
37533/**
37534 * Draw the SVG at the current instant from the
37535 * `currentFrame` value. Here is where most of the magic is.
37536 * The trick is to use the `strokeDashoffset` style property.
37537 *
37538 * For optimisation reasons, a new property called `progress`
37539 * is added in each item of `map`. This one contain the current
37540 * progress of the path element. Only if the new value is different
37541 * the new value will be applied to the DOM element. This
37542 * method save a lot of resources to re-render the SVG. And could
37543 * be improved if the animation couldn't be played forward.
37544 *
37545 */
37546Vivus.prototype.trace = function () {
37547  var i, progress, path, currentFrame;
37548  currentFrame = this.animTimingFunction(this.currentFrame / this.frameLength) * this.frameLength;
37549  for (i = 0; i < this.map.length; i++) {
37550    path = this.map[i];
37551    progress = (currentFrame - path.startAt) / path.duration;
37552    progress = this.pathTimingFunction(Math.max(0, Math.min(1, progress)));
37553    if (path.progress !== progress) {
37554      path.progress = progress;
37555      path.el.style.strokeDashoffset = Math.floor(path.length * (1 - progress));
37556      this.renderPath(i);
37557    }
37558  }
37559};
37560
37561/**
37562 * Method forcing the browser to re-render a path element
37563 * from it's index in the map. Depending on the `forceRender`
37564 * value.
37565 * The trick is to replace the path element by it's clone.
37566 * This practice is not recommended because it's asking more
37567 * ressources, too much DOM manupulation..
37568 * but it's the only way to let the magic happen on IE.
37569 * By default, this fallback is only applied on IE.
37570 *
37571 * @param  {Number} index Path index
37572 */
37573Vivus.prototype.renderPath = function (index) {
37574  if (this.forceRender && this.map && this.map[index]) {
37575    var pathObj = this.map[index],
37576        newPath = pathObj.el.cloneNode(true);
37577    pathObj.el.parentNode.replaceChild(newPath, pathObj.el);
37578    pathObj.el = newPath;
37579  }
37580};
37581
37582/**
37583 * When the SVG object is loaded and ready,
37584 * this method will continue the initialisation.
37585 *
37586 * This this mainly due to the case of passing an
37587 * object tag in the constructor. It will wait
37588 * the end of the loading to initialise.
37589 *
37590 */
37591Vivus.prototype.init = function () {
37592  // Set object variables
37593  this.frameLength = 0;
37594  this.currentFrame = 0;
37595  this.map = [];
37596
37597  // Start
37598  new Pathformer(this.el);
37599  this.mapping();
37600  this.starter();
37601
37602  if (this.onReady) {
37603    this.onReady(this);
37604  }
37605};
37606
37607/**
37608 * Trigger to start of the animation.
37609 * Depending on the `start` value, a different script
37610 * will be applied.
37611 *
37612 * If the `start` value is not valid, an error will be thrown.
37613 * Even if technically, this is impossible.
37614 *
37615 */
37616Vivus.prototype.starter = function () {
37617  switch (this.start) {
37618  case 'manual':
37619    return;
37620
37621  case 'autostart':
37622    this.play();
37623    break;
37624
37625  case 'inViewport':
37626    var self = this,
37627    listener = function () {
37628      if (self.isInViewport(self.parentEl, 1)) {
37629        self.play();
37630        window.removeEventListener('scroll', listener);
37631        //Uncode addition
37632        window.removeEventListener('fp-slide-changed', listener);
37633        window.removeEventListener('fp-slide-scroll', listener);
37634        //#END
37635      }
37636    };
37637    window.addEventListener('scroll', listener);
37638    //Uncode addition
37639    window.addEventListener('fp-slide-changed', listener);
37640    window.addEventListener('fp-slide-scroll', listener);
37641    //#END
37642    listener();
37643    break;
37644  }
37645};
37646
37647
37648/**
37649 * Controls
37650 **************************************
37651 */
37652
37653/**
37654 * Get the current status of the animation between
37655 * three different states: 'start', 'progress', 'end'.
37656 * @return {string} Instance status
37657 */
37658Vivus.prototype.getStatus = function () {
37659  return this.currentFrame === 0 ? 'start' : this.currentFrame === this.frameLength ? 'end' : 'progress';
37660};
37661
37662/**
37663 * Reset the instance to the initial state : undraw
37664 * Be careful, it just reset the animation, if you're
37665 * playing the animation, this won't stop it. But just
37666 * make it start from start.
37667 *
37668 */
37669Vivus.prototype.reset = function () {
37670  return this.setFrameProgress(0);
37671};
37672
37673/**
37674 * Set the instance to the final state : drawn
37675 * Be careful, it just set the animation, if you're
37676 * playing the animation on rewind, this won't stop it.
37677 * But just make it start from the end.
37678 *
37679 */
37680Vivus.prototype.finish = function () {
37681  return this.setFrameProgress(1);
37682};
37683
37684/**
37685 * Set the level of progress of the drawing.
37686 *
37687 * @param {number} progress Level of progress to set
37688 */
37689Vivus.prototype.setFrameProgress = function (progress) {
37690  progress = Math.min(1, Math.max(0, progress));
37691  this.currentFrame = Math.round(this.frameLength * progress);
37692  this.trace();
37693  return this;
37694};
37695
37696/**
37697 * Play the animation at the desired speed.
37698 * Speed must be a valid number (no zero).
37699 * By default, the speed value is 1.
37700 * But a negative value is accepted to go forward.
37701 *
37702 * And works with float too.
37703 * But don't forget we are in JavaScript, se be nice
37704 * with him and give him a 1/2^x value.
37705 *
37706 * @param  {number} speed Animation speed [optional]
37707 */
37708Vivus.prototype.play = function (speed, callback) {
37709  this.instanceCallback = null;
37710
37711  if (speed && typeof speed === 'function') {
37712    this.instanceCallback = speed; // first parameter is actually the callback function
37713    speed = null;
37714  }
37715  else if (speed && typeof speed !== 'number') {
37716    throw new Error('Vivus [play]: invalid speed');
37717  }
37718  // if the first parameter wasn't the callback, check if the seconds was
37719  if (callback && typeof(callback) === 'function' && !this.instanceCallback) {
37720    this.instanceCallback = callback;
37721  }
37722
37723
37724  this.speed = speed || 1;
37725  //Uncode addition
37726  if (!this.handle) {
37727    var $this = this,
37728    delay = (this.delayStart != null) ? this.delayStart : 0;
37729    setTimeout(function() {
37730      $this.drawer();
37731    }, delay);
37732  }
37733  //#END
37734  return this;
37735};
37736
37737/**
37738 * Stop the current animation, if on progress.
37739 * Should not trigger any error.
37740 *
37741 */
37742Vivus.prototype.stop = function () {
37743  if (this.handle) {
37744    cancelAnimFrame(this.handle);
37745    this.handle = null;
37746  }
37747  return this;
37748};
37749
37750/**
37751 * Destroy the instance.
37752 * Remove all bad styling attributes on all
37753 * path tags
37754 *
37755 */
37756Vivus.prototype.destroy = function () {
37757  this.stop();
37758  var i, path;
37759  for (i = 0; i < this.map.length; i++) {
37760    path = this.map[i];
37761    path.el.style.strokeDashoffset = null;
37762    path.el.style.strokeDasharray = null;
37763    this.renderPath(i);
37764  }
37765};
37766
37767
37768/**
37769 * Utils methods
37770 * include methods from Codrops
37771 **************************************
37772 */
37773
37774/**
37775 * Method to best guess if a path should added into
37776 * the animation or not.
37777 *
37778 * 1. Use the `data-vivus-ignore` attribute if set
37779 * 2. Check if the instance must ignore invisible paths
37780 * 3. Check if the path is visible
37781 *
37782 * For now the visibility checking is unstable.
37783 * It will be used for a beta phase.
37784 *
37785 * Other improvments are planned. Like detecting
37786 * is the path got a stroke or a valid opacity.
37787 */
37788Vivus.prototype.isInvisible = function (el) {
37789  var rect,
37790    ignoreAttr = el.getAttribute('data-ignore');
37791
37792  if (ignoreAttr !== null) {
37793    return ignoreAttr !== 'false';
37794  }
37795
37796  if (this.ignoreInvisible) {
37797    rect = el.getBoundingClientRect();
37798    return !rect.width && !rect.height;
37799  }
37800  else {
37801    return false;
37802  }
37803};
37804
37805/**
37806 * Parse attributes of a DOM element to
37807 * get an object of {attributeName => attributeValue}
37808 *
37809 * @param  {object} element DOM element to parse
37810 * @return {object}         Object of attributes
37811 */
37812Vivus.prototype.parseAttr = function (element) {
37813  var attr, output = {};
37814  if (element && element.attributes) {
37815    for (var i = 0; i < element.attributes.length; i++) {
37816      attr = element.attributes[i];
37817      output[attr.name] = attr.value;
37818    }
37819  }
37820  return output;
37821};
37822
37823/**
37824 * Reply if an element is in the page viewport
37825 *
37826 * @param  {object} el Element to observe
37827 * @param  {number} h  Percentage of height
37828 * @return {boolean}
37829 */
37830Vivus.prototype.isInViewport = function (el, h) {
37831  var scrolled   = this.scrollY(),
37832    viewed       = scrolled + this.getViewportH(),
37833    elBCR        = el.getBoundingClientRect(),
37834    elHeight     = elBCR.height,
37835    elTop        = scrolled + elBCR.top,
37836    elBottom     = elTop + elHeight;
37837
37838  // if 0, the element is considered in the viewport as soon as it enters.
37839  // if 1, the element is considered in the viewport only when it's fully inside
37840  // value in percentage (1 >= h >= 0)
37841  h = h || 0;
37842
37843  return (elTop + elHeight * h) <= viewed && (elBottom) >= scrolled;
37844};
37845
37846
37847/**
37848 * Get the viewport height in pixels
37849 *
37850 * @return {integer} Viewport height
37851 */
37852Vivus.prototype.getViewportH = function () {
37853  var client = this.docElem.clientHeight,
37854    inner = window.innerHeight;
37855
37856  if (client < inner) {
37857    return inner;
37858  }
37859  else {
37860    return client;
37861  }
37862};
37863
37864/**
37865 * Get the page Y offset
37866 *
37867 * @return {integer} Page Y offset
37868 */
37869Vivus.prototype.scrollY = function () {
37870  return window.pageYOffset || this.docElem.scrollTop;
37871};
37872
37873setupEnv = function () {
37874
37875  if (Vivus.prototype.docElem) {
37876    return;
37877  }
37878
37879  /**
37880   * Alias for document element
37881   *
37882   * @type {DOMelement}
37883   */
37884  Vivus.prototype.docElem = window.document.documentElement;
37885
37886  /**
37887   * Alias for `requestAnimationFrame` or
37888   * `setTimeout` function for deprecated browsers.
37889   *
37890   */
37891  requestAnimFrame = (function () {
37892    return (
37893      window.requestAnimationFrame       ||
37894      window.webkitRequestAnimationFrame ||
37895      window.mozRequestAnimationFrame    ||
37896      window.oRequestAnimationFrame      ||
37897      window.msRequestAnimationFrame     ||
37898      function(/* function */ callback){
37899        return window.setTimeout(callback, 1000 / 60);
37900      }
37901    );
37902  })();
37903
37904  /**
37905   * Alias for `cancelAnimationFrame` or
37906   * `cancelTimeout` function for deprecated browsers.
37907   *
37908   */
37909  cancelAnimFrame = (function () {
37910    return (
37911      window.cancelAnimationFrame       ||
37912      window.webkitCancelAnimationFrame ||
37913      window.mozCancelAnimationFrame    ||
37914      window.oCancelAnimationFrame      ||
37915      window.msCancelAnimationFrame     ||
37916      function(id){
37917        return window.clearTimeout(id);
37918      }
37919    );
37920  })();
37921};
37922
37923/**
37924 * Parse string to integer.
37925 * If the number is not positive or null
37926 * the method will return the default value
37927 * or 0 if undefined
37928 *
37929 * @param {string} value String to parse
37930 * @param {*}
37930 defaultValue Value to return if the result parsed is invalid
37931 * @return {number}
37932 *
37933 */
37934parsePositiveInt = function (value, defaultValue) {
37935  var output = parseInt(value, 10);
37936  return (output >= 0) ? output : defaultValue;
37937};
37938
37939
37940  if (typeof define === 'function' && define.amd) {
37941    // AMD. Register as an anonymous module.
37942    define([], function() {
37943      return Vivus;
37944    });
37945  } else if (typeof exports === 'object') {
37946    // Node. Does not work with strict CommonJS, but
37947    // only CommonJS-like environments that support module.exports,
37948    // like Node.
37949    module.exports = Vivus;
37950  } else {
37951    // Browser globals
37952    window.Vivus = Vivus;
37953  }
37954
37955}());

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.